在Golang开发的微服务架构中,滚动升级是避免服务中断的重要部署策略,它通过逐步替换旧版本实例的方式完成版本迭代,保证升级过程中业务请求可以正常处理。Golang本身提供了信号处理、优雅关闭等能力,结合容器编排工具可以很方便地实现微服务滚动升级。

Golang微服务滚动升级的核心前提
要实现平滑的滚动升级,Golang微服务本身需要满足两个基础条件,否则升级过程中很容易出现请求丢失的问题。
1. 实现优雅关闭逻辑
当容器编排工具需要终止旧版本实例时,需要先通知服务停止接收新请求,处理完存量请求后再退出。Golang可以通过监听系统信号实现这个逻辑。
package main
import (
"context"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
func main() {
// 创建HTTP服务
mux := http.NewServeMux()
mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
})
mux.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) {
// 模拟业务处理耗时
time.Sleep(2 * time.Second)
w.Write([]byte("response from v1"))
})
server := &http.Server{
Addr: ":8080",
Handler: mux,
}
// 启动服务
go func() {
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
fmt.Printf("server start failed: %vn", err)
}
}()
// 监听终止信号
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
fmt.Println("receive shutdown signal, start graceful shutdown")
// 设置5秒的优雅关闭超时时间
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
fmt.Printf("server shutdown failed: %vn", err)
}
fmt.Println("server exited successfully")
}
2. 提供健康检查接口
容器编排工具需要通过健康检查判断实例是否就绪,只有新实例健康检查通过后才会将流量切换到新实例,同时只有旧实例健康检查失败后才彻底终止旧实例。上面的代码中已经实现了/health接口,返回200状态码表示实例正常。
基于Kubernetes的滚动升级实现
Kubernetes原生支持滚动升级策略,只需要正确配置Deployment的升级参数,就可以结合Golang微服务的特性完成平滑升级。
Deployment配置示例
下面是一个Golang微服务的Deployment配置,包含了滚动升级的相关参数:
apiVersion: apps/v1
kind: Deployment
metadata:
name: golang-microservice
spec:
replicas: 3
# 滚动升级策略配置
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 最多可超出期望副本数的实例数
maxUnavailable: 0 # 升级过程中最多不可用的实例数
selector:
matchLabels:
app: golang-microservice
template:
metadata:
labels:
app: golang-microservice
spec:
containers:
- name: service
image: ipipp.com/golang-microservice:v1 # 初始版本镜像
ports:
- containerPort: 8080
# 就绪健康检查
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5 # 容器启动后等待5秒开始检查
periodSeconds: 3 # 每3秒检查一次
# 存活健康检查
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
# 优雅关闭等待时间,需要大于服务优雅关闭的超时时间
terminationGracePeriodSeconds: 10
升级操作流程
当需要升级到新版本时,只需要修改Deployment的镜像版本,执行以下命令即可触发滚动升级:
kubectl set image deployment/golang-microservice service=ipipp.com/golang-microservice:v2
Kubernetes会按照配置的策略执行升级:先启动1个新版本实例(maxSurge=1),等新实例就绪后,再终止1个旧版本实例,重复这个过程直到所有旧实例都被替换成新版本实例。整个过程中因为maxUnavailable=0,所以始终有3个实例在提供服务,不会出现请求中断。
滚动升级的注意事项
- 新版本实例的就绪检查一定要准确,避免未初始化完成的实例接收流量导致请求失败。
- terminationGracePeriodSeconds要设置得比Golang服务的优雅关闭超时时间长,保证旧实例有足够时间处理存量请求。
- 如果微服务有状态,需要提前做好状态迁移或者兼容处理,避免新旧版本实例同时运行时出现数据不一致问题。
- 可以通过kubectl rollout status deployment/golang-microservice命令查看升级进度,如果出现问题可以用kubectl rollout undo命令回滚到上一个版本。
Golang微服务滚动升级Kubernetes修改时间:2026-07-21 19:00:33