Sanic源码分析(核心篇)
本次分析只针对Sanic的核心部分进行分析,了解Sanic从接受一个请求到返回响应的全过程,基于的版本0.1.2
项目结构server 一个基于asyncio的Protocol的协议 sanic的核心,里面有收到请求到返回响应的钩子
requset sanic的请求对象 内有对form args json 的处理
response Sanic的响应对象
router Sanic的路由管理
Sanic Sanicapp的启动 添加路由的对象
整体流程sever接受到请求,触发接受请求的钩子
钩子内部使用httptools进行http解析,生成request对象
通过路由关系寻找到对应的处理函数,处理requset 生成response
把response写入
源码分析
定义server服务
class HttpProtocol(asyncio.Protocol):
里面有些要写的方法。具体参考Asyncio的Protocol的文档
启动服务
根据Protocl对象启动一个服务
server_coroutine = loop.create_server(lambda: HttpProtocol(
loop=loop,
connections=connections,
signal=signal,
request_handler=request_handler,
request_timeout=request_timeout,
request_max_size=request_max_size,
), host, port)
http_server = loop.run_until_complete(server_coroutine)
loop.run_forever()
获取数据的钩子
这个方法来源asyncio的protocol部分,获取数据后, 使用httptools解析,并填充requset
def data_received(self, data):
if self.parser is None:
assert self.request is None
self.parser = httptools.HttpRequestParser(self)
self.parser.feed_data(data)
有很多类似
def on_url(self, url):
self.url = url
的方法就是使用httptools解析request并填充,具体参考httptools
处理requset
def on_message_complete(self):
self.loop.create_task(self.request_handler(self.request, self.write_response))
requset_handler 是来源router的对应关系,这里暂时把router理解成一个URL和函数对应的字典
写返回值
这个方法由request_handle调用,发送respon并且关闭通讯
def write_response(self, response):
self.transport.write(response.output(self.request.version,
keep_alive, self.request_timeout)) keep_alive, self.request_timeout))
self.transport.close()
总结
至此Sanic的核心逻辑就结束了,结构十分清晰简单,是对python的异步io的一次十分棒的应用。 为什么Sanic性能这么高,主要是几个原因:异步io架构的天然优势
sanic把eventloop从async替换成了uvloop
http解析器采用的高性能的httptools
参考资料