使用 FastAPI 实例化和传递 Redis 客户端的推荐方法是什么

Ben*_*Ben 15 python redis fastapi

我将 FastAPI 与 Redis 结合使用。我的应用程序看起来像这样

from fastapi import FastAPI
import redis

# Instantiate redis client
r = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)

# Instantiate fastapi app
app = FastAPI()

@app.get("/foo/")
async def foo():
    x = r.get("foo")
    return {"message": x}

@app.get("/bar/")
async def bar():
    x = r.get("bar")
    return {"message": x}
Run Code Online (Sandbox Code Playgroud)

像这样创建r模块范围的变量是不好的做法吗?如果是的话有什么缺点?

在 Tiangolo 关于设置SQL 数据库连接的教程中,他使用了依赖项,我想在我的例子中它看起来像这样

from fastapi import Depends, FastAPI
import redis

# Instantiate fastapi app
app = FastAPI()

# Dependency
def get_redis():
    return redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)

@app.get("/foo/")
async def foo(r = Depends(get_redis)):
    x = r.get("foo")
    return {"message": x}

@app.get("/bar/")
async def bar(r = Depends(get_redis)):
    x = r.get("bar")
    return {"message": x}
Run Code Online (Sandbox Code Playgroud)

我有点困惑这些方法(或其他方法)中的哪一种是首选以及为什么。

Teg*_*gar 13

Depends每次您的函数收到请求时都会进行评估,因此您的第二个示例将为每个请求创建一个新连接。正如@JarroVGIT所说,我们可以使用连接池来维护从FastAPI到Redis的连接,并减少打开关闭连接的成本。

通常,我创建一个不同的文件来定义连接。假设我们有config/db.py

import redis

def create_redis():
  return redis.ConnectionPool(
    host='localhost', 
    port=6379, 
    db=0, 
    decode_responses=True
  )

pool = create_redis()
Run Code Online (Sandbox Code Playgroud)

然后在main.py

from fastapi import Depends, FastAPI
import redis

from config.db import pool

app = FastAPI()

def get_redis():
  # Here, we re-use our connection pool
  # not creating a new one
  return redis.Redis(connection_pool=pool)

@app.get("/items/{item_id}")
def read_item(item_id: int, cache = Depends(get_redis)):
  status = cache.get(item_id)
  return {"item_name": status}


@app.put("/items/{item_id}")
def update_item(item_id: int, cache = Depends(get_redis)):
  cache.set(item_id, "available")
  return {"status": "available", "item_id": item_id}
Run Code Online (Sandbox Code Playgroud)

通常,我也会像文档一样拆分依赖项文件,以便我们可以从路由模块中调用它,但为了简单起见,我将像这样保留它。

你可以查看这个 repo自行实验。它有更全面的代码,我已经创建了几个可能帮助您理解差异的场景。它还将介绍您的第一个示例如何阻止其他端点。