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

Unit 作为 python 应用服务器是否可靠
可靠,但仅限于特定场景:它不是 gunicorn 或 Uvicorn 的替代品,而是更接近“轻量级、配置驱动、多语言共存”的反向代理+运行时混合体。Unit 不做进程管理、不支持热重载、不内置日志聚合,但它启动快、配置热更新、原生支持多版本 Python 共存。
常见错误现象:502 Bad gateway(Python 程序没起来)、404 Not Found(script 路径写错或未指定 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:8080或proxy_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/,否则还是旧代码。