首页 >后端开发 >Python教程 >在并发 FastAPI/Uvicorn 应用程序中发出下游 HTTP 请求时,如何避免'H11._util.LocalProtocolError”?

在并发 FastAPI/Uvicorn 应用程序中发出下游 HTTP 请求时,如何避免'H11._util.LocalProtocolError”?

Patricia Arquette
Patricia Arquette原创
2024-12-07 19:25:17261浏览

How Can I Avoid `H11._util.LocalProtocolError` When Making Downstream HTTP Requests in a Concurrent FastAPI/Uvicorn Application?

在 Uvicorn/FastAPI 中处理下游 HTTP 请求

使用 FastAPI/Uvicorn 构建 API 端点时,通常会发出下游 HTTP 请求。然而,在处理多个并发请求时,开发者可能会遇到错误:

H11._util.LocalProtocolError: can't handle event type ConnectionClosed when role=SERVER and state=SEND_RESPONSE

出现此错误是因为 FastAPI 的默认请求会话不是完全线程安全的。为了克服这一挑战,我们需要采用另一种方法。

使用 Httpx 进行异步 HTTP 请求

一种解决方案是使用 httpx 库,它提供了异步API。我们可以使用 httpx.AsyncClient() 来代替 requests.Session()。该客户端允许对同一主机进行并发请求,因为底层 TCP 连接被重用。

在 FastAPI 中,我们可以定义生命周期处理程序以在启动时初始化 AsyncClient 并在关闭时关闭它。例如:

@asynccontextmanager
async def lifespan(app: FastAPI):
    async with httpx.AsyncClient() as client:
        yield {'client': client}  # Add the client to the app state

在我们的端点中,我们可以使用 request.state.client 访问客户端。我们可以按如下方式发出下游请求:

@app.get('/')
async def home(request: Request):
    client = request.state.client
    req = client.build_request('GET', 'https://www.example.com')
    r = await client.send(req, stream=True)
    return StreamingResponse(r.aiter_raw(), background=BackgroundTask(r.aclose))

流式响应与非流式响应

我们可以通过不同的方式将下游响应发送到客户端。如果我们想要流式传输响应,我们可以创建一个 StreamingResponse,它使用生成器异步循环响应数据。否则,我们可以使用 r.json()、PlainTextResponse 或自定义 Response。

使用 Httpx 的好处

使用 httpx 有几个好处:

  • 异步 API,用于高效处理并发请求。
  • 持久连接池以提高性能。
  • 控制连接池大小。
  • 与 FastAPI 的生命周期处理程序和端点轻松集成。

通过利用 httpx,开发人员可以有效地FastAPI/Uvicorn 应用程序中的下游 HTTP 请求不会遇到线程安全问题。这确保了可靠且可扩展的 API 行为。

以上是在并发 FastAPI/Uvicorn 应用程序中发出下游 HTTP 请求时,如何避免'H11._util.LocalProtocolError”?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn