在高并发Http服务中, 更新应用时会出现短暂的connect resuse和部分http请求数据丢失问题。这样在有些服务中是不可容忍的,所有需要Http服务做平滑重启处理。
1. 开源解决方案
2. 方案测试
1. grace
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package main
import ( "fmt" "net/http" "os" "time"
"github.com/facebookgo/grace/gracehttp" )
var startTime time.Time
type HttpHandle int
func (h HttpHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) { time.Sleep(time.Second * 10) w.Write([]byte(fmt.Sprintf("pid:%v, startTime:%v\n", os.Getpid(), startTime))) }
func main() { startTime = time.Now() gracehttp.Serve( &http.Server{Addr: ":7070", Handler: new(HttpHandle)}, ) }
|
测试结果:
2. endless
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package main
import ( "fmt" "net/http" "os" "time"
"github.com/fvbock/endless" )
var startTime time.Time
type HttpHandle int
func (h HttpHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) { time.Sleep(time.Second * 10) w.Write([]byte(fmt.Sprintf("pid:%v, startTime:%v\n", os.Getpid(), startTime))) }
func main() { startTime = time.Now() endless.ListenAndServe(":7070", new(HttpHandle)) }
|
测试结果:
3. overseer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| package main
import ( "fmt" "net/http" "os" "time"
"github.com/jpillora/overseer" )
var startTime time.Time
type HttpHandle int
func (h HttpHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) { time.Sleep(time.Second * 10) w.Write([]byte(fmt.Sprintf("pid:%v, startTime:%v\n", os.Getpid(), startTime))) }
func realMain(state overseer.State){ startTime = time.Now() http.Serve(state.Listener, new(HttpHandle)) }
func main() { overseer.Run(overseer.Config{ Program: realMain, Address: ":7070", }) }
|
测试结果:
3. 选择
从上面测试可以看出三个软件都能满足Http服务平滑启动的功能;
grace endless功能实现方式:两个都是以开启子进程来加载新可执行程序, 父进程处理完成当前请求后退出;
overseer功能实现方式:启动后会有两个进程[管理进程/功能进程],重启过程中, 管理进程后启动新子进程来执行新可执行程序, 旧子进程处理完成当前请求后退出;
overseer能够兼容进程管理软件(systemd, upstart, supervisor, etc),而grace endless不支持