分析邮件日志从每秒处理3个结果到每秒处理800个结果过程(grep提速)
由于业务需要,对EDM发出的邮件日志进行分析处理,我要做的是预处理,把posfix杂乱无章的日志中找到我需要的数据.
我用javamail发的邮件,发送邮件时获取到是一个messageId,形如:2135546465.103503.1400232891548.JavaMail.root@hostname
但是直接通过这个messageid是不能拿到发送邮件的status的,因为日志中是这么记录的:
May :: c1202 postfix/cleanup[]: 00020127E4D: message-id=<2135546465.103503..JavaMail.root@hostname>
May :: c1202 postfix/error[]: 00020127E4D: to=<xxxxxxx@.com>, relay=none, delay=0.1, delays=0.08///0.01, dsn=4.4., status=deferred (delivery temporarily suspended: lost connection with 163mx01.mxmail.netease.com[220.181.14.139] while sending DATA command)
这个日志已经把没有用的行过滤掉了,只剩这两行是有用的.这两行的关联ID是00020127E4D,也就是说我要先通过
2135546465.103503..JavaMail.root@hostname
获取到00020127E4D,然后再通过00020127E4D获取到第二行中的status.
Q:为什么不直接grep 邮件名?
A:因为发送邮件服务器是共用的,不能通过邮件名就确认这封邮件是由我的EDM服务发出,而messageid是EDM服务发出时的标志ID,所以需要通过messageid找到关联ID,再找到发送结果那么折腾.
#假设同一条mailid的记录在最近10行内
mailTmp=`grep -A "${line}" "${logFile2}"`
#获取mailid,例如582664BDA66
mailid=`echo "${mailTmp}"| fgrep -m "${line}" | awk '{print $6}'|sed 's/://g'`
#获取发送结果,可能会有重试多条,只读第一条.
sendStatus=`echo "${mailTmp}" | fgrep "${mailid}"| fgrep "postfix/smtp" | fgrep -m "to=" | sed 's/.*status=//g'`
获取到status的核心代码就是这三行.再加个外层while循环从文件中读取messageid输入line的样子.
版本一:
需求能实现,但速度很慢,每秒最高得出3条status结果.
版本二:
maillog的日志是并发写入的,虽然对同一封邮件发出写入的日志顺序是固定的,但同一个mailid可能要读1000行才能找到这关键的两行数据.
改进:
1. 为了减少第一条语句的搜索,过滤掉无用的行,例如postfix/qmgr,postfix/smtpd等行,我不关注的信息.
2. 根据mailid预先排序,把关联的mailid放在一起,这样更加能够减轻第一条grep的搜索.
结果:
每秒3条速度提升到每秒5条,还不错,但还是太慢了,因为第一天的日志有19W条...这样算下去要10个小时才能弄完.
版本三:
每秒5条,没想到什么好办法提升了,就想着能不能并发呢?开N个线程,那每秒不就可以处理N*5条了吗?
改进:
尝试使用shell下面的并发,找了一下资料,参考一位疑似TX员工分享的代码: http://my.oschina.net/sanpeterguo/blog/133304
我使用的服务器是8核CPU,为了尽量不影响原有的服务,我把线程开了5个.
结果:
果然很有效,开了5个线程,能把速度提升到每秒处理12~17个.
版本四:
grep有多个用法,其中有grep/fgrep/egrep,后面两个只不过是第一个带参数的alias,但网上说用fgrep会更快,fgrep是fix string grep,不解析pattern,搜索会更快.
还有的说法在grep前加LANC=C,即用的时候为LANC=C grep XXXX,我试了,几乎没影响.
改进:
使用fgrep
结果:
略微有效,现在每秒稳定在15~18个了.
版本五:
其实我这里非常需要用到一个数据结构,map,字典结构,要是我可以预先把日志里所有的messageId->status处理好,然后我直接查就可以了,但是没找到shell下面map结构的工具...据说bash 4.2有,但用起来也很复杂,如果用python/java来写就实在太简单了,但我想挑战shell,用shell实现这个需求,而且用grep来匹配字符串效率是最高的,尝试用map失败.
版本六:
由于用了多线程对同一个文件进行grep,那文件的写性能肯定很影响效率啊!
尝试一: 把mail.log文件读到内存里,即logFile3=`cat ${logFile2}`,然后再用echo "${logFile3}" |grep XXX这样去筛选.
结果: 一运行就报错了...不给这样用..也不知道为啥,报的是参数过长...mail.log文件有88MB,不行.
于是我想能不能搞个linux下的ramdisk,这样肯定能大大提升mail.log的读性能啊!
google了一下资料发现,linux下ramdisk原生就是支持的,就在ls -al /dev/ram*,预设了一些,但是用的时候,ramdisk大小是固定的,一旦分配了,重启前就不能改变了.这样不好,这台机器上的主要服务不是我现在用的日志分析小程序,不能独占那么多内存,而且日志大小每天都不一样,不能直接分配一个较大的内存来这样用.
然后我再找到了/dev/shm,这是默认是内存的一半大小,用于共享内存使用的.用的是tmpfs,更重要的是动态的,如果你不放东西进去 ,他占用内存就是0,如果你较大的东西进去再删掉,内存能释放掉让给其它程序使用.
而且/dev/shm是可以安全使用的,很多服务器会用这个目录来当一些临时文件的存储,更有甚者把/tmp挂载到/dev/shm下面!非常满足我的需求!
改进:
把mail.log放到/dev/shm
结果:
分析日志提升到每秒55条了~!YES!大喜~
以上就是我分析日志从每秒处理3个结果到每秒处理55个结果过程, 性能足足提升了16倍啊!现在仅需一个小时就可以把19W条messageid分析完了,不错的结果.或许还有改进的空间,继续折腾吧.
版本七:
过了一天,过滤后的日志变大了,从88MB涨到400MB,按版本六的速度只有15TPS了,于是只好用JAVA实现一下,把messageId跟status放到MAP里,直接命中查询,无论日志有多少,速度都稳定在800TPS了,郁闷~
分析邮件日志从每秒处理3个结果到每秒处理800个结果过程(grep提速)的更多相关文章
- 一天,python搞个分析NGINX日志的脚本
准备给ZABBIX用的. 统计接口访问字次,平均响应时间,4XX,5XX次数 以后可以再改进.. #!/usr/bin/env python # coding: utf-8 ############# ...
- 用c#读取并分析sql2005日志
用过logExplorer的朋友都会被他强悍的功能吸引,我写过一篇详细的操作文档可以参考http://blog.csdn.net/jinjazz/archive/2008/05/19/2459692. ...
- 利用python分析nginx日志
最近在学习python,写了个脚本分析nginx日志,练练手.写得比较粗糙,但基本功能可以实现. 脚本功能:查找出当天访问次数前十位的IP,并获取该IP来源,并将分析结果发送邮件到指定邮箱. 实现前两 ...
- shell 在手分析服务器日志【转】
自己的小网站跑在阿里云的 ECS 上面, 偶尔也去分析分析自己网站服务器日志,看看网站的访问量.看看有没有黑阔搞破坏!于是收集,整理一些服务器日志分析命令,大家可以试试! awk '{print $1 ...
- C# 分析 IIS 日志(Log)
由于最近又要对 IIS日志 (Log) 分析,以便得出各个搜索引擎每日抓取的频率,所以这两天一直在尝试各个办法来分析 IIS 日志 (Log),其中尝试过:导入数据库.Log parser.Powse ...
- elk系列7之通过grok分析apache日志【转】
preface 说道分析日志,我们知道的采集方式有2种: 通过grok在logstash的filter里面过滤匹配. logstash --> redis --> python(py脚本过 ...
- GoAccess分析Nginx日志详解
一.为了提高 GoAccess 分析准确度,建议配置 nginx.conf 的 log_format 项如下: log_format main '$remote_addr - $remote_user ...
- 烂泥:利用awstats分析nginx日志
本文由ilanniweb提供友情赞助,首发于烂泥行天下 想要获得更多的文章,可以关注我的微信ilanniweb 昨天把nginx的日志进行了切割,关于如何切割nginx日志,可以查看<烂泥:切割 ...
- 用OSSIM轻松分析网络设备日志
用OSSIM轻松分析网络设备日志 基于插件的日志收集与处理模式,使得用户可以轻松的利用OSSIM来分析异构网络环境下的各种网络设备日志,下面展示一些硬件设备日志的实例,我们在RAW LOG界面里,搜索 ...
随机推荐
- Css布局 响应式布局介绍
1. 概念: 写一套css样式可以同时适配多个终端,是为解决移动互联网诞生的. 2. 作用: 面对不同的分辨率设备灵活性强,能够快捷解决多设备显示适应问题 3. 原理 媒体查询 ① 外联式媒体查询语法 ...
- [ERROR] Failed to execute goal org.apache.maven.plugins:maven-install-plugin:2.4:install (default-cli) on project kircp-js-plan-resource: The packaging for this project did not assign a file to the bu
结合网上的相关资料,要使用Lifecycle下的install 原因好像是Lifecycle下才会走Maven完整的phase.
- AIX中的网络管理
1.AIX中网络配置 AIX支持的适配器: #lsdev -Cc adapter 查看网络适配器: #lsdev -Cc if 修改网卡属性 #smitty chgenet ...
- 调试dcc 试图将u-boot放入ocm运行碰到的问题
1. 起因: gd->mon_len = (ulong)&__bss_end - (ulong)_start; 在u-boot.map中查找,发现__bss_end并不是u-boot.b ...
- Rsync以守护进程(socket)的方式传输数据
Rsync以守护进程(socket)的方式传输数据 Rsync服务部署 一.以守护进程(socket)的方式传输数据(重点) 部署环境: 分别用uname命令查看各系统相关信息 1 2 ...
- ks代码助解
代码实现: data_test_2 = {'gd':[1,1,1,1,1,1,0,0,0,0,0,0,0],'score':[1,2,0,2,2,7,4,5,4,0,4,18,np.nan]} dat ...
- win10激活方法 windows 10 最简单的激活方法
1.首先,要用管理员权限打开cmd命令行窗口,可以搜索框中输入“cmd”,在出现的“命令行提示符”,图标上右击“以管理员身份运行”. 2.为了让其它激活工具的密钥清除,先卸载密钥,在命令行输入 ...
- UNIX标准C - 进程之间的通信
一.基本概念 进程间通信IPC:进程之间交换数据的过程叫进程间通信 进程间同性的方式: 简单的进程间的通信: 命令行:父进程通过exec函数创建子进程是可以附加一些数据 环境变量表:父进程通过exec ...
- Windows10 + VS2015 环境下对gdal2.0.1进行64bit编译小结
这是官方给出的编译指导,但是在实践过程中有几点仍然需要特别注意. Tip 1:不要使用默认的"VS开发人员命令提示"工具,使用该工具会遭遇如下的错误: 正在创建库 gdal_i.l ...
- 详解cocos2dx 3.0的release版本在android平台的签名过程
当您的游戏准备发布前,需要编译成为release版本,命令中需要增加 -m release,编译命令如下: cocos compile -p android -m release 在编译结束后,生成x ...