我正在嘗試在 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 Body2022/04/05 12:31:01 http: superfluous response.WriteHeader call from net/http/httputil.(*ReverseProxy).defaultErrorHandler (reverseproxy.go:190)如果我為每個請求創建一個新的反向代理而不是重復使用相同的代理,則不會發生錯誤。我認為代理是按主機而不是按請求(顧名思義),所以我想知道為什么會發生此錯誤?我知道我需要保護地圖免受并發讀/寫的影響,但目前這無關緊要。
1 回答
尚方寶劍之說
TA貢獻1788條經驗 獲得超4個贊
問題是,在以前的代理已經存在的情況下,您首先將請求傳遞給它 - 然后仍然重新創建代理,并再次傳遞請求。換句話說:當 tentantProxyMap 已經為該租戶填充時,您正在為每個傳入請求發出兩個代理請求。
該ReverseProxy實現會關閉req.Body,因此您第二次將請求傳遞給代理時,它會嘗試從已經關閉的主體中讀取。結果您看到了http: invalid Read on closed Body錯誤。
您應該嘗試在代理請求后返回,例如通過添加return:
if proxy, ok := o.tenantProxyMap[tenant]; ok {
proxy.ServeHTTP(w, req)
return
}
- 1 回答
- 0 關注
- 132 瀏覽
添加回答
舉報
0/150
提交
取消
