Медленный вызов WCF ServiceHost.Open()

Это вопрос, аналогичный этому: Win32Exception @ ServiceHost.Open() для службы WCF< /а>.

У меня есть машина, которая очень медленно работает при вызове ServiceHost.Open ниже. Каждый раз для открытия службы требуется около 7 секунд. Эта машина — мой домашний ящик, и она не является частью домена.

Я могу запустить тот же код на другом компьютере (мой рабочий ящик), который является частью домена, и узел службы открывается примерно через 3-4 секунды при первом вызове, но если я снова запущу программу узел службы открывается примерно через 1 секунду или меньше.

Я работал над этим со службой поддержки MS, и мы создали журналы трассировки, и часть, в которой они висят, это то, где они выходят и пытаются подключиться к домену, даже на машине, которая не является частью домена. И выдает "Указанный домен либо не существует, либо с ним невозможно связаться". исключение в журнале трассировки, и именно здесь все время съедается.

Но что действительно странно, так это то, что даже на моем рабочем компьютере, если я не подключен к домену (например, если я не в своей рабочей сети и просто работаю из дома), я все еще не могу получить отсрочку.

Я восстановил свою машину, используя 64-разрядную версию Windows 7, и происходит то же самое (использовал XP SP3, который я восстановил, когда Windows 7, похоже, не решила проблему).

Я просто задавался вопросом, есть ли у кого-нибудь идеи о том, что может быть причиной этого. Кстати, если я отключу «Клиент для сетей Microsoft», время открытия ServiceHost составит около 4 секунд, но это все еще не так быстро, как эта машина раньше могла открывать службу. Почему-то он думает, что это часть домена или что-то в этом роде.

    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;
    }

Вот мой app.config, но у меня нет никаких специальных параметров конфигурации безопасности для службы, только некоторые диагностические параметры для включения трассировки WCF.

<?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>

Также обратите внимание, что в моем определении службы требуется SessionMode (см. ниже). Если я уберу требование SessionMode, я не получу задержек.

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);

    }
}

person dcp    schedule 19.01.2011    source источник
comment
у вас есть антивирусный сканер / брандмауэр / пакет безопасности, установленный на этой машине?   -  person CaptainPlanet    schedule 19.01.2011
comment
@CaptainPlanet - Да, но даже после их удаления все еще работает медленно. Я пробовал без установленного антивирусного сканера и с выключенным брандмауэром Windows. Хотя спасибо за мысль.   -  person dcp    schedule 19.01.2011
comment
Можете ли вы показать нам конфигурацию службы, особенно настройки безопасности?? Тот факт, что он хочет связаться с доменом, будет означать, что либо вы используете привязку, которая по умолчанию использует учетные данные Windows, которые ServiceHost хочет установить ссылку на домен Windows для проверки учетных данных пользователя, либо у вас есть собственный механизм аутентификации, пытающийся для связи с доменом Active Directory.   -  person marc_s    schedule 19.01.2011
comment
@marc_s - Смотрите мою последнюю правку. Обратите внимание, что в app.config нет специальной конфигурации безопасности, однако обратите внимание, что SessionMode требуется в определении интерфейса контракта службы. Если я уберу SessionMode, у меня не будет проблемы. Но я до сих пор не понимаю, почему он все еще думает, что ему нужно связаться с доменом.   -  person dcp    schedule 19.01.2011
comment
@marc_s - То, что я опубликовал, было всем моим app.config. Как я уже сказал, в app.config нет специальной конфигурации безопасности. Если я что-то не понимаю, или вам нужно увидеть что-то еще, пожалуйста, дайте мне знать. Я знаю, что в обычном приложении WCF у меня будет узел служб и конфигурация конечной точки для клиентов и т. д., но в этом маленьком тестовом приложении у меня ничего этого нет.   -  person dcp    schedule 19.01.2011
comment
@marc_s - Нет, в данном случае 3,5.   -  person dcp    schedule 20.01.2011


Ответы (4)


Хорошо, я подозреваю, что вы используете привязку (WsHttpBinding), которая по умолчанию аутентифицирует вызывающих абонентов с использованием учетных данных Windows, если вы специально не запретите это делать.

В коде размещения службы вы просто создаете экземпляр WsHttpBinding по умолчанию — в этом случае никаких настроек в конфигурации или коде для изменения поведения безопасности по умолчанию.

Просто для целей тестирования: попробуйте изменить код хостинга вашего сервиса на:

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

Это эффективно отменит все настройки безопасности, например. ServiceHost больше не должен даже пытаться найти домен Windows для аутентификации вызывающих абонентов.

Изменяет ли это какое-либо из ваших наблюдений?

person marc_s    schedule 19.01.2011
comment
Нет, это вызывает исключение. Контракту System.InvalidOperationException требуется сеанс, но привязка «WSHttpBinding» не поддерживает его или не настроена должным образом для его поддержки. Но спасибо за предложение, я благодарен за него. Я отправил вам по электронной почте zip-файл, содержащий всю программу и файл решения, если вы хотите поиграть с ним (надеюсь, что все в порядке :)). - person dcp; 20.01.2011
comment
@dcp: попробуйте следующее: используйте SecurityMode.None в своем конструкторе и удалите SessionMode.Required из своего сервисного контракта — ваш ServiceHost теперь откроется в мгновение ока (менее 1 секунды). Настройка режима сеанса и все такое влечет за собой накладные расходы... так зачем вам нужен SessionMode.Required в таком сервисе?? - person marc_s; 20.01.2011
comment
Да, я уже знал, что удаление SessionMode.Required устраняет накладные расходы, и служба открывается быстро, потому что я пробовал это некоторое время назад. Но вопрос в том, почему при наличии SessionMode.Required компьютеру требуется 7 секунд, чтобы понять, что он не является частью домена? Что касается того, зачем нужен SessionMode.Required, на самом деле его нет в этом коротком примере, а в моих реальных службах WCF мы используем много транзакций и т. д., и иногда между конечными точками требуются сеансы. В любом случае, еще раз спасибо за ваши предложения. - person dcp; 20.01.2011

Оказывается, если я отключу netbios в своих сетевых подключениях, у меня не будет задержек в вызовах ServiceHost.Open. Я не уверен, почему, но это, казалось, решило проблему.

Странно то, что когда я выполнил чистую установку XP, у меня не было задержек даже при включенном Netbios, поэтому я понятия не имею, почему это происходит с моей существующей установкой (я выполнил чистую установку на той же машине, и затем восстановил мою резервную копию из образа для запуска этих тестов).

person dcp    schedule 22.01.2011

Также попробуйте остановить службу диспетчера автоматического подключения удаленного доступа. Для меня проблема сводилась к Dns.GetHostEntry(String.Empty) и этому сообщению http://social.msdn.microsoft.com/Forums/en/vbgeneral/thread/493d1b65-9ace-41de-b269-f178d27a8a1b

person Warren van Niekerk    schedule 14.02.2011

Кажется, у меня была такая же проблема. Длительная продолжительность открытого вызова, вызванная исключением. Я погуглил для настройки параметров безопасности для службы Wcf. Нашел следующее решение, которое сработало для меня:

Под элементом <wsHttpBinding> в файле Web.config поместите следующую запись:

<security mode="None" />

Ссылка на сервис в клиенте должна быть обновлена!

person Juergen    schedule 05.11.2013