请放弃RPC!分布式编程第一谎言:网络是可靠的 - David Boike


与几十年前相比,网络相当可靠,随着我们继续构建更大,更全球分布的系统,我们使自己容易受到可能发生的所有不良事件的影响。
为了解决这个问题,我们将不得不放弃同步请求/响应类型编程。调用方法(称为远程过程调用或RPC)的面向对象模型倾向于分解为网络不可靠时的条件,将我们的系统置于非确定性状态,这是非常难以摆脱的状态。

现象
请看两个事故:
我们上网的ISP有两个路由器:主路由器和备用路由器。如果有一天,主路由器出现故障。需要切换到备份,却发现其路由表在很长一段时间内没有更新,这导致大部分人无法上网。
另一种情况:项目使用Oracle数据库。一切在开发环境中都很有效,但在生产中还有一个额外的负载均衡器和防火墙。每隔一段时间,负载均衡器就会默默地将连接到数据库的TCP丢弃,但是这些错误的连接继续位于连接池中,因此下次需要连接时,就会得到一个意外抛错。
就在最近,6月12日,亚洲的一家互联网服务提供商在全球大部分地区打破了互联网,在欧洲引发了互联网问题。还有twitter Facebook google等同时出现大面积断网。
一般而言,无论是本地还是全球,您都不能信任任何网络。硬件,软件和安全性都可能导致问题。这在分布式计算的第一个谬论中被编纂:网络是可靠的。
这对于HTTP通信或任何请求/响应或远程过程调用(RPC)通信类型尤其成问题。

解决方案
要提供真正可靠的系统,您必须接受并非总是可以进行跨网络通信。因为我们无法保证通信尝试能够成功,所以我们需要提供一种在故障后自动重试的工具。为了防止在重试期间出现故障,我们可以使用名为store and forward的模式。我们可以将数据存储在本地存储中,而不是直接将数据发送到远程服务器。这样,当我们再次启动时,我们就准备好继续我们离开的地方。我们可以使用事务来确保我们继续重试,直到处理成功。
这超出了围绕Web服务调用的简单重试循环的级别,如果服务器在崩溃时运行,则会失败。我们需要额外的基础设施来实现这些保障

异步消息传递
有许多不同的技术,称为可靠消息传递或消息排队系统,可以解决这些类型的问题。在Microsoft平台上,最着名的是Microsoft消息队列(MSMQ),在Azure上,有Azure Queue StorageAzure Service Bus。在Microsoft生态系统之外,有RabbitMQActiveMQZeroMQ。基本上任何带有“MQ”的东西都表明该产品符合这一系列技术。
这些排队技术将诸如Web服务调用之类的东西包含在称为消息的孤立的,离散的工作单元中。消息队列使用存储和转发来确保消息到达它需要的位置。它可以促进自动重试,因为即使在系统崩溃之后也可以反复尝试消息处理。有些甚至支持事务,因此只有在业务事务成功时才会完全使用消息。这样,可以保证每个消息只成功处理一次。

与简单的重试循环相比,排队技术具有额外的优势。例如,如果我们试图创建一个客户并收到HTTP超时,我们将无法知道服务器是否收到了数据并且根本无法响应,或者是否相反,数据根本没有到达。

重试带来了服务器端复制的可能性。如果我们重新尝试创建客户,我们可能会意外地创建客户两次。

消息队列带有消息ID的概念,以便服务器可以决定尝试是否是重试。实质上,消息传递允许在服务器端进行重复数据删除。

放弃请求/响应
异步消息传递需要稍微改变思路,因为它不能提供执行典型Web服务调用中看到的传统请求/响应的能力。
将消息发送到消息队列是一种即发即弃的操作。您将消息放入队列中,最终它将进入服务器,服务器将处理它。您没有在下一行代码上获得立即返回值。
最终,通过解决某些基础架构问题,异步消息传递会迫使您重新设计系统的逻辑流程。
这是排队技术的艰难飞跃:并不是说他们有一个难以使用的API(他们没有),但他们需要放弃更传统的请求/响应编程模型。
不幸的是,你不能只使用HTTP系统,插入队列并运送它。它需要对系统进行重大的重新设计,有时需要重写。
这可能很吓人,但结果是值得的。

(banq注:这也是CAP定理的由来,CAP是分布式系统黄金定律,没有人能够逃脱其三选二,CAP其中有一个P分区容错,就是针对分布式网络的不可靠造成脑裂分区的容忍度,如果你需要P,那么只能C和A之间选择,但是普通人只会忽视P,选择CA,这也是关系数据库的特点,当人们处于一个世界舒适久了,忘记更大的世界,)

很吓人。。。吓不到我。。。