这建立在How to send messages between Companies之上。如果我决定公司S(upplier)应该以一些简单的基于HTTP的方式从公司(B)轮询订单,那么什么是最佳实施。
实施此类系统的最佳做法是什么?
答案 0 :(得分:3)
解决此类问题的一种方法是使用某种排队产品,作为IBM人员,我会立即考虑使用MQ。然而,因为我自己并不是MQ人,就像你一样,我可能会对你所采取的基于服务的方法感到满意。
有两种可能的方法可以想到。一种是使用WS Reliable Messaging,它将可靠性问题推入Web服务基础架构。另一种是在简单但不可靠的服务之上手动编写您自己的可靠协议。
我没有真正实现WS Reliable Messaging系统的实际经验,我相信它可以工作,但它确实需要对参与者进行一定程度的控制 - 因为它是一个相对较新的标准我们不能保证任何给定的IT商店都有实施手段,供应商之间的互操作性可能是个问题。我对每个SW堆栈的控制越多,我就越倾向于使用WS Reliable Messaging。 [我也应该提到WS Atomic Transaction,它也可用于构建可靠的服务,同样的操作间问题也适用。]
那么滚动你自己怎么样?这里的关键是使所有服务都是幂等的。由于我们没有跨越两个系统的事务保证,因此我们必须假设任何给定的服务调用可能会因未知结果而失败。
我将假设B想要确认S已接受订单,因此我们需要在转移订单时更新B和S的信息。
B必须提供以下服务:
Give me the next order(s)
I have stored {orders ...}
那么我们如何定义“下一步”。如果我们正在处理的卷可以允许我们有一个单独的传输“线程”,那么最简单的情况就可以很好地工作。然后B一次一个地勾选发送的订单,并且订单具有单调增加的ID。然后我们可以简化为:
I have stored order <65,004> please give me the next
请注意,这是一个幂等请求:它可以安全地重复多次。另请注意,S必须预期两次获得相同订单的可能性,并检查是否有重复。
答案 1 :(得分:1)
您可能正在寻找的是两阶段提交。它在互联网上有很好的描述,例如:
http://en.wikipedia.org/wiki/Two-phase_commit_protocol
它的要点:
提交过程如下:
* Phase 1
o Each participating resource manager coordinates local
operations and forces all log records out:
o If successful, respond "OK"
o If unsuccessful, either allow a time-out or respond "OOPS"
* Phase 2
o If all participants respond "OK":
* Coordinator instructs participating resource managers to "COMMIT"
* Participants complete operation writing the log record
for the commit
o Otherwise:
* Coordinator instructs participating resource managers to "ROLLBACK"
* Participants complete their respective local undos
适用于任何类型的数据。
答案 2 :(得分:1)
好的,首先,你不能保证任何不可靠的链接。 Two Generals' Problem证明了这一点对于确定性和非确定性协议。您所能做的就是将不可靠性降低到可接受的程度。
最简单的方法是,在您的情况下,一旦服务器收到轮询请求,它就会发送x
个回复,所有回复都具有相同的GUID
。例如。
S: B, anything new?
S: B, anything new?
S: B, anything new?
B: Yes, S, I need a jacket (order #123).
S: B, anything new?
B: Yes, S, I need a jacket (order #123).
S: B, anything new?
B: Yes, S, I need a jacket (order #123).
S: B, anything new?
B: Yes, S, I need a jacket (order #123).
B: Yes, S, I need some shoes (order #124).
S: B, anything new?
B: Yes, S, I need a jacket (order #123).
B: Yes, S, I need some shoes (order #124).
S: B, anything new?
B: Yes, S, I need some shoes (order #124).
S: B, anything new?
B: Yes, S, I need some shoes (order #124).
...
S
可能会被订单发送垃圾邮件,但由于每次请求都会发送#,所以这不是什么大问题。如果我们之前错过了它,我们现在就得到它。如果我们以前没有得到它,哇哦!我们现在有。系统有效!您会注意到B
在我的示例中发送了5
次消息。在现实情况下,您可能会发送数百或数千次消息,直到您获得所需的可靠性。
现在上面的解决方案是处理和带宽密集型,但它确实有效。一个更聪明的方法是做TCP做的事情:进行三次握手。
S: Hello B. Are you there? -> SYN
B: Hello S, yep I'm here. What's up? -> SYN+ACK
S: Oh good, you're there. -> ACK
S: B, anything new?
B: Yes, S, I need a jacket (order #123).
但是...... HTTP已经做到了。所以,如果某些东西没有到达某个地方,你就会知道。连接超时,连接中断等
现在,您可以在应用程序级别重新编写这些场景(输入WS-ReliableMessaging),但实际上TCP已经可靠。对这些SOAP(ish)框架和虚假协议(它们通常在HTTP之上工作)的一些批评者指责它们在更高的抽象层次上重新发明了轮子和轮子的问题。
最重要的是,任何系统都可能出现故障,包括可靠的消息系统。
就最终的一致性而言,我认为你可能会感到困惑。最终一致性仅适用于分布式存储系统,在Write()
之后,您可能无法使用Read()
确定性地检索它一段时间。这似乎不是你的问题。我的意思是,我看到你在说什么,但在eventually consistent
系统中,假设节点之间存在可靠(足够)的连接。你没有做出这样的假设(即使我认为你应该...... TCP非常可靠)。
答案 3 :(得分:1)
建立在什么,迪娜提到。 Web服务将是解决上述问题的完美解决方案。 可以商定一些协议来定义记录的数量。
S ---> D ( Call a service which would list record keys)
D----> S ( provide xml of keys)
S----> D ( Request each of the records)
D----> S ( Submit record)
如果在同步之后创建了新记录条目,则Destination可以调用在源处部署的服务,该服务将处理新记录。
由于处理通信需要购买Web服务引擎,因此您无需担心消息参数。可以添加SSL以确保安全。
干杯!
答案 4 :(得分:1)
我认为你试图说公司B是一个被动的参与者。 S(供应商)只需要能够获得B发布的所有订单(最终的一致性)。但是B不需要或不关心S已经拥有的订单(不需要提交)。
如果公司B有一个半精确的时钟,你可以使用日期作为单调增加的GUID,具体取决于事件的分辨率 - 如果你需要毫秒级的分辨率,你不会想要轮询。您只使用B的时钟,因此您不必担心同步。如果B发布所有订单,S可以从最后停止的地方获取订单。
我不确定您是否表示易于实施的系统的最佳实践或最佳权衡。根据音量和响应时间,如果您正在进行轮询,则无需将其设置为动态系统。将订单转储为文本文件(由时间戳命名)到由日期命名的目录中,并将它们全部拉下(或选择性地)。您甚至可以按小时或任何有意义的方式将它们存储在目录中。 HTTP GET是幂等的。
这可能很难看,但听起来你不会期望公司B的复杂程度太高。使用SSL和身份验证并将其锁定并加密。
如果你不需要表现,简单就没有错。你从复杂的协议中获得了什么?