Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/kubernetes/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 谷歌云HTTP(S)负载平衡器不取消与后端的连接_Go_Kubernetes_Google Kubernetes Engine_Http 1.1_Google Cloud Load Balancer - Fatal编程技术网

Go 谷歌云HTTP(S)负载平衡器不取消与后端的连接

Go 谷歌云HTTP(S)负载平衡器不取消与后端的连接,go,kubernetes,google-kubernetes-engine,http-1.1,google-cloud-load-balancer,Go,Kubernetes,Google Kubernetes Engine,Http 1.1,Google Cloud Load Balancer,我有一个Google Kubernetes引擎集群,在几个带有NodePorts的pod中,所有这些都通过一个Ingress公开,它创建了一个HTTP负载平衡器(LB)。我正在使用自定义域与谷歌管理的SSL证书的LB 我的后端是一个用Go编写的HTTP服务器,使用它的“net/HTTP”包。它使用带LB的MTL自签名证书(Google的HTTP LB接受MTL的任何证书) 除了一种情况外,一切都正常工作,即客户端与LB创建HTTP 1.1连接,然后取消请求。这将取消客户端和LB之间的连接,但LB

我有一个Google Kubernetes引擎集群,在几个带有
NodePort
s的pod中,所有这些都通过一个
Ingress
公开,它创建了一个HTTP负载平衡器(LB)。我正在使用自定义域与谷歌管理的SSL证书的LB

我的后端是一个用Go编写的HTTP服务器,使用它的
“net/HTTP”
包。它使用带LB的MTL自签名证书(Google的HTTP LB接受MTL的任何证书)

除了一种情况外,一切都正常工作,即客户端与LB创建HTTP 1.1连接,然后取消请求。这将取消客户端和LB之间的连接,但LB将保持与我的后端的开放连接,直到服务器超时

我的用例要求打开请求,甚至需要几个小时,所以我的服务器有巨大的超时值。请求内部的业务逻辑正确地使用了请求的
上下文
,并考虑了客户端是否取消了请求

如果客户端发出HTTP2请求并取消它(即,到我的后端的整个连接被取消),则一切正常

下面是一个模拟可取消长期运行任务的Go处理程序示例:

func handleLongRunningTask(w http.ResponseWriter, r *http.Request) {
    ctx := r.Context()
    t := time.Now()

    select {
    case <-ctx.Done():
        log.Println("request canceled")
    case <-time.After(30 * time.Second):
        log.Println("request finished")
    }
    log.Printf("here after: %v\n", time.Since(t))

    w.WriteHeader(http.StatusOK)
}
这并不是:

curl -v --http1.1 'https://example.com/long_running_task'
无论
NodePort
是HTTPS还是HTTP2,LB对于客户端取消的请求都有完全相同的行为

我试着用Go 1.14.4和1.13.12编译服务器,结果是一样的

这是Kubernetes、Ingres、Google Kubernetes引擎、Google的HTTP负载平衡器、Go的HTTP服务器中的一个bug吗?还是我缺少了HTTP 1.1的某些功能?可能有什么问题,我如何解决


…不可能知道后端的HTTP版本,因此我可以拒绝所有HTTP 1.1请求。LB在与其后端通信时始终使用相同的HTTP版本,无论客户端的HTTP版本如何。

根据您的描述,问题可能出现在和后端之间,因为

我的看法是,您看到了协议版本之间的这种差异,因为它们都处理连接持久性

对于HTTP2,连接将打开。但对于HTTP1.1,指定终止:

HTTP/1.1服务器可能假设HTTP/1.1客户端打算维护持久连接,除非在请求中发送了包含连接令牌“close”的连接头。如果服务器选择在发送响应后立即关闭连接,则应发送一个包含连接令牌close的连接头

这也许可以解释为什么HTTP1.1遵循了标准,而HTTP2没有

我建议在您想要终止连接时尝试主动发送终止头。安:

此外,似乎有一些成功的案例将您的集群转变为现实,因为它消除了kube代理连接管理

最后,你可能处于一个非常特殊的情况,值得单独评估。您可能希望尝试使用向GKE团队发送一些复制步骤


我希望这会有所帮助。

我已经尝试了HTTP(S)1.1和HTTP2后端,即使在客户端发出HTTP 1.1请求,LB向后端发出HTTP2请求(BE)的情况下,行为也是一样的,即当客户端取消其请求时,LB和BE之间的HTTP2连接不会终止。我的用例是特定的,因为在客户端取消请求之前,我的服务器一直在处理。因此,
连接
标题已退出游戏。我需要在LB和BE之间进行适当的请求取消。强制所有客户机使用HTTP2仍然是不可能的:(我打开了一个我忘记的问题;我的集群是VPC原生的。
curl -v --http1.1 'https://example.com/long_running_task'
func (m *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    log.Printf("HTTP request from %s", r.RemoteAddr)
    // Add this header to force to close the connection after serving the request.
    w.Header().Add("Connection", "close")
    fmt.Fprintf(w, "%s", m.hostname)
}