如何停止Golang中的http.ListenAndServe gRPCEndpoint
如何停止Golang中的http.ListenAndServe gRPCEndpoint
你好,我遇到了一个问题,不知道如何通过 os.Interrupt 信号来正确停止 gRPC 的代理服务器。我自己是这样停止服务器的:
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt)
go func() {
<-c
log.Printf("Stopping the Result-Server %s:%d", conf.Host, conf.Port)
serv.GracefulStop()
lis.Close()
close(c)
}()
但我不知道如何对 gRPC 的 HTTP 代理做同样的事情,请告诉我该怎么做?我在这里不能使用 Shutdown(context.TODO())。
func NewHTTPServerStart(conf config.GRPCConfig, httpConf config.HTTPConfig) error {
mux := runtime.NewServeMux()
opts := []grpc.DialOption{grpc.WithInsecure()}
gRPCEndpoint := fmt.Sprintf("%s:%d", conf.Host, conf.Port)
err := pb.RegisterResultServiceHandlerFromEndpoint(context.Background(), mux, gRPCEndpoint, opts)
if err != nil {
return err
}
log.Printf("HTTP Proxy-server started on: %s:%d", httpConf.Host, httpConf.Port)
//这里是我在收到 Interrupt 信号时如何完成它
return http.ListenAndServe(fmt.Sprintf("%s:%d", httpConf.Host, httpConf.Port), mux)
}
更多关于如何停止Golang中的http.ListenAndServe gRPCEndpoint的实战教程也可以访问 https://www.itying.com/category-94-b0.html
使用 close net.Listener,示例:
非常感谢,你帮了我大忙
更多关于如何停止Golang中的http.ListenAndServe gRPCEndpoint的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
n0kk:
ListenAndServe
使用 close net.Listener,示例:
// listen
ln, err := net.Listen("tcp","...")
... if err
go func() {
// accept signal
ln.Close()
}()
// start server
http.Serve(ln, mux)
要停止 http.ListenAndServe 启动的 gRPC HTTP 代理服务器,你需要创建一个可关闭的 http.Server 实例,并在收到中断信号时调用其 Shutdown 方法。以下是修改后的代码示例:
func NewHTTPServerStart(conf config.GRPCConfig, httpConf config.HTTPConfig) error {
mux := runtime.NewServeMux()
opts := []grpc.DialOption{grpc.WithInsecure()}
gRPCEndpoint := fmt.Sprintf("%s:%d", conf.Host, conf.Port)
err := pb.RegisterResultServiceHandlerFromEndpoint(context.Background(), mux, gRPCEndpoint, opts)
if err != nil {
return err
}
server := &http.Server{
Addr: fmt.Sprintf("%s:%d", httpConf.Host, httpConf.Port),
Handler: mux,
}
// 创建信号通道
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt)
// 启动服务器
go func() {
log.Printf("HTTP Proxy-server started on: %s:%d", httpConf.Host, httpConf.Port)
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("HTTP server error: %v", err)
}
}()
// 等待中断信号
<-stop
log.Printf("Stopping HTTP Proxy-server %s:%d", httpConf.Host, httpConf.Port)
// 优雅关闭服务器
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
log.Printf("HTTP server shutdown error: %v", err)
}
return nil
}
对于你的主函数,可以这样整合两个服务器的关闭:
func main() {
// 初始化配置...
// 启动 gRPC 服务器
serv := grpc.NewServer()
pb.RegisterResultServiceServer(serv, &resultServer{})
lis, err := net.Listen("tcp", fmt.Sprintf("%s:%d", conf.Host, conf.Port))
if err != nil {
log.Fatal(err)
}
// 启动 HTTP 代理服务器
go func() {
if err := NewHTTPServerStart(conf, httpConf); err != nil {
log.Fatal(err)
}
}()
// 启动 gRPC 服务器
go func() {
log.Printf("gRPC server started on: %s:%d", conf.Host, conf.Port)
if err := serv.Serve(lis); err != nil {
log.Fatal(err)
}
}()
// 等待中断信号
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
<-c
log.Printf("Stopping servers...")
// 先关闭 HTTP 代理服务器
// 这里需要传递 server 实例,可以将其作为返回值或全局变量
// 然后关闭 gRPC 服务器
serv.GracefulStop()
lis.Close()
}
这样,当收到 os.Interrupt 信号时,HTTP 代理服务器会通过 Shutdown 方法优雅关闭,而 gRPC 服务器会通过 GracefulStop 方法关闭。两个服务器都会处理完当前请求后再停止。

