欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

python3.x 多路IO复用补充asyncio

程序员文章站 2022-05-04 14:02:29
asyncio模块是python之父写的模块,按说应该是靠谱的,python3.6版本定义为稳定版本。 说明书:https://docs.python.org/3/library/asyncio.html?highlight=asyncio#module-asyncio 大概定义:该模块提供了使用协 ......

asyncio模块是python之父写的模块,按说应该是靠谱的,python3.6版本定义为稳定版本。

说明书:https://docs.python.org/3/library/asyncio.html?highlight=asyncio#module-asyncio

大概定义:该模块提供了使用协程编写单线程并发代码,通过套接字和其他资源复用i​​ / o访问,运行网络客户端和服务器以及其他相关原语的基础结构。

简单应用(基于wsgi的报警器)

 1 #!/usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 # @time    : 2018/8/21 10:40
 4 # @author  : wangyue
 5 # @site    : 
 6 # @file    : alertor_uwsgi.py
 7 # @software: pycharm
 8 
 9 #加入环境变量避免程序报错
10 import sys,os
11 sys.path.append(os.path.dirname(os.path.dirname(__file__)))
12 
13 #引入wsgi模型,这里主要是弄一个简单的http模型来说明asyncio的简单使用
14 from wsgiref.simple_server import make_server
15 
16 #引入asyncio
17 import asyncio
18 
19 #引入其他可能的依赖
20 from threading import thread
21 import json
22 
23 #引入本程序其他的内容,与asyncio无关是程序业务的其他部分
24 from conf.alertor_conf import alertor_config
25 from model.alert_method_class import sendmail
26 
27 #定义一个运行asyncio loop 的线程,去单独运行它
28 def start_loop(loop):
29     asyncio.set_event_loop(loop)
30     loop.run_forever()
31 new_loop = asyncio.new_event_loop() #这个new_loop将会用于运行异步程序
32 t = thread(target=start_loop, args=(new_loop,))
33 t.start() #利用多线程,额外起一个线程运行asyncio loop然后它在自身使用协程之类处异步处理业务
34 
35 
36 #这是wsgi主业务程序,application是wsgi的入口程序,wsgi就规定了这么个函数名,这样写wsgi就认可它是入口了。传参也是wsgi的规定,第一个是环境,第二个是响应
37 def application(env,start_res):
38     res_headers=[('content-type', 'text/plain')]
39     if env["request_method"]=='post':
40         # the environment variable content_length may be empty or missing
41         try:
42             if env['path_info'] != "/send_alert":
43                 status = "404 func is not in use"
44                 start_res(status, res_headers)
45                 return [b"func is not in use"]
46 
47             request_body_size = int(env.get('content_length', 0))
48             status = "200 ok"
49             request_body = env['wsgi.input'].read(request_body_size)
50             print("post_info -->", request_body.decode())
51             r_body=json.loads(request_body.decode())
52             #就这里一行代码,new_loop.call_soon_threadsafe(),告诉asyncio去运行第一个参数的函数名,后边的参数是被运行函数的传参,有多少就传参多少个,这是异步的,非阻塞的。
53             new_loop.call_soon_threadsafe(sendmail.sendemail,"alertor alarm level:"+r_body["level"]+"  server: "+r_body["server"],r_body)
54             start_res(status,res_headers)
55             return [b"ok send alert......."]
56         except (valueerror):
57             status = "404 json data not found key"
58             request_body_size = 0
59             start_res(status, res_headers)
60             return [b"get post info faild"]
61 
62     else:
63         status = "403 method error"
64         start_res(status,res_headers)
65         return [b'method error']
66 
67 # 1、只接受post请求。数据为json格式,json中标记的,包括但不限于,包括的信息将会入库,其他信息,在告警时会一并发出
68 # {
69 #     "level":"high", #告警级别,"high","medium","info",这个可以在配置文件中配置,配置信息是个列表,有序的从左至右为["high","medium","info"],对应后续告警逻辑及post中json的本字段。
70 #     "@timestamp":"",#告警时间
71 #     "server":"",#告警源,可以是ip,主机名,服务名等可标识的
72 #     "message":""#具体的告警信息
73 # }
74 # 2、根据json中的level自动选择告警途径,选择方式,在配置文件中的alert_method字典信息
75 # 3、将告警内容,存储数据库,便于日后查询
76 # 4、后续提供查询统计告警信息的方法
77 
78 
79 if __name__=="__main__":
80     wsgi_server=make_server(alertor_config['bind_ip'],alertor_config['port'],application)
81 
82     wsgi_server.serve_forever()

目前这里先这么用,这个模型的性能是基于uwsgi运行,2进程,每个进程内4个线程,基准性能是15000请求总量,5000客户端

 ab -n 15000-c 5000 -p test_alert.txt -t application/x-www-form-urlencoded "http://test.alert.com.cn/test.html"

效果还凑合吧。