【问题标题】:WCF: Per-Call sessions timeoutWCF:每次通话会话超时
【发布时间】:2012-03-24 05:55:02
【问题描述】:

我有一个 WCF 服务,其实例上下文模式设置为 PerCall,并使用 wsHttpBinding。编码不佳的客户端能够在不正确释放会话的情况下使用会话(即客户端不会在客户端代理上调用 Close())。通过查看“最大并发会话百分比”性能计数器,我可以看到每个连接都使用了一个会话,并且没有释放它。在正常、行为良好的情况下,会话仅在返回调用结果时使用片刻。

我一直试图找到一种方法让这些不良会话超时并消失,但没有成功。由于它不是一个可靠的会话,因此 RecieveTimeout 和 InactivityTimeout 设置似乎没有任何效果。这是我当前配置的一部分,其中设置了许多超时,但似乎不起作用:

        <behaviors>
        <serviceBehaviors>
            <behavior name="UpdaterBehavior">
                <serviceMetadata httpGetEnabled="true"/>
                <serviceCredentials>
                    <userNameAuthentication userNamePasswordValidationMode="MembershipProvider"/>
                    <serviceCertificate findValue="xxxxxx" x509FindType="FindBySubjectName"/>
                </serviceCredentials>
                <serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="SqlRoleProvider"/>
                <serviceThrottling maxConcurrentCalls="10" maxConcurrentSessions="10" maxConcurrentInstances="10" />                    
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <bindings>
        <wsHttpBinding>
            <binding name="UpdaterBinding" messageEncoding="Mtom" maxReceivedMessageSize="100000000"  closeTimeout="00:01:00" openTimeout="00:01:00"
                receiveTimeout="00:01:00" sendTimeout="00:01:00">
                <reliableSession ordered="true" inactivityTimeout="00:01:00"
                    enabled="false" />
                <readerQuotas maxArrayLength="100000000"/>
                <security>
                    <message clientCredentialType="UserName"/>
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>

我可以将 serviceThrottling 数字设置得更高,但这只是暂时隐藏了问题,最终一个坏客户端会用完所有会话。我希望服务器释放任何存在超过几分钟的会话,因为没有理由在此服务上的任何内容都需要这么长时间。

有什么建议吗?

【问题讨论】:

    标签: wcf


    【解决方案1】:

    好的,我可能在这里完全偏离基础,但根据我从您的问题中了解到的情况,这是一个可能的解决方案:

    显然您可以获得活动会话的列表,但您不能从服务端终止会话:

    http://social.msdn.microsoft.com/Forums/en/wcf/thread/a6a72bd7-bd06-43e3-8abb-d6c10432a07b

    我能想到的一件事是,如果您在 IIS 中托管 WCF 服务,您可以创建一个在服务器上运行并查看活动会话的 Windows 服务。您是否可以弄清楚服务器何时无法管理会话并强制它重新启动 IIS 应用程序池?

    Restarting (Recycling) an Application Pool

    【讨论】:

    • 我将不得不对此进行进一步调查,但从外部重新启动服务不是一种选择。该服务当前托管在一个小型 exe(不是 IIS)中。
    • 我不知道这是否不是一个选项,因为您不想结束所有会话,但您可以重新启动 Windows 中运行的任何服务。 csharp-examples.net/restart-windows-service
    • 抱歉,澄清一下:取消整个服务来处理这样的极端情况不是我愿意做的事情。定期中断服务的成本远远高于这成为问题的可能性。
    【解决方案2】:

    孤立会话的一个选项是将 wsHttpBinding 配置为不使用任何依赖于会话的功能(例如可靠的消息传递,这是现在配置服务的方式)。

    如果您有需要可靠消息传递的业务需求,请转到 netMsmqBinding 以获得有保证的消息传递,但代价是围绕单向消息传递模式进行设计。 DeviantSeev 是正确的,您无法控制服务会话的终止,但他推荐的解决方案非常激进。如果您有一个像电子商务网站这样的大容量环境,因为回收应用程序池会导致停机,这是不可行的。

    【讨论】:

    • 我不认为它被配置为可靠的消息传递(注意 enabled="false")。如果我需要做其他事情来禁用可靠消息传递,我不知道。
    • 很抱歉错过了enabled="false",我专注于ordered="true" 部分。作为测试,尝试禁用安全性,如forum post 所示,并从配置中删除可靠会话元素。查看该配置是否有助于解决孤立会话问题。如果确实如此,请重新启用安全性并查看问题是否再次出现。如果安全是原因,那么您需要确定禁用它是否真的适合您的情况。
    • 如果我有空闲时间,我可能会尝试一下,看看是否有帮助。即使是这样,不幸的是,为此关闭安全性并不是一个真正的选择。
    • ws-* 绑定中的 WCF 安全性部分是使用会话作为优化来实现的。这样,每个“会话”只执行一次授权。我突然想到另一个选择可能是使用基本 HTTP 身份验证在 HTTPS 上使用 basicHttpBinding。我不相信 basicHttpBinding 使用任何类型的会话,而且我很确定对每个请求都执行了身份验证。值得一试,它确实保留了经过加密的身份验证访问。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-22
    • 1970-01-01
    • 1970-01-01
    • 2010-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多