1

目标:将连续生成的记录可靠地传输到中央 SQL。

总结:卫星需要向中央询问自己这边的最新数据是什么,然后它会不断地发送更新的数据。

卫星 SQL 服务器有时可能会(重新)启动(与物理生产机器有关),中央 SQL 机器可能会运行更长时间,但也可能会有一些停机时间。这些线路大多是可靠的,但人们永远不知道......我希望SQL Server 服务代理能够自然地解决连接问题。但是,我需要解决初始握手和发送数据的问题。我需要设计协议,而我的 SSB 知识仍然很差。

我希望我了解使用 SSB 进行通信的基础知识,这些基础知识被很好地简要描述为

您应该从每个工作项开始进行自己的对话。生产者(发起者)开始对话并发送描述工作项的消息,然后提交。消费者(目标)接收消息(或被激活),检查有效负载以了解工作项详细信息,执行工作,然后结束对话并提交。生成的 EndDialog 消息被发送回发起者服务队列,发起者队列上的一个激活过程通过结束发起者端的对话来响应它。

... 由 Remus Rusanu 撰写(如果有兴趣,请参阅他之前的回答中的更多详细信息)。

我想将记录作为这样的 XML 消息发送(此处为多行字符串)

<row a="1" b="11" c="111" />
<row a="2" b="22" c="222" />
<row a="3" b="33" c="333" />
<row a="4" b="44" c="444" />

而且我已经学会了如何编写SELECT从 XML 消息中获取信息的方法

通信:假设SQL服务器之间的通信机制刚刚激活......

  1. 卫星 SQL 获得了新数据,不知怎的,它知道卫星和中央之间没有待处理的消息。但它也不知道哪些数据已经发送到中央。因此,它必须询问中央它最后可用的数据是什么。

  2. 如果我理解END CONVERSATION正确,该命令会导致仅发送一种空消息N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'。因此,中央可能应该ReplyMessageEND CONVERSATION.

  3. 同时,卫星可能不应该做任何异步行为(即在发送后等待RequestMessage)。一旦ReplyMessage到达,它就会激活一个卫星程序,该程序:

    • 接收消息并获得想要的信息,
    • 接收到 EndDialog 消息并在卫星端结束之前的对话,
    • 准备要发送到中央的数据(XML 字符串形式),
    • 打开新对话框,
    • 发送准备好的数据,
    • 并让自己处于休眠状态,直到另一个ReplyMessage人到来。
  4. 中央应该有类似的行为。一旦RequestMessage到达,它就会激活中央程序:

    • 接收请求消息,
    • 提取 XML 信息并更新中央数据库,
    • 获取有关卫星最后可用数据的信息,
    • 形成并发送ReplyMessage,
    • 在中间结束对话。

到目前为止,我的观点正确吗?

现在有一些我不确定的细节:因为我想让它变得健壮,在没有人为接触的情况下工作,它应该在安装机制时自行启动。通信应始终由卫星启动(即使卫星工作甚至存在,中央也可能不知道)。

卫星已经使用由原始数据触发的触发器,该触发器被处理以构建在中央收集的记录。这样,触发器可以以某种方式向中心发起卫星的第一个 SSB 请求。但...

  • 触发器如何检查卫星和中央之间没有挂起的通信?由于卫星始终是发起者,问题也可以表述为……触发器如何检查卫星是否等待一些ReplyMessage?或者,如何知道卫星和中央之间有一些开放的对话?
    • 如果没有对话,触发器形成数据记录(存储在本地表中),然后它可以启动通信过程(参见上面的第 1 点)。
    • 如果有任何对话,触发器只会形成稍后要发送的记录,不会做任何其他事情。ReplyMessage当通过激活的程序获得时,将发送数据(参见上面的第 3 点)。
  • 关于使卫星休眠(参见上面第 3 点的最后一个项目符号),我的意思是消息队列中可能没有其他消息(循环中没有要处理的内容),并且激活的过程自然会完成。但我不确定我在这里是否正确地思考。你能对此发表评论吗?
  • 如果没有任何问题,并且数据产生的速度足够快,那么卫星和中央总有一些东西可以交换。这样,触发器永远不应该尝试开始通信。
  • 当激活的卫星程序没有其他内容要发送到中央时(实际上,它不是活动的),或者当系统以某种方式重新启动(尚不存在对话)时,触发器启动通信过程。但我怎么能做到呢?触发器是否应该简单地将 发送RequestMessage到中央?(这种方式ReplyMessage将激活卫星程序,并且程序将继续,直到有任何事情要处理。)
  • 比如说,这里的RequestMessage手段是一些数据,处理它们,然后回复最后一个(或者下一个应该发送什么或者从中央推荐下一个动作——取决于业务逻辑,在这里可能并不重要)。在我不知道您还需要什么的意义上发送空 XML是否可以 - 告诉我?RequestMessage

第一次更新- 基于以下 Remus Rusanu 的回答

我不得不同意这将是健谈的协议。此外,这些记录是作为来自真实环境的温度样本创建的,并且采样频率相当低。这意味着复杂的协议只有在重启一切的特殊情况下才有用。

但是当对话应该永远打开时,对话句柄的唯一标识符应该永久存储在某个配置表中,或者它甚至可以硬连线到代码中。触发器将立即即时发送记录,而中央根本不会发送ReplyMessage. 这是对的吗?这种覆盖可以有效地被认为是独白吗?

第二次更新使这个问题相当简短。

请参阅续篇Service Broker:触发器应如何启动无限打开的对话框?

4

1 回答 1

2

我需要解决初始握手和发送数据的问题。

我无法告诉你阅读这篇文章是如何带回 2004 年的闪存的……当时我们在设计发布-订阅协议(“独白”与“对话”),其中一个设计要点是要求“检查点”。这样想:“发布者”分发项目目录。它最初将目录的内容作为检查点消息发送,然后继续将任何更新发送到目录(添加或删除的项目、价格变化等)作为更新消息。每当有人订阅此发布时,它都需要获取检查点消息和所有后续更新消息,以便他的目录是最新的。随着时间的推移,更新列表变得非常长,因此发布者会定期重新发送当前目录状态作为“检查点”。后续订阅者只需要最后一个检查点,以及此后的任何更新。此外,发布者基础设施可以删除在最后一个检查点之前发送的所有消息,因为订阅者将不再需要它。这解决了新订阅者加入“中间”数据流并获得一致状态的问题。问题(和解决方案)与 SQL Server 本身处理日志记录和恢复的方式没有什么不同(并且名称“检查点”并非巧合......)。现在当然,

我将您提出的消息交换模式总结如下:卫星需要向中心站询问中心的当前状态(“水印”)。它以典型的请求-响应模式执行此操作:BEGIN_TRAN->BEGIN_DIALOG->SEND_Request->COMMIT 在发送方,Activation->BEGIN_TRAN->RECEIVE->SEND_Response->END->COMMIT 在接收方大小,Activation->BEGIN_TRAN ->RECEIVE->END->COMMIT 在发送方。

一般来说,这是一个不错的模式,但我认为这不是你想要的模式。你最终会得到类似这样的结果:对于卫星拥有的每一条新信息,它都会询问中心:“你已经拥有了吗?” 然后中心会回复“嗯,是的,我愿意”或“不,请发给我”. 这是一个令人难以置信的健谈协议,涉及为最终从卫星到中心的每条信息交换大量消息。我认为您应该长时间保持对话畅通,将其视为沟通渠道。一旦建立,卫星将在每次有一些新信息时简单地发送数据。您不需要询问中心状态,这是 SSB 的工作,以确保您发送的任何内容都到达中心,即使存在网络故障。在 SSB 编程中,开始对话、发送 1MM 消息并将其保持打开状态是完全可以的。3 个月后发送另一条 1MM 消息也是如此。甚至在系统断开 2 周并且只能在感恩节之后才能真正传递消息的情况下这样做。那是正是SSB 旨在处理的内容。问题是您的程序代码也应该准备好处理这个问题(即永远不要等待回复,它可能会在...... 2周内出现)。

关于 SSB 编程模型的更多信息。通常,任何时候都没有任何人积极地“等待”任何事情,SSB 编程就是对事件的响应。激活模型更接近现在的“函数式编程”。想想 node.js。您的绝大多数代码将依赖于激活的程序。您的代码应始终采用以下形式:“开始事务->接收消息->从数据库中读取消息所属项目的当前状态->确定结果->更新数据库状态->发送响应(如果有)->提交- >退出。onyl 异常是您拥有的触发器之类的东西,即在此激活驱动程序的乒乓球中注入新消息的代码。这个代码(触发器)永远不应该等待它发送的任何响应。它应该发送并继续。对此触发器的 SEND 的任何响应都应通过激活来处理。异步,再次。想想 C# 的新 await async。

于 2012-11-02T15:55:48.987 回答