2. Go Web服务基础:标准库net/http快速搭建REST API、路由与中间件概念

在微服务压测与故障排查之前,必须掌握Go语言最核心的Web服务构建方式。Go标准库 net/http 提供了完整的HTTP服务器、路由分发与中间件扩展能力,无需依赖任何第三方框架即可搭建生产级REST API。本章将围绕“快速搭建-路由设计-中间件机制”三条主线,建立后续压测与修复的基础认知。

2.1 标准库net/http核心组件

net/http 包围绕三个核心接口构建Web服务:

组件 类型 职责
Handler interface 定义 ServeHTTP(ResponseWriter, *Request) 方法,处理每个HTTP请求
ServeMux struct 默认路由表,根据请求路径匹配对应的Handler
Server struct 监听端口、TLS配置、超时控制、连接管理
关键认知: Go的HTTP处理模型是 goroutine-per-request。每个请求在独立的goroutine中执行,天然支持高并发,这也是压测时性能表现优异的基础。

2.2 快速搭建REST API:三步法

以下代码演示如何使用标准库搭建一个包含 GET 和 POST 方法的用户资源REST API:

package main

import (
    "encoding/json"
    "log"
    "net/http"
)

type User struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
}

var users = []User{{ID: 1, Name: "Alice"}}

func handleUsers(w http.ResponseWriter, r *http.Request) {
    switch r.Method {
    case http.MethodGet:
        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(users)
    case http.MethodPost:
        var u User
        if err := json.NewDecoder(r.Body).Decode(&u); err != nil {
            http.Error(w, "Bad Request", http.StatusBadRequest)
            return
        }
        u.ID = len(users) + 1
        users = append(users, u)
        w.WriteHeader(http.StatusCreated)
        json.NewEncoder(w).Encode(u)
    default:
        http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
    }
}

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/api/users", handleUsers)

    server := &http.Server{
        Addr:    ":8080",
        Handler: mux,
    }
    log.Fatal(server.ListenAndServe())
}
实践要点:
  • 使用 http.Error() 返回标准错误状态码,便于压测时识别故障
  • 始终设置 Content-Type 响应头,避免客户端解析异常
  • ListenAndServe() 是阻塞调用,生产环境建议配合 signal.Notify 实现优雅关闭

2.3 路由匹配规则与路径模式

Go 1.22 之前的 ServeMux 仅支持固定路径和以 / 结尾的前缀匹配。Go 1.22 引入了增强路由模式,支持方法限定和路径参数:

模式 示例 匹配说明
固定路径 /api/users 精确匹配 /api/users
前缀匹配 /api/ 匹配所有以 /api/ 开头的路径
方法+路径 GET /api/users 仅匹配GET请求到该路径(Go 1.22+)
路径参数 /api/users/{id} 捕获路径段为参数 id(Go 1.22+)
压测陷阱: 使用前缀匹配 /api/ 时,/api/users 和 /api/users/ 会被视为不同路径。压测脚本中URL末尾的斜杠不一致会导致404错误,这是REST API故障的常见来源。

2.4 中间件概念与链式实现

中间件(Middleware)是包裹 Handler 的装饰器函数,用于在请求处理前后执行横切逻辑。Go标准库通过 func(http.Handler) http.Handler 模式实现中间件链。

典型中间件职责:

  • 日志记录:记录请求方法、路径、状态码、耗时
  • 恢复处理:捕获panic,返回500错误,防止服务崩溃
  • 请求限流:基于令牌桶或计数器控制并发
  • 认证鉴权:校验Token或API Key
  • 超时控制:通过 context.WithTimeout 限制请求处理时间
// 日志中间件示例
func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        log.Printf("[%s] %s %s", r.Method, r.URL.Path, r.RemoteAddr)
        next.ServeHTTP(w, r)
    })
}

// 恢复中间件示例
func recoveryMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        defer func() {
            if err := recover(); err != nil {
                log.Printf("panic recovered: %v", err)
                http.Error(w, "Internal Server Error", http.StatusInternalServerError)
            }
        }()
        next.ServeHTTP(w, r)
    })
}

// 链式组合
func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/api/users", handleUsers)

    var h http.Handler = mux
    h = loggingMiddleware(h)
    h = recoveryMiddleware(h)

    http.ListenAndServe(":8080", h)
}
中间件执行顺序: 先注册的中间件在外层,后注册的在内层。请求进入时按注册顺序执行,响应返回时逆序执行。压测中若中间件存在性能瓶颈(如日志同步写),会显著影响吞吐量。
net/http 请求处理流程与中间件链 HTTP 客户端 http.Server 日志中间件 (外层) 恢复中间件 (内层) Mux Handler (业务逻辑) /api/users 响应返回路径(逆序经过中间件) 流程说明 1. 客户端发送HTTP请求到 http.Server 2. 请求依次经过注册的中间件(日志 → 恢复) 3. ServeMux 根据路径匹配到对应的 Handler 4. 响应沿原路径逆序返回,中间件可修改响应头或记录状态

2.5 路由与中间件的压测关注点

在后续压测章节中,以下与路由和中间件相关的故障模式将反复出现:

故障模式 根因 压测表现
路由404 路径末尾斜杠不匹配、方法未允许 请求全部返回404,吞吐量骤降
中间件panic未恢复 缺少recovery中间件或恢复逻辑不完善 服务进程崩溃,连接中断
日志中间件阻塞 同步写日志导致IO等待 高并发下延迟飙升,超时增加
路由参数解析错误 Go版本低于1.22,使用 {id} 语法不兼容 部分请求返回500,压测结果不稳定
本章小结: 标准库 net/http 提供了完整的REST API构建能力,路由匹配规则和中间件链是后续压测脚本设计和故障注入的基础。建议读者在本地运行上述代码,使用 curl 或 wrk 进行简单验证,为第3章的压测工具选型做好准备。