设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

分布式系统编程,你到哪一级了?

2012-6-6 09:59| 发布者: 红黑魂| 查看: 3581| 评论: 0|来自: 伯乐在线

摘要: 介绍当分布式系统编程成为你生活中的一部分时,你需要经历一段学习曲线。这篇文章描述了一下我当前在这个领域大致属于哪个层次,并希望能为你指出足够多 的错误,从别人的错误中学习,从而使你能以最优的路径通向成 ...

介绍

当分布式系统编程成为你生活中的一部分时,你需要经历一段学习曲线。这篇文章描述了一下我当前在这个领域大致属于哪个层次,并希望能为你指出足够多 的错误,从别人的错误中学习,从而使你能以最优的路径通向成功。先声明一下,我在1995年时达到第1级,我现在处于第3级。你自己属于哪一级呢?

第0级:完全一无所知

每个程序员都从这一级开始。我不会在此浪费太多口舌,因为这实在没什么太多可说的。相反,我会引用一些我曾经经历过的对话,为从未接触过分布式系统的开发者们提供一些建议。

对话1:

NN:在分布式系统中,复制是个很容易的操作,你只需要让所有的结点同时存储你要复制的东东就行了 

另一段对话(从我记忆深处挖出来的):

NN: “为了我们的第一人称射击游戏,我们得写一个自己的网络处理引擎。”

我:“为什么?”

NN: “虽然已经有一些优秀的商业引擎了,但获取license的费用非常高昂,我们不想为此买单。”

我:“你之前对于分布式系统有什么经验吗?”

NN:“是的,我之前写过一个套接字服务器。”

我:“你觉得你要花多久能完成这个网络引擎?”

NN:“我想2周吧。保险起见,我计划用4周时间。”

好吧,有时候还是保持沉默比较好。

第1级:RPC

RMI是一种非常强 大的用来构建大型系统的技术。事实上,这个技术用Java来描述的话,结合一些工作的例子可以在短短几页纸内描述清楚。RMI技术非常令人振奋,而且它很 容易使用。你可以调用你所能绑定到的任何服务器资源,而且你可以构建出分布式的网络对象。过去人们常常为构建复杂的软件系统犯难,现在RMI打开了这道大 门。    ——   Peter van der Linden, Just Java(第4版, Sun Microsystems)

我先声明,我并不是说这本书很烂。我清楚的记得这本书读起来很有趣(尤其是章节之间插入的轶闻),我曾经学习Java的时候就是用的这本书(太久以 前了,简直不像在一个时空里似的)。一般情况下,我觉得作者说的挺好。他对RMI的态度就是典型的分布式系统设计的第1级水平。处于这个等级的人对统一的 对象有共同的看法。事实上,Waldo在他们著名的论文“a note on distributed computing”(1994)上曾深入描述过,这里我做下总结:

我所倡导的写分布式应用的策略可分为3个阶段。第1阶段,写这个应用时不用担心对象 存储的位置,以及它们之间的通讯如何实现。第2阶段,通过具体化对象的位置以及通讯方法来调整程序性能。第3阶段,真枪实弹的测试(网络隔离、机器宕机等 各种情况)。这里的思想就是,不管一个调用是本地的还是远程的,对程序的正确性都不会产生任何影响。

同样还是这篇论文,随后进一步挖掘了这个主题并展示了其中的问题。这个观点是错误的,而且已经错了快20年。不管如何,如果说Java RMI达成了一个目标,那就是:就算你从等式中拿掉传输协议、命名、绑定以及序列化,它还是不成立。能记得起CORBA的老程序员们同样也会记得它也是不好使的,但他们有一个借口:CORBA还在同各种底层的问题缠斗中。Java RMI将所有这些都抛开了,但使剩下的问题变得更为突出。其中有两点,第一点纯粹就是个麻烦:

网络不是透明的

让我们看看这段简单的Java RMI代码示例(同样取自Just Java一书)

1
2
3
public interface WeatherIntf extends java.rmi.Remote {
     public String getWeather() throws java.rmi.RemoteException;
}

想要使用天气服务的客户端需要这样做:

1
2
3
4
5
6
7
try {
     Remote robj = Naming.lookup(“ //localhost/WeatherServer”);
     WeatherIntf weatherserver = (WeatherInf)robj;
     String forecast = weatherserver.getWeather();
     System.out.println(“The weather will be “ + forecast);
} catch (Exception e) {
     System.out.println(e.getMessage());

客户端代码需要将RemoteExceptions考虑在内。如果你想看看你究竟会遇到什么样的异常错误,可以看看那20多个子类的定义。这样你的代码就会变得丑陋,好吧,这个我们就忍了。

局部性错误

RMI的真正问题在于这些调用可能会出现局部性失败的情况。比如,调用可能会在对其他层的请求操作执行前失败,又或者请求成功了,但之后的返回值又不正确。引起这类局部性失败的原因非常多。其实,这些故障模式正是分布式系统特性的明确定义:

“分布式系统就是某一台你根本意识不到其存在的计算机,它的故障会造成你的计算机无法正常使用。”  ——  Leslie Lamport

如果这个方法只是去检索天气预报,出现问题时你可以简单的进行重试,但如果你想递增一个计数器,重试可能会导致产生0到2次的更新,结果就不确定 了。这个解决方案应该来自幂等操作,但构建这样的操作并不总是可行的。此外,因为你决定改变方法调用的语义,那你基本上就承认了RMI与本地调用是不同 的。而这也就承认了RMI实际上是个悖论。

不论什么情况下,这种范式都是失败的。因为网络的透明度和分布式系统的架构抽象从来就是无法实现的。这也表明了某些软件所采用的方法比其他软件为此 所受到的影响更多。Scrum的一些变种方法中倾向于做原型化。原型更集中于“好的方面”(happy path),而好的方面通常都不是问题所在之处。这基本上意味着你将永远停留在第1级的水平。(不好意思,我知道这是个小小的打击)

那些脱离了第一级水平的人懂得对于需要解决的这个问题,我们要有足够的尊重。他们摒弃了网络透明化的思想,从战略性的角度来处理局部性失败的问题。

第2级:分布式算法 + 异步消息传递 + 语言级支持

OK,你已经学习了分布式计算中的悖论是什么。你决定吞下这颗子弹,然后对消息传递机制建模,以此显式地控制出现失败的情况。你将应用分为两个层次,底层负责网络和消息传递,而上层处理消息的到达,以及需要处理的各种请求。

这个上层实现了一种分布式状态机,如果你去问设计者这个状态机是用来做什么的,他们可能会这样回答你:这是建立在TCP之上的一个Multi-Paxos算法实现。


酷毙

雷人
1

鲜花

鸡蛋

漂亮

刚表态过的朋友 (1 人)

  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部