modify: 集成 granian/uvicorn(gunicorn 保留),启动参数保持现状用函数转换
This commit is contained in:
+21
@@ -123,6 +123,27 @@ base = [
|
|||||||
"fastapi.middleware.cors",
|
"fastapi.middleware.cors",
|
||||||
"fastapi.middleware.gzip",
|
"fastapi.middleware.gzip",
|
||||||
"uvicorn",
|
"uvicorn",
|
||||||
|
"granian", # 备选服务器(APP_SERVER=granian,见 public/main.py),含 Rust 内核
|
||||||
|
"granian._compat",
|
||||||
|
"granian._futures",
|
||||||
|
"granian._granian",
|
||||||
|
"granian._imports",
|
||||||
|
"granian._internal",
|
||||||
|
"granian._loops",
|
||||||
|
"granian._signals",
|
||||||
|
"granian._types",
|
||||||
|
"granian.asgi",
|
||||||
|
"granian.constants",
|
||||||
|
"granian.errors",
|
||||||
|
"granian.http",
|
||||||
|
"granian.log",
|
||||||
|
"granian.net",
|
||||||
|
"granian.rsgi",
|
||||||
|
"granian.server",
|
||||||
|
"granian.server.common",
|
||||||
|
"granian.server.mp",
|
||||||
|
"granian.server.mt",
|
||||||
|
"granian.wsgi",
|
||||||
"chongming_cache",
|
"chongming_cache",
|
||||||
"chongming_cache.backends",
|
"chongming_cache.backends",
|
||||||
"chongming_cache.backends.sqlite_",
|
"chongming_cache.backends.sqlite_",
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
#
|
#
|
||||||
# 可选:/etc/chongming.env 中写 APP_WORKERS=<N> 覆盖 worker 数(默认取
|
# 可选:/etc/chongming.env 中写 APP_WORKERS=<N> 覆盖 worker 数(默认取
|
||||||
# config.toml [production.server].workers,打包版通常为 4)。
|
# config.toml [production.server].workers,打包版通常为 4)。
|
||||||
|
# 可选:APP_SERVER=granian|uvicorn|gunicorn 切换 HTTP 服务器(默认 Linux 下
|
||||||
|
# gunicorn,Windows 下 uvicorn);三者的启动参数同取自 [production.server]。
|
||||||
|
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Chongming Zenoh Gateway (FastAPI + Zenoh + MQTT)
|
Description=Chongming Zenoh Gateway (FastAPI + Zenoh + MQTT)
|
||||||
@@ -29,7 +31,8 @@ StartLimitBurst=5
|
|||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
|
|
||||||
# 打包应用入口:Nuitka 编译产物,前台运行 gunicorn master(Linux 分支)
|
# 打包应用入口:Nuitka 编译产物,前台运行所选服务器 master(默认 Linux 分支为
|
||||||
|
# gunicorn,可用 APP_SERVER 切到 granian/uvicorn)
|
||||||
ExecStart=/data/chongming/chongming
|
ExecStart=/data/chongming/chongming
|
||||||
# 所有相对路径(config.toml / config/ / resources/*.mbank / static.svfs /
|
# 所有相对路径(config.toml / config/ / resources/*.mbank / static.svfs /
|
||||||
# data/ / logs/ / uploads/)均相对工作目录解析,必须指向安装目录
|
# data/ / logs/ / uploads/)均相对工作目录解析,必须指向安装目录
|
||||||
@@ -48,7 +51,7 @@ Environment=PYTHONUNBUFFERED=1
|
|||||||
# 私有动态库,再补一条 Environment=LD_LIBRARY_PATH=/opt/sophon/sophon-ffmpeg-latest/lib
|
# 私有动态库,再补一条 Environment=LD_LIBRARY_PATH=/opt/sophon/sophon-ffmpeg-latest/lib
|
||||||
Environment=PATH=/opt/sophon/sophon-ffmpeg-latest/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
Environment=PATH=/opt/sophon/sophon-ffmpeg-latest/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||||
|
|
||||||
# 优雅停机:SIGTERM 由 gunicorn 排空 worker,等在途请求/告警上传完成
|
# 优雅停机:SIGTERM 由服务器 master 排空 worker,等在途请求/告警上传完成
|
||||||
KillSignal=SIGTERM
|
KillSignal=SIGTERM
|
||||||
KillMode=control-group
|
KillMode=control-group
|
||||||
TimeoutStopSec=30
|
TimeoutStopSec=30
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ debug = false
|
|||||||
env = "production"
|
env = "production"
|
||||||
|
|
||||||
[production.server]
|
[production.server]
|
||||||
|
# 启动参数对各服务器通用(由 main.py 的转换函数映射,无需按服务器改配置);
|
||||||
|
# 服务器/副本数可用环境变量覆盖:APP_SERVER=granian|uvicorn|gunicorn、APP_WORKERS=<N>
|
||||||
access_log = false
|
access_log = false
|
||||||
host = "0.0.0.0"
|
host = "0.0.0.0"
|
||||||
port = 8000
|
port = 8000
|
||||||
|
|||||||
+127
-44
@@ -3,23 +3,126 @@
|
|||||||
"""
|
"""
|
||||||
FastAPI chongming 示例
|
FastAPI chongming 示例
|
||||||
主入口文件,适配 chongming 打包系统
|
主入口文件,适配 chongming 打包系统
|
||||||
|
|
||||||
|
服务器选择(APP_SERVER 环境变量,默认见 DEFAULT_SERVER):
|
||||||
|
- gunicorn:现状保留(Linux 默认,uvloop worker + preload 多进程)
|
||||||
|
- uvicorn:Windows 默认(gunicorn 依赖 fork,Windows 不可用)
|
||||||
|
- granian:Rust HTTP 内核,多进程
|
||||||
|
|
||||||
|
启动参数保持 config.toml `[<env>.server]` 现状(host / port / workers /
|
||||||
|
reload / access_log / timeout_keep_alive),由 `_to_uvicorn`、`_to_granian`、
|
||||||
|
`_to_gunicorn_args` 转换为对应服务器的参数。
|
||||||
"""
|
"""
|
||||||
|
import asyncio # noqa: F401
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
import platform
|
import platform
|
||||||
from utils.launch import launch
|
import sys
|
||||||
from multiprocessing import freeze_support
|
from multiprocessing import freeze_support
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import server # noqa: F401 # 预加载:master 内完成模块银行装载,fork 出的 worker 共享
|
||||||
|
import uvloop # noqa: F401 # 显式导入保证打包时收集 uvloop(uvicorn/granian loop 依赖)
|
||||||
|
from utils.launch import launch
|
||||||
from uvicorn.workers import UvicornWorker
|
from uvicorn.workers import UvicornWorker
|
||||||
import server
|
|
||||||
import uvloop
|
|
||||||
import asyncio
|
|
||||||
|
|
||||||
use_shell = platform.system() == "Windows"
|
use_shell = platform.system() == "Windows"
|
||||||
|
|
||||||
|
# 未设置 APP_SERVER 时的平台默认(保持现状)
|
||||||
|
DEFAULT_SERVER = "uvicorn" if use_shell else "gunicorn"
|
||||||
|
SUPPORTED_SERVERS = ("gunicorn", "uvicorn", "granian")
|
||||||
|
|
||||||
|
# 热重载(reload=true)监听的源码目录,避免 granian 默认扫 cwd 时被 logs/ 写日志触发
|
||||||
|
RELOAD_PATHS = [Path("src/chongming"), Path("src/plugins")]
|
||||||
|
|
||||||
|
|
||||||
class UvloopUvicornWorker(UvicornWorker):
|
class UvloopUvicornWorker(UvicornWorker):
|
||||||
CONFIG_KWARGS = {"loop": "uvloop"}
|
CONFIG_KWARGS = {"loop": "uvloop"}
|
||||||
|
|
||||||
|
|
||||||
|
def _server_params(app_config: dict) -> dict:
|
||||||
|
"""把 `[<env>.server]` 的现状参数整理为各服务器共用的启动参数。
|
||||||
|
|
||||||
|
只做缺省兜底与运行环境覆盖(打包环境强制禁 reload、APP_WORKERS 覆盖副本数),
|
||||||
|
键名保持 config.toml 现状,改名交给下面的转换函数。
|
||||||
|
"""
|
||||||
|
server_config = app_config.get("server", {})
|
||||||
|
# 打包环境强制禁用重载
|
||||||
|
is_frozen = getattr(sys, "frozen", False)
|
||||||
|
# 支持通过环境变量 APP_WORKERS 覆盖 worker 数量(方便嵌入式设备调优)
|
||||||
|
default_workers = server_config.get("workers", 4)
|
||||||
|
workers = int(os.environ.get("APP_WORKERS", str(default_workers)))
|
||||||
|
return {
|
||||||
|
"host": server_config.get("host", "0.0.0.0"),
|
||||||
|
"port": server_config.get("port", 8000),
|
||||||
|
"workers": workers,
|
||||||
|
"reload": False if is_frozen else server_config.get("reload", False),
|
||||||
|
"access_log": server_config.get("access_log", False),
|
||||||
|
"timeout_keep_alive": server_config.get("timeout_keep_alive", 5),
|
||||||
|
"log_level": "debug" if app_config.get("debug", False) else "info",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _to_uvicorn(params: dict) -> dict:
|
||||||
|
"""共用参数 → uvicorn.run 关键字参数(键名一致)。"""
|
||||||
|
return {
|
||||||
|
"host": params["host"],
|
||||||
|
"port": params["port"],
|
||||||
|
"reload": params["reload"],
|
||||||
|
"workers": params["workers"],
|
||||||
|
"log_level": params["log_level"],
|
||||||
|
"access_log": params["access_log"],
|
||||||
|
"timeout_keep_alive": params["timeout_keep_alive"],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _to_granian(params: dict) -> dict:
|
||||||
|
"""共用参数 → granian.Granian 关键字参数。
|
||||||
|
|
||||||
|
仅两处改名:host → address、access_log → log_access;
|
||||||
|
timeout_keep_alive 在 granian 无对应项(HTTP/1 keep-alive 只有开关、无空闲
|
||||||
|
超时配置),忽略。
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
"address": params["host"],
|
||||||
|
"port": params["port"],
|
||||||
|
"interface": "asgi",
|
||||||
|
"workers": params["workers"],
|
||||||
|
"reload": params["reload"],
|
||||||
|
"log_level": params["log_level"],
|
||||||
|
"log_access": params["access_log"],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _to_gunicorn_args(params: dict) -> list:
|
||||||
|
"""共用参数 → gunicorn 命令行参数(保持现状:uvloop worker + preload)。"""
|
||||||
|
return [
|
||||||
|
"gunicorn",
|
||||||
|
"server:app",
|
||||||
|
"-k",
|
||||||
|
"__main__.UvloopUvicornWorker",
|
||||||
|
"--preload",
|
||||||
|
"-w",
|
||||||
|
str(params["workers"]),
|
||||||
|
"-b",
|
||||||
|
f"{params['host']}:{params['port']}",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def _select_server(logger) -> str:
|
||||||
|
"""按 APP_SERVER 环境变量选择服务器,非法值/平台不兼容时回退默认。"""
|
||||||
|
server_kind = (os.environ.get("APP_SERVER") or DEFAULT_SERVER).strip().lower()
|
||||||
|
if server_kind not in SUPPORTED_SERVERS:
|
||||||
|
logger.warning(
|
||||||
|
f"未知 APP_SERVER={server_kind!r}(可选: {', '.join(SUPPORTED_SERVERS)}),"
|
||||||
|
f"回退 {DEFAULT_SERVER}"
|
||||||
|
)
|
||||||
|
server_kind = DEFAULT_SERVER
|
||||||
|
if server_kind == "gunicorn" and use_shell:
|
||||||
|
logger.warning("Windows 不支持 gunicorn(依赖 fork),回退 uvicorn")
|
||||||
|
server_kind = "uvicorn"
|
||||||
|
return server_kind
|
||||||
|
|
||||||
|
|
||||||
def app_run(app_config: dict, default_config: dict):
|
def app_run(app_config: dict, default_config: dict):
|
||||||
"""
|
"""
|
||||||
应用运行函数 - 适配模块银行环境
|
应用运行函数 - 适配模块银行环境
|
||||||
@@ -35,18 +138,8 @@ def app_run(app_config: dict, default_config: dict):
|
|||||||
|
|
||||||
logger = get_logger("app")
|
logger = get_logger("app")
|
||||||
|
|
||||||
# 获取服务器配置
|
params = _server_params(app_config)
|
||||||
server_config = app_config.get("server", {})
|
server_kind = _select_server(logger)
|
||||||
host = server_config.get("host", "0.0.0.0")
|
|
||||||
port = server_config.get("port", 8000)
|
|
||||||
timeout_keep_alive = server_config.get("timeout_keep_alive", 5)
|
|
||||||
|
|
||||||
# 打包环境强制禁用重载
|
|
||||||
is_frozen = getattr(sys, "frozen", False)
|
|
||||||
reload = False if is_frozen else server_config.get("reload", False)
|
|
||||||
# 支持通过环境变量 APP_WORKERS 覆盖 worker 数量(方便嵌入式设备调优)
|
|
||||||
default_workers = server_config.get("workers", 4)
|
|
||||||
workers = int(os.environ.get("APP_WORKERS", str(default_workers)))
|
|
||||||
|
|
||||||
# 显示启动信息
|
# 显示启动信息
|
||||||
env = app_config.get("env", "development")
|
env = app_config.get("env", "development")
|
||||||
@@ -54,41 +147,31 @@ def app_run(app_config: dict, default_config: dict):
|
|||||||
logger.info(f"🚀 启动 {default_config.get('app.name', 'FastAPI 应用')}")
|
logger.info(f"🚀 启动 {default_config.get('app.name', 'FastAPI 应用')}")
|
||||||
logger.info(f"📦 版本: {default_config.get('app.version', '1.0.0')}")
|
logger.info(f"📦 版本: {default_config.get('app.version', '1.0.0')}")
|
||||||
logger.info(f"🌍 环境: {env}")
|
logger.info(f"🌍 环境: {env}")
|
||||||
logger.info(f"📍 地址: http://{host}:{port}")
|
logger.info(f"🖥️ 服务器: {server_kind}")
|
||||||
logger.info(f"📚 文档: http://{host}:{port}/docs")
|
logger.info(f"📍 地址: http://{params['host']}:{params['port']}")
|
||||||
|
logger.info(f"📚 文档: http://{params['host']}:{params['port']}/docs")
|
||||||
logger.info(f"🔧 调试: {'启用' if app_config.get('debug', False) else '禁用'}")
|
logger.info(f"🔧 调试: {'启用' if app_config.get('debug', False) else '禁用'}")
|
||||||
logger.info(f"🔄 重载: {'启用' if reload else '禁用'}")
|
logger.info(f"🔄 重载: {'启用' if params['reload'] else '禁用'}")
|
||||||
logger.info(f"👥 Workers: {workers}")
|
logger.info(f"👥 Workers: {params['workers']}")
|
||||||
logger.info("=" * 50)
|
logger.info("=" * 50)
|
||||||
|
|
||||||
# 根据操作系统选择不同的服务器启动方式
|
# 根据所选服务器启动(默认平台分支保持现状)
|
||||||
if use_shell:
|
if server_kind == "granian":
|
||||||
|
import granian
|
||||||
|
|
||||||
|
granian.Granian(
|
||||||
|
target="server:app",
|
||||||
|
**_to_granian(params),
|
||||||
|
reload_paths=RELOAD_PATHS,
|
||||||
|
).serve()
|
||||||
|
elif server_kind == "uvicorn":
|
||||||
import uvicorn
|
import uvicorn
|
||||||
|
|
||||||
uvicorn.run(
|
uvicorn.run("server:app", **_to_uvicorn(params))
|
||||||
"server:app",
|
|
||||||
host=host,
|
|
||||||
port=port,
|
|
||||||
reload=reload,
|
|
||||||
workers=workers,
|
|
||||||
log_level="debug" if app_config.get("debug", False) else "info",
|
|
||||||
access_log=False,
|
|
||||||
timeout_keep_alive=timeout_keep_alive,
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
from gunicorn.app.wsgiapp import run
|
from gunicorn.app.wsgiapp import run
|
||||||
|
|
||||||
sys.argv = [
|
sys.argv = _to_gunicorn_args(params)
|
||||||
"gunicorn",
|
|
||||||
"server:app",
|
|
||||||
"-k",
|
|
||||||
"__main__.UvloopUvicornWorker",
|
|
||||||
"--preload",
|
|
||||||
"-w",
|
|
||||||
str(workers),
|
|
||||||
"-b",
|
|
||||||
f"{host}:{port}",
|
|
||||||
]
|
|
||||||
run()
|
run()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+10
-1
@@ -9,6 +9,7 @@ dependencies = [
|
|||||||
"eclipse-zenoh",
|
"eclipse-zenoh",
|
||||||
"fastapi[uvicorn]",
|
"fastapi[uvicorn]",
|
||||||
"gunicorn",
|
"gunicorn",
|
||||||
|
"granian[reload,uvloop]>=2.8.4",
|
||||||
"module-bank",
|
"module-bank",
|
||||||
"openai",
|
"openai",
|
||||||
"python-multipart",
|
"python-multipart",
|
||||||
@@ -36,7 +37,14 @@ requires-python = ">=3.12"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
[dependency-groups]
|
[dependency-groups]
|
||||||
dev = ["chongming-cli", "nuitka", "pyarmor", "pyinstaller", "ruff"]
|
dev = [
|
||||||
|
"chongming-cli",
|
||||||
|
"greenlet>=3.5.6",
|
||||||
|
"nuitka",
|
||||||
|
"pyarmor",
|
||||||
|
"pyinstaller",
|
||||||
|
"ruff",
|
||||||
|
]
|
||||||
|
|
||||||
[tool.hatch.build.targets.wheel]
|
[tool.hatch.build.targets.wheel]
|
||||||
packages = ["src/chongming"]
|
packages = ["src/chongming"]
|
||||||
@@ -49,5 +57,6 @@ url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple"
|
|||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
gunicorn = "chongming:gunicorn_serve"
|
gunicorn = "chongming:gunicorn_serve"
|
||||||
|
granian = "chongming:granian_serve"
|
||||||
serve = "chongming:serve"
|
serve = "chongming:serve"
|
||||||
worker_serve = "chongming_worker.process:worker_serve"
|
worker_serve = "chongming_worker.process:worker_serve"
|
||||||
|
|||||||
@@ -1,7 +1,66 @@
|
|||||||
|
"""chongming 网关启动入口(uvicorn / granian / gunicorn)。
|
||||||
|
|
||||||
|
config.toml 中 `[<env>.server]` 的启动参数保持现状(host / port / workers /
|
||||||
|
reload / access_log / timeout_keep_alive),由 `_to_uvicorn`、`_to_granian` 在
|
||||||
|
启动时转换为对应服务器的关键字参数,切换服务器不必改配置格式。
|
||||||
|
"""
|
||||||
|
|
||||||
|
from collections.abc import Mapping
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
import uvicorn
|
import uvicorn
|
||||||
from chongming_config import load_config
|
from chongming_config import Server, load_config
|
||||||
|
|
||||||
from .app.core.logger import get_logger
|
from .app.core.logger import get_logger
|
||||||
|
|
||||||
|
# 开发期热重载(reload=true)监听的源码目录(granian 用;uvicorn 走其默认扫描)
|
||||||
|
RELOAD_PATHS = [Path("src/chongming"), Path("src/plugins")]
|
||||||
|
|
||||||
|
|
||||||
|
def _server_config_view(server_config: Server) -> Mapping[str, Any]:
|
||||||
|
"""[<env>.server] 的宽松视图:实际 TOML 可能带 Server 之外的键
|
||||||
|
(如 timeout_keep_alive,chongming_config.Server 尚未声明)。"""
|
||||||
|
return server_config
|
||||||
|
|
||||||
|
|
||||||
|
def _to_uvicorn(server_config: Server) -> dict:
|
||||||
|
"""把 [<env>.server] 的现状参数转为 uvicorn.run 的关键字参数。
|
||||||
|
|
||||||
|
uvicorn 的参数名与配置项一致,这里只做缺省兜底。
|
||||||
|
"""
|
||||||
|
cfg = _server_config_view(server_config)
|
||||||
|
converted: dict = {
|
||||||
|
"host": cfg.get("host", "0.0.0.0"),
|
||||||
|
"port": cfg.get("port", 8000),
|
||||||
|
"reload": cfg.get("reload", False),
|
||||||
|
}
|
||||||
|
for key in ("workers", "access_log", "timeout_keep_alive"):
|
||||||
|
if key in cfg:
|
||||||
|
converted[key] = cfg[key]
|
||||||
|
return converted
|
||||||
|
|
||||||
|
|
||||||
|
def _to_granian(server_config: Server) -> dict:
|
||||||
|
"""把 [<env>.server] 的现状参数转为 granian.Granian 的关键字参数。
|
||||||
|
|
||||||
|
仅两处改名:host → address、access_log → log_access;
|
||||||
|
timeout_keep_alive 在 granian 无对应项(HTTP/1 keep-alive 只有开关、无空闲
|
||||||
|
超时配置),忽略。
|
||||||
|
"""
|
||||||
|
cfg = _server_config_view(server_config)
|
||||||
|
converted: dict = {
|
||||||
|
"address": cfg.get("host", "0.0.0.0"),
|
||||||
|
"port": cfg.get("port", 8000),
|
||||||
|
"interface": "asgi",
|
||||||
|
}
|
||||||
|
for key in ("reload", "workers"):
|
||||||
|
if key in cfg:
|
||||||
|
converted[key] = cfg[key]
|
||||||
|
if "access_log" in cfg:
|
||||||
|
converted["log_access"] = cfg["access_log"]
|
||||||
|
return converted
|
||||||
|
|
||||||
|
|
||||||
def serve():
|
def serve():
|
||||||
"""
|
"""
|
||||||
@@ -20,7 +79,34 @@ def serve():
|
|||||||
logger = get_logger("app")
|
logger = get_logger("app")
|
||||||
logger.info(f"启动服务: {server_config}")
|
logger.info(f"启动服务: {server_config}")
|
||||||
logger.info(f"启动日志: {log_config}")
|
logger.info(f"启动日志: {log_config}")
|
||||||
uvicorn.run("chongming.app:app", **server_config)
|
uvicorn.run("chongming.app:app", **_to_uvicorn(server_config))
|
||||||
|
|
||||||
|
|
||||||
|
def granian_serve():
|
||||||
|
"""
|
||||||
|
使用 granian 启动服务
|
||||||
|
|
||||||
|
从配置文件中加载服务器配置和日志配置,然后使用 granian 启动应用服务。
|
||||||
|
该函数适用于开发环境或单进程部署场景。
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None: 该函数不返回值,会阻塞运行直到服务停止
|
||||||
|
"""
|
||||||
|
# 延迟导入:未选用 granian 的部署环境不必安装它
|
||||||
|
import granian
|
||||||
|
|
||||||
|
config = load_config()
|
||||||
|
env = config["default"]["env"]
|
||||||
|
server_config = config[env]["server"]
|
||||||
|
log_config = config[env]["logging"]
|
||||||
|
logger = get_logger("app")
|
||||||
|
logger.info(f"启动服务: {server_config}")
|
||||||
|
logger.info(f"启动日志: {log_config}")
|
||||||
|
granian.Granian(
|
||||||
|
target="chongming.app:app",
|
||||||
|
**_to_granian(server_config),
|
||||||
|
reload_paths=RELOAD_PATHS,
|
||||||
|
).serve()
|
||||||
|
|
||||||
|
|
||||||
def gunicorn_serve():
|
def gunicorn_serve():
|
||||||
@@ -36,6 +122,7 @@ def gunicorn_serve():
|
|||||||
None: 该函数不返回值,会阻塞运行直到服务停止
|
None: 该函数不返回值,会阻塞运行直到服务停止
|
||||||
"""
|
"""
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from gunicorn.app.wsgiapp import run
|
from gunicorn.app.wsgiapp import run
|
||||||
|
|
||||||
config = load_config()
|
config = load_config()
|
||||||
|
|||||||
Reference in New Issue
Block a user