我正在嘗試在 Go 中實作一個反向代理,它根據嵌入在 URL 中的某些租戶代理到不同主機的流量。實作如下所示:
type Offloader struct {
tenantHostMap map[string]string // Map a tenant to its host:port
tenantProxyMap map[string](*httputil.ReverseProxy) // Map a tenant to its reverse proxy
}
func (o *Offloader) OnCreate() {
// Tenants Map
o.tenantHostMap = make(map[string]string)
o.tenantProxyMap = make(map[string]*httputil.ReverseProxy)
o.PopulateTenantHostMap()
// Rx
http.HandleFunc("/", o.ServeHTTP)
go http.ListenAndServe(":5555", nil)
}
// ServeHTTP is the callback that is called each time a Http Request is received.
func (o *Offloader) ServeHTTP(w http.ResponseWriter, req *http.Request) {
incomingUrl := req.URL.RequestURI()
tenant := o.GetTenantFromUrl(incomingUrl)
if proxy, ok := o.tenantProxyMap[tenant]; ok {
proxy.ServeHTTP(w, req)
}
if remoteHostAddr, ok := o.tenantHostMap[tenant]; ok {
remoteUrl, err := url.Parse(fmt.Sprintf("http://%s", remoteHostAddr))
if err != nil {
return
}
proxy := httputil.NewSingleHostReverseProxy(remoteUrl)
o.tenantProxyMap[tenant] = proxy
proxy.ServeHTTP(w, req) // non blocking
} else {
panic("Unknown Tenant")
}
}
收到新的 HTTP 請求時,我從 URL 獲取租戶。如果這是我第一次看到這個租戶,我會創建一個新的 ReverseProxy,否則我會嘗試使用我之前創建并存盤在tenantProxyMap.
當我對此進行測驗時,我收到以下錯誤:
2022/04/05 12:31:01 http: proxy error: readfrom tcp ****: http: invalid Read on closed Body
2022/04/05 12:31:01 http: superfluous response.WriteHeader call from net/http/httputil.(*ReverseProxy).defaultErrorHandler (reverseproxy.go:190)
如果我為每個請求創建一個新的反向代理而不是重用相同的代理,則不會發生錯誤。
我認為代理是每個主機而不是每個請求(顧名思義),所以我想知道為什么會發生這個錯誤?
我知道我需要保護地圖免受并發讀/寫的影響,但目前這無關緊要。
謝謝,
uj5u.com熱心網友回復:
問題在于,在以前的代理已經存在的情況下,您首先將請求傳遞給該代理 - 然后仍然重新創建代理,并再次傳遞請求。換句話說:當 tentantProxyMap 已經為該租戶填充時,您正在為每個傳入請求發出兩個代理請求。
該ReverseProxy實作關閉了req.Body,因此第二次將請求傳遞給代理時,它會嘗試從已經關閉的主體中讀取。結果,您看到了http: invalid Read on closed Body錯誤。
您應該嘗試在代理請求后回傳,例如通過添加return:
if proxy, ok := o.tenantProxyMap[tenant]; ok {
proxy.ServeHTTP(w, req)
return
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/456625.html
上一篇:拒絕時未完成的承諾
