WCF slow ServiceHost.Open() call

扶醉桌前 提交于 2019-12-12 13:57:59

问题


This is a similar question as this one: Win32Exception @ ServiceHost.Open() for WCF service.

I have a machine that is very slow on the ServiceHost.Open call below. It consistently takes 7 seconds or so to open the service, every time. This machine is my home box, and it is not part of a domain.

I can run the same code on another box (my work box) which is part of a domain and the service host opens in about 3-4 seconds on the first call, but if I run the program again the service host opens in about 1 second or less.

I have worked with MS support on this, and we generated trace logs and the part it's hanging in is where is goes out and tries to connect to a domain, even on the machine that isn't part of a domain. And it gets the "The specified domain either does not exist or could not be contacted." exception in the trace log, and that's where all the time is getting eaten up.

But what's really weird is that even on my work machine, if I'm not connected to a domain (like if I'm not on my work network and just running from home) I still don't get the delay.

I rebuilt my machine using Windows 7 64-bit, and the same behavior occurs (was running XP SP3, which I restored when Windows 7 didn't seem to fix the problem).

I just wondered if anyone had any ideas of what could cause this. By the way, if I disable "Client for microsoft networks", the time is like 4 seconds to open the ServiceHost, but that's still not as fast as this machine used to be able to open the service. Somehow, it thinks it's supposed to be part of a domain or something.

    static void RunServiceWithinEXE()
    {
        Uri baseAddress = new Uri("http://localhost:11111/Demo");
        ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService), baseAddress);

        try
        {
            // Add a service endpoint
            serviceHost.AddServiceEndpoint(
                typeof(ICalculator),
                new WSHttpBinding(),
                "CalculatorService");

            // Enable metadata exchange
            ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
            smb.HttpGetEnabled = true;
            serviceHost.Description.Behaviors.Add(smb);
            serviceHost.Opening += new EventHandler(serviceHost_Opening);
            serviceHost.Opened += new EventHandler(serviceHost_Opened);
            serviceHost.Open();
            Console.WriteLine("The service is ready.");

            // Close the ServiceHostBase to shutdown the service.
            serviceHost.Close();
        }
        catch (CommunicationException ce)
        {
            Console.WriteLine("An exception occured: {0}", ce.Message);
            serviceHost.Abort();
        }
    }

    static void serviceHost_Opened(object sender, EventArgs e)
    {
        TimeSpan timeToOpen = DateTime.Now - shOpening;
        Console.WriteLine("Time To Open: :" + timeToOpen.Seconds);
    }

    static void serviceHost_Opening(object sender, EventArgs e)
    {
        shOpening = DateTime.Now;
    }

Here is my app.config, but I don't have any special security configuration settings for the service in there, only some diagnostic settings to enable the WCF trace.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <diagnostics>
            <messageLogging maxMessagesToLog="30000"
                    logEntireMessage="true"
                    logMessagesAtServiceLevel="false"
                    logMalformedMessages="true"
                    logMessagesAtTransportLevel="true">
                <filters>
                    <clear/>
                </filters>
            </messageLogging>
        </diagnostics>
    </system.serviceModel>

    <system.diagnostics>
        <sources>
            <source name="System.ServiceModel" switchValue="Warning, ActivityTracing" propagateActivity="true" >
                <listeners>
                    <add name="xml" />
                </listeners>
            </source>
            <source name="System.ServiceModel.MessageLogging" switchValue="Warning">
                <listeners>
                    <add name="xml" />
                </listeners>
            </source>
        </sources>
        <sharedListeners>
            <add name="xml" type="System.Diagnostics.XmlWriterTraceListener" initializeData="C:\Temp\Server.svclog" />
        </sharedListeners>
        <trace autoflush="true" indentsize="4">
            <listeners>
                <remove name="Default" />
                <add name="ScottsConsoleListener" type="System.Diagnostics.ConsoleTraceListener" />
                <add name="ScottsTextListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="C:\Temp\DebugLog.txt" />
            </listeners>
        </trace>
    </system.diagnostics>
</configuration>

Note also that my service definition has SessionMode required (see below). If I take the SessionMode requirement out, I don't get the delays.

using System;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace Microsoft.ServiceModel.Samples
{
    // Define a service contract.
    [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode = SessionMode.Required)]
    public interface ICalculator
    {
        [OperationContract]
        double Add(double n1, double n2);

        [OperationContract]
        double Subtract(double n1, double n2);

        [OperationContract]
        double Multiply(double n1, double n2);

        [OperationContract]
        double Divide(double n1, double n2);

        [OperationContract]
        string PrintName(string firstName, string lastName);

        [OperationContract]
        Point MakePoint(double x, double y);

    }
}

回答1:


Okay, my suspicion is the fact you're using a binding (WsHttpBinding) which defaults to authenticating its callers using Windows credentials unless you specifically tell it not to.

In your service hosting code, you're just instantiating a default WsHttpBinding instance - no settings in config or code to change the default security behavior, in that case.

Just for testing purposes: try to change your service hosting code to:

 // Add a service endpoint
 serviceHost.AddServiceEndpoint(
            typeof(ICalculator),
            new WSHttpBinding(SecurityMode.None),  // pass in SecurityMode.None
            "CalculatorService");

This will effectively cancel out all security settings, e.g. the ServiceHost should no longer even attempt to find the Windows domain to authenticate callers against.

Does that change any of your observations?




回答2:


It turns out that if I disable netbios on my network connections, I don't get the delays on the ServiceHost.Open calls. I am not sure why, but this seemed to fix the problem.

What's weird is that when I did a clean install of XP, I didn't have the delays even with the Netbios enabled, so I have no idea why it happens with my existing installation (I did the clean install on this same machine, and then restored my backup from an image to run these tests).




回答3:


Also try stopping the Remote Access Auto Connection Manager service. For me, the issue came down to Dns.GetHostEntry(String.Empty) and this post http://social.msdn.microsoft.com/Forums/en/vbgeneral/thread/493d1b65-9ace-41de-b269-f178d27a8a1b




回答4:


It seems I had the same Problem. Long Duration of Open call caused by an exception. I googled for configuration of security Settings for Wcf Service. Found the following solution which worked for me:

Under <wsHttpBinding> element in the Web.config file place the following entry:

<security mode="None" />

The Service Reference in the Client must be updated!



来源:https://stackoverflow.com/questions/4739546/wcf-slow-servicehost-open-call

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!