go - 正常应用程序关闭中的通道和信号使用
问题描述
下面的示例处理此处记录的正常服务器关闭。基于我在阅读其他帖子和示例后的研发工作,我想出了这篇实际上优雅地关闭服务器的工作。但是,由于我对 Golang 的经验/知识非常有限,我无法证明我是否正确使用了通道和信号。我只是想避免 Goroutine 泄漏和其他看不见的潜在问题。有人可以告诉我这篇作品是否是惯用的 Go 代码和通道和信号的使用吗?
内部/服务器/server.go
package server
import (
"net/http"
)
type Server struct {
*http.Server
}
func NewServer() Server {
return Server{
&http.Server{Addr: ":8080", Handler: nil},
}
}
func (s Server) Start() error {
if err := s.ListenAndServe(); err != http.ErrServerClosed {
return err
}
return nil
}
cmd/api/main.go
package main
import (
"api/internal/app"
"api/internal/server"
"context"
"fmt"
"os"
"os/signal"
"syscall"
)
func main() {
// Some other bootstrapping and configuration code here ...
// ....
fmt.Printf("app starting")
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
ctx, cancel := context.WithCancel(context.Background())
go listenSignals(cancel, sigChan)
if err := app.New(server.NewServer()).Start(ctx); err != nil {
panic(err)
}
fmt.Print("app shutdown completed")
}
func listenSignals(cancel context.CancelFunc, sigChan chan os.Signal) {
sig := <-sigChan
fmt.Printf("app shutdown started with %v signal", sig)
cancel()
}
内部/app/api.go
package app
import (
"api/internal/server"
"context"
"errors"
"fmt"
"time"
)
type App struct {
srv server.Server
}
func New(srv server.Server) App {
return App{srv: srv}
}
func (app App) Start(ctx context.Context) error {
doneChan := make(chan struct{})
go shutdown(ctx, doneChan, app)
// Start HTTP server
if err := a.srv.Start(); err != nil {
return errors.New("failed to start HTTP server")
}
// Start DB server
// ...
<-doneChan
return nil
}
func shutdown(ctx context.Context, doneChan chan<- struct{}, app App) {
<-ctx.Done()
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Shutdown HTTP server
err := app.srv.Shutdown(ctx)
if err != nil {
fmt.Print("some active HTTP connections are interrupted at shutdown")
} else {
fmt.Print("no HTTP connections are interrupted at shutdown")
}
// Shutdown DB server
// ...
close(doneChan)
}
输出
INFO[0000] app starting
^C
INFO[0001] app shutdown started with interrupt signal
INFO[0001] no HTTP connections are interrupted at shutdown
INFO[0001] the application shutdown has been completed
INFO[0000] app starting
^C
INFO[0001] app shutdown started with interrupt signal
INFO[0001] some active HTTP connections are interrupted at shutdown
INFO[0001] the application shutdown has been completed
编辑
我做了一些 goroutine 分析,结果如下。我不确定结果是否正常!需要您的意见。
- 单个请求的响应返回6 for
runtime.NumGoroutine()
-pprof 堆栈跟踪在此处。但是,如果我发送 10 个并发请求,则它介于17和22之间。
我不知道如何阅读这个所以两个问题:
- 一个请求 6 个 goroutine 正常吗?
- 多个并发请求的增加是否正常?
- 我认为这很正常,因为我正在使用
httprouter
它,它会针对每个请求启动。
- 我认为这很正常,因为我正在使用
解决方案
推荐阅读
- docker - 在本地主机上连接到 Docker 容器中的服务器非常慢
- mysql - 什么是mysql中的“DEFAULT((-1))FOR”等价物
- dialogflow-es - DialogFlow 中用于电子邮件验证的 OTP
- amazon-web-services - ELB 能否用于通过 URL 将流量路由到其他托管服务?
- java - 如何将 XML 转换为忽略父子关系的哈希映射
- d3.js - 如何定义 d3 数据路径和数据字段分隔符
- java - 面板中组件的对齐方式
- python - 检查数据集的行是否也在另一个数据集中并提取索引
- sql-server - 是否可以对多行查询运行 SQL 注入攻击?
- android - 如何在 Gmail 中制作 webview?