按日期切割nginx访问日志--及性能优化
先谈下我们需求,一个比较大的nginx访问日志,根据访问日期切割日志,保存在/tmp目录下。
测试机器为腾讯云机子,单核1G内存。测试日志大小80M。
不使用多线程版:
- #!/usr/bin/env python
- # coding=utf-8
- import re
- import datetime
- if __name__ == '__main__':
- date_pattern = re.compile(r'\[(\d+)\/(\w+)\/(\d+):')
- with open('./access_all.log-20161227') as f:
- for line in f:
- day, mon, year = re.search(date_pattern, line).groups()
- mon = datetime.datetime.strptime(mon, '%b').month
- log_file = '/tmp/%s-%s-%s' % (year, mon, day)
- with open(log_file, 'a+') as f:
- f.write(line)
耗时:
- [root@VM_255_164_centos data_parse]# time python3 log_cut.py
- real 0m41.152s
- user 0m32.578s
- sys 0m6.046s
多线程版:
- #!/usr/bin/env python
- # coding=utf-8
- import re
- import datetime
- import threading
- date_pattern = re.compile(r'\[(\d+)\/(\w+)\/(\d+):')
- def log_cut(line):
- day, mon, year = re.search(date_pattern, line).groups()
- mon = datetime.datetime.strptime(mon, '%b').month
- log_file = '/tmp/%s-%s-%s' % (year, mon, day)
- with open(log_file, 'a+') as f:
- f.write(line)
- if __name__ == '__main__':
- with open('./access_all.log-20161227') as f:
- for line in f:
- t = threading.Thread(target=log_cut, args=(line,))
- t.setDaemon(True)
- t.start()
耗时:
- # time python3 log_cut.py
- real 1m35.905s
- user 1m10.292s
- sys 0m19.666s
使用多线程版竟然比不使用多进程版要慢的多。。cpu密集型任务使用上下文切换果然很耗时。
线程池版:
线程池类
- #!/usr/bin/env python
- # coding=utf-8
- import queue
- import threading
- import contextlib
- import time
- StopEvent = object()
- class ThreadPool(object):
- def __init__(self, max_num, max_task_num = None):
- if max_task_num:
- self.q = queue.Queue(max_task_num)
- else:
- self.q = queue.Queue()
- self.max_num = max_num
- self.cancel = False
- self.terminal = False
- self.generate_list = []
- self.free_list = []
- def run(self, func, args, callback=None):
- if self.cancel:
- return
- if len(self.free_list) == 0 and len(self.generate_list) < self.max_num:
- self.generate_thread()
- w = (func, args, callback,)
- self.q.put(w)
- def generate_thread(self):
- t = threading.Thread(target=self.call)
- t.start()
- def call(self):
- current_thread = threading.currentThread()
- self.generate_list.append(current_thread)
- event = self.q.get()
- while event != StopEvent:
- func, arguments, callback = event
- try:
- result = func(*arguments)
- success = True
- except Exception as e:
- success = False
- result = None
- if callback is not None:
- try:
- callback(success, result)
- except Exception as e:
- pass
- with self.worker_state(self.free_list, current_thread):
- if self.terminal:
- event = StopEvent
- else:
- event = self.q.get()
- else:
- self.generate_list.remove(current_thread)
- def close(self):
- self.cancel = True
- full_size = len(self.generate_list)
- while full_size:
- self.q.put(StopEvent) #
- full_size -= 1
- def terminate(self):
- self.terminal = True
- while self.generate_list:
- self.q.put(StopEvent)
- self.q.queue.clear()
- @contextlib.contextmanager
- def worker_state(self, state_list, worker_thread):
- state_list.append(worker_thread)
- try:
- yield
- finally:
- state_list.remove(worker_thread)
threadingPool.py
代码
- #!/usr/bin/env python
- # coding=utf-8
- import re
- import datetime
- from threadingPool import ThreadPool
- date_pattern = re.compile(r'\[(\d+)\/(\w+)\/(\d+)\:')
- def log_cut(line):
- day, mon, year = date_pattern.search(line).groups()
- mon = datetime.datetime.strptime(mon, '%b').month
- log_file = '/tmp/%s-%s-%s' % (year, mon, day)
- with open(log_file, 'a+') as f:
- f.write(line)
- def callback(status, result):
- pass
- pool = ThreadPool(1)
- with open('./access_all.log-20161227') as f:
- for line in f:
- pool.run(log_cut, (line,), callback)
- pool.close()
耗时:
- # time python3 log_cut2.py
- real 0m53.371s
- user 0m44.761s
- sys 0m5.600s
线程池版比多线程版要快,看来写的线程池类还是有用的。减少了上下文切换时间。
进程池版:
- #!/usr/bin/env python
- # coding=utf-8
- import re
- import datetime
- from multiprocessing import Pool
- date_pattern = re.compile(r'\[(\d+)\/(\w+)\/(\d+):')
- def log_cut(line):
- day, mon, year = re.search(date_pattern, line).groups()
- mon = datetime.datetime.strptime(mon, '%b').month
- log_file = '/tmp/%s-%s-%s' % (year, mon, day)
- with open(log_file, 'a+') as f:
- f.write(line)
- if __name__ == '__main__':
- pool = Pool(1)
- with open('./access_all.log-20161227') as f:
- for line in f:
- pool.apply_async(func=log_cut, args=(line,))
- pool.close()
单个进程耗时:
- # time python3 log_cut.py
- real 0m28.392s
- user 0m23.451s
- sys 0m1.888s
2个进程耗时:
- # time python3 log_cut.py
- real 0m40.920s
- user 0m33.690s
- sys 0m3.206s
看来使用多进程时,如果是单核cpu只开一个进程,多核cpu的话开多个速度更快,单核cpu开多个进程速度很慢。
shell版
- #!/bin/bash
- Usage(){
- echo "Usage: $0 Logfile"
- }
- if [ $# -eq ] ;then
- Usage
- exit
- else
- Log=$
- fi
- date_log=$(mktemp)
- cat $Log |awk -F'[ :]' '{print $5}'|awk -F'[' '{print $2}'|uniq > date_log
- for i in `cat date_log`
- do
- grep $i $Log > /tmp/log/${i::}-${i::}-${i::}.access
- done
耗时:
- # time sh log_cut.sh access_all.log-
- real 0m2.435s
- user 0m2.042s
- sys 0m0.304s
shell的效果非常棒啊,只用2s多久完成了。
按日期切割nginx访问日志--及性能优化的更多相关文章
- 性能调优之访问日志IO性能优化
性能调优之访问日志IO性能优化 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821 ...
- 访问日志IO性能优化
在高并发量的场景下磁盘IO往往是性能的瓶颈所在,访问日志涉及到频繁的写操作,所以这部分要尽可能地优化,不然将拖累系统的整体性能.针对文件记录及数据库记录两种方式可以有以下措施提高写性能, l 避免频繁 ...
- 采集并分析Nginx访问日志
日志服务支持通过数据接入向导配置采集Nginx日志,并自动创建索引和Nginx日志仪表盘,帮助您快速采集并分析Nginx日志. 许多个人站长选取了Nginx作为服务器搭建网站,在对网站访问情况进行分析 ...
- Nginx访问日志.Nginx日志切割
11月27日任务 12.10 Nginx访问日志12.11 Nginx日志切割12.12 静态文件不记录日志和过期时间 1.Nginx访问日志 示例一: 日志格式 vim /usr/local/ngi ...
- Nginx 访问日志轮询切割
Nginx 访问日志轮询切割脚本 #!/bin/sh Dateformat=`date +%Y%m%d` Basedir="/application/nginx" Nginxlog ...
- Nginx访问日志、 Nginx日志切割、静态文件不记录日志和过期时间
1.Nginx访问日志 配制访问日志:默认定义格式: log_format combined_realip '$remote_addr $http_x_forwarded_for [$time_loc ...
- Nginx访问日志、日志切割、静态文件不记录日志和过期时间
6月8日任务 12.10 Nginx访问日志12.11 Nginx日志切割12.12 静态文件不记录日志和过期时间 12.10 Nginx访问日志 除了在主配置文件nginx.conf里定义日志格式外 ...
- Linux centosVMware Nginx访问日志、Nginx日志切割、静态文件不记录日志和过期时间
一.Nginx访问日志 vim /usr/local/nginx/conf/nginx.conf //搜索log_format 日至格式 改为davery格式 $remote_addr 客户端IP ...
- nginx访问日志(access_log)
一.nginx访问日志介绍 nginx软件会把每个用户访问网站的日志信息记录到指定的日志文件里,供网站提供者分析用户的浏览行为等,此功能由ngx_http_log_module模块负责,对应的官方地址 ...
随机推荐
- [Android]异步 layout inflation(翻译)
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5829809.html 异步 layout inflation ...
- c#进阶之神奇的CSharp
CSharp 简写为c#,是一门非常年轻而又有活力的语言. CSharp的诞生 在2000年6月微软发布了c#这门新的语言.作为微软公司.NET 平台的主角,c#吸收了在他之前诞生的语言(c ...
- 强大的flash头像上传插件(支持旋转、拖拽、剪裁、生成缩略图等)
今天介绍的这款flash上传头像功能非常强大,支持php,asp,jsp,asp.net 调用 头像剪裁,预览组件插件. 本组件需要安装Flash Player后才可使用,请从http://dl.pc ...
- python安装numpy、scipy和matplotlib等whl包的方法
最近装了python和PyCharm开发环境,但是在安装numpy和matplotlib等包时出现了问题,现总结一下在windows平台下的安装方法. 由于现在找不到了工具包新版本的exe文件,所以采 ...
- Context值和bool开关
Context值和bool开关的相关内容 Context值分为2种 系统默认的context值 服务的context值 Context值的作用 主要是防止有未知文件进入目录文件之中(如将病毒拷贝到 ...
- svn web页面管理svnadmin部署
1.yum install subversion 创建svn目录 mdkir -p /data/svndirroot 建立svn库 svnadmin create /data/svndirroo ...
- href="javascript:xxx(this);"和onclick="javascript:xxx(this);"的区别
href="javascript:xxx(this);"和onclick="javascript:xxx(this);" 一直以为这两种写法是等同的,今天在项目 ...
- [转]How to: Create a Custom Principal Identity
本文转自:https://msdn.microsoft.com/en-us/library/aa702720(v=vs.110).aspx The PrincipalPermissionAttribu ...
- Android应用架构之Android MVP使用
前两篇已经将Retrofit和RxAndroid应用到了项目中,这篇本打算直接将Dagger2引进项目,但是考虑到整个项目结构,就来个结构整理吧,一起来看看网上炒得火热MVP模式. 说到MVP就不得不 ...
- ultraiso制作大于4GB的镜像的启动盘
ultraiso这个软件用来做启动盘很方便, 一般linux啦, windows啦, 神马的都用他来做, 但是, 因为ubuntu一般只有1-2GB, win桌面版一般也就3GB左右, 所以不必考虑这 ...