A FastAPI-friendly integration with Nacos that provides configuration management, service registration and discovery, and client-side load-balanced service calls.
Project description
FastAPI–Nacos Integration Guide
This document describes how to quickly integrate FastAPI with Nacos using the fastapi-nacos package. It provides the following capabilities:
- Unified management of local configuration and Nacos remote configuration
- Service registration, service discovery, and client-side load-balanced service invocation
Before use, install the fastapi-nacos dependency:
# Install via pip
pip install fastapi-nacos
# Install via uv
uv add fastapi-nacos
1. Basic Integration
1.1. Load Local Configuration
from fastapi_nacos import FastApiNacos
from yamlpyconfig.models import AlgorithmEnum
def get_fastapi_nacos():
# Initialize FastApiNacos — local configuration is already loaded
# Singleton instance: only the first initialization takes effect
return FastApiNacos("./", AlgorithmEnum.SM4, "/Oa0TQLjIQ8EQUrYqROmBQ==")
This code loads the local configuration and returns a FastApiNacos object. It accepts three parameters:
-
The path to the configuration files. It loads the following:
application.yaml— requiredapplication-{profile}.yaml— optional. Theprofilevalue must be defined inapplication.yaml, e.g.profile: dev.
-
The encryption algorithm (currently supports SM4 and SM2)
-
The key. For SM4, this is the symmetric key; for SM2, this is the private key.
Notes:
-
FastApiNacosis a singleton — only the first initialization takes effect. -
Local configuration supports:
- Environment variable expansion, e.g.
${ENV_VAR}or${ENV_VAR:default_value} - Encrypted configuration in both local and Nacos configs using the
{encrypted}prefix, e.g.{encrypted}xxxxxx.
- Environment variable expansion, e.g.
1.1.1. Local Configuration File Example
application.yaml:
profile: dev
application-dev.yaml:
# Nacos remote configuration settings
config-sources:
nacos:
server-addr: "192.168.30.36:9090"
namespace: "dev"
group: "DEFAULT_GROUP"
username: "nacos"
password: "{encrypted}YXx6whAK7qytz8K7rF9VHQ=="
imports:
- data-id: "gateway.yaml"
- data-id: "application-ext.yaml"
# Service caller configuration
service-caller:
# Supported LB types: round_robin, random, weight_round_robin, weight_random
lb-type: round_robin
connection-timeout: 6
read-timeout: 6
connection-pool-size: 100
# Nacos service registration and discovery
app-registry:
nacos:
app-name: "my-app"
server-addr: ${NACOS_SERVER:192.168.30.36:9090}
namespace: ${NACOS_NAMESPACE:dev}
ip: ${SERVER_IP:127.0.0.1}
port: ${SERVER_PORT:8000}
username: ${NACOS_USERNAME:nacos}
password: ${NACOS_PASSWORD:{encrypted}YXx6whAK7qytz8K7rF9VHQ==}
weight: 1.0
# fastdfs configuration for aiofdfs
fastdfs:
tracker-servers: 192.168.30.36:22122
connect-timeout: 6
network-timeout: 6
store-path-index: 1
port: ${SERVER_PORT:8000}
1.1.2. Using Local Configuration in gunicorn
You can load local configuration inside gunicorn.conf.py:
import multiprocessing
import os
from api.configs import get_fastapi_nacos
fastapi_nacos_manager = get_fastapi_nacos()
server_config = fastapi_nacos_manager.config.get("server", {})
bind = f"0.0.0.0:{server_config.get("port", 8000)}"
# Worker count: #CPU * 2
if "SERVICE_WORKERS" in os.environ:
workers = int(os.environ["SERVICE_WORKERS"])
else:
workers = multiprocessing.cpu_count() * 2
worker_class = "uvicorn.workers.UvicornWorker"
max_requests = 1000
max_requests_jitter = 100
timeout = server_config.get("timeout", 30)
Then start the service using:
gunicorn -c gunicorn.conf.py api.main:app
1.2. Loading Remote Configuration & Service Registration
It is recommended to integrate this with FastAPI’s lifespan hook.
api.configs.py:
import logging
from contextlib import asynccontextmanager
from typing import Optional
from aio_service_caller import LoggingInterceptor, AuthInterceptor, MetricsInterceptor
from aiofdfs import FastDfsConf, Async_Fdfs_Client
from fastapi import FastAPI
from fastapi_nacos import FastApiNacos, ServiceRegistryConfigError
from yamlpyconfig.models import AlgorithmEnum
logger = logging.getLogger(__name__)
__fdfs_client: Optional[Async_Fdfs_Client] = None
def get_fdfs() -> Optional[Async_Fdfs_Client]:
global __fdfs_client
return __fdfs_client
def get_fastapi_nacos():
return FastApiNacos("./", AlgorithmEnum.SM4, "lSU543Tes6wmjnb+PMVQNg==")
@asynccontextmanager
async def lifespan(app: FastAPI):
global __fdfs_client
try:
async with get_fastapi_nacos() as fastapi_nacos_manager:
try:
# Add interceptors
await fastapi_nacos_manager.service_manager.add_interceptors(
[LoggingInterceptor(), AuthInterceptor(token="123456"),
MetricsInterceptor()])
except ServiceRegistryConfigError as e:
logger.warning(f"{e}")
# If the aiofdfs package is used, you can refer to this code snippet to initialize the fdfs_client using configuration.
async with Async_Fdfs_Client(FastDfsConf.from_dict(fastapi_nacos_manager.config)) as __fdfs_client:
yield
except Exception as e:
logger.error(f"lifespan init error: {e}")
api.main.py:
from fastapi import FastAPI
from .configs import lifespan
app = FastAPI(lifespan=lifespan, title="Demo", description="Demo API", version="0.1.0", redoc_url=None)
This accomplishes two things:
-
Loads remote configuration and merges it with local configuration. Access full configuration via:
get_fastapi_nacos().config
-
Registers this service instance in Nacos under the name defined in:
app-registry.nacos.app-name
1.3. Configuration Priority
(From low to high)
- Local
application.yaml - Local
application-{profile}.yaml - Remote configuration listed in
config-sources.nacos.imports(later entries override earlier ones)
2. Service Invocation
You can invoke remote services with:
get_fastapi_nacos().service_manager
Service-caller configuration:
service-caller:
lb-type: round_robin
connection-timeout: 6
read-timeout: 6
connection-pool-size: 100
Example
@router.get("/hello-config")
async def get_hello_config():
return await get_fastapi_nacos().service_manager.get("my-app", "/demo/config")
@router.get("/hello-config-raw")
async def get_hello_config_raw():
async with get_fastapi_nacos().service_manager.raw_get("my-app", "/demo/config") as response:
return await response.json()
Each HTTP method provides two invocation styles:
service_manager.<method>(...)→ returns processed business resultservice_manager.raw_<method>(...)→ returns the rawClientResponse
Extra arguments (headers, params, json, timeout, etc.) are passed through **kwargs.
2.1. Interceptors
Example in lifespan:
await fastapi_nacos_manager.service_manager.add_interceptors(
[LoggingInterceptor(), AuthInterceptor(token="123456"), MetricsInterceptor()]
)
Interceptors implement the IServiceInterceptor interface:
class IServiceInterceptor(ABC):
async def before_request(self, context: RequestContext) -> None: ...
async def after_response(self, context: RequestContext) -> None: ...
async def handle_exception(self, context: RequestContext) -> None: ...
@property
def name(self) -> str: ...
@property
def order(self) -> int: return 0
Interceptors execute in ascending order value.
Rules:
-
Interceptors with duplicate names are ignored
-
You can manage interceptors via:
add_interceptor(interceptor)remove_interceptor(name)clear_interceptors()
2.1.1. RequestContext Fields
Available in all phases:
method— HTTP methodservice_name— service to callpath— request pathprotocol— defaulthttpkwargs— modifiable request args (headers, params, json, etc.)attributes— custom attribute dictionary
Available in after_response & handle_exception:
resolved_url— final request URLselected_instance— chosen service instanceresponse— aiohttp responseexception— captured exceptionresult— final processed resultstart_timeresponse_timeend_timeduration
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fastapi_nacos-0.0.6.tar.gz.
File metadata
- Download URL: fastapi_nacos-0.0.6.tar.gz
- Upload date:
- Size: 6.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cced4cb9cfc3d4d1aee035acf0753740a8360987e1d70eb61e1df83da90c4231
|
|
| MD5 |
9dd7c174551713f7e7e1e0a26b1d167e
|
|
| BLAKE2b-256 |
5aa1116560f0833c5a1d6d41abbdc99d3ffaf52b25296326ce907c56674def60
|
File details
Details for the file fastapi_nacos-0.0.6-py3-none-any.whl.
File metadata
- Download URL: fastapi_nacos-0.0.6-py3-none-any.whl
- Upload date:
- Size: 7.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5b48058565a75dbebcf18ccd58af911e36160825c16514025dc71b562eca59f
|
|
| MD5 |
c90c28043c1a7f3bcfea1c050911df60
|
|
| BLAKE2b-256 |
0b024673242f2f5ec4876bb831f530a3c7e6f516988f29b40e246ba5937c2bd1
|