diff --git a/app/core/config.py b/app/core/config.py index 813b651..3c44ea2 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -112,66 +112,6 @@ client_config = (ClientConfigBuilder() nacos_config_data: Dict[str, Any] = {} -async def register_service_to_nacos(): - """启动时把服务注册到 Nacos""" - if not nacos_initialized_successfully: - logger.warning("Nacos 未初始化成功,跳过服务注册") - return - - nacos_config_client = await NacosConfigService.create_config_service(client_config) - - if not nacos_config_client: # 如果配置客户端都没连上,就不注册 - logger.warning("Nacos 配置客户端未初始化,跳过服务注册") - return - - try: - nacos_naming_client = await NacosNamingService.create_naming_service(client_config) - param = RegisterInstanceParam( - service_name="aida.python", - group_name=NACOS_GROUP, - ip="210.0.194.163", - port=1671, - cluster_name="DEFAULT", - weight=1.0, - metadata={ - "version": "1.0.0", - "env": settings.SERVE_ENV, - "framework": "fastapi", - "debug": str(settings.DEBUG), - }, - enabled=True, - healthy=True, - ephemeral=True, # 临时实例,推荐生产使用 - ) - - await nacos_naming_client.register_instance(request=param) - logger.info(f"✅ 服务已成功注册到 Nacos! → {SERVICE_NAME} | {"10.1.1.249"}:{settings.PORT} | env={settings.SERVE_ENV}") - - except Exception as e: - logger.error(f"❌ 服务注册到 Nacos 失败: {e}") - - -async def deregister_service_from_nacos(): - """服务关闭时优雅注销(防止 Nacos 长时间显示不健康实例)""" - try: - nacos_naming_client = await NacosNamingService.create_naming_service(client_config) - param = DeregisterInstanceParam( - service_name=SERVICE_NAME, - group_name=NACOS_GROUP, - ip="210.0.194.163", - port=1671, - cluster_name='c1', - ephemeral=True, - ) - await nacos_naming_client.deregister_instance(request=param) - logger.info(f"✅ 服务已从 Nacos 注销 → {SERVICE_NAME}") - except Exception as e: - logger.warning(f"服务注销时出现异常(通常可忽略): {e}") - - -nacos_initialized_successfully = False - - async def load_nacos_config() -> None: """初始化 Nacos 配置并监听变化""" global nacos_config_data, settings @@ -212,7 +152,6 @@ async def load_nacos_config() -> None: await client.add_listener(NACOS_DATA_ID, NACOS_GROUP, listener) logger.info("✅ Nacos 配置监听器已注册(支持热更新)") nacos_initialized_successfully = True - await register_service_to_nacos() except Exception as e: logger.error(f"❌ Nacos 初始化失败: {e}") nacos_initialized_successfully = False diff --git a/app/main.py b/app/main.py index 6a496d7..197cab9 100644 --- a/app/main.py +++ b/app/main.py @@ -1,5 +1,9 @@ import sys from contextlib import asynccontextmanager +from typing import Dict, Any + +import yaml +from v2.nacos import ClientConfigBuilder, GRPCConfig, NacosNamingService, RegisterInstanceParam, DeregisterInstanceParam, NacosConfigService, ConfigParam try: import asyncore @@ -15,7 +19,7 @@ from fastapi import HTTPException from fastapi.responses import JSONResponse from app.api.api_route import router -from app.core.config import settings, load_nacos_config, get_settings, Settings, register_service_to_nacos, deregister_service_from_nacos, nacos_initialized_successfully +from app.core.config import settings, get_settings, Settings from app.schemas.response_template import ResponseModel from logging_env import LOGGER_CONFIG_DICT from starlette.middleware.cors import CORSMiddleware @@ -25,23 +29,125 @@ logging.getLogger("pika").setLevel(logging.WARNING) logger = logging.getLogger(__name__) +naming_client: NacosNamingService | None = None +config_client: NacosConfigService | None = None +current_config: dict = {} + +# ==================== 配置区 ==================== +NACOS_SERVER = "18.167.251.121:28848" # ← 改成你 Nacos 的公网IP:8848(推荐标准端口) +NACOS_USERNAME = "nacos" +NACOS_PASSWORD = "Aidlab123123!" +NAMESPACE_ID = "zcr" # 你的 namespace_id +SERVICE_NAME = "fastapi-demo-service" +SERVICE_GROUP = "DEFAULT_GROUP" +SERVICE_PORT = 8040 # FastAPI 监听端口 +REGISTER_IP = "10.1.1.43" + +# 配置相关 +CONFIG_DATA_ID = "aida.python" +CONFIG_GROUP = "LOCAL" + +nacos_config_data: Dict[str, Any] = {} + @asynccontextmanager async def lifespan(app: FastAPI): - # 启动阶段 + """FastAPI 生命周期管理:启动时注册,关闭时注销""" + global naming_client, config_client + global nacos_config_data, settings + + client_config = ( + ClientConfigBuilder() + .username(NACOS_USERNAME) + .password(NACOS_PASSWORD) + .namespace_id(NAMESPACE_ID) + .server_address(NACOS_SERVER) + .log_level("DEBUG") # 先开 DEBUG 方便排查 + .grpc_config(GRPCConfig(grpc_timeout=5000)) + .build() + ) + # Naming Service(服务注册发现) + naming_client = await NacosNamingService.create_naming_service(client_config) + logger.info("Nacos NamingService 初始化成功") + config_client = await NacosConfigService.create_config_service(client_config) + logger.info("Nacos ConfigService 初始化成功") + + # ==================== 1. 获取配置 ==================== try: - await load_nacos_config() # 里面已包含配置加载 + 服务注册 - logger.info(f"🚀 服务启动完成 | SERVE_ENV={settings.SERVE_ENV} | PORT={settings.PORT} | Nacos={'已连接' if nacos_initialized_successfully else '未连接(使用.env)'}") + config_param = ConfigParam(data_id=CONFIG_DATA_ID, group=CONFIG_GROUP, ) + config_content = await config_client.get_config(config_param) + logger.info(f"获取配置: {config_content}") + if config_content: + loaded = yaml.safe_load(config_content) or {} + nacos_config_data = loaded + # 用 Nacos 配置覆盖 settings + for key, value in loaded.items(): + if hasattr(settings, key): + setattr(settings, key, value) + logger.info(f"✅ Nacos 配置加载成功: {CONFIG_DATA_ID} | 覆盖字段数量: {len(loaded)}") + else: + logger.warning("Nacos 返回配置为空,使用 .env + 默认值") + + # 2. 注册动态监听器(配置变更自动刷新) + async def listener(content: str): + + try: + new_config = yaml.safe_load(content) if content else {} + nacos_config_data = new_config + # 实时覆盖 settings + for key, value in new_config.items(): + if hasattr(settings, key): + old_val = getattr(settings, key) + setattr(settings, key, value) + if old_val != value: + logger.info(f"🔄 配置更新 → {key}: {old_val} → {value}") + logger.info(f"【Nacos 动态更新】{CONFIG_DATA_ID}") + except Exception as e: + logger.error(f"Nacos 配置解析失败: {e}") + + await config_client.add_listener(CONFIG_DATA_ID, CONFIG_GROUP, listener) + logger.info("✅ Nacos 配置监听器已注册(支持热更新)") except Exception as e: - logger.error(f"启动时发生严重错误: {e}") - raise + logger.error(f"获取配置失败: {e}") + current_config["content"] = "获取配置失败" - yield + # ====================2. 注册到 Nacos ==================== + try: + register_param = RegisterInstanceParam( + service_name=SERVICE_NAME, + group_name=SERVICE_GROUP, + ip=REGISTER_IP, + port=SERVICE_PORT, + weight=1.0, + cluster_name="DEFAULT", + metadata={"version": "1.0", "framework": "fastapi"}, + enabled=True, + healthy=True, + ephemeral=False, # ← 先用 False 测试,成功后再改成 True + ) - # 关闭阶段(优雅下线) - await deregister_service_from_nacos() - # 如果有 nacos client,可以在这里 shutdown - logger.info("✅ 服务已优雅关闭") + response = await naming_client.register_instance(request=register_param) + logger.info(f"Nacos 注册成功!Response: {response}") + print(f"✅ 服务已注册到 Nacos: {SERVICE_NAME} @ {REGISTER_IP}:{SERVICE_PORT}") + except Exception as e: + logger.error(f"Nacos 注册失败: {e}") + + yield # FastAPI 正常运行 + + # ====================3. 应用关闭时注销 ==================== + if naming_client: + try: + deregister_param = DeregisterInstanceParam( + service_name=SERVICE_NAME, + group_name=SERVICE_GROUP, + ip=REGISTER_IP, + port=SERVICE_PORT, + cluster_name="DEFAULT", + ) + await naming_client.deregister_instance(request=deregister_param) + logger.info("Nacos 注销成功") + except Exception as e: + logger.warning(f"Nacos 注销失败: {e}") app = FastAPI(lifespan=lifespan, docs_url="/docs", redoc_url='/re-docs', openapi_url=f"/openapi.json", description=''' Base frame with FastAPI - Super Resolution API ''')