RestSharp:底层连接已关闭:服务器关闭了预期保持活动状态的连接

Posted

技术标签:

【中文标题】RestSharp:底层连接已关闭:服务器关闭了预期保持活动状态的连接【英文标题】:RestSharp: The underlying connection was closed: A connection that was expected to be kept alive was closed by the server 【发布时间】:2014-02-22 05:20:49 【问题描述】:

我使用 RestSharp 作为底层 HTTP 客户端库,在黑盒服务上创建压力/吞吐量测试客户端。 Threadpool 和 Servicepoint 连接限制已提升到 5000,但这不应该太担心,因为我们正在测试每秒大约 500-1000 个请求。高分辨率(微秒)计时器组件用于以我们想要测试的速率抛出请求。

RestSharp 代码大致是这样的

restClient.ExecuteAsync(postRequest, res =>
                
                    stopwatch.Stop();

                    lock (this.countLocker)
                    
                        this.roundTrips.Add(stopwatch.ElapsedMilliseconds);

                        if (res.ResponseStatus == ResponseStatus.Completed &&
                            (res.StatusCode == HttpStatusCode.OK ||
                            res.StatusCode == HttpStatusCode.NoContent))
                        
                            this.responseCount++;
                        
                        else
                        
                            // Treat all other status codes as errors.
                            this.reportError(res);
                        
                    
                );

在发送过多请求时,我们会观察到服务会在一段时间后溢出一些错误 503 响应,但 RestSharp 将这些响应视为完整响应,因为这是来自服务器的有效响应;没有抛出任何实际异常。

不清楚的是RestSharp何时因底层连接错误而遇到异常

The underlying connection was closed: A connection that was expected to be kept alive was closed by the server.
at RestSharp.Http.GetRawResponseAsync(IAsyncResult result, Action`1 callback)
at RestSharp.Http.ResponseCallback(IAsyncResult result, Action`1 callback)

The underlying connection was closed: An unexpected error occurred on a receive.
   at RestSharp.Http.GetRawResponseAsync(IAsyncResult result, Action`1 callback)
   at RestSharp.Http.ResponseCallback(IAsyncResult result, Action`1 callback)

这似乎表明 RestSharp 正在使用 HTTP keep-alive 进行连接。有没有办法控制这种行为?我似乎找不到任何设置来指示 RestSharp使用 keep-alive。

除此之外,我还试图更好地了解如何进一步调查服务器中断这些连接的实际问题?仅仅是客户端发出的连接数超过了服务器可以处理的问题吗? (因为它跟不上它的响应速度)

【问题讨论】:

【参考方案1】:

在对测试客户端代码进行额外调查和修改后,我想我已经对正在发生的事情有所了解。

通过向服务器打开的 HTTP/TCP 连接数添加监控计数,可以观察到 RestSharp 将 HTTP 连接保持在保持活动状态,并将它们重用于后续请求。对于一个可持续的请求率和吞吐量,没有问题; RestSharp 可以重用某个连接池并使其永久保持活动状态。

但是对于服务器可能不时满足的速率,客户端必须打开更多连接,因为之前的 HTTP 请求还没有完成;导致打开的连接跳跃。稍后,如果它最终重用了它认为服务器仍在使用的保留 HTTP 连接,它最终会出现“预期保持活动状态的连接已被服务器关闭。 "消息。

【讨论】:

我知道已经有一段时间了,但您还记得找到解决问题的方法吗?你提到关闭保持活动。你能做到吗,是否解决了问题? 对于任何偶然发现这一点的人,我使用 RestSharp 的解决方案是配置客户端: var client = new RestClient(domain); client.ConfigureWebRequest((r) => r.ServicePoint.Expect100Continue = false; r.KeepAlive = true; ); 那么解决办法是什么? @fuzzy_logic 这些设置的含义是什么?【参考方案2】:

我用这条简单的线解决了它

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

【讨论】:

tls 1.1,当然还有 tls 1 现在已经过时并且存在已知的安全漏洞,不应使用【参考方案3】:

解决方案是将 keep-alive 设置为 false。

    var client = new RestClient("https://test.com");
        client.ConfigureWebRequest((r) =>
        
            r.ServicePoint.Expect100Continue = false;
            r.KeepAlive = false;
        );

在此更改后,每个连接都会在收到响应后关闭。这将增加每次打开连接的一些努力。但是,将防止奇怪的意外连接泄露错误。

【讨论】:

以上是关于RestSharp:底层连接已关闭:服务器关闭了预期保持活动状态的连接的主要内容,如果未能解决你的问题,请参考以下文章

WebException:底层连接已关闭

远程服务器上的错误“底层连接已关闭:发送时发生意外错误”

System.ServiceModel.CommunicationException:底层连接已关闭

自签名证书。底层连接已关闭:无法建立信任关系

底层连接被关闭:连接被意外关闭

https 请求:底层连接已关闭:无法为 SSL/TLS 安全通道建立信任关系