演示 HTTP 服务器的基础实现与优雅管理
Go HTTP服务器实现
实现了一个简单的HTTP服务器,它能够处理客户端请求并返回 JSON响应
1.主要功能
-
创建一个监听在本地127.0.0.1:8282的地址 HTTP 服务器
srv := &http.Server{ Addr: "127.0.0.1:8282", // 监听地址 Handler: nil, // 使用默认的多路复用器 }
-
设置了请求读取超时、响应写入超时和空闲连接超时
srv := &http.Server{ ReadTimeout: 10 * time.Second, // 请求读取超时 WriteTimeout: 10 * time.Second, // 响应写入超时 IdleTimeout: 120 * time.Second, // 空闲连接超时 }
-
注册了一个又处理函数 Myhandler,处理 /go路径的请求
http.HandleFunc("/go", Myhandler)
2.请求处理函数
-
打印客户端连接信息、请求方法、URL路劲和请求体内容
fmt.Println(r.RemoteAddr, "连接成功") fmt.Println("method:", r.Method) // 请求方式:GET POST DELETE PUT UPDATE fmt.Println("url:", r.URL.Path) // URL 路径
-
读取请求体数据并进行错误处理
body, err := io.ReadAll(r.Body) // 读取请求体并正确处理错误 if err != nil { http.Error(w, "读取请求体失败...", http.StatusBadRequest) }
-
设置响应头 JSON 格式,并且返回状态码 200
// 设置响应头为JSON格式,并返回状态码200 w.Header().Set("Content-Type", "application/json") // 设置 JSON 响应 w.WriteHeader(http.StatusOK) // 200
-
返回 JSON 响应 {"Message":"www.baidu.com"}
w.Write([]byte(`{"Message":"www.baidu.com"}`)) // 可自行写入自己想要的内容
3.自动请求测试
-
服务器启动后,立即向自己发送一个 GET 请求到 /go 路径
res, err := http.Get("http://127.0.0.1:8282/go")
-
接收并打印响应状态、响应头和响应体内容
fmt.Println(r.RemoteAddr, "连接成功") fmt.Println("method:", r.Method) // 请求方式:GET POST DELETE PUT UPDATE fmt.Println("url:", r.URL.Path) // URL 路径
4.优雅关闭机制
-
监听系统信号 (SIGINT 和 SIGTERM),用于除法服务器关闭
-
收到关闭信号后,使用 5 秒的超时上下文执行优雅关闭
-
确保现有请求处理完成后关闭服务器
quit := make(chan os.Signal, 1) // 创建通道 signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit fmt.Println("正在关闭服务器...") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { log.Fatalf("服务器关闭失败:%v", err) }
5.整体代码
package main import ( "context" "fmt" "io" "log" "net/http" "os" "os/signal" "syscall" "time" ) func Myhandler(w http.ResponseWriter, r *http.Request) { fmt.Println(r.RemoteAddr, "连接成功") fmt.Println("method:", r.Method) // 请求方式:GET POST DELETE PUT UPDATE fmt.Println("url:", r.URL.Path) // URL 路径 body, err := io.ReadAll(r.Body) // 读取请求体并正确处理错误 if err != nil { http.Error(w, "读取请求体失败...", http.StatusBadRequest) } defer r.Body.Close() // 优雅关闭 fmt.Println("body: ", string(body)) // 设置 JSON 响应头 w.Header().Set("Content-Type", "application/json") // 设置 JSON 响应 w.WriteHeader(http.StatusOK) // 设置返回有效的 JSON 格式 w.Write([]byte(`{"Message":"www.baidu.com"}`)) // 写入内容 } func main() { // 注册路由 http.HandleFunc("/go", Myhandler) srv := &http.Server{ Addr: "127.0.0.1:8282", // 监听地址 Handler: nil, // 使用默认的多路复用器 ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, IdleTimeout: 120 * time.Second, } go srv.ListenAndServe() // 启动服务器(后台运行) go func() { fmt.Println("服务器在启动 http://127.0.0.1:8282/") if err := srv.ListenAndServe(); err != nil { log.Fatal("ListenAndServe: ", err) } }() // 等待服务器(简单延迟) time.Sleep(1 * time.Second) // 发送自动请求 res, err := http.Get("http://127.0.0.1:8282/go") // 获取 http 地址 if err != nil { fmt.Println("请求失败:", err) return } defer res.Body.Close() // 防止资源泄露 // 200OK fmt.Println("响应状况:", res.Status) // 200OK fmt.Println("响应头部:", res.Header) // 响应体读取 body, err := io.ReadAll(res.Body) if err != nil { fmt.Println("读取响应失败...", err) return } fmt.Println("读取完毕...") fmt.Println(string(body)) // 优雅关闭服务器 quit := make(chan os.Signal, 1) // 创建通道 signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit // 发送通道 fmt.Println("正在关闭服务器...") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { log.Fatalf("服务器关闭失败:%v", err) } fmt.Println("服务器已关闭") }
6.技术亮点
-
优雅关闭机制
// 优雅关闭服务器 quit := make(chan os.Signal, 1) // 创建通道 signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit // 发送通道 fmt.Println("正在关闭服务器...") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { log.Fatalf("服务器关闭失败:%v", err) } fmt.Println("服务器已关闭")
说明:
-
使用 Go 的信号处理机制捕获系统终端信号 (SIGTERM)
-
通过 context.WithTimeout 创建一个带超时的上下文,确保服务器指定时间关闭
-
srv.Shudown() 方法实现了优雅关闭,允许完成当前请求而不接受新请求
-
这是生成环境中非常重要的特性,可避免服务中断导致的数据丢失
-
-
请求超时机制
srv := &http.Server{ ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, IdleTimeout: 120 * time.Second, }
说明:
-
设置了三种超时机制,防止慢客户端攻击和资源耗尽
-
ReadTimeout :限制读取请求头和请求体的时间
-
WriteTimeout:限制写入响应的时间
-
IdleTimeout : 限制空闲连接的存活时间
-
这些设置增强了服务器的安全性和稳定性
-
-
HTTP 服务器自测试机制
// 启动服务器(后台运行) go func() { fmt.Println("服务器在启动 http://127.0.0.1:8282/") if err := srv.ListenAndServe(); err != nil { log.Fatal("ListenAndServe: ", err) } }() // 等待服务器(简单延迟) time.Sleep(1 * time.Second) // 发送自动请求 res, err := http.Get("http://127.0.0.1:8282/go") // 获取 http 地址
说明:
-
服务器启动后立即进行测试,验证服务可用性
-
这是一种简单 ”冒烟测试“,确保服务能够正常响应请求
-
开发和部署过程中非常有用,可以快速检测配置错误
-
-
清晰的请求处理流程
func Myhandler(w http.ResponseWriter, r *http.Request) { fmt.Println(r.RemoteAddr, "连接成功") fmt.Println("method:", r.Method) // 请求方式:GET POST DELETE PUT UPDATE fmt.Println("url:", r.URL.Path) // URL 路径 body, err := io.ReadAll(r.Body) // 读取请求体并正确处理错误 if err != nil { http.Error(w, "读取请求体失败...", http.StatusBadRequest) } defer r.Body.Close() // 优雅关闭 fmt.Println("body: ", string(body)) // 设置 JSON 响应头 w.Header().Set("Content-Type", "application/json") // 设置 JSON 响应 w.WriteHeader(http.StatusOK) // 设置返回有效的 JSON 格式 w.Write([]byte(`{"Message":"www.baidu.com"}`)) // 写入内容 }
说明:
-
遵循了清晰的请求处理模式:接收请求 —> 处理数据 —> 返回响应
-
正确处理了请求体的读取和关闭,防止资源泄露
-
设置了适当的响应头和状态码,符合 HTTP 协议规范
-
-
使用 Go 的并发模型
go srv.ListenAndServe()
说明:
-
利用 Go 的 goroutine 轻量级线程特性,在后台启动 HTTP 服务器
-
这允许主程序继续执行其他任务 (自测试),而不必阻塞等待
-
体现了 Go 语言在并发编程方面简洁和高效性
-
总结
小项目的技术两点主要体现在服务器的可靠性、安全性和可测试性方面。特别是优雅关闭机制,请求超时控制,是构建生产级别 HTTP 服务不可或缺的特性。
本文地址:https://www.vps345.com/15227.html