воскресенье, апреля 19, 2015

Orleans Silo Host + TopShelf windows service

TopShelf - хорошо сделанная библиотека для создания windows сервисов. Чтобы с ней сделать windows service достаточно просто добавить пакет Topshelf из NuGet и написать несколько строчек в Main(). Получается сервис, который можно запускать как консольное приложение, а можно установить в службы, запустив с командой install.

Orleans - интересная реализация системы акторов для .NET. Некоторых вещей в orleans пока сильно не хватает, например возможности управлять запущенной нодой (Silo). То есть, чтобы обновить код работающего под управлением Orleans приложения, мне придётся сначала грохнуть процесс, потом переписать файлы и запустить процесс заново.

Решил совместить оба варианта, чтобы можно было управлять запущенной нодой как windows-сервисом и останавливать-запускать из командной строки. Заодно появляется возможность разворачивать сервис с помощью, например, удобного Octopus Deploy.

Черновик на github.

Чтобы не дублировать код, берём из sdk orleans готовый OrleansHost.exe и добавляем как reference в наш проект. Для того, чтобы остановить запуск сервиса при ошибках запуска Orleans, используем предоставленный TopShelf экземпляр HostControl, и вызываем .Stop(), после того как отработает OrleansHost.Run().

internal class Program
{
private static void Main(string[] args)
{
HostFactory.Run(x =>
{
x.EnableServiceRecovery(a =>
{
a.OnCrashOnly();
a.RestartService(1);
});
x.Service<WindowsServerHost>(s =>
{
s.ConstructUsing(name => new WindowsServerHost());
s.WhenStarted((tc, hc) =>
{
if (!tc.ParseArguments(SiloStartupArgs()))
{
tc.PrintUsage();
}
else
{
Task.Factory.StartNew(() =>
{
tc.Init();
tc.Run();
hc.Stop();
});
}
return true;
});
s.WhenStopped(tc => { tc?.Dispose(); });
});
x.RunAsLocalSystem();
x.SetDescription("my orleans service");
x.SetDisplayName("testorleans");
x.SetServiceName("testorleans");
});
}
private static string[] SiloStartupArgs()
{
var siloName = ConfigurationManager.AppSettings.Get("SiloName");
if (!string.IsNullOrEmpty(siloName))
{
return new[] {siloName};
}
return new string[] {};
}
}
view raw program.cs hosted with ❤ by GitHub

Комментариев нет: