繁体   English   中英

如何在Sanic中使用aiohttp ClientSession?

[英]How to use an aiohttp ClientSession with Sanic?

我想了解在Sanic中使用aiohttp的正确方法是什么。

从aiohttp 文档中 ,我发现以下内容:

不要为每个请求创建会话 很可能每个应用程序都需要一个会话来完成所有请求。 更复杂的情况可能需要每个站点一个会话,例如一个用于Github,另一个用于Facebook API。 无论如何,为每个请求进行会话是一个非常糟糕的主意。 会话内部包含连接池。 连接重用和保持活动(两者都默认打开)可以加快总体性能。

当我去Sanic文档时,我发现了一个这样的例子:

这是一个例子:

from sanic import Sanic
from sanic.response import json

import asyncio
import aiohttp

app = Sanic(__name__)

sem = None

@app.route("/")
async def test(request):
    """
    Download and serve example JSON
    """
    url = "https://api.github.com/repos/channelcat/sanic"

    async with aiohttp.ClientSession() as session:
         async with sem, session.get(url) as response:
         return await response.json()

app.run(host="0.0.0.0", port=8000, workers=2)

这不是管理aiohttp会话的正确方法......

那么正确的方法是什么?
我应该在应用程序中初始化会话并将会话注入所有层中的所有方法吗?

我找到的唯一问题是这个,但这没有用,因为我需要创建自己的类来使用会话,而不是sanic。
在Sanic文档中也发现了一点,它说你不应该在eventloop之外创建一个会话。

我有点困惑:(什么是正确的方法?

为了使用单个aiohttp.ClientSession我们只需要实例化一次会话,并在应用程序的其余部分中使用该特定实例。

为了实现这一点,我们可以使用before_server_start监听器 ,它允许我们在应用程序提供第一个字节之前创建实例。

from sanic import Sanic 
from sanic.response import json

import aiohttp

app = Sanic(__name__)

@app.listener('before_server_start')
def init(app, loop):
    app.aiohttp_session = aiohttp.ClientSession(loop=loop)

@app.listener('after_server_stop')
def finish(app, loop):
    loop.run_until_complete(app.aiohttp_session.close())
    loop.close()

@app.route("/")
async def test(request):
    """
    Download and serve example JSON
    """
    url = "https://api.github.com/repos/channelcat/sanic"

    async with app.aiohttp_session.get(url) as response:
        return await response.json()


app.run(host="0.0.0.0", port=8000, workers=2)

代码细分:

  • 我们正在创建一个aiohttp.ClientSession ,将Sanic应用程序在开始时创建的循环作为参数传递,从而避免了这个过程中的陷阱
  • 我们将该会话存储在Sanic app
  • 最后,我们正在使用此会话来提出请求。

这基本上就是我在做的事情。

我创建了一个模块( interactions.py ),例如这样的函数:

async def get(url, headers=None, **kwargs):
    async with aiohttp.ClientSession() as session:
        log.debug(f'Fetching {url}')
        async with session.get(url, headers=headers, ssl=ssl) as response:
            try:
                return await response.json()
            except Exception as e:
                log.error(f'Unable to complete interaction: {e}')
                return await response.text()

然后我就await

results = await interactions.get(url)

我不确定为什么这不是“正确的方式”。 会话(至少根据我的需要)可以在我的请求完成后立即关闭。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM