golang写的web application 怎么优雅的更新?
小浩·2016-12-23 01:56:45·564次阅读·发布于 Go问答

像php这种解释型语言开发的web application ,更新代码的时候都是直接push就可以了,不会中断服务,但是像golang这种编译型的语言更新完代码还要编译

我的问题是怎么在不中断服务的前提下更新golang web application?通常的做法有哪些?还请各位不吝赐教

用Kubernetes对外提供服务,起多个实例,然后用CI/CD系统每次的提交都打成镜像,那么每次你做的事情就是:推代码然后滚动升级Kubernetes上你的应用就可以了。

2022-01-21 12:52:48

一般都是集群了啊,杀一个重启一个

2022-01-21 12:52:46

首先, 肯定一下 nginx 方法比较成熟, 配置简单.

不过, 我用更简单的方法, 只适用于 macOS / linux :

package main import ( "fmt" "github.com/kavu/go_reuseport" "golinksmart/config" "golinksmart/handler" "runtime" ) func main() { runtime.GOMAXPROCS(runtime.NumCPU()) // 使用 reuseport 进行连接监听, 以便使用 taskset 来绑定 CPU listener, err := reuseport.Listen("tcp", config.Configuration.Server.AaaPort) if err != nil { panic(err) } //interrupt := make(chan os.Signal, 1) //signal.Notify(interrupt, os.Interrupt, os.Kill, syscall.SIGTERM) handler.AaaServer(listener) fmt.Println("AAA listening on ", config.Configuration.Server.AaaPort) /** for { select { case killSignal := <-interrupt: fmt.Println("Got signal:", killSignal) fmt.Println("Stoping listening on ", listener.Addr()) listener.Close() } } */ }

代码见上面, 其中这个
handler.AaaServer(listener)
其实是下面代码的封装
http.Serve(listener, router)

由于对端口侦听是 reuseport 所以, go 的 http server 可以运行多个实例, 只要更新其中某一个就完成灰度更新了.

2022-01-21 12:52:46

可以用golang自己实现,但是只在类unix系统中有用,利用系统信号量和启动子进程,将旧的socket描述符传递给新的socket描述符,github已经有不少这样的库,很多golang的http框架也实现了。这种实现叫“graceful restart”或者“zero downtime server”,实现不中断服务更新。
具体参考可以看看这些项目和几篇文章:

2022-01-21 12:51:05

1楼正解,补充一下,灰度更新可以用openresty,国人的热门项目。

2022-01-21 12:51:04

web application基本上都是短连接的应用,所以采用Nginx的upsteam是更好的方式

2022-01-21 12:51:03

利用graceful restart,更新二进制文件后发送指令重启服务器

2022-01-21 12:51:03

一般的做法都是在webapp前加一层nginx之类的,由nginx的upsteam group搞定灰度更新的问题,例如可新、旧版本webapp同时工作一段时间,稳定后去掉旧版本只留新版本,如此类推。

以上。

2022-01-21 12:51:03
发起回帖
未登录,登录后可以回帖