Функции автозапуска / предварительного прогрева не работают в службе 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 ответов
Это немного другой подход к вашей проблеме:
- использовать Windows Server AppFabric для автоматического запуска сервиса
- используйте инфраструктуру 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-битную папку и, таким образом, никакие изменения не будут подобраны
(я преобразовал мой комментарий к ответу, поскольку ответы могут быть легче найти)