From 9225d0a7e05902192642a148e3553a6e860000e3 Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 1 Jan 2025 18:57:20 +0800 Subject: [PATCH] improve fastapi (#295) --- cookbook/system_services/redis.md | 9 +++++---- cookbook/web/fastapi/fastapi_app.md | 27 +++++++++++++++++++++++---- examples/web/fastapi/main.py | 14 ++++++++------ 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/cookbook/system_services/redis.md b/cookbook/system_services/redis.md index 1f9d619..f307389 100644 --- a/cookbook/system_services/redis.md +++ b/cookbook/system_services/redis.md @@ -95,23 +95,24 @@ redis_client.close() ### Async ```python -from redis.asyncio import redis +from redis.asyncio import Redis HOST = 'localhost' PORT = 6379 DB = 1 CACHE_KEY = 'python-cookbook:redis' -# redis_client = await redis.from_url( +# redis_client = await Redis.from_url( # 'redis://[[username]:[password]]@localhost:6379/0', decode_responses=True # ) # # Unix Socket -# redis_client = redis.Redis(unix_socket_path='/tmp/redis.sock') -redis_client = redis.Redis( +# redis_client = Redis(unix_socket_path='/tmp/redis.sock') +redis_client = Redis( HOST, PORT, DB, + password=None, decode_responses=True, max_connections=2**12, socket_connect_timeout=3.5, diff --git a/cookbook/web/fastapi/fastapi_app.md b/cookbook/web/fastapi/fastapi_app.md index 16ebba8..6c70583 100644 --- a/cookbook/web/fastapi/fastapi_app.md +++ b/cookbook/web/fastapi/fastapi_app.md @@ -98,12 +98,13 @@ def get_settings() -> Settings: import asyncio import json +import logging +import os from collections.abc import AsyncGenerator from contextlib import asynccontextmanager from typing import TypedDict import aiomqtt -import uvicorn from fastapi import FastAPI, Request from fastapi.openapi.docs import ( get_redoc_html, @@ -124,6 +125,8 @@ settings = get_settings() API_DOC_STATIC_DIR = 'examples/web/fastapi/static' API_DOC_STATIC_PATH = f'{settings.app_doc_url}/{API_DOC_STATIC_DIR}' +LOGGER = logging.getLogger('uvicorn') + MONGODB_CLIENT = AsyncIOMotorClient(str(settings.mongodb_url)) DB_XXX = MONGODB_CLIENT[settings.mongodb_db_name] TB_XXX = DB_XXX['examples'] @@ -155,6 +158,7 @@ async def lifespan(_: FastAPI) -> AsyncGenerator: max_connections=settings.cache_max_conns, socket_connect_timeout=settings.cache_conn_timeout, socket_timeout=settings.cache_timeout, + client_name=f'python-cookbook-{os.getpid()}', ) as redis_client, aiomqtt.Client( settings.mqtt_host, @@ -162,6 +166,7 @@ async def lifespan(_: FastAPI) -> AsyncGenerator: username=settings.mqtt_username, password=settings.mqtt_password, timeout=settings.mqtt_timeout, + identifier=f'python-cookbook-{os.getpid()}', ) as mqtt_client, ): # Subscribe MQTT @@ -176,6 +181,8 @@ async def lifespan(_: FastAPI) -> AsyncGenerator: except asyncio.CancelledError: pass + LOGGER.debug(f'Redis client [python-cookbook-{os.getpid()}] disconected') + LOGGER.debug(f'MQTT client [python-cookbook-{os.getpid()}] disconected') MONGODB_CLIENT.close() @@ -239,11 +246,23 @@ async def root(request: Request) -> dict[str, str | None]: app.include_router(router, prefix='/api/router', tags=['router']) +``` +### Run -# Only for develop environment -if __name__ == '__main__': - uvicorn.run(app='main:app', host='', reload=True) +```bash +pipenv run uvicorn --host 0.0.0.0 --port 8000 \ + --proxy-headers \ + --forwarded-allow-ips "*" \ + --workers 8 \ + --limit-concurrency 1024 \ + --backlog 4096 \ + --log-level debug \ + --timeout-keep-alive 5 \ + --use-colors \ + --no-server-header \ + examples.web.fastapi.main:app \ + --log-config examples/web/uvicorn_logging.json ``` ## More diff --git a/examples/web/fastapi/main.py b/examples/web/fastapi/main.py index 75f1d4b..ad85e3e 100644 --- a/examples/web/fastapi/main.py +++ b/examples/web/fastapi/main.py @@ -2,12 +2,13 @@ import asyncio import json +import logging +import os from collections.abc import AsyncGenerator from contextlib import asynccontextmanager from typing import TypedDict import aiomqtt -import uvicorn from fastapi import FastAPI, Request from fastapi.openapi.docs import ( get_redoc_html, @@ -28,6 +29,8 @@ API_DOC_STATIC_DIR = 'examples/web/fastapi/static' API_DOC_STATIC_PATH = f'{settings.app_doc_url}/{API_DOC_STATIC_DIR}' +LOGGER = logging.getLogger('uvicorn') + MONGODB_CLIENT = AsyncIOMotorClient(str(settings.mongodb_url)) DB_XXX = MONGODB_CLIENT[settings.mongodb_db_name] TB_XXX = DB_XXX['examples'] @@ -59,6 +62,7 @@ async def lifespan(_: FastAPI) -> AsyncGenerator: max_connections=settings.cache_max_conns, socket_connect_timeout=settings.cache_conn_timeout, socket_timeout=settings.cache_timeout, + client_name=f'python-cookbook-{os.getpid()}', ) as redis_client, aiomqtt.Client( settings.mqtt_host, @@ -66,6 +70,7 @@ async def lifespan(_: FastAPI) -> AsyncGenerator: username=settings.mqtt_username, password=settings.mqtt_password, timeout=settings.mqtt_timeout, + identifier=f'python-cookbook-{os.getpid()}', ) as mqtt_client, ): # Subscribe MQTT @@ -80,6 +85,8 @@ async def lifespan(_: FastAPI) -> AsyncGenerator: except asyncio.CancelledError: pass + LOGGER.debug(f'Redis client [python-cookbook-{os.getpid()}] disconected') + LOGGER.debug(f'MQTT client [python-cookbook-{os.getpid()}] disconected') MONGODB_CLIENT.close() @@ -143,8 +150,3 @@ async def root(request: Request) -> dict[str, str | None]: app.include_router(router, prefix='/api/router', tags=['router']) - - -# Only for develop environment -if __name__ == '__main__': - uvicorn.run(app='main:app', host='', reload=True)