我在 ubuntu 16 上使用 uwsgi 和 systemd。
我按照此处每个应用程序一项服务下的说明进行操作:http://uwsgi-docs.readthedocs.io/en/latest/Systemd.html
如果我启动 systemd 套接字并访问该站点,一切都会正常工作。 但是在空闲时间(在 ini 文件中指定)之后,uwsgi 进程被终止,并且进一步的请求似乎不会重新启动/重新激活该进程。
workers have been inactive for more than 30 seconds (1501589319-1501589288)
SIGINT/SIGQUIT received...killing workers...
worker 1 buried after 1 seconds
worker 2 buried after 1 seconds
goodbye to uWSGI.
这是我的 ini 文件:
[uwsgi]
module = wsgi
logto = /tmp/uwsgi.log
master = true
processes = 2
cheap = true
idle = 30
die-on-idle = true
manage-script-name = true
这是我的 systemd 套接字配置:
[Unit]
Description=Socket for uWSGI app
[Socket]
ListenStream=/var/run/uwsgi/myapp.socket
SocketUser=www-data
SocketGroup=www-data
SocketMode=0666
[Install]
WantedBy=sockets.target
这是我的 systemd 服务配置:
[Unit]
Description=uWSGI app
After=syslog.target
[Service]
ExecStart=/home/myapp/venv/bin/uwsgi \
--ini /home/myapp/uwsgi/uwsgi.ini \
--socket /var/run/uwsgi/myapp.socket
User=www-data
Group=www-data
Restart=on-failure
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all
RuntimeDirectory=uwsgi
WorkingDirectory=/home/myapp
摆弄这个问题近一天后,我在相关设置的文档中找到了答案。虽然这不是同一种设置,因为我不使用皇帝,但它确实给了我一个线索,了解发生了什么。
套接字激活仅在第一次起作用的原因是因为 uwsgi 覆盖了 systemd 套接字创建的套接字文件。
看到绿色的“!”此页面上的重要框: http://uwsgi-docs.readthedocs.io/en/latest/OnDemandVassals.html
它说:
如果您将在您的vassal配置中定义与使用的相同的套接字 emperor 对于按需操作,vassal 将覆盖该套接字文件。 这可能会导致意外的行为,例如按需 该附庸的激活仅有效一次。
所以就我而言,我没有皇帝,但 systemd 的行为就像皇帝一样。
那么解决办法是什么呢?
从 systemd 服务文件中的
--socket
中删除 ExecStart
参数。
而不是拥有
ExecStart=/home/myapp/venv/bin/uwsgi \
--ini /home/myapp/uwsgi/uwsgi.ini \
--socket /var/run/uwsgi/myapp.socket
我把它改成了
ExecStart=/home/myapp/venv/bin/uwsgi \
--ini /home/myapp/uwsgi/uwsgi.ini
之后我停止了 systemd 服务和套接字,执行了
systemctl daemon-reload
操作并再次启动了 systemd 套接字。一切开始按预期工作 - systemd 套接字激活与 uwsgi 一起工作! :)
问题是
RuntimeDirectory=uwsgi
下的 [Service]
,它不在文档中的 uWSGI 示例中。
这将在服务重新启动时删除并创建 /var/run/uwsgi (现在为 /run/uwsgi)目录。由于此配置在此目录中设置了套接字文件,因此它会在服务重新启动时被删除。
我怀疑删除 --socket 开关是否会改变任何内容,因为 uWSGI 检测到它是从 systemd 运行并从 systemd 套接字文件猜测套接字。因此,在使用临时套接字文件从 systemd 服务文件调用 uwsgi 时不使用
--socket
是相同的。
应该有帮助的是,您在重新启动 systemd 服务文件(RuntimeDirectory = uwsgi 的文件)后重新启动了 systemd 套接字单元,因此在新的 /run/uwsgi 中重新创建了套接字。
最终的修复方法是在
RuntimeDirectoryPreserve=yes
下面添加 RuntimeDirectory=uwsgi
,以便在 systemd 服务重新启动或停止时保留 /run/uwsgi 目录内容(包括套接字)。
或删除
RuntimeDirectory=uwsgi
。但就我而言,我向 uwsgi 添加了 --master-fifo
开关,指向运行时目录,并且在 systemd 在 /run/uwsgi 中创建套接字的默认权限下,该目录只能由 root 写入。因此 uwsgi 用户无法创建 master-fifo。在这种情况下,使用 RuntimeDIRECTORY 和 RuntimeDirectoryPreserve 的选项更容易。
这个master-fifo权限错误是:
uwsgi[264019]: uwsgi_master_fifo()/mkfifo(): Permission denied [core/fifo.c line 112]