友情提示:该结论当前只在Golang http server上测试过,其他语言编写的http server可以参考测试方法进行验证。
测试:
- 使用golang写一个支持优雅关闭的http server,示例代码如下:
package main
import (
"context"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
// handler 处理 HTTP 请求
func handler(w http.ResponseWriter, r *http.Request) {
time.Sleep(20 * time.Second)
fmt.Fprintf(w, "Hello, World!")
}
func main() {
// 创建 HTTP 服务器
mux := http.NewServeMux()
mux.HandleFunc("/", handler)
server := &http.Server{
Addr: ":8080",
Handler: mux,
}
// 创建一个通道来监听系统信号
stop := make(chan os.Signal, 1)
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
// 启动服务器
go func() {
fmt.Println("Server is running on :8080")
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
fmt.Printf("ListenAndServe error: %v\n", err)
}
}()
// 阻塞等待系统信号
<-stop
fmt.Println("Shutting down server...")
// 创建超时上下文用于关闭服务器
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
fmt.Printf("Server forced to shutdown: %v\n", err)
} else {
fmt.Println("Server exited properly")
}
}
- 使用http客户端请求
http://127.0.0.1:8080
,客户端不限,比如:curl、telnet、浏览器等等 - 使用wireshark抓包,查看服务端与客户端之间的通信
结论:
- [http-client-1] 如果在http server Shutdown之前发起的请求,http server会继续处理,如果在timeout时间内处理完成则正常响应(图中未给出),如果timeout时间内还未处理完成则http server强制使用FIN终止连接,应用层的表现,以curl工具为例:
$ curl -v http://127.0.0.1:8080/
* Trying 127.0.0.1:8080...
* Connected to 127.0.0.1 (127.0.0.1) port 8080
> GET / HTTP/1.1
> Host: 127.0.0.1:8080
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
* Empty reply from server
* Closing connection
curl: (52) Empty reply from server
- [http-client-2] 如果客户端在http server Shutdown过程中发起请求,则http server不会处理该请求,直接以RST包终止连接,应用层的表现,以curl工具为例:
$ curl -v http://127.0.0.1:8080/
* Trying 127.0.0.1:8080...
* connect to 127.0.0.1 port 8080 from 127.0.0.1 port 61852 failed: Connection refused
* Failed to connect to 127.0.0.1 port 8080 after 0 ms: Couldn't connect to server
* Closing connection
curl: (7) Failed to connect to 127.0.0.1 port 8080 after 0 ms: Couldn't connect to server
- [http-client-3] 如果客户端在http server Shutdown之前建立了连接,但是在Shutdown之前没有发起http请求或者所有请求都已经完成,那么http server会立即使用FIN包终止该连接。也就是说http server Shutdown时,会关闭空闲连接
时序图:更清晰的展示http server优雅关闭的过程和行为
image.png