You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GoLang API特定端点限流问题:错误原因及解决方案咨询

Go API特定端点限流问题分析与解决方案

错误实现失效的原因

你第二段代码的核心问题是误用了ListenAndServeTLS的根Handler参数:

  • http.HandleFunc是往Go默认的ServeMux(路由多路复用器)中注册路由规则,但你最终将limit(sendPushNotificationToAllTokens)作为根Handler传给ListenAndServeTLS,这直接绕过了默认ServeMux的路由匹配逻辑。
  • 所有请求(不管访问/还是/notify)都会直接进入这个被限流包裹的sendPushNotificationToAllTokens函数,之前注册的/路径的Handler完全没有执行机会;同时,该函数仅处理/notify的业务逻辑,其他路径的请求也会得到错误的处理结果。

仅对/notify端点限流的可行方案

方案1:给单个Handler直接套限流中间件

利用ServeMux注册路由时,单独给/notify的Handler包裹限流逻辑,其他端点正常注册:

import (
    "log"
    "net/http"
    "time"

    "golang.org/x/time/rate"
)

var limiter = rate.NewLimiter(rate.Every(1*time.Hour/3), 1)

// 限流中间件,接收HandlerFunc并返回带限流逻辑的HandlerFunc
func limit(next http.HandlerFunc) http.HandlerFunc {
    return func(res http.ResponseWriter, req *http.Request) {
        if !limiter.Allow() {
            http.Error(res, http.StatusText(http.StatusTooManyRequests), http.StatusTooManyRequests)
            return
        }
        next.ServeHTTP(res, req)
    }
}

func main() {
    mux := http.NewServeMux()
    // 正常注册无需限流的端点
    mux.HandleFunc("/", createNewToken)
    // 给/notify端点的Handler套上限流中间件
    mux.HandleFunc("/notify", limit(sendPushNotificationToAllTokens))

    log.Fatal(http.ListenAndServeTLS(":5050", "localhost.crt", "localhost.key", mux))
}

方案2:在全局中间件中判断路径限流

如果需要保留全局中间件的结构,可以在中间件内部判断请求路径,仅对/notify应用限流:

import (
    "log"
    "net/http"
    "time"

    "golang.org/x/time/rate"
)

var limiter = rate.NewLimiter(rate.Every(1*time.Hour/3), 1)

// 全局中间件,仅对指定路径应用限流
func limit(next http.Handler) http.Handler {
    return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
        // 仅当请求路径为/notify时,触发限流判断
        if req.URL.Path == "/notify" && !limiter.Allow() {
            http.Error(res, http.StatusText(http.StatusTooManyRequests), http.StatusTooManyRequests)
            return
        }
        // 其他路径直接放行到下一个Handler
        next.ServeHTTP(res, req)
    })
}

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", createNewToken)
    mux.HandleFunc("/notify", sendPushNotificationToAllTokens)

    // 将整个mux传入限流中间件,由中间件决定是否限流
    log.Fatal(http.ListenAndServeTLS(":5050", "localhost.crt", "localhost.key", limit(mux)))
}

内容的提问来源于stack exchange,提问作者John Harrington

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 06:55:21