我编写了一个小的包装函数,该函数使用计数信号量概念来限制到特定处理程序的连接数(因为此处理程序很耗资源)。下面是实现相同功能的代码。
func LimitNumClients(f http.HandlerFunc, maxClients int) http.HandlerFunc {
// Counting semaphore using a buffered channel
sema := make(chan struct{}, maxClients)
return func(w http.ResponseWriter, req *http.Request) {
sema <- struct{}{}
defer func() { <-sema }()
f(w, req)
}
}
Run Code Online (Sandbox Code Playgroud)
然后将其包装在处理程序中,如下所示
Route{
"Test",
"GET",
/test,
LimitNumClients(testhandler, 5),
},
Run Code Online (Sandbox Code Playgroud)
现在,当任何新连接达到客户端限制时,我想以501错误回复。如何实现相同。
您可以使用非阻塞发送操作。如果成功,则继续正常操作,如果继续发送sema将阻塞,然后发送错误并从限制器返回而无需调用处理程序:
return func(w http.ResponseWriter, req *http.Request) {
select {
case sema <- struct{}{}:
default:
http.Error(w, "rate limit reached", 501)
return
}
defer func() { <-sema }()
f(w, req)
}
Run Code Online (Sandbox Code Playgroud)
还要注意的是信号是“限速达”的错误,返回的状态码应该是HTTP 429 Too Many Requests,见RFC 6585。
所以改为返回:
http.Error(w, "rate limit reached", http.StatusTooManyRequests)
Run Code Online (Sandbox Code Playgroud)