Функции автозапуска / предварительного прогрева не работают в службе IIS 7.5 / WCF

для тестирования многих головных болей реализации IIS / WCF с нуля я построил службу HelloWorld, и клиент прошел (очень красиво)здесь. Я добавил конечные точки для net.tcp, и служба работает должным образом от начала до конца для обеих Привязок под IIS 7.5 (в Windows 7) в собственных ApplicationPool называется HW.

то, что я пытаюсь получить работу,-это объявленные функции автозапуска и предварительной загрузки (или "предварительного кэширования"). Я следовал инструкциям. здесь и здесь (очень похожи друг на друга, но всегда хорошо иметь второе мнение) очень близко. Что означает "я"!--18-->

1) Установите пул приложений startMode...

<applicationPools> 
     <!-- ... -->
     <add name="HW" managedRuntimeVersion="v4.0" startMode="AlwaysRunning" /> 
</applicationPools>

2) ...включено serviceAutoStart и установите указатель на my serviceAutoStartProvider

<site name="HW" id="2">
    <application path="/" applicationPool="HW" serviceAutoStartEnabled="true" serviceAutoStartProvider="PreWarmMyCache" />
    <!-- ... -->
</site>

3) ...и по имени сказал провайдер, с GetType().AssemblyQualifiedName класса, перечисленных в полном объеме ниже

<serviceAutoStartProviders> 
    <add name="PreWarmMyCache" type="MyWCFServices.Preloader, HelloWorldServer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
</serviceAutoStartProviders>

using System;

namespace MyWCFServices
{
    public class Preloader : System.Web.Hosting.IProcessHostPreloadClient
    {
        public void Preload(string[] parameters)
        {
            System.IO.StreamWriter sw = new System.IO.StreamWriter(@"C:tempPreloadTest.txt");
            sw.WriteLine("Preload executed {0:G}", DateTime.Now);
            sw.Close();
        }
    }
}

увы, все это руководство конфигурация, плюс пара iisreset звонит, и я ничего не получу. Нет!--11--> процесс запуска в Диспетчере задач (хотя я получаю его, если я запускаю HelloWorldClient), нет текстового файла и, прежде всего, нет удовлетворения.

существует удручающе скудное количество дискуссий об этой функции, либо на SO, либо в более широкой сети, и несколько подобных вопросов здесь получили мало внимания, все из которых звонит сигнал тревоги или два. Возможно, без необходимости,хотя-любые эксперты там, которые были вниз этой самой дороге раз или два ухода застесняетесь? (Рад предложить все решение, если вы можете предложить хорошее место для его размещения.)


редактировать: я попытался сбросить этот путь в Preload метод к относительному App_Data папка (другой ответ так предполагал, что), не имело значения. Кроме того, я узнал w3wp.exe процесс срабатывает при простом просмотре localhost. Процесс уничтожает импрессивное 17MB памяти для служения вверх по своему одиночному малюсенькому OperationContract, в то время как для цены, предлагающей нулевое значение предварительной загрузки. 17 Мб ColdDeadCache.

4 ответов


Это немного другой подход к вашей проблеме:

  1. использовать Windows Server AppFabric для автоматического запуска сервиса
  2. используйте инфраструктуру WCF для выполнения пользовательского кода запуска

Re 1:функция автозапуска Appfabric должен просто работать из коробки (при условии, что вы не используете ServiceRoute MVC для регистрации ваших услуг, они должны быть указаны либо в Интернете.конфигурации или с помощью физическое *.svc файлы.

Re 2: чтобы ввести пользовательский код запуска в конвейер WCF, вы можете использовать такой атрибут:

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

namespace WCF.Extensions
{
    /// <summary>
    /// Allows to specify a static activation method to be called one the ServiceHost for this service has been opened.
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
    public class ServiceActivatorAttribute : Attribute, IServiceBehavior
    {
        /// <summary>
        /// Initializes a new instance of the ServiceActivatorAttribute class.
        /// </summary>
        public ServiceActivatorAttribute(Type activatorType, string methodToCall)
        {
            if (activatorType == null) throw new ArgumentNullException("activatorType");
            if (String.IsNullOrEmpty(methodToCall)) throw new ArgumentNullException("methodToCall");

            ActivatorType = activatorType;
            MethodToCall = methodToCall;
        }

        /// <summary>
        /// The class containing the activation method.
        /// </summary>
        public Type ActivatorType { get; private set; }

        /// <summary>
        /// The name of the activation method. Must be 'public static void' and with no parameters.
        /// </summary>
        public string MethodToCall { get; private set; }


        private System.Reflection.MethodInfo activationMethod;

        #region IServiceBehavior
        void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }

        void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            serviceHostBase.Opened += (sender, e) =>
                {
                    this.activationMethod.Invoke(null, null);
                };
        }

        void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            // Validation: can get method
            var method = ActivatorType.GetMethod(name: MethodToCall,
                             bindingAttr: System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public,
                             callConvention: System.Reflection.CallingConventions.Standard,
                             types: Type.EmptyTypes,
                             binder: null,
                             modifiers: null);
            if (method == null)
                throw new ServiceActivationException("The specified activation method does not exist or does not have a valid signature (must be public static).");

            this.activationMethod = method;
        }
        #endregion
    }
}

..который можно использовать следующим образом:

public static class ServiceActivation
{
    public static void OnServiceActivated()
    {
        // Your startup code here
    }
}

[ServiceActivator(typeof(ServiceActivation), "OnServiceActivated")]
public class YourService : IYourServiceContract
{

}

это точный подход, который мы используем в течение довольно долгого времени и на большом количестве услуг. Дополнительное преимущество использования WCF ServiceBehavior для пользовательского кода запуска (в отличие от использования инфраструктуры IIS) является то, что он работает в любой среде размещения (ВКЛ. резидентной) и можно более легко проверить.


Я знаю, что это звучит абсурдно, но я столкнулся с той же проблемой (w3wp.exe не запускается автоматически после внесения изменений конфигурации), и это было потому, что я не запускал текстовый редактор в режиме администратора, когда я редактировал applicationHost.конфигурационный файл. Глупая ошибка с моей стороны.

в свою защиту я использовал Notepad++, который сказал мне, что он экономит, когда на самом деле это не так.


Я сделал то же самое. это работает...

в методе предварительной загрузки у меня есть код, скопированный из хорошей белой бумагиздесь!

выглядит метод предварительной загрузки...

 public void Preload(string[] parameters) 
 {     
        bool isServceActivated = false; 
        int attempts = 0; 
        while (!isServceActivated && (attempts <10)) 
        {
            Thread.Sleep(1 * 1000);
            try
            {
                string virtualPath = "/Test1/Service1.svc";
                ServiceHostingEnvironment.EnsureServiceAvailable(virtualPath);
                isServceActivated = true;
            }
            catch (Exception exception)
            {
                attempts++;
                //continue on these exceptions, otherwise fail fast 
                if (exception is EndpointNotFoundException ||
                    exception is ServiceActivationException || 
                    exception is ArgumentException) 
                {
                    //log 
                }
                else
                {
                    throw;
                }
            }
        }
   }

может быть, вы находитесь на 64-битной системе? Есть известный "функции" в Windows, где сохранение перенаправляется в 32-битную папку и, таким образом, никакие изменения не будут подобраны

(я преобразовал мой комментарий к ответу, поскольку ответы могут быть легче найти)