零星异常调用负载平衡的Web服务

Jim*_*Jim 5 c# web-services

我有一个Web服务,我在三个负载平衡的Web服务器上运行,我得到零星的错误.现在,我承认负载平衡部分可能有点红鲱鱼,但是当我只用1个Web服务器进行测试时,我无法重现错误.如果我测试所有三个Web服务器,我可以得到错误(但它不是100%的时间,更像是50%).所有测试都是通过负载均衡器完成的,我们只告诉负载均衡器我们想要多少台服务器.

代码是简单的单个请求代码.也就是说,没有国家.发出请求并返回响应.Web服务代码是在IIS 7.5上运行的c#.NET 4.客户端代码既是网站又是桌面应用程序.

我得到两个例外之一:

System.ServiceModel.Security.MessageSecurityException:从另一方收到了不安全或不正确安全的故障.请参阅内部FaultException以获取故障代码和详细信息.---> System.ServiceModel.FaultException:安全上下文令牌已过期或无效.邮件未处理.

或者我得到:

System.ServiceModel.Security.SecurityNegotiationException:无法打开安全通道,因为与远程端点的安全协商失败.这可能是由于在用于创建通道的EndpointAddress中缺少或错误指定了EndpointIdentity.请验证EndpointAddress指定或暗示的EndpointIdentity是否正确标识远程端点.---> System.ServiceModel.FaultException:安全令牌请求包含无效或格式错误的元素.

从我的.config文件中可以看到以下剪辑,我没有使用安全性,因为这严格来说是一个内部Web服务.(名称已被更改以保护无辜者 - 即我).

服务器端:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- Service Side web.config -->
...
  <system.serviceModel>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    <services>
      <service behaviorConfiguration="InternalUseOnly.InternalUseOnlyServiceBehavior" name="InternalUseOnly.InternalUseOnlyService">
        <endpoint address="" bindingNamespace="http://somecompany.com/webservices" binding="wsHttpBinding" contract="InternalUseOnly.IInternalUseOnlyService">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="InternalUseOnly.InternalUseOnlyServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
...
</configuration>
Run Code Online (Sandbox Code Playgroud)

客户端

<?xml version="1.0" encoding="UTF-8"?>
<!-- Client Side web.config -->
<configuration>
...
    <system.serviceModel>
      <bindings>
        <wsHttpBinding>
          <binding name="WSHttpBinding_IInternalUseOnlyService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
            <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
            <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
            <security mode="Message">
              <transport clientCredentialType="Windows" proxyCredentialType="None" realm="" />
              <message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default" />
            </security>
          </binding>
        </wsHttpBinding>
      </bindings>
      <client>
        <endpoint address="http://intranet.somecompany.com/InternalUseOnly/InternalUseOnlyService.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IInternalUseOnlyService" contract="InternalUseOnlyService.IInternalUseOnlyService" name="WSHttpBinding_IInternalUseOnlyService">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
      </client>
    </system.serviceModel>
...
</configuration>
Run Code Online (Sandbox Code Playgroud)

想什么?


附加信息:在回顾下面的答案后,我尝试了两件事,但都没有成功.

最明显的变化(我最初没有注意到)是更改客户端上的一个属性以允许cookie <system.serviceModel><bindings><wsHttpBinding><binding name="blah, blah, blah" ... other properties... allowCookies="true" />它默认为false.此外,我们的负载均衡器使用cookie来保持亲和力.但是,它没有什么区别(不知道为什么).

接下来,我在客户端app.config文件中尝试了各种安全选项.这包括两者<security mode="None" />和更详细的:

<security mode="None">
    <transport clientCredentialType="None" proxyCredentialType="None" />
    <message clientCredentialType="None" establishSecurityContext="false" negotiateServiceCredential="false"/>
</security>
Run Code Online (Sandbox Code Playgroud)

虽然最后一个设置只是我的猜测.我没有对app.config进行任何服务器端更改,因为我不知道要改变什么,遗憾的是,我只能测试生产,因为我们只有1个开发Web服务器,而不是3个.

Jim*_*Jim 1

虽然 Chris 和 Jeff 帮助我找到了答案,但真正为我解决问题的是我从 Microsoft 找到的关于负载平衡 Web 服务的这篇文章。简而言之,要解决我们的网络场的这个问题,我们必须做的就是从默认切换wsHttpBindingbasicHttpBinding. 这并不困难,但却是一个孤注一掷的举动。主 Web 服务和每个客户端都必须同时重新配置,否则就会崩溃。

虽然wsHttpBinding确实有一个可以设置为true的allowCooikes属性,但它显然直到连接建立之后才使用它们,此时请求可能会在第一个请求时跳转服务器并因此失败。