先谈下我们需求,一个比较大的nginx访问日志,根据访问日期切割日志,保存在/tmp目录下。

测试机器为腾讯云机子,单核1G内存。测试日志大小80M。

不使用多线程版:

  1. #!/usr/bin/env python
  2. # coding=utf-8
  3.  
  4. import re
  5. import datetime
  6.  
  7. if __name__ == '__main__':
  8. date_pattern = re.compile(r'\[(\d+)\/(\w+)\/(\d+):')
  9. with open('./access_all.log-20161227') as f:
  10. for line in f:
  11. day, mon, year = re.search(date_pattern, line).groups()
  12. mon = datetime.datetime.strptime(mon, '%b').month
  13. log_file = '/tmp/%s-%s-%s' % (year, mon, day)
  14. with open(log_file, 'a+') as f:
  15. f.write(line)

耗时:

  1. [root@VM_255_164_centos data_parse]# time python3 log_cut.py
  2. real 0m41.152s
  3. user 0m32.578s
  4. sys 0m6.046s

多线程版:

  1. #!/usr/bin/env python
  2. # coding=utf-8
  3.  
  4. import re
  5. import datetime
  6. import threading
  7.  
  8. date_pattern = re.compile(r'\[(\d+)\/(\w+)\/(\d+):')
  9.  
  10. def log_cut(line):
  11. day, mon, year = re.search(date_pattern, line).groups()
  12. mon = datetime.datetime.strptime(mon, '%b').month
  13. log_file = '/tmp/%s-%s-%s' % (year, mon, day)
  14. with open(log_file, 'a+') as f:
  15. f.write(line)
  16.  
  17. if __name__ == '__main__':
  18. with open('./access_all.log-20161227') as f:
  19. for line in f:
  20. t = threading.Thread(target=log_cut, args=(line,))
  21. t.setDaemon(True)
  22. t.start()

耗时:

  1. # time python3 log_cut.py
  2.  
  3. real 1m35.905s
  4. user 1m10.292s
  5. sys 0m19.666s

使用多线程版竟然比不使用多进程版要慢的多。。cpu密集型任务使用上下文切换果然很耗时。

线程池版:

线程池类

  1. #!/usr/bin/env python
  2. # coding=utf-8
  3.  
  4. import queue
  5. import threading
  6. import contextlib
  7. import time
  8.  
  9. StopEvent = object()
  10.  
  11. class ThreadPool(object):
  12.  
  13. def __init__(self, max_num, max_task_num = None):
  14. if max_task_num:
  15. self.q = queue.Queue(max_task_num)
  16. else:
  17. self.q = queue.Queue()
  18. self.max_num = max_num
  19. self.cancel = False
  20. self.terminal = False
  21. self.generate_list = []
  22. self.free_list = []
  23.  
  24. def run(self, func, args, callback=None):
  25. if self.cancel:
  26. return
  27. if len(self.free_list) == 0 and len(self.generate_list) < self.max_num:
  28. self.generate_thread()
  29. w = (func, args, callback,)
  30. self.q.put(w)
  31.  
  32. def generate_thread(self):
  33. t = threading.Thread(target=self.call)
  34. t.start()
  35.  
  36. def call(self):
  37. current_thread = threading.currentThread()
  38. self.generate_list.append(current_thread)
  39.  
  40. event = self.q.get()
  41. while event != StopEvent:
  42.  
  43. func, arguments, callback = event
  44. try:
  45. result = func(*arguments)
  46. success = True
  47. except Exception as e:
  48. success = False
  49. result = None
  50.  
  51. if callback is not None:
  52. try:
  53. callback(success, result)
  54. except Exception as e:
  55. pass
  56.  
  57. with self.worker_state(self.free_list, current_thread):
  58. if self.terminal:
  59. event = StopEvent
  60. else:
  61. event = self.q.get()
  62. else:
  63. self.generate_list.remove(current_thread)
  64.  
  65. def close(self):
  66. self.cancel = True
  67. full_size = len(self.generate_list)
  68. while full_size:
  69. self.q.put(StopEvent) #
  70. full_size -= 1
  71.  
  72. def terminate(self):
  73. self.terminal = True
  74.  
  75. while self.generate_list:
  76. self.q.put(StopEvent)
  77.  
  78. self.q.queue.clear()
  79.  
  80. @contextlib.contextmanager
  81. def worker_state(self, state_list, worker_thread):
  82. state_list.append(worker_thread)
  83. try:
  84. yield
  85. finally:
  86. state_list.remove(worker_thread)

threadingPool.py

代码

  1. #!/usr/bin/env python
  2. # coding=utf-8
  3.  
  4. import re
  5. import datetime
  6. from threadingPool import ThreadPool
  7.  
  8. date_pattern = re.compile(r'\[(\d+)\/(\w+)\/(\d+)\:')
  9.  
  10. def log_cut(line):
  11. day, mon, year = date_pattern.search(line).groups()
  12. mon = datetime.datetime.strptime(mon, '%b').month
  13. log_file = '/tmp/%s-%s-%s' % (year, mon, day)
  14. with open(log_file, 'a+') as f:
  15. f.write(line)
  16.  
  17. def callback(status, result):
  18. pass
  19.  
  20. pool = ThreadPool(1)
  21.  
  22. with open('./access_all.log-20161227') as f:
  23. for line in f:
  24. pool.run(log_cut, (line,), callback)
  25.  
  26. pool.close()

耗时:

  1. # time python3 log_cut2.py
  2.  
  3. real 0m53.371s
  4. user 0m44.761s
  5. sys 0m5.600s

线程池版比多线程版要快,看来写的线程池类还是有用的。减少了上下文切换时间。

进程池版:

  1. #!/usr/bin/env python
  2. # coding=utf-8
  3.  
  4. import re
  5. import datetime
  6. from multiprocessing import Pool
  7.  
  8. date_pattern = re.compile(r'\[(\d+)\/(\w+)\/(\d+):')
  9.  
  10. def log_cut(line):
  11. day, mon, year = re.search(date_pattern, line).groups()
  12. mon = datetime.datetime.strptime(mon, '%b').month
  13. log_file = '/tmp/%s-%s-%s' % (year, mon, day)
  14. with open(log_file, 'a+') as f:
  15. f.write(line)
  16.  
  17. if __name__ == '__main__':
  18. pool = Pool(1)
  19. with open('./access_all.log-20161227') as f:
  20. for line in f:
  21. pool.apply_async(func=log_cut, args=(line,))
  22. pool.close()

单个进程耗时:

  1. # time python3 log_cut.py
  2.  
  3. real 0m28.392s
  4. user 0m23.451s
  5. sys 0m1.888s

2个进程耗时:

  1. # time python3 log_cut.py
  2.  
  3. real 0m40.920s
  4. user 0m33.690s
  5. sys 0m3.206s

看来使用多进程时,如果是单核cpu只开一个进程,多核cpu的话开多个速度更快,单核cpu开多个进程速度很慢。

shell版

  1. #!/bin/bash
  2.  
  3. Usage(){
  4. echo "Usage: $0 Logfile"
  5. }
  6.  
  7. if [ $# -eq ] ;then
  8. Usage
  9. exit
  10. else
  11. Log=$
  12. fi
  13.  
  14. date_log=$(mktemp)
  15.  
  16. cat $Log |awk -F'[ :]' '{print $5}'|awk -F'[' '{print $2}'|uniq > date_log
  17.  
  18. for i in `cat date_log`
  19. do
  20. grep $i $Log > /tmp/log/${i::}-${i::}-${i::}.access
  21.  
  22. done

耗时:

  1. # time sh log_cut.sh access_all.log-
  2.  
  3. real 0m2.435s
  4. user 0m2.042s
  5. sys 0m0.304s

shell的效果非常棒啊,只用2s多久完成了。

按日期切割nginx访问日志--及性能优化的更多相关文章

  1. 性能调优之访问日志IO性能优化

    性能调优之访问日志IO性能优化   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821 ...

  2. 访问日志IO性能优化

    在高并发量的场景下磁盘IO往往是性能的瓶颈所在,访问日志涉及到频繁的写操作,所以这部分要尽可能地优化,不然将拖累系统的整体性能.针对文件记录及数据库记录两种方式可以有以下措施提高写性能, l 避免频繁 ...

  3. 采集并分析Nginx访问日志

    日志服务支持通过数据接入向导配置采集Nginx日志,并自动创建索引和Nginx日志仪表盘,帮助您快速采集并分析Nginx日志. 许多个人站长选取了Nginx作为服务器搭建网站,在对网站访问情况进行分析 ...

  4. Nginx访问日志.Nginx日志切割

    11月27日任务 12.10 Nginx访问日志12.11 Nginx日志切割12.12 静态文件不记录日志和过期时间 1.Nginx访问日志 示例一: 日志格式 vim /usr/local/ngi ...

  5. Nginx 访问日志轮询切割

    Nginx 访问日志轮询切割脚本 #!/bin/sh Dateformat=`date +%Y%m%d` Basedir="/application/nginx" Nginxlog ...

  6. Nginx访问日志、 Nginx日志切割、静态文件不记录日志和过期时间

    1.Nginx访问日志 配制访问日志:默认定义格式: log_format combined_realip '$remote_addr $http_x_forwarded_for [$time_loc ...

  7. Nginx访问日志、日志切割、静态文件不记录日志和过期时间

    6月8日任务 12.10 Nginx访问日志12.11 Nginx日志切割12.12 静态文件不记录日志和过期时间 12.10 Nginx访问日志 除了在主配置文件nginx.conf里定义日志格式外 ...

  8. Linux centosVMware Nginx访问日志、Nginx日志切割、静态文件不记录日志和过期时间

    一.Nginx访问日志 vim /usr/local/nginx/conf/nginx.conf //搜索log_format  日至格式 改为davery格式 $remote_addr  客户端IP ...

  9. nginx访问日志(access_log)

    一.nginx访问日志介绍 nginx软件会把每个用户访问网站的日志信息记录到指定的日志文件里,供网站提供者分析用户的浏览行为等,此功能由ngx_http_log_module模块负责,对应的官方地址 ...

随机推荐

  1. [Android]异步 layout inflation(翻译)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5829809.html 异步 layout inflation ...

  2. c#进阶之神奇的CSharp

    CSharp 简写为c#,是一门非常年轻而又有活力的语言. CSharp的诞生      在2000年6月微软发布了c#这门新的语言.作为微软公司.NET 平台的主角,c#吸收了在他之前诞生的语言(c ...

  3. 强大的flash头像上传插件(支持旋转、拖拽、剪裁、生成缩略图等)

    今天介绍的这款flash上传头像功能非常强大,支持php,asp,jsp,asp.net 调用 头像剪裁,预览组件插件. 本组件需要安装Flash Player后才可使用,请从http://dl.pc ...

  4. python安装numpy、scipy和matplotlib等whl包的方法

    最近装了python和PyCharm开发环境,但是在安装numpy和matplotlib等包时出现了问题,现总结一下在windows平台下的安装方法. 由于现在找不到了工具包新版本的exe文件,所以采 ...

  5. Context值和bool开关

      Context值和bool开关的相关内容 Context值分为2种 系统默认的context值 服务的context值 Context值的作用 主要是防止有未知文件进入目录文件之中(如将病毒拷贝到 ...

  6. svn web页面管理svnadmin部署

    1.yum install subversion  创建svn目录  mdkir -p /data/svndirroot  建立svn库 svnadmin create /data/svndirroo ...

  7. href="javascript:xxx(this);"和onclick="javascript:xxx(this);"的区别

    href="javascript:xxx(this);"和onclick="javascript:xxx(this);" 一直以为这两种写法是等同的,今天在项目 ...

  8. [转]How to: Create a Custom Principal Identity

    本文转自:https://msdn.microsoft.com/en-us/library/aa702720(v=vs.110).aspx The PrincipalPermissionAttribu ...

  9. Android应用架构之Android MVP使用

    前两篇已经将Retrofit和RxAndroid应用到了项目中,这篇本打算直接将Dagger2引进项目,但是考虑到整个项目结构,就来个结构整理吧,一起来看看网上炒得火热MVP模式. 说到MVP就不得不 ...

  10. ultraiso制作大于4GB的镜像的启动盘

    ultraiso这个软件用来做启动盘很方便, 一般linux啦, windows啦, 神马的都用他来做, 但是, 因为ubuntu一般只有1-2GB, win桌面版一般也就3GB左右, 所以不必考虑这 ...