关于 go gin 程序如果热更新的问题

2022-09-15 16:10:53 +08:00
 Nasser

大家好,请教一下 我准备使用 gin 来做后端 api 接口 但是在部署和热更新方案上比较困惑 应该怎样来实现 gin 程序的热更新呢 (还望大家不吝赐教)

2844 次点击
所在节点    Go 编程语言
16 条回复
hdczsf
2022-09-15 16:23:02 +08:00
不是有负载均衡吗,逐个重启更新节点,服务不会中断的.
Nasser
2022-09-15 16:27:12 +08:00
@hdczsf gin 直接打包到服务器运行的,怎么重启不会导致服务重点呢?
treblex
2022-09-15 16:28:07 +08:00
https://github.com/fvbock/endless 优雅重启
https://github.com/cosmtrek/air 外部工具,监控文件变动,重新编译

需要配合使用
moliliang
2022-09-15 16:28:38 +08:00
```golang
func runServer(addr string, engine *gin.Engine) error {
server := &http.Server{
Addr: addr,
Handler: engine,
WriteTimeout: 60 * time.Second,
ReadTimeout: 60 * time.Second,
}

// 平滑关闭
// 下面的 notify 是基于 signal.Notify 封装的,当监听到 kill ,会将 server shutdown
notify.Subscribe(func() {
timeoutCtx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
server.Shutdown(timeoutCtx)
})

return server.ListenAndServe()
}
```

上面的代码会监听 kill notify ,然后触发 shutdown ,shutdown 里面会停掉 listeners ,然后处理完所有已经连接的 socket 。

理论上可以在启动新进程的时候,来给旧进程发送 kill ,旧进程挂掉,新进程启动监听端口就好啦
Nasser
2022-09-15 16:53:58 +08:00
@treblex air 工具的文档上提示了:NOTE: This tool has nothing to do with hot-deploy for production.,不能用于生产环境
yyttrr
2022-09-15 16:59:10 +08:00
负载均衡加 k8s 的滚动部署策略
lankunblue
2022-09-15 17:10:26 +08:00
引入 k8s ?
dzdh
2022-09-15 17:13:11 +08:00
endless 足够
dzdh
2022-09-15 17:13:30 +08:00
reuseport 起新进程然后 kill 老服务
Nasser
2022-09-15 17:22:09 +08:00
@lankunblue 小产品,不足以引入 k8s😂
Nasser
2022-09-15 17:22:34 +08:00
@dzdh 好嘞,感谢,也是准备试试这个方案。
seth19960929
2022-09-15 18:03:09 +08:00
@Nasser
单机器的话, 写个脚本部署自动部署到不同的端口, 然后 nginx -s reload 监听新端口, 停止旧服务
多机器的话, 滚动更新就好了
PungentSauce
2022-09-15 18:07:42 +08:00
@Nasser 官网有方案,写了用
```go
routes.RegisterRoutes(engine)

srv := &http.Server{
Addr: ":" + port,
Handler: engine,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
logger.Info("Thousand-hand:listen " + port)
fmt.Printf("use http://localhost:%s\n", port)

go func() {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen: %s\n", err)
}
}()

quit := make(chan os.Signal)
signal.Notify(quit, os.Interrupt)
_ = <-quit
```


其实就是用一下 `quit := make(chan os.Signal)` 这个监听信号量 `endless ` 这个有点老了,已经好多年都不更新了,官网也写了
`https://gin-gonic.com/zh-cn/docs/examples/graceful-restart-or-stop/`,而且如果你用的 1.8 以上,注意 1.8 不是 1.18 只要你用的版本不是很老很老的版本,你用信号量处理就好。这个是防止请求过程中出现重启的情况。
ryalu
2022-09-15 18:21:27 +08:00
xiaoz
2022-09-15 18:50:49 +08:00
@Nasser #2 ,1 楼的意思是用了负载均衡的情况下,就是你后端启用了 2 个以上的服务。你在更新 A 的时候 B 依然可以提供服务,当 A 更新完毕后再更新 B ,这样最终完成所有后端服务的版本更新。但如果你后端是单机在跑的话就不太适合。
a132811
2022-09-15 19:40:17 +08:00
试下这个吧 reuseport+gracefulShutdown: https://github.com/jensneuse/GoGracefulReusePort

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/880300

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX