【问题标题】:C# HttpWebRequest to Socket 3 second delay in writing to Request StreamC# HttpWebRequest to Socket 3 秒延迟写入请求流
【发布时间】:2014-01-21 10:03:52
【问题描述】:

我有一个使用套接字的自定义 HTTP 服务器和一个使用 HttpWebRequest 连接到该服务器的客户端。客户端是多线程的,使用这段代码:

ServicePointManager.UseNagleAlgorithm = false;
ServicePointManager.Expect100Continue = false;
ServicePointManager.DefaultConnectionLimit = 48;

var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = verb;
request.Timeout = timeout;
request.AutomaticDecompression = DecompressionMethods.GZip;
request.Proxy = null;
request.SendChunked = false;

/*offending lines*/
var writer = new StreamWriter(request.GetRequestStream(),Encoding.UTF8);
writer.Write(stringData);
writer.Close();
/*end offending lines*/

var response = (HttpWebResponse)request.GetResponse();

我已经通过这段代码运行了数千个请求,并且大部分时间都运行良好。平均响应时间约为 200 毫秒,包括在服务器上完成的一些工作。

问题是大约 0.2% 的请求非常慢。在测量时,我注意到缓慢的请求在获取和写入请求流时会暂停 3 秒(+- 20 毫秒)。 GetResponse() 仍然很快,服务器上没有任何东西需要额外的时间。

服务器被实现为一个侦听器 Socket 在端口上异步侦听,使用 Listen() 和 BeginAccept()。接受连接后,在新的 Socket 上调用 BeginRecieve(从 EndAccept() 获取)并在侦听器套接字上再次调用 BeginAccept。根据我的阅读,这是这样做的方法。

所以我的问题是:在 GetRequestStream() 和写入期间会发生什么?数据实际上是在此处发送还是在 GetResponse() 上刷新?为什么有些请求会在没有任何明显原因的情况下多花 3 秒?我的服务器实现是否存在某种缺陷?奇怪的是它总是 3 秒,但有时可能是 9 秒。由于某种原因,它似乎是 3 的倍数。

几种可能的情况:

  • 连接是在 GetRequestStream() 上启动的,但服务器不会立即接受它。如果是这种情况,我该如何测试?
  • GetRequestStream() 的幕后发生了一些事情或正在对其进行写入。
  • 等待网络硬件?
  • 等待 DNS 解析?
  • 还有别的吗?

非常感谢任何帮助。

编辑:我尝试通过 Web 代理进行连接,然后延迟从 GetRequestStream() 移动到 GetResponse(),表明问题确实出在 Web 服务器上。似乎它不接受连接。我意识到 EndAccept() 和 BeginAccept() 之间可能会有一些延迟,但它不应该等于 3 秒的延迟,对吧?

我也尝试过单线程运行我的客户端,问题似乎消失了。这表明只有同时发出多个请求时才会出现连接延迟。

【问题讨论】:

    标签: c# sockets http httpwebrequest


    【解决方案1】:

    我想我有点太晚了,但我遇到了类似的问题并找到了一篇文章,其中描述了导致此类问题的似乎相当低级的原因 - http://www.percona.com/blog/2011/04/19/mysql-connection-timeouts/

    【讨论】:

    • 我不确定该链接是否与这个问题特别相关。但它涉及到连接队列的类似问题。在我的情况下,问题是我的套接字队列太短 - 所以当同时有许多连接时,其中一些被拒绝返回到操作系统(或网络设备?)队列,这意味着响应时间非常慢。跨度>
    【解决方案2】:

    可能是因为您没有处理请求流。尝试用以下内容替换您的违规行

    var stream = request.GetRequestStream();
    var buffer = Encoding.UTF8.GetBytes(stringData);
    stream.Write(buffer, 0, buffer.Length);
    stream.Dispose();

    【讨论】:

    • 不,似乎没有帮助。仍然大约 0.2% 需要 3 秒多一点。
    【解决方案3】:

    初步测试表明问题确实是服务器上的连接拥挤。通过对 Socket 代码的一些重组,我设法摆脱了慢速连接。我今晚会进行更多测试以确保,但它看起来很有希望!

    【讨论】:

    • 所以?接下来发生了什么?
    • 这差不多是 4 年前的事了,但据我记得应用程序中的套接字队列太短,这导致连接被拒绝,从而导致 TCP 重新传输,通常使用默认的 3 秒 TCP 超时。请参阅我在上述答案中的评论。
    • 你是怎么解决的?更大的套接字队列?
    • @Alakanu 是的,完全正确。一段时间后,我们用 Kestrel 替换了我们自己开发的 HTTP 侦听器,这样我们就不必再担心这些问题了。
    猜你喜欢
    • 2013-11-17
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    • 2014-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多