我们在Windows服务中托管了一个WCF服务,该服务在长时间不活动后挂起:即在周末之后。
此行为发生在不同的位置。
该服务使用WSHttpBinding设置为使用传输安全性自定义serviceAuthorization authorizationPolicy,它使用Windows身份验证。
使用Spring框架。 Spring.ServiceModel.Activation.ServiceHostFactory创建服务主机。
服务限制设置为200个会话,实例和调用。系统最多有15个用户。
已启用跟踪并设置为警告,应该让我了解油门问题。 服务跟踪日志中没有消息。 事件日志中没有看起来相关的消息。 HTTPPerf日志中没有相关日志。 我们在服务器端应用程序中进行了大量日志记录,但系统挂起时没有记录任何活动。 系统挂起时,它是一个完整的黑盒子。
客户端失败并显示以下消息。 08:13:32.014 [1] ERROR App - System.TimeoutException:客户端无法在配置的超时(00:00:59.9941374)内完成安全协商。目前的谈判支持是1(00:00:59.9863206)。 ---> System.TimeoutException:请求通道在00:00:59.9628702之后等待回复时超时。增加传递给Request的调用的超时值或增加Binding上的SendTimeout值。分配给此操作的时间可能是较长超时的一部分。 ---> System.TimeoutException:对“http:// localhost:8080 / OrderManagementService.svc”的HTTP请求已超过分配的超时00:00:59.9690000。分配给此操作的时间可能是较长超时的一部分。 ---> System.Net.WebException:操作已超时 在System.Net.HttpWebRequest.GetResponse()
我花了很多时间搜索相关信息。
我认为这与不活动超时有关,因为这应该记录在跟踪日志中。
我能想到的只是与Active Directory凭据缓存或某种性质有关,或者与Spring框架的使用有关。
非常感谢任何帮助。
我想完全放弃WSHttpBinding或WCF,因为这是一个不可接受的情况。
服务端配置如下。
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false" maxBufferPoolSize="2147483646" maxReceivedMessageSize="2147483646">
<readerQuotas maxDepth="2147483646" maxStringContentLength="2147483646" maxArrayLength="2147483646" maxBytesPerRead="2147483646" maxNameTableCharCount="2147483646" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
<security>
<transport></transport>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceAuthorization principalPermissionMode="Custom">
<authorizationPolicies>
<add policyType="Kodi.Kodiak.Security.AuthorizationPolicy, Kodi.Kodiak.Security" />
</authorizationPolicies>
</serviceAuthorization>
<serviceCredentials>
<windowsAuthentication includeWindowsGroups="true" allowAnonymousLogons="false" />
</serviceCredentials>
<serviceThrottling maxConcurrentCalls="200" maxConcurrentSessions="200" maxConcurrentInstances="200" />
<dataContractSerializer maxItemsInObjectGraph="2147483646" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="rest">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="ServiceBehavior" name="OrderManagementService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding" contract="Kodi.Kodiak.Services.ServiceContracts.IOrderManagementService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
SPRING CONFIG
<object id="OrderManagementService"
singleton="false"
type="Kodi.Kodiak.Services.OrderManagementService, Kodi.Kodiak.Services"
scope="session">
</object>
答案 0 :(得分:0)
客户如何调用该服务?如果他们通过SvcUtil
生成的代理调用服务; 他们是否正确关闭代理连接?我认为客户端没有关闭连接,或者只是连接没有正确关闭。
重要的是,在创建代理时应避免使用using
语句。
更好的方法是这样的,
ServiceClient client = null;
try
{
client = new ServiceClient();
client.CallMethod();
}
finally
{
client.CloseConnection(); // extension method
}
public static void CloseConnection(this ICommunicationObject client)
{
if (client.State != CommunicationState.Opened)
{
return;
}
try
{
client.Close();
}
catch (CommunicationException)
{
client.Abort();
throw;
}
catch (TimeoutException)
{
client.Abort();
throw;
}
catch (Exception)
{
client.Abort();
throw;
}
}
答案 1 :(得分:0)
我认为这可以通过维护客户端和服务器绑定端点和行为相同来实现,客户端和服务器配置中指定的超时值应该相同。