簡體   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