Golang中使用超时、截止时间和上下文取消构建健壮的net/http服务器
Golang中使用超时、截止时间和上下文取消构建健壮的net/http服务器

使用超时、截止时间和上下文取消构建健壮的 Go net/http 服务器
当谈到超时时,有两种人:一种是知道它们有多棘手的人,另一种是尚未发现这一点的人。 尽管很棘手,但超时是我们所处的互联世界中的一个现实。就在我写这篇文章的时候,在另一…
也许你们中的一些人会觉得这很有趣 🙂
更多关于Golang中使用超时、截止时间和上下文取消构建健壮的net/http服务器的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于Golang中使用超时、截止时间和上下文取消构建健壮的net/http服务器的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go中构建健壮的HTTP服务器时,正确设置超时、截止时间和上下文取消至关重要。以下是关键配置示例:
package main
import (
"context"
"net/http"
"time"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// 模拟长时间运行的操作
ctx := r.Context()
select {
case <-time.After(5 * time.Second):
w.Write([]byte("请求完成"))
case <-ctx.Done():
// 客户端取消或超时
http.Error(w, "请求超时", http.StatusRequestTimeout)
}
})
server := &http.Server{
Addr: ":8080",
Handler: mux,
ReadTimeout: 5 * time.Second, // 读取整个请求的超时
WriteTimeout: 10 * time.Second, // 写入响应的超时
IdleTimeout: 120 * time.Second, // 空闲连接超时
}
// 使用带超时的上下文启动服务器
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// 优雅关闭
go func() {
<-ctx.Done()
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 5*time.Second)
defer shutdownCancel()
server.Shutdown(shutdownCtx)
}()
server.ListenAndServe()
}
对于处理程序级别的超时控制:
func handlerWithTimeout(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
defer cancel()
// 将上下文传递给下游操作
resultCh := make(chan string, 1)
go func() {
resultCh <- expensiveOperation(ctx)
}()
select {
case result := <-resultCh:
w.Write([]byte(result))
case <-ctx.Done():
http.Error(w, "处理超时", http.StatusGatewayTimeout)
}
}
func expensiveOperation(ctx context.Context) string {
// 检查上下文是否已取消
if err := ctx.Err(); err != nil {
return ""
}
// 执行耗时操作,定期检查上下文
for i := 0; i < 10; i++ {
select {
case <-ctx.Done():
return "已取消"
case <-time.After(500 * time.Millisecond):
// 继续处理
}
}
return "完成"
}
对于客户端请求,设置请求超时:
func makeRequest() {
client := &http.Client{
Timeout: 10 * time.Second, // 整个请求的超时时间
}
req, _ := http.NewRequest("GET", "http://example.com", nil)
// 设置请求级别的超时上下文
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
req = req.WithContext(ctx)
resp, err := client.Do(req)
if err != nil {
// 处理超时或取消错误
return
}
defer resp.Body.Close()
}
这些配置确保了服务器在面对慢客户端、网络问题或资源竞争时能够保持稳定。关键点包括:设置适当的服务器级超时、在处理程序中使用上下文传播取消信号、以及为客户端请求配置超时。

