如何确保通过网络服务器的拉/查询传输邮件
这建立在How to send messages between Companies上。如果我决定公司S(upplier)应该以某种简单的基于HTTP的方式轮询公司(B)的订单,那么最好的实现方式是什么。如何确保通过网络服务器的拉/查询传输邮件
- 我假设公司B有一个Web服务器正在运行,并且该Web服务器的后端数据库是持久的。我们应该尽可能少地假设S上的存储过程,并且他们是否能够保持状态(例如,已经传输的GUID列表)
- B和S之间的因特网连接是不可靠的。
- 我们必须达到eventual consistency这意味着在一个时间点B和S之间的所有订单都应该被转移。
实施此类系统的最佳实践是什么?
这种问题的一种方法是使用某种排队产品,作为我立即考虑MQ的IBM人员。然而,因为我自己并不是真正的MQ人,所以我可能会对您采用的基于服务的方法感到满意。
想到两种可能的方法。一种是使用WS Reliable Messaging,它将可靠性问题推入Web服务基础架构。另一种方法是在简单但不可靠的服务之上提供自己的可靠协议。
我对WS Reliable Messaging实现系统没有认真的实践经验,我确信它可以工作,但它确实需要对参与者进行某种程度的控制 - 因为它是一个相对较新的标准我们不能保证任何给定的IT商店都将实施交付,并且供应商之间的互操作性可能是一个问题。我对每一端的SW堆栈的控制越多,我就越倾向于使用WS Reliable Messaging。 [我也应该提到WS Atomic Transaction,它也可以用来构建可靠的服务,同样的操作间问题也适用。]
那么你自己怎么样?这里的关键是要使所有服务都是幂等的。由于我们没有跨越两个系统的交易保证,因此我们必须假定任何给定的服务呼叫都可能会因未知结果而失败。
我打算假设B想要确认S已经下了订单,因此我们需要在订单转移时更新B和S的信息。所以
Give me the next order(s)
I have stored {orders ...}
我们如何定义 “下一步”:
B必须提供诸如这些。如果我们正在处理的卷可以让我们有一个单一的“线程”转移,最简单的情况很好地工作。然后,B一次一个地发送已发送的订单,并且订单具有单调递增的ID。我们可以简化为:
I have stored order <65,004> please give me the next
请注意,这是一个幂等的请求:它可以安全地重复多次。另外请注意,S必须预期两次获得相同订单的可能性,并检查重复项。
您可能正在寻找的是两阶段提交。它是在互联网很好的描述,这里例如:
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
应该对任何类型的数据工作。
我认为让“另一端”实现(和测试)两个阶段的原子提交将是相当困难的。 – max 2010-11-03 22:26:30
好吧,首先你不能保证任何东西在一个不可靠的链接。 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是相当可靠的)。
有趣的评论。我所描述的确实可以模拟为分布式存储系统 - 但是大多数分布式系统都可以。想想看,你重复和参考TCP的方法正在攻击错误的问题(可能我曾经笨拙地描述过)。在公司之间IP连接关闭(没问题,只是重试),或者它工作。但后端系统经常停机,或者无法处理该非ASCII字符,或者对于超过35个字符的电子邮件地址有缓冲区溢出......所以更多的是关于“在正确的位置重试”。 – max 2010-11-03 22:30:28
建立在什么,蒂娜提到。 Webservices将是上述问题的完美解决方案。 有些协议可以商定哪些可以定义记录的数量。
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)
在一个新的记录条目的情况下,同步后制成,目的地可以调用部署在源服务,这会处理的新纪录。
由于通信处理购买Web服务引擎,您不必担心消息参数。为了安全起见,可以添加SSL。
干杯!
我认为你试图说B公司是被动参与者。 S(供应商)只需要能够获得所有B岗位的订单(最终一致性)。但是B不需要也不关心S已经有什么命令(不需要提交)。
如果公司B具有半精确时钟,则可以使用日期作为单调递增的GUID,具体取决于事件的分辨率 - 无论如何您都不需要轮询是否需要毫秒分辨率。你只使用B的时钟,所以你不必担心同步。如果B公布所有订单,S可以从最后一次停止的订单中提取订单。
我不确定您是否意味着最佳实践或最佳折衷方案,以实现易于实施的系统。根据音量和响应时间,无论如何您都无需使其成为动态系统。将订单作为文本文件(由时间戳命名)转储到由日期命名的目录中,并将它们全部向下(或有选择地)拉下。你甚至可以按小时或任何有意义的方式将它们存储在目录中。 HTTP GET是幂等的。
这可能很丑陋,但听起来您并不认为B公司会带来太多复杂性。使用SSL和授权,它被锁定并加密。
如果你不需要性能,简单就没有问题。你真的从复杂的协议中获得了什么?
在分钟左右的时间间隔内进行轮询的好主意,从而削弱了时钟同步的要求。 – max 2010-11-10 07:59:09
在e分布式系统中,单调递增的ID有些困难,但是我们可以额外添加:“我现在已经存储了消息,可以删除它”请求。 – max 2010-10-27 09:37:11
++为网络服务 – 2010-11-09 16:43:17
您能否给我一个“Web服务”的例子,WS- *堆栈似乎给我一个不兼容的复杂混乱,但这可能只是我缺乏经验。我在哪里可以找到Github上的WS- *的Ruby/Python/PHP/Perl库? – max 2010-11-11 19:00:29