使用MongoDB分析Nginx日志的方法详解

本文我们要从日志文件中找出IP访问最多的10条记录,然后判断其是否合法,从而采取对应的措施。感兴趣的朋友们一起来看看吧。

日志解析流程

正常情况下,关于Nginx日志解析的流程如下所示:

一般情况下我们会对要解析的日志提前进行切分,常用的方式是按照日期,然后保存1个星期的日志。然后接下来就是日志的解析了,在这个过程中会使用到一些工具或编程语言,例如awk、grep、perl、python。

最后的入库和可视化处理一般视业务而定,没有强制的要求。

日志查询的解决方案

而关于Nginx日志解析的常用解决方案主要有如下4种方式:

  1. 通过awk和grep进行解析
  2. 通过Postgresql外联表进行日志的映射
  3. 通过Python与MongoDB的组合来进行日志查询
  4. 通过ELK这个开源套件进行查询

其中Postgresql外联表的方式在之前公司的时候已经使用过,当然是对公司多个3GB大小的日志进行处理。而第1种和第4种解决方案没有太多的实践的经验,这里我们主要来看第2种解决方案。

日志格式

关于日志解析处理,我们比较常用的方式是使用正则表达式来进行匹配,而常用的1个库是nginxparser,我们可以直接通过pip进行安装。当然还有其他的方式来进行解析,这个要视业务而定。

在日志解析中,比较重要的是日志的格式,默认情况下Nginx的日志格式如下:

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
     '$status $body_bytes_sent "$http_referer" '
     '"$http_user_agent" "$http_x_forwarded_for"'
     '$upstream_addr $upstream_response_time $request_time; 

下面我们来看实际业务中的1个应用。之前公司有1个抢微信红包的活动,当然有用户反映好几天都无法抢到1个红包。因此,我们团队成员认为可能在这个过程中存在作弊的现象,因此便决定对Nginx的日志进行解析。

下面是1条真实的日志的记录:

101.226.89.14 - - [10/Jul/2016:07:28:32 +0800] "GET /pocketmoney-2016-XiKXCpCK.html HTTP/1.1" 302 231 "-" "Mozilla/5.0 (Linux; Android 5.1; OPPO R9tm Build/LMY47I) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/37.0.0.0 Mobile MQQBrowser/6.2 TBS/036548 Safari/537.36 MicroMessenger/6.3.22.821 NetType/WIFI Language/zh_CN" 

日志分析

通过awk进行解析

接着,我们来看下如何使用awk解析出IP访问最多的记录,关于awk语法可以参考进行学习:

dog@dog-pc:~$ awk '{a[$1]++}END{for(i in a)print i,a[i]}' nginx.log |sort -t ' ' -k2 -rn|head -n 10
111.167.50.208 26794
183.28.6.143 16244
118.76.216.77 9560
14.148.114.213 3609
183.50.96.127 3377
220.115.235.21 3246
222.84.160.249 2905
121.42.0.16 2212
14.208.240.200 2000
14.17.37.143 1993 

默认情况下,awk以空格作为分隔符号,因此$1将获取到Nginx默认格式中的远程地址。在这里,我们通过定义1个字段,使用IP作为键名,如果对应的键名存在则将其数量加1处理。最后我们遍历这个字典,之后通过数量进行排序,最后通过head获取10条记录。
当然这种操作方式是有较大误差的,因为我们没有指定状态码等其他条件,下面我们来看根据状态码和请求方式这2个条件后过滤的数据:

dog@dog-pc:~$ awk '{if($9>0 && $9==200 && substr($6,2)== "GET") a[$1]++}END{for(i in a)print i,a[i]}' nginx.log|sort -t ' ' -k2 -rn|head -n 10
222.84.160.249 2856
183.28.6.143 2534
116.1.127.110 1625
14.208.240.200 1521
14.17.37.143 1335
219.133.40.13 1014
219.133.40.15 994
14.17.37.144 988
14.17.37.161 960
183.61.51.195 944 

这样我们就可以将这10个IP进行分析,考虑下一步的操作,比如通过iptables组合禁止该IP的访问或限制其访问的次数等。

通过Postgresql

通过Postgresql入库后使用SQL进行查询的方式可以通过如下2种图片来查看:

在上图中主要是查看日志中请求状态码的总数量。而下图是对状态码为200的前10条IP的筛选:

可以看到基本上与上面awk解析的方式一致。

通过MongoDB进行查询

我们知道,MongoDB是1个文档型数据库,通过这个数据库我们辅助解决关系型数据库一些不太擅长的工作。

在Python中,主要的MongoDB客户端驱动是PyMongo,我们可以通过如下的方式建立1个连接:

In [1]: from pymongo import MongoClient
In [2]: client = MongoClient()

由于这里我们使用的是默认的端口和地址,因此在MongoClient类中不传入任何的参数。

在这里,我们先说下我们插入到MongoDB中日志的格式:

{
 "status": 302, //HTTP状态码
 "addr": "101.226.89.14", //远程IP地址
 "url": "-",
 "req": "/pocketmoney-2016-XiCXCpCK.html", //请求的地址
 "agent": "Mozilla/5.0 (Linux; Android 5.1; OPPO R9tm Build/LMY47I) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/37.0.0.0 Mobile MQQBrowser/6.2 TBS/036548 Safari/537.36 MicroMessenger/6.3.22.821 NetType/WIFI Language/zh_CN", //请求的user-agent
 "referer": "NetType/WIFI",
 "t": "2016/07/10 06:28:32", //请求的时间
 "size": 231, //响应的大小
 "method": "GET", //请求的方法
 "user": "-" //用户名称
} 

在这里我们通过Python进行解析后,组装成如上的格式后插入到MongoDB中,在这里主要用到的是MongoDB文档对象的insert_one方法插入1条记录。

db = client['log']
col = db['nginx']
data = {}
...
col.insert_one(data)

接着我们开始对上述的记录进行查询操作,主要是通过MongoDB提供的map-reduce来实现聚合操作,其对应的Python代码为:

In [3]: db = client['log']
In [4]: col = db['nginx']
In [5]: pipeline = [
 ...: {"$match":{"status":200}},
 ...: {"$group":{"_id":"$addr","count":{"$sum":1}}},
 ...: {"$sort":{"count":-1}},
 ...: {"$limit":10}
 ...: ]
In [6]: list(col.aggregate(pipeline))
Out[6]:
[{u'_id': u'222.84.160.249', u'count': 2856},
 {u'_id': u'183.28.6.143', u'count': 2534},
 {u'_id': u'116.1.127.110', u'count': 1625},
 {u'_id': u'14.208.240.200', u'count': 1521},
 {u'_id': u'14.17.37.143', u'count': 1335},
 {u'_id': u'219.133.40.13', u'count': 1014},
 {u'_id': u'219.133.40.15', u'count': 994},
 {u'_id': u'14.17.37.144', u'count': 988},
 {u'_id': u'14.17.37.161', u'count': 960},
 {u'_id': u'183.61.51.195', u'count': 944}]

可以看到这个过程与之前的2种方式得到的结果是一致的。

关于可视化处理

关于可视化处理,我们可以选择一些Javascript的库,例如:

  1. 百度的Echarts
  2. d3.js及其衍生的库

对于Python,可视化处理可以使用如下的一些库:

  1. matplotlib
  2. pandas

当然还有一些其他的库这里就不一一叙述了。

下面是1个使用百度Echart绘制的界面:

看起来还是挺漂亮的。

参考文章:http://api.mongodb.com/python/current/examples/aggregation.html

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

(0)

相关推荐

  • nginx动态添加访问白名单的方法

    本文实现的功能是:网站启用访问白名单,对于不在白名单中又需要访问的客户,只需打开一个不公开的网址,然后自动获得2小时的访问权限,时间达到后自动删除访问权限 实现此功能需要以下几个步骤: nginx启用访问白名单 客户打开指定网址自动添加访问白名单 为网址添加简单的认证 每两个小时自动恢复默认白名单,删除临时IP访问权限 一.nginx配置访问白名单 这个就比较简单了,简单贴一下配置: ............nginx.conf........... geo $remote_addr $ip_w

  • Nginx 禁止IP访问如何实现

    Nginx 禁止IP访问 我们在使用的时候会遇到很多的恶意IP攻击,这个时候就要用到Nginx 禁止IP访问了.下面我们就先看看Nginx的默认虚拟主机在用户通过IP访问,或者通过未设置的域名访问(比如有人把他自己的域名指向了你的ip)的时候生效最关键的一点是,在server的设置里面添加这一行: listen 80 default; 后面的default参数表示这个是默认虚拟主机. Nginx 禁止IP访问这个设置非常有用. 比如别人通过ip或者未知域名访问你的网站的时候,你希望禁止显示任何有

  • Nginx反向代理一个80端口下配置多个微信项目详解

    Nginx反向代理一个80端口下配置多个微信项目详解 我们要接入微信公众号平台开发,需要填写服务器配置,然后依据接口文档才能实现业务逻辑.但是微信公众号接口只支持80接口(80端口).我们因业务需求需要在一个公众号域名下面,发布两个需要微信授权的项目,怎么办? 我们可以用nginx服务器做反向代理来解决这个问题.nginx服务器对外80端口,然后根据URL参数不同,对内访问不同的项目. nginx配置如下: 打开/usr/local/nginx/conf/nginx.conf worker_pr

  • 详解nginx过滤url实现前台js的配置问题

    我们在开发的过程中,可能需要一些配置,这些配置可能就是仅仅为了开发的方便,比方说,订单过期时间,生产环境需要半小时失效,但是真正开发时,我不可能等上个半小时,所以这个时间这个失效时间我们会写在配置文件中,这样开发环境和生产环境各一套配置,来回切换很方便的. 基于摘要里的,在Java后台实现很方便,只需要读取properties配置文件即可 但是在前台js,js是在浏览器里执行的,无法读取服务器上的配置,除非请求后台,但是每次的开销也是挺大的,所以这个想法被ps了 这时候可以利用nginx,前台静

  • Linux下安装配置nginx详解

    一.Linux下安装配置nginx 第一次安装nginx,中间出现的问题一步步解决. 用到的工具secureCRT,连接并登录服务器. 1.1 rz命令,会弹出会话框,选择要上传的nginx压缩包. #rz 1.2 解压 [root@vw010001135067 ~]# cd /usr/local/ [root@vw010001135067 local]# tar -zvxf nginx-1.10.2.tar.gz 1.3 进入nginx文件夹,执行./configure命令 [root@vw0

  • Nginx配置文件nginx.conf详细说明

    在此记录下Nginx服务器nginx.conf的配置文件说明, 部分注释收集与网络. #运行用户 user www-data; #启动进程,通常设置成和cpu的数量相等 worker_processes 1; #全局错误日志及PID文件 error_log /var/log/nginx/error.log; pid /var/run/nginx.pid; #工作模式及连接数上限 events { use epoll; #epoll是多路复用IO(I/O Multiplexing)中的一种方式,但

  • Nginx启用GZIP压缩网页传输方法(推荐)

    原理: 浏览器-请求--> 声明可以接受 gzip压缩 或 deflate压缩 或compress 或 sdch压缩 从http协议的角度看–请求头 声明 acceopt-encoding: gzip deflate sdch (是指压缩算法,其中sdch是google倡导的一种压缩方式,目前支持的服务器尚不多) 服务器–>回应-把内容用gzip方式压缩-->发给浏览器 浏览<-–解码gzip-–接收gzip压缩内容-- gzip配置的常用参数 参数 含义 gzip on/off

  • 微信小程序Server端环境配置详解(SSL, Nginx HTTPS,TLS 1.2 升级)

    微信小程序Server环境配置详解 主要内容: 1. SSL免费证书申请步骤 2. Nginx HTTPS 配置 3. TLS 1.2 升级过程 微信小程序要求使用 https 发送请求,那么Web服务器就要配置成支持 https,需要先申请SSL证书 小程序也要求 TLS(传输层安全协议)的版本至少为 1.2,在配置好 https之后,如果 TLS 的版本较低,就涉及到升级问题 所以 Server端环境配置的主要步骤: 申请 SSL 证书 配置web服务器支持https(我使用的是nginx)

  • 微信小程序 Nginx环境配置详细介绍

    微信小程序Server环境配置详解 主要内容: 1. SSL免费证书申请步骤 2. Nginx HTTPS 配置 3. TLS 1.2 升级过程 微信小程序要求使用 https 发送请求,那么Web服务器就要配置成支持 https,需要先申请SSL证书 小程序也要求 TLS(传输层安全协议)的版本至少为 1.2,在配置好 https之后,如果 TLS 的版本较低,就涉及到升级问题 所以 Server端环境配置的主要步骤: 申请 SSL 证书 配置web服务器支持https(我使用的是nginx)

  • 使用MongoDB分析Nginx日志的方法详解

    本文我们要从日志文件中找出IP访问最多的10条记录,然后判断其是否合法,从而采取对应的措施.感兴趣的朋友们一起来看看吧. 日志解析流程 正常情况下,关于Nginx日志解析的流程如下所示: 一般情况下我们会对要解析的日志提前进行切分,常用的方式是按照日期,然后保存1个星期的日志.然后接下来就是日志的解析了,在这个过程中会使用到一些工具或编程语言,例如awk.grep.perl.python. 最后的入库和可视化处理一般视业务而定,没有强制的要求. 日志查询的解决方案 而关于Nginx日志解析的常用

  • MongoDB中MapReduce的使用方法详解

    前言 玩过Hadoop的小伙伴对MapReduce应该不陌生,MapReduce的强大且灵活,它可以将一个大问题拆分为多个小问题,将各个小问题发送到不同的机器上去处理,所有的机器都完成计算后,再将计算结果合并为一个完整的解决方案,这就是所谓的分布式计算.本文我们就来看看MongoDB中MapReduce的使用. 打算用mongodb mapreduce之前一定要知道的事!!! mapreduce其实是分批处理数据的,每一百次重新reduce处理,所以到reduce里的数据如果是101条,那就会分

  • nginx日志配置指令详解

    日志对于统计排错来说非常有利的.本文总结了nginx日志相关的配置如access_log.log_format.open_log_file_cache.log_not_found.log_subrequest.rewrite_log.error_log. nginx有一个非常灵活的日志记录模式.每个级别的配置可以有各自独立的访问日志.日志格式通过log_format命令来定义.ngx_http_log_module是用来定义请求日志格式的. 1. access_log指令 语法: access_

  • 使用alwayson后如何收缩数据库日志的方法详解

    问题描述: 在使用了alwayson后,主从库实时同步,原理是通过事务日志同步的,所以造成主数据库的事务日志一直在使用,而且无法收缩主数据库的事务日志. 在主从库同步时,收缩数据库是不起作用的.由于主数据库无法收缩,所以从数据库的日志也会一直跟着增长,造成磁盘空间一直增长. 网上大量的收缩日志的方法,基本上都不管用,怀疑根本没有在实际环境中使用过,以下方案是我在实际中使用后总结记录的. 解决方案: 最开始发现这个问题后,也是研究了好久,发现的方法,先是全手动操作.因为这些操作,并不能用语句来实现

  • 利用shell命令统计日志的方法详解

    前言 大家都知道,通过使用 shell 命令可以很方便地对日志进行统计和分析,当服务有异常的时候,需要去排查日志,那么掌握一种统计日志的技巧就是必不可少的了. 假设有一个包含下面内容的日志文件 access.log.我们以统计这个文件的日志为例. date=2017-09-23 13:32:50 | ip=40.80.31.153 | method=GET | url=/api/foo/bar?params=something | status=200 | time=9.703 | bytes=

  • iOS App连续闪退时上报crash日志的方法详解

    前言 当一个iOS应用程序崩溃时,系统会创建一份crash日志保存在设备上.这份crash日志记录着应用程序崩溃时的信息,通常包含着每个执行线程的栈调用信息(低内存闪退日志例外),对于开发人员定位问题很有帮助. 为保障线上 App 的用户体验,我们一般都会对线上 App 的 crash 率做实时监控,一旦检测到 spike,可以即刻调查原因,但这一切的前提是 crash 日志能够准确上报. crash 日志上报有两个难点: crash handler 安装之前的代码要绝对稳定 如果日志采集器还没

  • Spring Boot集成Shiro并利用MongoDB做Session存储的方法详解

    前言 shiro是一个权限框架,具体的使用可以查看其官网 http://shiro.apache.org/ 它提供了很方便的权限认证和登录的功能. 而springboot作为一个开源框架,必然提供了和shiro整合的功能! 之前项目鉴权一直使用的Shiro,那是在Spring MVC里面使用的比较多,而且都是用XML来配置,用Shiro来做权限控制相对比较简单而且成熟,而且我一直都把Shiro的session放在mongodb中,这个比较符合mongodb的设计初衷,而且在分布式项目中mongo

  • 把MongoDB作为循环队列的方法详解

    我们在使用MongoDB的时候,一个集合里面能放多少数据,一般取决于硬盘大小,只要硬盘足够大,那么我们可以无休止地往里面添加数据. 然后,有些时候,我只想把MongoDB作为一个循环队列来使用,期望它有这样一个行为: 设定队列的长度为10 插入第1条数据,它被放在第1个位置 插入第2条数据,它被放在第2个位置 ... 插入第10条数据,它被放在第10个位置 插入第11条数据,它被放在第1个位置,覆盖原来的内容 插入第12条数据,它被放在第2个位置,覆盖原来的内容 ... MongoDB有一种Co

  • 在php7中MongoDB实现模糊查询的方法详解

    前言 在实际开发中, 有不少的场景需要使用到模糊查询, MongoDB shell 模糊查询很简单: db.collection.find({'_id': /^5101/}) 上面这句就是查询_id以'5101'开始的内容. 在老的MogoDB中模糊查询挺简单的,这里简单记录下模糊查询的操作方式: 命令行下: db.letv_logs.find({"ctime":/uname?/i}); php操作 $query=array("name"=>new Mongo

  • Springboot项目优雅地处理日志的方法详解

    如上图,每天会生成一个新的日志文件,然后日志进行分类,我这里只对error和info进行分类. 怎么做呢? 首先,在resource目录创建一个新文件,取名logback-spring.xml <?xml version="1.0" encoding="UTF-8" ?> <configuration > <appender name="consoleLog" class="ch.qos.logback.c

随机推荐