首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

协程试用

Python或者准确来说CPython,存在GIL(global interpreter lock)的问题,会导致多线程处理的速度远低于预期,并动辄出现运行异常,而多进程的开销和通信也是个麻烦。

近期看到了一个协程的概念(嘿嘿,不是某旅游app),通过异步机制,可以在遇到网络访问阻塞之类的应用场景下,进行自动切换,理论上来说可以大幅降低系统负载以提升处理速度。考虑到前期做的多线程扫描器的高负载情况,打算用协程对其改造一番。

在python的自带功能中,yield可以实现基本的协程功能,这里则使用了gevent库,通过其monkey及pool进行实施,其中monkey用于对阻塞操作打补丁,pool则用于保持固定的协程数量,导入示例如下:

创建协程池及初步处理部分代码如下:

51行为创建上限300的协程池。

53-56行则为通过xlrd库读取目标文件(03及之前的Excel格式)。

58行则通过IPy来判断IP地址的正确性,省得写那个超长的正则了。

59行即为通过pool的spawn方法,调用do_scan进行目标扫描操作。

协程池的大小和系统的同时打开文件数量参数是相关的(因为do_scan的网络操作),这个参数可以通过ulimit看一下:

如果协程池过大,而且确实也派生了那么多,就会看到下面的错误:

这个呢可以通过ulimit -n调整一下就能解决,不过在实际操作中,将“open files”增大到65535,协程池扩大到2000后,发现运行反而异常缓慢,所以还是调成了300来进行操作。

do_scan的操作是通过nmap的PortScanner实现的,scan_res用来暂存扫描结果入库(入库的代码就不列了),示例如下:

启动扫描功能后,通过top观察负载情况:

可以看到,系统负载相对还是挺低的,与之前的多线程模式下,200线程CPU负荷即超过了50%相比,可说是改善良多。另外还可以看到,python中进行nmap模块导入,实际上是会调用系统中nmap程序去执行扫描,所以nmap还是版本新点比较好。

执行过程通过time记录了一下,结果如下:

real为实际执行时间,可以看到用了52分钟,处理记录数为20260条,与之前多线程模式处理足足用了近4个小时相比,同样是提升巨大,嘿嘿,这样扫描模式完全可以考虑改成全端口扫描了。

总体来说,试用还是挺成功的,在网络操作或类似的访问阻塞场景下,协程对线程具备非常好的替代性,后续还可以考虑从以下几个方面再改进一下:

增加多进程模式,进程+协程进一步提升扫描能力。

目标文件的读取也可以采用独立进程实施。

协程中不做数据库操作提交,通过一个单独进程进行合并提交。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180728G1N6Y300?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券