Python nginx unit 的应用服务器角色

3次阅读

unit 是轻量级多语言应用服务器,适用于小型内部服务,需显式指定解释器路径、模块名和可调用对象,不支持热重载与asgi原生运行,常见错误包括502、404及importError

Python nginx unit 的应用服务器角色

Unit 作为 python 应用服务器是否可靠

可靠,但仅限于特定场景:它不是 gunicorn 或 Uvicorn 的替代品,而是更接近“轻量级、配置驱动、多语言共存”的反向代理+运行时混合体。Unit 不做进程管理、不支持热重载、不内置日志聚合,但它启动快、配置热更新、原生支持多版本 Python 共存。

常见错误现象:502 Bad gateway(Python 程序没起来)、404 Not Foundscript 路径写错或未指定 path)、ImportError(Unit 用的不是你 virtualenv 里的 Python 解释器)。

  • 必须显式指定 interpreter 路径,不能依赖 PATH;比如 /opt/venv/bin/python3.11,而不是 python3
  • 应用入口必须是可调用对象(如 app),且需在模块顶层;Unit 不执行 if __name__ == "__main__"
  • 不支持 async def 直接暴露——Unit 的 Python 驱动是同步 WSGI 模式,ASGI 应用需套一层 asgiref.WsgiToAsgi 或改用 Uvicorn + nginx

如何让 Unit 正确加载你的 flask/fastapi 应用

核心在于路径和入口的精确匹配。Unit 不扫描文件,也不执行 pip install -e .,它只按你写的配置去 import 模块、取变量。

使用场景:部署单个小型内部服务,不想额外维护 Gunicorn 进程、又希望比 python -m http.server 更健壮。

立即学习Python免费学习笔记(深入)”;

示例配置片段(unit.conf):

{     "listeners": {         "*:8080": {             "pass": "applications/myapp"         }     },     "applications": {         "myapp": {             "type": "python 3.11",             "path": "/var/www/myapp",             "interpreter": "/var/www/myapp/venv/bin/python3.11",             "module": "main",             "callable": "app"         }     } }
  • path 是模块所在目录(即 sys.path 的一部分),不是 .py 文件路径
  • module 是文件名(不含 .py),比如 main.py"module": "main"
  • FastAPI 需先转 WSGI:from asgiref.wsgi import WsgiToAsgi; application = WsgiToAsgi(app),然后把 application 设为 callable
  • Flask 默认 app 可直接用;但若用工厂函数(create_app()),得在 main.py 里调用并赋值:app = create_app()

为什么 Unit 启动后 Python 进程立刻退出

根本原因:Unit 在 import 模块阶段就执行了全部顶层代码,一旦抛异常或提前 exit,进程就终止,不会等请求进来。

典型错误包括:import 失败、数据库连接阻塞超时、os.chdir() 切到不存在路径、误写了 sys.exit(0)

  • 检查 Unit 日志:journalctl -u unit --since "1 hour ago",重点看 stderr 输出
  • 确保所有初始化逻辑都包裹在 if __name__ == "unit"(无效)或更实际的做法:延迟到 callable 被调用时再执行(如用闭包或类的 __call__
  • 避免在模块顶层做耗时操作;Unit 的 import 阶段是同步阻塞的,失败即退出
  • 确认 interpreter 有权限读取 path 下所有文件(SELinux 或文件权限常被忽略)

nginx 和 Unit 的协作边界在哪

Unit 不是 nginx 插件,也不是它的子进程;它是独立进程,通过监听 socket(TCP 或 unix domain)与 nginx 通信。nginx 在这里只是纯反向代理,不做 Python 运行时管理。

性能影响:Unix socket 比 TCP 快一点,但差别不大;主要瓶颈在 Python 应用本身。兼容性上,Unit 支持 HTTP/1.1,不支持 HTTP/2 终止(需 nginx 做 TLS 终止和协议升级)。

  • nginx 配置里 proxy_pass http://127.0.0.1:8080proxy_pass http://unix:/var/run/unit.sock 都可以,后者略省端口资源
  • 不要在 nginx 里配 proxy_set_header Host $host 再传给 Unit——Unit 的路由不依赖 Host 头,它靠 listener 绑定决定分发
  • 静态文件建议由 nginx 直接 serve,Unit 不处理 location /Static;Unit 的 static 类型功能弱,无缓存控制、无目录索引
  • Unit 的 access log 和 error log 是独立的,nginx 的 error_log 不会记录 Python 层异常

最易被忽略的一点:Unit 的配置热更新不触发 Python 模块重载——改了 main.py 必须手动 curl -X PUT --data-binary @unit.conf http://localhost:8443/config/,否则还是旧代码。

text=ZqhQzanResources