Python中asyncio内部如何基于select实现?
基于 select+socket+asynico 的基础实现.
将 asyncio.get_event_loop() 换成自己写的 selfayncio.get_event_loop(), 然后其他调用方法完全一样
每秒能处理 5000 个 index html 请求. ab 并发 2w 没压力, 好像最高只能写-c 20000?
<script src=“
Python中asyncio内部如何基于select实现?
root@env-pay:~# siege -b -c 200 http://127.0.0.1:8080/
** SIEGE 3.0.8
** Preparing 200 concurrent users for battle.
The server is now under siege…^C
Lifting the server siege… done.
Transactions: 422665 hits
Availability: 100.00 %
Elapsed time: 73.83 secs
Data transferred: 12.50 MB
Response time: 0.03 secs
Transaction rate: 5724.84 trans/sec
Throughput: 0.17 MB/sec
Concurrency: 199.12
Successful transactions: 422665
Failed transactions: 0
Longest transaction: 3.22
Shortest transaction: 0.00
Python的asyncio在底层确实基于select(更准确地说是selectors模块),但实现机制比直接使用select要复杂得多。核心在于事件循环(Event Loop)和协程调度器。
简单来说,asyncio的事件循环会:
- 维护一个任务队列(ready队列)
- 使用selector监控所有注册的socket文件描述符
- 当某个socket可读/可写时,唤醒对应的协程继续执行
看个最简化的实现原理:
import selectors
import socket
from collections import deque
class SimpleEventLoop:
def __init__(self):
self.selector = selectors.DefaultSelector()
self.ready = deque() # 就绪任务队列
self.scheduled = [] # 定时任务
def add_reader(self, fd, callback):
"""注册读事件回调"""
self.selector.register(fd, selectors.EVENT_READ, callback)
def run_forever(self):
while True:
# 1. 执行就绪任务
while self.ready:
task = self.ready.popleft()
task()
# 2. 等待IO事件
events = self.selector.select(timeout=0)
for key, mask in events:
callback = key.data
self.ready.append(callback)
实际asyncio的实现要处理更多细节:
- 每个socket关联一个Future对象
- 协程通过
await挂起时,会注册到selector - IO就绪时,事件循环将对应的Future设为完成状态
- 调度器恢复协程执行
真正的asyncio在Linux下默认用epoll,BSD用kqueue,都通过selectors模块统一接口。Windows用IOCP,但Python通过proactor事件循环支持。
总结:asyncio本质是IO多路复用+协程调度的组合拳。
asynico 跟 多个客户端建立连接之后,服务端如何主动跟客户端发送 tcp 包呢?
直接创建一个 task, 然后在里面写逻辑就行了,
create_task(muti_handler(client_socket))
更多是通过 epoll 来调度你的服务器处理函数, 想清楚怎么调度就好了…
我写的这个, 就是不管客户端发什么过来, 我都直接 return html, 其实处理逻辑都可以和以前一样的

