.Net 2.0 Windows 服务进程通信:数据库还是 IPC?

Posted

技术标签:

【中文标题】.Net 2.0 Windows 服务进程通信:数据库还是 IPC?【英文标题】:.Net 2.0 Windows Service Process Communication: Database or IPC? 【发布时间】:2009-07-02 14:25:45 【问题描述】:

我有一个在 .Net 2.0 环境中运行的 Windows 服务(不能升级到 3/3.5)。 该服务在 X 秒间隔上使用 System.Timers.Timer 轮询数据库表上的项目。

Timer.Elapsed 事件处理代码包裹在 lock 语句周围,以防止在前一个处理尚未完成时运行下一个 Elapsed 事件。对于每个项目,执行流程 A,然后从数据库中删除该项目。这是当前的“生产”代码。

需要执行第二个进程(进程 B),但仅针对某些项目(我可以使用条件轻松隔离)并且仅在进程 A 处理它们之后。用于运行进程 B 的资源一次只接受一个连接。 (因此,不能选择为每个 Process B 执行多个线程)如果我要在 Timer.Elapsed 事件处理代码和 Process A 上运行 Process B,这将大大延迟事件处理程序的执行并使其更有可能Elapsed 事件将无法及时完成下一个事件的执行,从而使系统响应速度变慢等。

我认为最好让一个新的单线程执行进程 B(或其他服务,我认为这会有点过分)。进程 A 会为进程 B 排队项目,因此如果进程 B 完成处理项目的时间比进程 A 长,那么下一次进程 A 运行只会将更多项目添加到进程 B 队列中。

我知道使用数据库作为 IPC 并不是一个很好的做法,但考虑到我不能使用 WCF IPC(这可能是我的方法)并且我已经在这里使用了数据库。 ..

如果我继续使用数据库作为我的 IPC 机制并在进程 A 完成后标记数据库上的项目以便进程 B 可以选择和处理它们(包括删除)?还是应该尝试在线程之间使用某种直接 IPC?

如果系统崩溃或服务关闭,我保证队列中的项目将持续存在,这一点非常重要。

 //This is how my Elapsed event handler should look
    private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    
       lock(this)
       
          //Load items from DB
          //foreach item
             //Run Process A
             //if(item.Member == condition)
             //   Queue item for Process B  (DB = reflag,  IPC = send message)
             //If using IPC delete the item from the DB
       
    

【问题讨论】:

【参考方案1】:

除了在 timer_elapsed 中使用“锁定”之外,您可以禁用/启用计时器吗?在开始时禁用计时器,然后在“最终”中启用计时器。这样您就不必担心重叠事件。

如果这不是一个选项并且计时器必须在每个间隔触发,无论处理如何,然后在数据库中标记该项目并使用两个计时器。一个计时器用于“进程 A”,一个计时器用于“进程 B”。

【讨论】:

【参考方案2】:

相反,由于您在问题末尾提到的共同要求,使用数据库作为您的进程间通信渠道是一种了不起的做法:

我很重要 保证队列中的项目 如果系统崩溃或 服务已关闭。

只需确保标记发生在与进程 A 进行的任何其他数据更改相同的事务范围内。

您甚至可以考虑将其拆分为两个服务,并在逻辑进程 A 和 B 之间使用 MessageQueue

【讨论】:

以上是关于.Net 2.0 Windows 服务进程通信:数据库还是 IPC?的主要内容,如果未能解决你的问题,请参考以下文章

为应用程序池“应用程序池”提供服务的进程与 Windows 进程激活服务发生了致命的通信错误

用于进程间通信的 wcf 服务

.Net Core 2.0 Windows 服务

ASP.NET 2.0 中的模拟

Windows Server 2008 R2 上的 .NET 2.0 Web 服务未找到模块异常

大型项目中进程间通信的最佳和最简单方法