【问题标题】:Listening events in a web service or API over Database changes通过数据库更改侦听 Web 服务或 API 中的事件
【发布时间】:2013-10-25 04:34:35
【问题描述】:

我有这种情况,我真的不知道从哪里开始。假设在服务器上托管了一个类似 Web 服务的应用程序(可能是 API)。该应用收到处理某些数据的请求(通过某种方法,我们将调用 processData(data theData))。

另一方面,有一个处理数据的机器人(可能安装在同一台服务器上)。因此,Web 服务将请求插入到一个公共数据库(两个程序都可以访问它),它应该等待该行更改并将结果发回。

机器人定期检查数据库中的新行,处理数据并为该行设置某种标志,表明数据已被处理。

所以这里的主要问题是,proccessData(..) 方法应该如何检查数据行的更改?

我知道一种方法:我可以构建一个迭代块,每 x 秒检查一次行。但我不想那样做。我想要做的是构建某种事件侦听器,当行更改时触发。我知道这可能涉及一些异步编程

我可能在做梦,但在网络环境中这是否可能。

我一直在阅读有关 SqlDependency 类、Async 和 AWait 类等的信息。

【问题讨论】:

  • 很有可能。你能告诉我们更多细节吗?你的客户是什么?您将如何将更改通知您的用户?
  • My Client 是一个 API,它接收要从多个 POS 收取的信用卡。通过支付网关,有多个安全组件,以及一个接收来自所有这些 API 的每个请求的集中式滚刀。机器人所在的地方,数据库所在的地方。

标签: c# sql web listeners


【解决方案1】:

根据您对该分布式系统设计的控制程度,如果您退后一步并尝试在您已将问题缩小到目前的解决方案领域之外进行思考,它的架构可能会更好。您已经确定“主要问题”是寻找分布式服务通过公共数据库相互通信的方法。也许这是你应该挑战的想法。

这些组件有许多潜在的通信方式,如果您的设计目标是减少延迟并因此避免轮询,实际上这可能是需要通知服务完成此工作项的正确方式立即获悉。但是,如果将来该系统的吞吐量必须增加,则批量处理工作项并轮询信息可能成为唯一可行的选择。这也是为什么我选择将我的答案表述得更笼统一些,并更抽象地讨论这个分布式系统的设计。

如果在此考虑之后您的答案保持不变并且您确实希望立即通知,请考虑让处理工作项的组件通知需要通知的组件。作为分布式系统的一般设计原则,最好让对给定数据集最权威的组件也成为回答有关该数据的请求的组件。在这种情况下,您拥有的数据是工作项的完成状态,因此对此采取行动的最佳组件将是完成工作项的组件。该组件最好通知调用客户端和组件该完成。同样重要的是要知道您是否只是为了组件之间的通信而将此数据写入数据库,或者这些行是否具有超出给定工作项完成的任何价值,例如用于报告目的或绩效指标 (KPI)。

不过,我认为您可能不希望进行这样的调用是有正当理由的,例如减少组件之间的耦合或无法以直接方式与其他组件通信。有许多允许此类通知的通信原语,例如 Windows 下的 MSMQ,或 Windows Azure 中的队列。也有反对它的原因,例如依赖于系统内通信的第三个组件,这可能会降低系统的可用性并导致中断。您可能想在这里问自己的问题是:“当周围的一切都发生故障时,我的组件可以做多少工作?”以及“在可靠性和可用性方面,我对该系统的设计优先级是什么?”

所以我认为你可能真正想要解决的主要问题有点抽象:这个分布式系统的组件通信的接口应该是什么样的?

如果在完成所有这些操作之后,您仍将这些组件之间的通信接口设置为 SQL 数据库,那么您可以探索在 SQL 中使用 INSERT 和 UPDATE 触发器。您可以轻松查找这些命令的语法并指定随后执行的存储过程。在这些存储过程中,您可能希望检查任何新行的完成标志,并可能限制您按日期检查的行数或具有最后处理的工作项的 ID。然后通知其他组件,您可以使用内置存储过程XP_cmdshell 在 Windows 下执行命令行。您执行的命令可能是一个简单的工具,可以 ping 您的服务以完成任务。

很抱歉最初忽略了您使用 SQL 查询通知的建议。这也是一种可行的方式,并且通过 Service Broker 组件工作。您将定义一个SqlCommand,就像通常查询您的数据库一样,将其传递给SqlDependency 的实例,然后订阅名为OnChange 的事件。执行SqlCommand 后,您应该会调用添加到OnChange 的事件处理程序。

但是,我不确定如何从将传递给事件处理程序的 SqlNotificationEventArgs 对象中获取对数据库的确切更改,因此您的查询可能需要足够具体,以便应用程序能够告诉您每当查询更改时,工作项就完成了,或者您可能必须在每次收到通知时从应用程序到数据库进行另一次往返,才能知道究竟发生了什么变化。

【讨论】:

  • 嗯,我最初的方法是在数据库记录上设置某种“标志”,表示数据已被处理。然后我的 SqlDependency 检查该标志是否更改。问题似乎是网络服务。在它创建 SqlDependency 对象的那一刻,它会继续执行并可能在没有处理数据的情况下结束它,因此我需要将该执行置于某种空闲进程中,直到发生变化。我所做的是在 web 服务实例上声明一个全局标志,on-change 事件更改该标志,并且 web 服务迭代直到该标志更改。
  • 我当然不喜欢这种方法,它包含了我试图避免的相同迭代,只是它不会针对数据库记录,而是一个全局位标志,我认为这会大大减少对数据库的影响..(我不知道我的解释是否正确,我现在脑子里有很多想法,加上英语不是我的母语,所以如果你读到这里我很抱歉完全没有意义)
【解决方案2】:

您指的是消息队列吗? .Net 框架已经提供了这种功能。我想说让 Web 服务管理应用程序级别的队列。机器人将请求相同的 Web 服务来完成任务。假设作业所需的数据很小,您可以将整个数据保存在内存中。如果您还没有数据库,我宁愿不涉及数据库。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-07
    相关资源
    最近更新 更多