一、优雅关机
生活化例子
餐馆关门:你去餐馆吃火锅,刚坐下点完菜(客户端发请求),餐馆老板突然接到通知要停电(收到关机指令)。老板很贴心,先停止接待新客人(停止接收新请求),等你这桌和其他正在吃饭的客人(正在处理的请求)都吃完了,再关门走人。这样你的火锅就能安安全全吃完,不会有任何损失。
代码示例
package main
import (
"context"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/gin-gonic/gin"
)
func main() {
// 创建路由器
router := gin.default()
router.get("/cook-hotpot", func(c *gin.context) {
time.sleep(5 * time.second) // 模拟煮火锅需要时间
c.string(http.statusok, "火锅煮好了,可以吃啦!")
})
// 创建服务器
srv := &http.server{
addr: ":8080",
handler: router,
}
// 在单独的goroutine中启动服务器
go func() {
if err := srv.listenandserve(); err != nil && err != http.errserverclosed {
log.fatalf("服务器监听错误: %s", err)
}
}()
// 创建一个通道来接收系统信号
quit := make(chan os.signal, 1)
signal.notify(quit, syscall.sigint, syscall.sigterm) // 监听ctrl+c和系统终止信号
// 阻塞等待信号
<-quit
log.println("开始优雅关机...")
// 设置一个5秒超时的上下文
ctx, cancel := context.withtimeout(context.background(), 5*time.second)
defer cancel()
// 调用shutdown方法优雅关闭服务器
if err := srv.shutdown(ctx); err != nil {
log.fatalf("服务器优雅关机失败: %s", err)
}
log.println("服务器已安全退出")
}验证效果
- 运行上面的代码,启动服务。
- 打开浏览器访问 http://127.0.0.1:8080/cook-hotpot,模拟开始煮火锅。
- 在终端迅速执行 ctrl+c 命令,向程序发送关机信号。
- 观察程序不会立即退出,而是等待火锅煮好(请求处理完)后才退出,实现优雅关机。
二、优雅重启
生活化例子
保安换班:小区门口有两名保安,保安a(老进程)正在值班,保安b(新进程)来接班。保安a不会直接走人,而是等手头的事(比如处理一辆正在进入的车)忙完,再让保安b接管工作。这样小区门口的秩序不会因为换班而受到影响。
代码示例
package main
import (
"log"
"net/http"
"time"
"github.com/fvbock/endless"
"github.com/gin-gonic/gin"
)
func main() {
// 创建路由器
router := gin.default()
router.get("/greet", func(c *gin.context) {
time.sleep(5 * time.second) // 模拟处理请求需要时间
c.string(http.statusok, "你好呀,欢迎来到小区!")
})
// 使用endless启动服务器,支持优雅重启
if err := endless.listenandserve(":8080", router); err != nil {
log.fatalf("服务器监听错误: %s", err)
}
log.println("服务器已安全退出")
}验证效果
- 编译并运行上述代码,终端会输出当前进程的 pid。
- 修改代码中处理请求函数的返回值,如将 "你好呀,欢迎来到小区!" 修改为 "欢迎光临,小区新保安在此!",然后重新编译。
- 打开浏览器访问 http://127.0.0.1:8080/greet,模拟车辆进入小区。
- 在终端迅速执行 kill -1 <pid> 命令,向程序发送优雅重启信号。
- 等当前请求处理完(保安a处理完手头的事),再次访问时会收到新的欢迎语,说明在不影响当前请求的情况下完成了优雅重启,同时进程号也变成了新的(保安b接班)。
三、总结
优雅关机和优雅重启的核心就是“有始有终”,不甩手不管正在做的事。
优雅关机就像餐馆老板等你吃完火锅再关门,通过监听系统信号(如ctrl+c),调用shutdown()方法,停止接收新请求并等待现有请求处理完。
优雅重启就像保安换班,使用endless库监听特定信号(如sighup),启动新进程处理新请求,同时让老进程处理完现有请求再退出。
在实际项目中,根据需求选择:需要安全关闭服务就用优雅关机;需要更新代码且不影响现网运行就用优雅重启。
到此这篇关于go语言实现优雅关机和重启的示例详解的文章就介绍到这了,更多相关go语言优雅关机和重启内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论