| """Grok2API""" |
|
|
| import os |
| import sys |
| from contextlib import asynccontextmanager |
| from pathlib import Path |
|
|
| from fastapi import FastAPI |
| from fastapi.middleware.cors import CORSMiddleware |
| from fastapi.staticfiles import StaticFiles |
| from app.core.logger import logger |
| from app.core.exception import register_exception_handlers |
| from app.core.storage import storage_manager |
| from app.core.config import setting |
| from app.services.grok.token import token_manager |
| from app.api.v1.chat import router as chat_router |
| from app.api.v1.models import router as models_router |
| from app.api.v1.images import router as images_router |
| from app.api.admin.manage import router as admin_router |
| from app.services.mcp import mcp |
|
|
| |
| try: |
| if sys.platform != 'win32': |
| import uvloop |
| uvloop.install() |
| logger.info("[Grok2API] 启用uvloop高性能事件循环") |
| else: |
| logger.info("[Grok2API] Windows系统,使用默认asyncio事件循环") |
| except ImportError: |
| logger.info("[Grok2API] uvloop未安装,使用默认asyncio事件循环") |
|
|
| |
| mcp_app = mcp.http_app(stateless_http=True, transport="streamable-http") |
|
|
| |
| @asynccontextmanager |
| async def lifespan(app: FastAPI): |
| """ |
| 启动顺序: |
| 1. 初始化核心服务 (storage, settings, token_manager) |
| 2. 异步加载 token 数据 |
| 3. 启动批量保存任务 |
| 4. 启动MCP服务生命周期 |
| |
| 关闭顺序 (LIFO): |
| 1. 关闭MCP服务生命周期 |
| 2. 关闭批量保存任务并刷新数据 |
| 3. 关闭核心服务 |
| """ |
| |
| |
| await storage_manager.init() |
|
|
| |
| storage = storage_manager.get_storage() |
| setting.set_storage(storage) |
| token_manager.set_storage(storage) |
| |
| |
| await setting.reload() |
| logger.info("[Grok2API] 核心服务初始化完成") |
| |
| |
| from app.core.proxy_pool import proxy_pool |
| proxy_url = setting.grok_config.get("proxy_url", "") |
| proxy_pool_url = setting.grok_config.get("proxy_pool_url", "") |
| proxy_pool_interval = setting.grok_config.get("proxy_pool_interval", 300) |
| proxy_pool.configure(proxy_url, proxy_pool_url, proxy_pool_interval) |
| |
| |
| await token_manager._load_data() |
| logger.info("[Grok2API] Token数据加载完成") |
| |
| |
| from app.services.api_keys import api_key_manager |
| await api_key_manager.init() |
| logger.info("[Grok2API] API Key数据加载完成") |
|
|
| |
| from app.services.request_stats import request_stats |
| from app.services.request_logger import request_logger |
| await request_stats.init() |
| await request_logger.init() |
| logger.info("[Grok2API] 统计和日志数据加载完成") |
| |
| |
| await token_manager.start_batch_save() |
|
|
| |
| mcp_lifespan_context = mcp_app.lifespan(app) |
| await mcp_lifespan_context.__aenter__() |
| logger.info("[MCP] MCP服务初始化完成") |
|
|
| logger.info("[Grok2API] 应用启动成功") |
| |
| try: |
| yield |
| finally: |
| |
| |
| await mcp_lifespan_context.__aexit__(None, None, None) |
| logger.info("[MCP] MCP服务已关闭") |
| |
| |
| await token_manager.shutdown() |
| logger.info("[Token] Token管理器已关闭") |
| |
| |
| await storage_manager.close() |
| logger.info("[Grok2API] 应用关闭成功") |
|
|
|
|
| |
| logger.info("[Grok2API] 应用正在启动...") |
| logger.info("[Grok2API] Fork 版本维护: @Tomiya233") |
|
|
| |
| app = FastAPI( |
| title="Grok2API", |
| description="Grok API 转换服务", |
| version="1.3.1", |
| lifespan=lifespan |
| ) |
|
|
| |
| register_exception_handlers(app) |
|
|
| |
| app.include_router(chat_router, prefix="/v1") |
| app.include_router(models_router, prefix="/v1") |
| app.include_router(images_router) |
| app.include_router(admin_router) |
|
|
| |
| app.mount("/static", StaticFiles(directory="app/template"), name="template") |
|
|
| @app.get("/") |
| async def root(): |
| """根路径""" |
| from fastapi.responses import RedirectResponse |
| return RedirectResponse(url="/login") |
|
|
|
|
| @app.get("/health") |
| async def health_check(): |
| """健康检查接口""" |
| return { |
| "status": "healthy", |
| "service": "Grok2API", |
| "version": "1.0.3" |
| } |
|
|
| |
| app.mount("", mcp_app) |
|
|
|
|
| if __name__ == "__main__": |
| import uvicorn |
| import os |
| |
| |
| workers = int(os.getenv("WORKERS", "1")) |
| |
| |
| if workers > 1: |
| logger.info( |
| f"[Grok2API] 多进程模式已启用 (workers={workers})。" |
| f"建议使用 Redis/MySQL 存储以获得最佳性能。" |
| ) |
| |
| |
| loop_type = "auto" |
| if workers == 1 and sys.platform != 'win32': |
| try: |
| import uvloop |
| loop_type = "uvloop" |
| except ImportError: |
| pass |
| |
| uvicorn.run( |
| "main:app", |
| host="0.0.0.0", |
| port=8000, |
| workers=workers, |
| loop=loop_type |
| ) |
|
|