参考:
https://blog.csdn.net/qq_36517296/article/details/123993095(gin项目平滑重启)
https://studygolang.com/articles/32123(go项目平滑重启)
什么是平滑重启
进程在不关闭其所监听端口的情况下进行重启,并且重启的整个过程保证所有请求都能被正确处理。
主要步骤:
- 原进程(父进程)先
fork
一个子进程,同时让fork
出来的子进程继承父进程所监听的socket
。 - 子进程完成初始化后,开始接收
socket
的请求。 - 父进程停止接收新的请求,并将当下的请求处理完,等待连接空闲后,平滑退出。
一般有三种方案:
- 生产环境会通过四层(lb)->七层(gateway)->服务,那么可以通过流量调度的方式实现平滑重启
- k8s管理
- 程序自身完成平滑重启(本章介绍)
show me the code
func main(){ // ------------------------- 平滑重启 ----------------------- g := router.Load() // 这里的g 代表 *gin.Engine s := &http.Server{ Addr: ":" + viper.GetString("gin.port"), Handler: g, ReadTimeout: 10 * time.Second, //WriteTimeout: 10 * time.Second, //MaxHeaderBytes: 1 << 20 } go func() { // service connections if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed { //log.Fatalf(err, "listen: %s\n", err) log.Fatal(err) } }() listenSignal(s) // two 处理优雅重启 } func listenSignal(httpSrv *http.Server) { sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) select { case sig := <-sigs: log.Println("收到信号notify sigs", sig) zlog.F().Info("收到信号notify sigs", sig) ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) // 2s没有处理完,则强制关闭 defer cancel() err := httpSrv.Shutdown(ctx) if err != nil { log.Println(err) zlog.F().Error(err) } log.Println("关闭,http shutdown") zlog.F().Info("关闭,http shutdown") } }
startWeb.sh
#!/bin/sh # chkconfig: 2345 87 88 # Description: huidu-go-ulive-app service . /etc/init.d/functions APP_HOME=/data/yekong_api prog=yekong_api start_scripts_name="yekong_api" process="./yekong_api" function startSer() { chmod +x ${start_scripts_name} cd ${APP_HOME} && nohup ./${start_scripts_name} > output.log 2>&1 & if [ $? -eq 0 ];then action "Starting $prog Server" /bin/true else action "Starting $prog Server" /bin/false fi } function stopSer() { PID=$(ps aux | grep -w ${process} | grep -v grep | awk '{print $2}') if [ "${PID}" ];then time=2 time_interval=0.5 TIME_NUM=$(echo "${time} ${time_interval}" | awk '{print $1 / $2}') echo "次数 $TIME_NUM" kill -2 ${PID} i=0 while(( $i<=$TIME_NUM )) do PID=$(ps aux | grep -w ${process} | grep -v grep | awk '{print $2}') if [ "$PID" ];then [ $i == ${TIME_NUM} ] && kill -9 $PID || sleep ${time_interval} echo "pid为: $PID" else echo "平滑退出,break" break fi let "i++" done fi [ $? -eq 0 ] && action "Stop $prog Server" /bin/true || action "Stop $prog Server" /bin/false } function status() { PID=$(ps aux | grep -w ${process} | grep -v grep | awk '{print $2}') if [ "$PID" ];then if kill -0 $PID > /dev/null 2> /dev/null ; then return 0 else return 2 # program is dead but pid file exists fi else return 3 # program is not running fi } case "$1" in start) status code=$? if [ $code -eq 0 ]; then echo "$prog server is already running" else startSer code=$? fi exit $code ;; stop) stopSer ;; restart) stopSer startSer ;; status) status if [ $? -eq 0 ];then echo -e "$prog server \033[32mRunning\033[0m (PID:$PID)..." else echo -e "$prog server \033[31m Not running\033[0m..." fi ;; *) echo "Usage: service $prog {start|stop|restart|status}" exit 1 esac exit 0
标签:web,code,平滑,echo,time,prog,重启 From: https://www.cnblogs.com/tkzc2013/p/16599270.html