【问题标题】:Implementing a Windows Service - how do I meet these requirements?实施 Windows 服务 - 如何满足这些要求?
【发布时间】:2011-04-15 12:59:58
【问题描述】:

我正在寻找有关实施 Windows 服务的一般建议。我的要求如下:

  • 该服务处理来自数据库的行 - 因此,如果存在具有特定状态的行,它需要做一些工作,写入其他一些表,然后将该行标记为正在处理。
  • 服务启动时可能有数千行等待处理 - 它应该全部处理。
  • 然后服务应该继续运行,处理写入我的 ForProcessing 表中的所有行。
  • 我需要能够优雅地关闭它 - 我不想要任何半处理的行
  • 它需要高效执行 - 如果可能,我不想轮询数据库

所以我的具体问题是:

  • 如何保持它的活跃性并在写入新行时对其做出响应?我可以使用某种SQLDependency 对象来有效地处理新行吗?
  • 如何处理正常启动和关闭?
  • 从数据库中获取行时,我应该获取所有正在等待处理的行,还是一次只获取一个?
  • 假设它已经是后台服务,我会同步处理行吗?换句话说,不需要在后台线程上处理行?
  • 在帐户方面我需要考虑什么以及它在什么权限下运行?这是部署问题吗?
  • 还有其他需要注意的问题吗?

感谢您的建议。

附言。是否有任何其他合理的替代方法可以使用 Windows 服务来实现这一目标?

【问题讨论】:

  • 听起来您正在使用 ForProcessing 表作为队列形式。您是否阅读/考虑过 Service Broker - 它内置在 SQL Server 中。它有一些自己的学习曲线(尽管您可以将大部分逻辑放在 CLR 存储过程中,所以您仍然主要编写 .NET 代码)
  • 如果您刚刚开始创建服务,这里是 C# 中的一步一步:stackoverflow.com/questions/593454/…

标签: c# sql-server windows-services


【解决方案1】:

编写 Windows 服务并没有那么难,但诚然,一开始可能会让人望而生畏。

就刷新业务逻辑而言,我通常会先编写一个命令提示符程序,因为它整个更容易调试。

现在,开始服务。当然,使用 Visual Studio 创建一个 Windows 服务项目。

如何保持它的活力并在写入新行时对其做出响应?我可以使用某种 SQLDependency 对象来有效地处理新行吗?

好吧,我不确定你是否可以,但我可以告诉你你需要什么。你将需要一个线程。如果您不在 OnStart 事件中创建新线程,您的服务将立即停止。该线程可以直接使用 .NET 的众多线程机制之一创建,也可以通过某种 Timer、FileSystemWatcher(可能不适用于您)或其他可能间接完成。

如何处理优雅启动和 关机?

您可以在 OnStop 中执行此操作。你可以通过信号通知你的线程,也许是通过一个全局变量,是时候关闭了。然后,由您的线程及时通知信号并清理并退出线程。如果您正在处理可能需要超过 20 秒的事情,您需要告诉 SCM(服务控制管理器)您需要更多时间。如果你不这样做,停止服务的用户会收到消息说服务没有响应,最终会被杀死。

当从数据库中获取行时,我应该获取所有正在等待处理的行,还是一次只获取一个?

这是一个商业决策。可能应该取决于每个处理需要多长时间,以便在发生停止时及时处理。

假设它已经是一个后台服务,我会同步处理行吗?也就是说,不需要在后台线程上处理行?

同样,这是一个商业决策,但是是的,我可能会保持同步。

在帐户方面我需要考虑什么以及它在什么权限下运行?这是部署问题吗?

嗯,这一切都取决于。 SQL Server 在同一个盒子上吗?您是否使用 Windows 身份验证?如果 SQL 不在同一个框上,您将不得不使用用户帐户或 Network Service。创建服务项目时,您需要添加安装程序。创建项目后,您将获得一个组件类——在灰色屏幕上,右键单击并选择Add Installer。这将创建一个新的组件类,其中已经安装了两个模块。 serviceIntaller1 包含服务名称、显示名称和描述以及启动类型(手动、自动等)。另一个是 serviceProcessInstaller1,由您决定使用哪个登录帐户。

还有其他需要注意的问题吗?

呃,大概吧。但是今天早上我还没有喝咖啡。

真的,最重要的是计划如何让您的线程保持活力并响应最终的 OnStop 请求。例如,如果您要尝试使用 SqlDependency 类,您可能需要在 OnStart 中创建一个 Manual 或 AutoResetEvent,启动您的线程并让您的线程设置 SqlDependency,然后阻止重置事件。然后,在您的 OnStop 中释放您的重置事件,以便您的线程可以清理并离开。在那之后,它只是一个滑下山!

玩得开心!

【讨论】:

  • 我要补充一点,如果您正确地将业务逻辑与 UI(控制台应用程序或 Windows 服务)分开,那么从控制台应用程序迁移到服务。您可以在单独的程序集中处理在服务项目之外创建其他线程和信号,这意味着您可以从控制台或 Windows 服务启动和停止服务,就像 CruiseControl.Net 所做的那样。
【解决方案2】:

我的第一个问题是为什么触发器或 SQL 作业不够好?似乎任何一个都足够了。运行脚本以赶上处理,然后打开触发器。

如果您设置了一项服务,那么 Jim 对首先作为控制台程序运行有很好的建议。或者做这样的事情http://tech.einaregilsson.com/2007/08/15/run-windows-service-as-a-console-program/

另外http://topshelf-project.com/ 看起来也是一个很好的起点。

您可能还想处理服务的暂停和重新启动事件。就像吉姆说的那样,在另一个线程中产生你的处理。我只需要在我没有这样做的地方修复我的服务,并且该服务将处于启动状态,您将无法轻易杀死它。 onStart 方法必须返回。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-17
    • 1970-01-01
    • 2019-09-15
    • 1970-01-01
    • 1970-01-01
    • 2011-03-21
    • 1970-01-01
    相关资源
    最近更新 更多