2 回答

TA貢獻1993條經驗 獲得超6個贊
服務器在serveHandler返回時關閉響應。
一種解決方法是阻塞serveHandler直到請求被處理。在以下代碼中,worker 關閉done以表示請求已完成。處理程序等待done關閉。
type clientRequest struct {
r *http.Request
w http.ResponseWriter
done chan struct{} // <-- add this line
}
func serveHandler(w http.ResponseWriter, r *http.Request) {
var newRequest = new(clientRequest)
newRequest.r = r
newRequest.w = w
newRequest.done = make(chan struct{})
reqChannel <- newRequest // send the new request to the request channel
fmt.Printf("Sent request to reqChannel for URL: %q\n", html.EscapeString(r.URL.Path))
<-newRequest.done // wait for worker goroutine to complete
}
func processRequest(instanceNbr int) {
fmt.Printf("processRequest started for instance #%d\n", instanceNbr)
for theRequest := range reqChannel { // receive requests from the channel until it is closed
fmt.Printf("Got request from reqChannel for URL: %q\n", html.EscapeString(theRequest.r.URL.Path))
fmt.Fprintf(theRequest.w, "processRequest instance #%d: URL is %q", instanceNbr, html.EscapeString(theRequest.r.URL.Path))
if f, ok := theRequest.w.(http.Flusher); ok {
f.Flush()
}
close(theRequest.done) // signal handler that request is complete
}
}
如果目標是限制活動處理程序的數量,那么您可以使用通道作為計數信號量來限制活動處理程序 goroutine 的數量:
var reqChannel = make(chan struct{}, MaxRequests)
func serveHandler(w http.ResponseWriter, r *http.Request) {
reqChannel <- struct{}{}
// handle the request
<-reqChannel
}
請注意,服務器在每個連接的 goroutine 中運行處理程序。
更簡單的是只編寫一個處理程序。大多數服務器不需要限制請求處理程序的并發性。

TA貢獻1817條經驗 獲得超6個贊
您的答案在net/http 代碼的這一部分:
// HTTP cannot have multiple simultaneous active requests.[*]
// Until the server replies to this request, it can't read another,
// so we might as well run the handler in this goroutine.
// [*] Not strictly true: HTTP pipelining. We could let them all process
// in parallel even if their responses need to be serialized.
serverHandler{c.server}.ServeHTTP(w, w.req)
if c.hijacked() {
return
}
w.finishRequest()
后ServeHTTP返回時,請求完成。
所以你有幾個解決方案:
放棄你的工人模式并完成工作 serveHandler
在完成之前等待請求被完全處理serveHandler,如下所示:
(在我的本地測試)
type clientRequest struct {
r *http.Request
w http.ResponseWriter
done chan struct{}
}
func serveHandler(w http.ResponseWriter, r *http.Request) {
var newRequest = new(clientRequest)
newRequest.r = r
newRequest.w = w
newRequest.done = make(chan struct{})
reqChannel <- newRequest // send the new request to the request channel
fmt.Printf("Sent request to reqChannel for URL: %q\n", html.EscapeString(r.URL.Path))
<-newRequest.done // wait for the worker to finish
}
func processRequest(instanceNbr int) {
fmt.Printf("processRequest started for instance #%d\n", instanceNbr)
for theRequest := range reqChannel { // receive requests from the channel until it is closed
fmt.Printf("Got request from reqChannel for URL: %q\n", html.EscapeString(theRequest.r.URL.Path))
// xxx this isn't working:
fmt.Fprintf(theRequest.w, "processRequest instance #%d: URL is %q", instanceNbr, html.EscapeString(theRequest.r.URL.Path))
if f, ok := theRequest.w.(http.Flusher); ok {
f.Flush()
}
theRequest.done <- struct{}{}
}
}
- 2 回答
- 0 關注
- 277 瀏覽
添加回答
舉報