Spaces:
Sleeping
Sleeping
File size: 5,485 Bytes
1a9e2c2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | """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
# 0. 兼容性检测
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事件循环")
# 1. 创建MCP的FastAPI应用实例
mcp_app = mcp.http_app(stateless_http=True, transport="streamable-http")
# 2. 定义应用生命周期
@asynccontextmanager
async def lifespan(app: FastAPI):
"""
启动顺序:
1. 初始化核心服务 (storage, settings, token_manager)
2. 异步加载 token 数据
3. 启动批量保存任务
4. 启动MCP服务生命周期
关闭顺序 (LIFO):
1. 关闭MCP服务生命周期
2. 关闭批量保存任务并刷新数据
3. 关闭核心服务
"""
# --- 启动过程 ---
# 1. 初始化核心服务
await storage_manager.init()
# 设置存储到配置和token管理器
storage = storage_manager.get_storage()
setting.set_storage(storage)
token_manager.set_storage(storage)
# 2. 重新加载配置
await setting.reload()
logger.info("[Grok2API] 核心服务初始化完成")
# 2.5. 初始化代理池
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)
# 3. 异步加载 token 数据
await token_manager._load_data()
logger.info("[Grok2API] Token数据加载完成")
# 3.5. 加载 API Key 数据
from app.services.api_keys import api_key_manager
await api_key_manager.init()
logger.info("[Grok2API] API Key数据加载完成")
# 3.6. 加载统计和日志数据
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] 统计和日志数据加载完成")
# 4. 启动批量保存任务
await token_manager.start_batch_save()
# 5. 管理MCP服务的生命周期
mcp_lifespan_context = mcp_app.lifespan(app)
await mcp_lifespan_context.__aenter__()
logger.info("[MCP] MCP服务初始化完成")
logger.info("[Grok2API] 应用启动成功")
try:
yield
finally:
# --- 关闭过程 ---
# 1. 退出MCP服务的生命周期
await mcp_lifespan_context.__aexit__(None, None, None)
logger.info("[MCP] MCP服务已关闭")
# 2. 关闭批量保存任务并刷新数据
await token_manager.shutdown()
logger.info("[Token] Token管理器已关闭")
# 3. 关闭核心服务
await storage_manager.close()
logger.info("[Grok2API] 应用关闭成功")
# 初始化日志
logger.info("[Grok2API] 应用正在启动...")
logger.info("[Grok2API] Fork 版本维护: @Tomiya233")
# 创建FastAPI应用
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"
}
# 挂载MCP服务器
app.mount("", mcp_app)
if __name__ == "__main__":
import uvicorn
import os
# 读取 worker 数量,默认为 1
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
)
|