我正在设计一个我计划构建的应用程序的体系结构,需要一些关于实现下面描述的特定windows服务组件的最佳方法的建议。我将使用MSMQ4.0构建服务,这样我就可以利用新的并行和任务API,我也考虑过使用.net服务,但我不确定这是否适合我希望实现的目标。
解释我的用例的最简单的方法是,用户可以为他们需要完成的任务创建许多不同类型的提醒,这些提醒是使用ASP.NET MVC2中内置的基于web的应用程序创建的。这些提醒可以是各种类型的,例如电子邮件和短信,这些提醒必须在指定的时间发送。提醒可以被更改,直到它们被发送给用户,暂停和取消一起,我猜这使得基于队列的服务,如MSMQ不合适?
我计划定期托管一个windows服务(除非有更合适的方式?)检查是否有任何到期的提醒,确定它们的类型,并将它们传递给特定的组件来处理它们并发送它们。如果发生异常,提醒将以设置的间隔排队并再次尝试,这将随着间隔的增加而继续发生,直到它们达到设置的阈值,此时它们将被丢弃并记录为失败。为了给服务增加最后一层复杂性,我希望在配置文件中指定每种类型的具体实现(这意味着我可以说,由于成本或其他原因而更改SMS服务),它们在服务启动时动态加载。任何未知或不可用类型的提醒都会自动失败,并像以前一样记录下来。
一旦提醒成功发送,它就会简单地丢弃它,但是对于我计划使用的SMS网关,它需要我调用它的API来确定消息是否成功传递,这意味着需要以设置的时间间隔额外的计时器来检查它。如果能够在服务启动时添加符合统一接口的额外提醒类型服务,而不需要更改其代码,那将是一件很好的事情。
最后,我不知道这是否应该作为一个单独的问题发布,但我想知道是否可以说构建一个控制台应用程序,它可以在任何时候启动/停止,并且在运行时可以看到windows服务当前正在做什么?
这是我在Stackoverflow上的第一个问题,尽管我已经使用这个社区有一段时间了,所以如果我做错了一些事情,我要道歉。
提前谢谢你,韦恩
发布于 2010-09-07 06:59:48
对于你的问题的第二部分,我一直在思考这个问题,下面是我整理的一个类,它有助于创建一个既可以作为控制台应用程序运行,也可以作为Windows服务运行的服务。这是刚刚出版的,所以可能会有一些问题需要解决,并且需要一些重构。围绕反射代码。
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服务作为您的服务的一部分,然后您可以使用它与服务通信,以查询特定于您的服务的内部详细信息。
处理调度的
老实说,我在回答这方面的问题时犹豫不决,因为有太多的方法,每种方法都有优缺点。因此,我将只提供一些高级选项供您考虑。您可能已经考虑过这一点,但这里有几件事是我想不到的
如果使用SQL Server存储通知,则为。
有一个SP,您可以调用它来检索到期的提醒,然后处理结果以相应地引发提醒。
使用此SP时,您有一些选项
SQL定期从您的服务调用SP,并处理reminders
如果未使用SQL Server存储提醒,则为
您仍然可以使用与SQL Server类似的方法。当然,Windows服务可以使用任何适当的方式查询数据存储并处理提醒。要实现这一点有点困难,因为您需要确保多个服务器不会处理相同的提醒等,而不是火车碰撞。
我认为这涵盖了它的要点,其他所有东西都是上面的一些变体。最终,您的决定将取决于目标卷、可靠性要求等。
https://stackoverflow.com/questions/3654629
复制相似问题