我有一个问题,我有很多非常小的 Web 服务调用到 Java 端点(托管在 Oracle GlassFish 3.1.X 上)。我将此服务添加为服务引用(使用远程 wsdl 文件)并使用 BasicHttpBinding 来访问它。
由于该服务位于半个地球之外,而且还要通过互联网,所以我们在到达目的地时经常会遇到一些丢包现象。我们正在寻找任何可能的方法来减少这些事件的影响。我们一直在使用 Wireshark 为我们提供有关通过电线到达目的地并再次返回的详细信息。我很好奇地看到,对于我们生成的每个请求,我们都会发送 2 个数据包。数据包边界始终位于 HTTP 标头和<s:Envelope>
标记之间。对我来说,这是一个很大的开销,特别是在我想要最小化发送的数据包数量(以减少整体数据包丢失)的环境中。
在大多数情况下(我们调用的 99%),HTTP 标头数据包是 210 字节,然后是 291 字节的 SOAP 信封数据包(不包括每个数据包的 54 字节 TCP/IP 开销)。将这些加起来有 501 个字节——刚好超过我们最大段大小 1460 字节的三分之一。为什么 WCF 不将此 HTTP POST 请求作为 501 字节的单个数据包发送(如果包括 54 字节的 TCP/IP 开销,则为 555 字节)?
有谁知道它为什么这样做?似乎 HttpWebRequest 对象在写入其标头后正在流上调用 .Flush() 但我不确定它为什么会这样做?
我在这些上尝试了不同的组合:
ServicePointManager.UseNagleAlgorithm = false;
ServicePointManager.Expect100Continue = false;
没有效果。
编辑
错误的:我进行了更深入的调查,当调用 HttpWebRequest.GetRequestStream() 时,它会立即将标头写入流。在您写入返回给您的 Stream 之前的某个阶段,网络会刷新这些(我猜?除非某处发生故意刷新)。当您最终开始写入流时,它已经发送了标头数据包。不知道如何防止这种情况,在调用 GetRequestStream() 的 HttpWebRequest 代码中似乎有一个非常硬的断言将写入标头。对于我的小请求,我希望在关闭流之前什么都不写,但这违背了流的本质。