为了账号安全,请及时绑定邮箱和手机立即绑定

每个主机的 Golang ReverseProxy

每个主机的 Golang ReverseProxy

Go
冉冉说 2022-11-28 10:36:25
我正在尝试在 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

}


查看完整回答
反对 回复 2022-11-28
  • 1 回答
  • 0 关注
  • 143 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号