我有一个网络服务器,大致如下:
async def websocket_handler(request):
ws = web.WebSocketResponse()
await ws.prepare(request)
# ==========================================
cards = []
async for msg in ws:
if msg.type == aiohttp.WSMsgType.TEXT:
Q = json.loads(msg.data)
if "q" in Q:
async with aiohttp.ClientSession(cookies=request.cookies) as session:
async with session.get(f"{SEARCH_ROOT}/s", params=Q) as resp:
doc_order = await resp.json()
cards = [
*doc_order["results"],
{"done": True},
]
if len(cards) > 0:
card = cards.pop(0)
await ws.send_json(card)
else:
ws.close()
return ws
Run Code Online (Sandbox Code Playgroud)
问题是,这工作得很好,但在大约 13-15 个新的 websocket 连接之后,我开始看到声称could not start a new thread.
文档提到客户端会话应该在每个服务器实例中存在一次,但我无法弄清楚如何做到这一点。我有一些想法: …
我有一个 API 端点(FastAPI / Uvicorn)。除此之外,它还向另一个 API 请求信息。当我使用多个并发请求加载 API 时,我开始收到以下错误:
h11._util.LocalProtocolError: can't handle event type ConnectionClosed when role=SERVER and state=SEND_RESPONSE
Run Code Online (Sandbox Code Playgroud)
在正常环境中,我会利用request.session,但我知道它不是完全线程安全的。
因此,在 FastAPI 等框架内使用请求的正确方法是什么,其中多个线程将requests同时使用该库?
Django 从 3.1 版本开始支持异步视图,因此它非常适合对外部 HTTP API 等非阻塞调用(例如使用aiohttp)。
\n我经常看到以下代码示例,我认为它在概念上是错误的(尽管它工作得很好):
\nimport aiohttp\nfrom django.http import HttpRequest, HttpResponse\n\nasync def view_bad_example1(request: HttpRequest):\n async with aiohttp.ClientSession() as session:\n async with session.get("https://example.com/") as example_response:\n response_text = await example_response.text()\n return HttpResponse(response_text[:42], content_type="text/plain")\nRun Code Online (Sandbox Code Playgroud)\n此代码ClientSession为每个传入请求创建一个,效率低下。aiohttp然后不能使用例如连接池。
\n\n不要\xe2\x80\x99t为每个请求创建一个会话。您很可能需要每个应用程序有一个会话来共同执行所有请求。
\n来源:https ://docs.aiohttp.org/en/stable/client_quickstart.html#make-a-request
\n
这同样适用于 httpx:
\n\n\n另一方面,客户端实例使用 HTTP 连接池。这意味着当您向同一主机发出多个请求时,客户端将重用底层 TCP 连接,而不是为每个请求重新创建一个连接。
\n\n
有什么方法可以aiohttp.ClientSession在 Django 中全局实例化,以便可以在多个请求之间共享该实例吗?不要忘记必须ClientSession在正在运行的事件循环中创建(为什么在事件循环之外创建 ClientSession …