import threading import logging import socket import uvicorn from fastapi import FastAPI from gewechat.api.callback import router as callback_router # 配置日志 logger = logging.getLogger(__name__) def is_port_in_use(port, host='0.0.0.0'): """检查端口是否被占用""" with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: try: s.bind((host, port)) return False except socket.error: return True def start_fastapi_server(host="0.0.0.0", port=8999): """启动FastAPI服务器""" # 检查端口是否被占用 if is_port_in_use(port, host): logger.warning(f"端口 {port} 已被占用,尝试使用其他端口") # 尝试其他端口 for test_port in range(9000, 9100): if not is_port_in_use(test_port, host): port = test_port break else: logger.error("无法找到可用端口,服务器启动失败") return False try: app = FastAPI() app.include_router(callback_router) # 添加健康检查路由 @app.get("/health") async def health_check(): return {"status": "ok"} logger.info(f"正在启动FastAPI服务器,地址: http://{host}:{port}") # 使用线程启动uvicorn服务器 server_thread = threading.Thread( target=uvicorn.run, args=(app,), kwargs={"host": host, "port": port, "log_level": "info"}, daemon=True ) server_thread.start() logger.info(f"FastAPI 服务已在 http://{host}:{port} 启动") logger.info(f"回调URL: http://{host}:{port}/gewechat/callback") # 返回启动的端口,以便调用者知道实际使用的端口 return port except Exception as e: logger.error(f"启动FastAPI服务器失败: {e}", exc_info=True) return False if __name__ == '__main__': # 配置日志 logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) # 启动服务器 port = start_fastapi_server() if port: print(f"服务器启动成功,端口: {port}") print(f"回调URL: http://localhost:{port}/gewechat/callback") print(f"健康检查URL: http://localhost:{port}/health") # 保持主线程运行 try: import time while True: time.sleep(1) except KeyboardInterrupt: print("服务器已停止") else: print("服务器启动失败")