如何平滑重启Caddy 作者: 灯小笼 时间: 2018-09-01 分类: 工具 网站讲究高可用,讲究不间断服务。而对于刚接触caddy的我们而言,修改配置文件是加家常便饭,比如:增加日志监控,增加一个301重定向什么的。那么修改了配置文件,配置文件是否配置正确呢?配置后又该怎么重启呢?如何确保重启过程的不间断服务呢?如果出现服务挂掉该怎么确保服务的自动启动呢?这一系列的疑问,我们今天来一一释怀吧。但是,需要相信的是,caddy作为一个新生代的web服务器软件,这些方面肯定会考虑到的。本文将参考官方的[命令行模式](https://caddyserver.com/docs/cli)文档,为这些问题一一解答。 > ps.关于Caddy的命令行参数,也可以参考我翻译的中文文档:[Caddy命令行参数](/caddy/cn-doc/cli.md) ## 如何检查配置文件正确性 caddy指定配置文件的参数是`-conf`,那么怎么验证配置文件是否正确呢?就像nginx的`-t`参数一样,caddy有`-validate`参数可供使用。看一下官方文档: > -validate > Parse the Caddyfile and exit. If syntactically valid, a message will be printed to stdout and the process log (if any) and will exit with status 0. If not, an error will be returned with a non-zero exit status. 解析Caddyfile并退出,如果句法结构正确,将会通过标准输出打印一条信息,记录日志(如果配置了),最后会退出,退出码为0。否则,会报出相应的错误信息,状态码为非0。 我们先来看一个错误的配置文件: ```caddy localhost:8110{ helloworld } ``` ```bash $: caddy -conf Caddyfile -validate 2018/09/01 09:45:31 Caddyfile:2 - Error during parsing: Unknown directive 'helloworld' $: echo $? 1 ``` 退出码是1,提示`helloworld`是一个未知指令 再来看一个例子: ```bash $: cat Caddyfile localhost:8110{ gzip } $: caddy -conf Caddyfile -validate 2018/09/01 09:49:41 error inspecting server blocks: parse //localhost:8110{: invalid character "{" in host name $: echo $? $: 1 ``` 退出码还是1,提示域名中的{是个非法字符。也就是说,解析的时候,会把第一行连在一起的字符整个识别为字符串(其实这里可以更智能点,如果最后一个字符是{,可以认定之前的才是域名)。 那我们改进一下,在8110和{之间增加一个空格,再来验证一下: ```bash $:cat Caddyfile localhost:8110 { gzip } $: caddy -validate -log result.log Caddyfile is valid $: cat result.log 2018/09/01 09:59:57 [INFO] Caddyfile is valid $: echo $? $: 0 ``` 这次命令里边,没有再指定`-conf`参数,因为默认的配置文件就是当前文件夹的Caddyfile。另外,我们加了一个参数`-log`,前面提过,验证成功的时候如果配置了这个参数,就会将相关信息记录到日志。而配置错误的时候,即使有`-log`参数,也不会做任何记录。 总之,这个命令对于后面的重启至关重要,如果改了配置文件,不先对其进行正确性校验,后面重启很可能失败,这时再来检查问题就有些措手不及了。 ## 如何重启 重启还不简单,直接kill,再启动就行了。确实,对于访问量不高的站点,找个访问空闲的时候,一两秒中断还是可以的。不过,作为对高可用有特殊癖好的我们,还是会对自己有更高的要求的。我们希望caddy也能像nginx那样,通过`-s reload`命令,实现web服务器的平滑重启。 通过官网的`Signals`一节,可以很轻松地找到你需要的命令。 > ## Signals > On POSIX-compliant systems, Caddy can be controlled with signals. Here we list them roughly in order from the most forceful action to most graceful. > ### KILL > Forcefully exits the process immediately. This signal cannot be caught, so Caddy won't know what hit it. Any pidfile created with the -pidfile flag and other runtime assets will NOT be cleaned up by Caddy. > ### QUIT > Forcefully exits the process without executing shutdown hooks. > ### INT > Forcefully exits the process after executing shutdown hooks. This is the only "signal" that works on Windows (Ctrl+C). A second SIGINT forces immediate termination, even if shutdown hooks are still running. > ### TERM > Gracefully stops the server after executing shutdown hooks. > ### USR1 > Reloads the configuration file, then gracefully restarts the server. If there is an error with the new configuration, the error is logged and the configuration rolls back with zero downtime. > ### USR2 > Gracefully restarts the process with an updated binary. Useful when upgrading the Caddy binary. Replace the binary with a new version and send this signal. Configuration will be transferred to the new process. If an error occurs, the error will be logged and the configuration rolls back with zero downtime. 翻译一下,该使用哪个信号来`kill`caddy,就清楚了。 > ## 信号 > 对于POSIX兼容的系统而言,可以通过信号来控制caddy。下面我们粗略按照先强制后优雅的顺序列举相关的控制信号: > ### `KILL` > 强制马上退出进程。这个信号不能被捕捉到,因此caddy对此毫无感知。通过`-pidfile`指定的pid文件,以及运行时资源都不会被清理。 ps:相比如`KILL`,大家更熟悉地可能是kill -9 [pid]。对,`KILL`就是-9。 我们可以通过`kill -l`命令来进一步熟悉所有的信号量: ```bash $: kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX ``` > ### `QUIT` > 不执行关闭时的钩子而强制性退出进程。 > ### `INT` > 在执行关闭时的钩子后强制性退出进程。这也是在Windows系统里边唯一支持的信号了(通过`Ctrl+C`触发)。如果终端再次传输一次`SIGINT`信号,即使还在执行关闭时的钩子,也会立即退出进程。 > ### `TERM` > 在执行完关闭时的钩子后优雅地退出。 ps:优雅退出和强制退出有什么不同呢?我们一会在来看看 > ### `USR1` > 重新加载配置文件,然后优雅(平滑)重启服务。如果新的配置文件有错误,错误会打印到日志,配置文件会自动回滚到之前的状态,整个过程是不会中断服务的。 > ### `USR2` > 平滑重启进程,重启后使用新的二进制包。这个信号在升级caddy二进制包的时候非常有用。把二进制文件替换为新版本的,并且发生这个心血号,配置信息将会被传输给新的进程。如果发生错误,错误信息将会打印到日志,配置也会回滚,服务不会中断。 这里实际上还有一种可能性,配置文件没有做任何更改,那么上次正确的配置也还是当前的配置。如果配置文件和新的版本出现不兼容,那么无论如何新的程序也启动不了,所以升级的时候,需要关注旧版本caddy和新版本caddy的配置文件的格式兼容性问题。 ## 如何确保服务不中断 谁也不敢担保caddy就不会无缘无故挂掉,因此,可以加上开机启动脚本,简单加一下就行了,如: ``` echo "caddy /etc/caddy/Caddyfile" >> /etc/rc.d/rc.local ``` centos7里需要确保 /etc/rc.d/rc.local 有可执行权限。 另外,当机器运行期间,caddy异常退出时,要确保其能自动重启,可以通过[supervisor](http://supervisord.org/)来予以监控。 ```yun pip install supervisor ``` 详细的安装可以参考: 编写配置文件`/etc/supervisord.d/caddy.ini`,内容如下: ``` command=caddy -conf /etc/caddy/Caddyfile numprocs=1 user=root autostart=true autorestart=true redirect_stderr=true stdout_logfile=/var/log/caddy/caddy.log ``` 启动服务并配置开机启动: ```bash systemctl restart supervisord systemctl enable supervisord ``` 这样,其实之前那个/etc/rc.d/rc.local的配置也不需要了,可以通过supervisor来确保服务是在运行的。 ### 退出码 再补充一个资料,caddy的退出码的详细解释。 | 退出码 | 含义 | |-------|-----------------------| | 0 | 正常或符合预期的退出 | | 1 | 服务未启动前就退出了。比如,配置文件出错 | | 2 | 第二次发送`SIGINT`(强制退出) | | 3 | 发送信号`SIGTERM`导致的退出 | | 4 | 关闭时的回调(钩子)执行时产生的错误 | ## 注册服务 当然,我们可以考虑将Caddy注册成服务,这样使用起来会更加简单。这里不展开了,要了解详情,可以参考“[Caddy注册服务示例](https://dengxiaolong.com/caddy/cn-doc/wiki.Caddy-as-a-service-examples.html)”一文。 ## 总结 经过上述的探讨,我们已经掌握了如何检查配置文件正确性,如何重启等知识。加以灵活运用,就可以确保caddy的高可用了。 标签: caddy, nginx
学到一招
感谢分享