带有消息的零星 WCF 服务激活错误 - 访问 IIS 元数据库时发生错误

Posted

技术标签:

【中文标题】带有消息的零星 WCF 服务激活错误 - 访问 IIS 元数据库时发生错误【英文标题】:Sporadic WCF Service activation error with message - An error occurred while accessing the IIS Metabase 【发布时间】:2014-01-03 22:55:29 【问题描述】:

我正在处理一个项目,在该项目中,我之前只托管单个 WCF 服务。过去一切正常。后来,作为增强功能的一部分,我们在同一个项目中添加了另外两个具有不同接口和不同 SVC 文件的 WCF 服务。所有三个服务共享相同的 web.config,它定义了三个端点(对应于每个服务)。

我的项目的 WCF 服务托管为具有自己的应用程序池和端口号的单独网站。我的所有三个服务共享同一个应用程序池。

当我多次部署应用程序以测试服务器时,使用此设置时,我会遇到如下零星错误,并且服务停止工作。在这三个服务中,一次有一个或两个会出现此错误,其他的会继续工作。

    System.ServiceModel.ServiceHostingEnvironment+HostingManager/4032828
    System.ServiceModel.ServiceActivationException: The service '...svc' cannot be activated due to an exception during compilation.  The exception message is: An error occurred while accessing the IIS Metabase.. ---> 

    System.Runtime.InteropServices.COMException: An error occurred while accessing the IIS Metabase.
   at System.ServiceModel.Activation.MetabaseReader..ctor

我为 web 服务启用了 svclogs,我看到了类似的东西

......
AppDomain unloading
To: construct ServiceHost 'myservice1'
From: construct ServiceHost 'myservice1'
To: Open ServiceHost 'myservice1'
From: ServiceHost 'myservice1'
ASP.NET hosted service activated
**Wrote To Eventlog**     << Exception at this point for myservice2.

我试过This options,但没有帮助。我也在网上搜索过,但没有找到任何其他可以提供帮助的解决方案。

我在测试服务器上安装了 IIS6。

任何帮助将不胜感激。

更新:


我观察到了一种模式。在空闲时间之后,无论哪个服务首先被正确激活,其他服务都会失败。此外,为了添加到端口部分,我们特别提到了运行此服务的端口。对于我的应用程序来说端口号是 25000,那么这个服务器上没有其他应用程序共享这个端口号,只有我的应用程序。因此,如果有多个服务,那么它们共享端口,但是对于具有多个 SVC 服务的其他项目,同样的设置也存在,并且没有人遇到过这个问题(据我所知)。

更新 2:下面是配置文件。我已经输入了配置文件,但尽量保持准确。 (请忽略区分大小写的东西)

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="MyBinding">
                <security mode="TransportCredentialOnly">
                    <transport clientCredentialType="Basic" proxyCredentialType="Basic" realm="prod.xxx.net" />
                    <message clientCredentialType="UserName" algorithmSuite="Default"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>

    <behaviours>
        <serviceBehaviours>
            <behaviour name="firstServiceBehaviour">
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
                <serviceCredentials>
                    <clientCertificate>
                        <authentication mapClientCertificateToWindowsAccount="true" />
                    </clientCertificate>
                </serviceCredentials>
                <dataContractSerializer maxItemsInObjectGraph="2147483646" />
            </behaviour>

<behaviours>
    <serviceBehaviours>
        <behaviour name="secondServiceBehaviour">
            <serviceMetadata httpGetEnabled="true" />
            <serviceDebug includeExceptionDetailInFaults="true" />
            <serviceCredentials>
                <clientCertificate>
                    <authentication mapClientCertificateToWindowsAccount="true" />
                </clientCertificate>
            </serviceCredentials>
        </behaviour>

<behaviours>
    <serviceBehaviours>
        <behaviour name="thirdServiceBehaviour">
            <serviceMetadata httpGetEnabled="true" />
            <serviceDebug includeExceptionDetailInFaults="true" />
            <serviceCredentials>
                <clientCertificate>
                    <authentication mapClientCertificateToWindowsAccount="true" />
                </clientCertificate>
            </serviceCredentials>
            <dataContractSerializer maxItemsInObjectGraph="2147483646" />
        </behaviour>

    <services>
        <service behaviourConfiguration="firstServiceBehaviour" name="...">
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="MyBinding" name="firstServiceEndPoint" contract="IfirstServiceContract" />
        </service>

        <service behaviourConfiguration="secondServiceBehaviour" name="...">
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="MyBinding" name="secondServiceEndPoint" contract="IsecondServiceContract" />
        </service>

        <service behaviourConfiguration="thirdServiceBehaviour" name="...">
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="MyBinding"
name="thirdServiceEndPoint" contract="IthirdServiceContract" />
        </service>
    </services>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</System.ServiceModel>

【问题讨论】:

所以,有时有效,有时无效?你能看到已完成的通话吗? @Cyber​​maxs-Betclic 是的,我可以看到已完成的通话 如果它有时有效,我猜可能是端口冲突。有问题的端口可能来自任何应用程序,并且可能会提示为什么会随机出错 如果您可以发布 web.config 数据会更好,特别是配置端点的位置。 @Paddy 如何识别端口冲突。它是一个共享服务器,多个应用程序共享服务器,但拥有各自独立的 AppPools 和虚拟目录。 【参考方案1】:

我不会说这是完整的答案,但这在一定程度上有助于解决我们的问题。我仍然想知道问题的实际原因的原因/解决方案。我提到这项工作,因为这可能有助于临时解决他们的问题以及可能面临类似问题的人。

正如我所提到的,仅当应用程序空闲一段时间时才会出现问题。在这种情况下,IIS 正在关闭(卸载)应用程序的 AppDomain(来自 SVC 日志)。

因此,我们创建了一个简单的控制台应用程序,它每 5-10 分钟访问我们应用程序的所有服务,并且不会让 AppDomain 关闭。有一种替代方法可以实现这一点 - 将 IIS 配置设置为不卸载 AppDomain(这对我们来说不太可行,因为我们提供了共享基础架构)。这帮助我们完成了测试。

然后,当我们转移到负载平衡环境(接近生产的测试环境)时,我们突然停止了问题,通过一些分析,我们发现负载平衡器本身正在 ping 这些服务,以确保它们是起来,并且由于这些服务的这个 App Domain 永远不会被卸载。

所以,现在我们可以说我们在负载平衡环境中没有遇到这个问题,但问题仍然是为什么它会发生(对于非负载平衡环境)。

【讨论】:

以上是关于带有消息的零星 WCF 服务激活错误 - 访问 IIS 元数据库时发生错误的主要内容,如果未能解决你的问题,请参考以下文章

WCF:使用带有消息契约的流式传输

WCF net.msmq 服务自动激活

WCF 无法激活服务,因为它不支持 ASP.NET 兼容性

带有客户端证书身份验证的 Wcf 不适用于 soapui

WCF Web 服务错误:无法激活该服务,因为它不支持 ASP.NET 兼容性

带有 WCF 调用的 Ajax 返回 404 错误