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
Release files for fastapi-nacos 0.0.7
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| fastapi_nacos-0.0.7.tar.gz | 6.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fastapi_nacos-0.0.7-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 14.6 kB
Release files / fastapi_nacos-0.0.7.tar.gz
| Download URL | fastapi_nacos-0.0.7.tar.gz |
|---|---|
| Size | 6.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
40a161c017c0cd6ba7e966fbbb2490e540c81ea206931df2408957094731fd3d
|
|
BLAKE2b-256 checksum How to use checksums |
5848435f49da1f37c6cb5d61daebebf4e79058eedb97a055e22f17a7313e6ab3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.8
|
Release files / fastapi_nacos-0.0.7-py3-none-any.whl
| Download URL | fastapi_nacos-0.0.7-py3-none-any.whl |
|---|---|
| Size | 7.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c4c12da2566925cbf2a4e51645e437fcfdc94a629c55e2827f895b967270d764
|
|
BLAKE2b-256 checksum How to use checksums |
48f48d008c1ac14af6e6e09dec8a4ac4eda4262706af9769a9ee2f4757a9c184
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.8
|