2010-09-06 2 views
1

Я занимаюсь разработкой архитектуры приложения, которое планирую строить, и нуждаюсь в советах по наилучшему способу реализации определенного компонента службы Windows, описанного ниже. Я буду строить службу с помощью .net 4.0, чтобы я мог использовать новые параллельные и целевые API-интерфейсы, я также посмотрел на использование службы MSMQ, но я не уверен, что это подходит для того, чего я надеюсь достичь.Помощь в разработке Windows Service

Самый простой способ объяснить мой пример использования состоит в том, что пользователи могут создавать несколько напоминаний разных типов для задачи, которую они должны выполнить, которую они создают, используя веб-приложение, созданное в ASP.NET MVC 2. Эти напоминания могут быть разных типов, например, электронной почты и SMS, которые должны быть отправлены в указанное время. Напоминания могут быть изменены до момента, когда они были отправлены пользователю, приостановлены и отменены вместе, что, я думаю, делает обслуживание на основе очередей, такое как MSMQ, не подходит?

Я планирую разместить службу Windows, которая будет периодически (если нет более подходящего способа?) Проверить, есть ли какие-либо напоминания, определить их тип и передать их конкретному компоненту, чтобы справиться с ними и отправить их. Если возникает исключение, напоминание будет помещено в очередь с заданным интервалом и повторится снова, это будет продолжаться с увеличением интервала до тех пор, пока они не достигнут установленного порога, в который они будут отброшены и зарегистрированы как сбой. Чтобы добавить последний уровень сложности к службе, я надеюсь указать в файле конфигурации конкретную реализацию каждого типа (это означает, что я могу сказать, что меняют услугу SMS из-за стоимости или чего-то еще), которые загружаются при запуске службы динамически. Любые напоминания о неизвестном или недоступном типе будут автоматически выходить из строя и регистрироваться по-прежнему.

После того, как напоминание было успешно отправлено, оно просто отбрасывает его, однако с помощью шлюза SMS, который я планирую использовать, он требует, чтобы я вызывал его API, чтобы узнать, было ли сообщение успешно доставлено или нет, что означает для проверки этого требуется дополнительный таймер на заданный интервал. Было бы неплохо иметь возможность добавлять дополнительные службы типа напоминания, которые соответствуют унифицированному интерфейсу при запуске службы без необходимости изменения его кода.

И, наконец, я не знаю, должно ли это быть опубликовано как отдельный вопрос или нет, но я подумал, можно ли сказать, создать консольное приложение, которое можно было запустить/остановить в любое время, и при запуске может видеть, что служба windows в настоящее время?

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

Спасибо заранее, Wayne

ответ

4

Для второй части Вашего вопроса, я думал об этом, и вот это класс, я ставлю вместе, что помогает создать службу, которая может быть запущена как в консоли приложения, а также службы Windows. Это свежо с прессой, поэтому могут возникнуть некоторые проблемы для решения, и некоторые рефакторинги требуют esp. вокруг кода отражения.

NB: Вы должны установить тип вывода Сервисного проекта на Console Application, это будет работать нормально как обычное обслуживание.

using System; 
using System.Collections.Generic; 
using System.Reflection; 
using System.ServiceProcess; 
using System.Threading; 

namespace DotNetWarrior.ServiceProcess 
{ 
    public class ServiceManager 
    { 
    private List<ServiceBase> _services = new List<ServiceBase>(); 

    public void RegisterService(ServiceBase service) 
    { 
     if (service == null) throw new ArgumentNullException("service"); 
     _services.Add(service); 
    } 

    public void Start(string[] args) 
    { 
     if (Environment.UserInteractive) 
     { 
     foreach (ServiceBase service in _services) 
     { 
      Start(service, args); 
     } 
     Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress); 
     Thread.Sleep(Timeout.Infinite); 
     } 
     else 
     { 
     ServiceBase.Run(_services.ToArray()); 
     } 
    }  

    public void Stop() 
    { 
     foreach (ServiceBase service in _services) 
     { 
     Stop(service); 
     } 
    } 

    private void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e) 
    { 
     Stop(); 
     Environment.Exit(0); 
    } 

    private void Start(ServiceBase service, string[] args) 
    { 
     try 
     { 
     Type serviceType = typeof(ServiceBase);  

     MethodInfo onStartMethod = serviceType.GetMethod(
      "OnStart", 
      BindingFlags.NonPublic | BindingFlags.Instance, 
      null, 
      new Type[] { typeof(string[]) }, 
      null); 

     if (onStartMethod == null) 
     { 
      throw new Exception("Could not locate OnStart"); 
     } 

     Console.WriteLine("Starting Service: {0}", service.ServiceName); 
     onStartMethod.Invoke(service, new object[] { args }); 
     Console.WriteLine("Started Service: {0}", service.ServiceName); 
     } 
     catch (Exception ex) 
     { 
     Console.WriteLine("Start Service Failed: {0} - {1}", service.ServiceName, ex.Message); 
     } 
    } 

    private void Stop(ServiceBase service) 
    { 
     try 
     { 
     Type serviceType = typeof(ServiceBase); 
     MethodInfo onStopMethod = serviceType.GetMethod(
      "OnStop", 
      BindingFlags.NonPublic | BindingFlags.Instance); 
     if (onStopMethod == null) 
     { 
      throw new Exception("Could not locate OnStart"); 
     } 
     Console.WriteLine("Stoping Service: {0}", service.ServiceName); 
     onStopMethod.Invoke(service, null); 
     Console.WriteLine("Stopped Service: {0}", service.ServiceName); 
     } 
     catch (Exception ex) 
     { 
     Console.WriteLine("Stop Service Failed: {0} - {1}", service.ServiceName, ex.Message); 
     } 
    } 
    } 
} 

Чтобы использовать эту функцию, вы можете копировать стандартный код из точки входа Main службы и заменить его следующим образом.

static void Main(string[] args) 
{ 
    ServiceManager services = new ServiceManager(); 
    services.RegisterService(new Service1()); 

    services.Start(args);  
} 

Метод services.Start() обнаружит, что служба в настоящее время работает как интерактивное приложение и вручную вызвать OnStart метод всех зарегистрированных услуг, после начала основной поток переходит в спящий режим. Чтобы остановить службы, просто нажмите «Ctrl + C», что приведет к остановке Сервисов, вызвав метод OnStop службы.

Конечно, приложение запускается службой SCM, а затем все работает как обычный сервис. Единственное предостережение заключается в том, что служба не должна запускаться с «Разрешить службе взаимодействовать с рабочим столом», поскольку это приведет к тому, что служба будет запущена в интерактивном режиме, даже если она запущена как служба. Это можно обойти, если это необходимо, но эй, я только что написал код.

Мониторинг и запуск/остановка службы

Из командной строки можно использовать net.exe Пуск/Остановка службы

Start a service 
net start <service name> 

Stop a service 
net stop <service name> 

Для управления службы из .NET вы можете использовать System.ServiceProcess.ServiceController

// Stop a service 
System.ServiceProcess.ServiceController sc = new 
    System.ServiceProcess.ServiceController("<service name>"); 
sc.Stop(); 

Для общего общения с сервисом, кроме того, что обеспечивается за счет ServiceController Я предлагаю вам разместить службу WCF как часть вашей службы, которую вы затем можете использовать для связи с сервисом для запроса внутренних данных, специфичных для вашей службы.

Обработка Scheduling

Честно говоря, я был колеблющимся, чтобы ответить на этот аспект вопроса, поскольку существует так много подходов, каждый с там Pros/Cons. Поэтому я просто дам вам несколько вариантов высокого уровня. Вероятно, вы уже это продумали, но вот несколько вещей с моей головы

Если вы используете SQL Server для хранения уведомлений.

Имейте SP, который вы можете вызвать, чтобы получить напоминания, которые подлежат оплате, а затем обработать результат, чтобы поднять напоминания надлежащим образом.

С этой SP у вас есть некоторые варианты

  1. Вызвать SP периодически от службы и обрабатывать напоминания
  2. Have в SQL Работа, которая периодически запускает SP и добавляет напоминание к Service Broker Queue. Затем ваша служба может подписаться на очередь и обрабатывать напоминания, как они появляются в очереди. Преимущество этого подхода заключается в том, что вы можете масштабировать работу с несколькими серверами, обрабатывая генерацию уведомлений напоминания без какого-либо специального кодирования, просто добавьте еще один сервер, на котором выполняется ваша служба, и сообщения будут автоматически распределены между двумя серверами.

Если вы не используете SQL Server для хранения напоминаний

Вы все еще можете использовать подобный подход, как для SQL Server. Конечно, служба Windows может запросить хранилище данных, используя то, что когда-либо было одобрено и обрабатывает напоминания.Получение этого масштаба немного сложнее, так как вам нужно будет убедиться, что несколько серверов не обрабатывают одно и то же напоминание и т. Д., Но не разбивают поезд.

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

+0

@Chris Спасибо за обмен кодом, я надеялся использовать консольное приложение в качестве монитора для работы службы Windows, с которой я мог бы начать и остановить любой момент, чтобы «прослушивать». Однако вы не будете потрачены впустую, так как он пригодится для чего-то еще, что я хотел сделать =) Спасибо, что вам нужна помощь. –

+0

@Wayne, извините, я полностью пропустил точку там. См. Обновленное обновление. –

+0

@Chris Спасибо за обновление, у вас есть какие-либо ссылки или код для размещения службы WCF, поэтому я могу получить внутренний статус. Основная идея заключалась в том, чтобы иметь возможность запускать приложение, чтобы точно видеть, что служба выполняла в любой момент времени, например. Обработка сообщения 1 из 2 и т.д. –

Смежные вопросы