如何重新加载mojolicious内置的webserver守护进程?

时间:2012-06-21 15:04:42

标签: perl mojolicious systemd

我从systemd复制了这个service lighttpd-package文件并对其进行了调整,使systemd启动了内置的mojolic内置服务器守护程序。 我可以保留mojolicious守护进程的ExecReloadKillSignal设置吗?

[Unit]
Description=Start mojolicious.pl daemon
After=syslog.target network.target

[Service]
ExecStart=/path/to/mojolicious.pl daemon --listen "http://*:3001"
ExecReload=/bin/kill -HUP $MAINPID
KillSignal=SIGINT

[Install]
WantedBy=multi-user.target

4 个答案:

答案 0 :(得分:7)

我认为Alex在考虑自动重新加载时会考虑morbo。对于生产,您最好使用hypnotoad。如果切换到hypnotoad,则会有各种有用的信号。例如/bin/kill -USR2 $MAINPID会做优美重载,避免打乱到任何电流连接。有关更多信号(对于催眠),请参阅http://mojolicio.us/perldoc/Mojo/Server/Hypnotoad#SIGNALS

答案 1 :(得分:2)

我不知道为什么你需要“重新加载”,Mojolicious在应用程序代码更改时执行内部重新加载。您可以将其替换为

/bin/kill -0 $MAINPID

如果该行应该在那里,HUP将是正常应用的终端(除非你以不同的方式处理它)

答案 2 :(得分:0)

systemd reload和hypnotoad reload需要一个包装器脚本才能正常协同工作

注意:此解决方法适用于Mojolicious 6.x. SystemD兼容性已在Mojolicious 7.x

中修复

如果您想在systemd下重新加载,那么标准的hypnotoad重新加载(即hypnotoad myapp.pl)或kill -USR $MAINPID是不可取的。 SystemD假定一旦重新加载催眠服务器的命令返回,重新加载就完成了。但是,相反,这两个选项都会立即退出,并且不会等待重新加载完成。

当我尝试了这些标准的重新加载选项时,systemd完成了reload命令的执行,然后,监控pid文件被删除并替换当hypnotoad执行“启动零停机软件升级>升级成功”时

如果您将systemd配置为始终运行hypnotoad应用程序,则systemd将再次重新启动(停止并启动)应用程序 - 在hypnotoad正常执行之后。

以下是发生的事情:

  • systemd reload hypnotoad-app(ExecReload = hypnotoad myapp.pl)
  • hypnotoad-app在被告知重新加载后退出
  • hypnotoad使用最新的myapp.pl
  • 启动一个新进程
  • systemd认为重新加载刚刚完成,并且发现PID中的pid没有改变
  • hypnotoad看到旧进程没有加载,杀死它们,并在“升级[成功]”时删除并创建一个带有新进程PID的新PIDFile(这是催眠器的“零停机时间”重载程序)< / LI>
  • systemd看到删除了pid文件(它忽略了它被重新创建,可能是因为在设计上,systemd想要控制分叉)
  • systemd等待HOLDOFF(RestartSec=<seconds>)(如果已配置)
  • systemd执行hypnotoad-app
  • 的完整单元启动

systemd文档明确指出,当ExecReload=命令返回时,systemd期望进程已经完成重新加载,并且pid文件具有重新加载进程的新PID。但是Hypnotoad并不像那样同步工作。因此,systemd和hypnotoad不能很好地协同工作。

https://www.freedesktop.org/software/systemd/man/systemd.service.html

  

但请注意,通过发送信号重新加载守护程序(与   上面的示例行)通常不是一个好的选择,因为这是一个   异步操作,因此不适合订购重载   多种服务相互对立。强烈建议   将ExecReload =设置为不仅触发配置的命令   重新加载守护进程,同时等待它完成。

解决方案是在重新加载过程中编写一个包装器。

#!/bin/bash

SERVER="/path/to/myapp.pl"
HYPNOTOAD="/usr/bin/hypnotoad"
PIDFILE="/var/run/myapp.pid"

# Timeout == LOOPSAFE x SLEEPTIME
SLEEPTIME="0.5"
LOOPSAFE=20
LOOPCOUNT=0
#

if [ ! -f "${PIDFILE}" ]; then
  # The PID files does not exist, maybe $SERVER is not running
  exit 1
fi

OLDPID=$(cat ${PIDFILE})
NEWPID=$OLDPID

# Reload the application
${HYPNOTOAD} ${SERVER}

while (( $LOOPCOUNT <= $LOOPSAFE )); do
  let LOOPCOUNT++
  if [ -f ${PIDFILE} ]; then
    NEWPID=$(cat ${PIDFILE})
    if (( $NEWPID > 1 )) && (( $NEWPID != $OLDPID )); then
      exit 0
    fi
  fi
  sleep ${SLEEPTIME}
done

exit 1

这是Hypnotoad

所需的systemd单元文件
[Unit]
Description=Hypnotoad-app
Requires=network.target
After=network.target

[Service]
Type=simple
SyslogIdentifier=hypnotoad-app
PIDFile=/var/run/myapp.pid
EnvironmentFile=-/etc/sysconfig/myapp
ExecStart=/usr/bin/hypnotoad --foreground /path/to/myapp.pl
ExecStop=/usr/bin/hypnotoad --stop /path/to/myapp.pl
ExecReload=/path/to/reload-myapp.sh
KillMode=process
Restart=always
RestartSec=5
User=myuser
Group=mygroup

[Install]
WantedBy=multi-user.target

以下是重装过程的工作原理

  • systemd reload hypnotoad-app
  • systemd执行重装脚本
  • 重新加载脚本重新加载hypnotoad-app,并等待“成功升级” - 基本上睡眠,直到PID文件具有新重载的myapp.pl进程的PID
  • systemd现在使用新PID监视pid文件,该PID不会再发生变化 - 所以现在systemd不会尝试重新启动它

答案 3 :(得分:0)

另一种选择是在前台hypnotoad&amp;运行-f。使用runit&amp;的服务监督一个简单的/etc/sv/myapp/run脚本:

#!/bin/sh

app=/path/to/my/app
daemon=/path/to/hypnotoad

exec 2>&1
exec $daemon -f $app

然后,您可以hypnotoad使用sv hup myapp

重新阅读配置

Red Hat不提供runit,但最新版本的rpm可以为built from here

不要忘记ln -s /etc/sv/myapp /etc/service/myapp使用runit启用服务。