dvt*_*tan 13 python-asyncio aiohttp sanic
文档说要重用ClientSession:
不要为每个请求创建会话.很可能每个应用程序都需要一个会话来完成所有请求.
会话内部包含连接池,连接重用和保持活动(两者都默认打开)可以加快总体性能.1
但是在文档中似乎没有任何解释如何做到这一点?有一个例子可能是相关的,但它没有说明如何在其他地方重用池:http://aiohttp.readthedocs.io/en/stable/client.html#keep-alive-connection-pooling-and-cookie-分享
这样的事情是正确的做法吗?
@app.listener('before_server_start')
async def before_server_start(app, loop):
app.pg_pool = await asyncpg.create_pool(**DB_CONFIG, loop=loop, max_size=100)
app.http_session_pool = aiohttp.ClientSession()
@app.listener('after_server_stop')
async def after_server_stop(app, loop):
app.http_session_pool.close()
app.pg_pool.close()
@app.post("/api/register")
async def register(request):
# json validation
async with app.pg_pool.acquire() as pg:
await pg.execute() # create unactivated user in db
async with app.http_session_pool as session:
# TODO send activation email using SES API
async with session.post('http://httpbin.org/post', data=b'data') as resp:
print(resp.status)
print(await resp.text())
return HTTPResponse(status=204)
Run Code Online (Sandbox Code Playgroud)
我认为可以改进的东西很少:
1)
实例ClientSession是一个会话对象.这个会话包含连接池,但它本身不是"session_pool".我建议重命名http_session_pool到http_session或可能client_session.
2)
Session的close()方法是一个方法.你应该等待它:
await app.client_session.close()
Run Code Online (Sandbox Code Playgroud)
甚至更好(恕我直言),而不是考虑如何正确打开/关闭会话使用标准异步上下文管理器等待__aenter__/ __aexit__:
@app.listener('before_server_start')
async def before_server_start(app, loop):
# ...
app.client_session = await aiohttp.ClientSession().__aenter__()
@app.listener('after_server_stop')
async def after_server_stop(app, loop):
await app.client_session.__aexit__(None, None, None)
# ...
Run Code Online (Sandbox Code Playgroud)
3)
注意这个信息:
但是,如果在关闭基础连接之前停止事件循环,则会
ResourceWarning: unclosed transport发出警告(启用警告时).要避免这种情况,必须在关闭事件循环之前添加一个小延迟,以允许任何打开的底层连接关闭.
我不确定在你的情况下这是强制性的,但在await asyncio.sleep(0)内部添加after_server_stop文档建议并没有什么不好:
@app.listener('after_server_stop')
async def after_server_stop(app, loop):
# ...
await asyncio.sleep(0) # http://aiohttp.readthedocs.io/en/stable/client.html#graceful-shutdown
Run Code Online (Sandbox Code Playgroud)
UPD:
实现__aenter__/ __aexit__可以用作异步上下文管理器的类(可以在async with语句中使用).它允许在执行内部块之前和之后执行一些操作.这与常规上下文管理器非常相似,但asyncio相关.与常规上下文管理器相同,异步可以直接使用(不async with)手动等待__aenter__/ __aexit__.
为什么我认为最好使用__aenter__/ __aexit__手动创建/释放会话而不是使用close(),例如?因为我们不应该担心__aenter__/ 里面实际发生了什么__aexit__.想象一下,在未来aiohttp的会话创建版本中将会更改,open()例如需要等待.如果您将使用__aenter__/ __aexit__您不需要以某种方式更改您的代码.
| 归档时间: |
|
| 查看次数: |
3001 次 |
| 最近记录: |