这是来自richardrodger一篇博文,主要阐述微服务和模式匹配(消息),通过Node.js建立一个Http服务器作为微服务,微服务之间通过消息传递,以微服务构建模块,进而模块化构建一个大型系统。原文大意如下:
Node.js能做大型系统吗?回答是肯定的,沃尔玛(Walmart)和Paypal的案例已经证明,那么大型的Node.JS适合主流的开发者吗?如果你认为Node.js这样的大型系统类似Java和.Net,那么你肯定认为不行:javascript在支持复杂系统扩展性方面是一个弱性的语言。它不是强类型语言,而且有一半的语言是无法使用的。
尽管如此,我们已经建立一些大型的NodeJS系统,下面是我们的总结:
传统的主流的最大型的系统是庞大的铁板一块的monolithic,一个特别大的代码库,有很多文件,几千个类无数个配置文件。如果在javascript中建立这样的体制,可能会发疯。那些将Node.js看成类似蜘蛛侠的人只会推崇使用Java和.NET建立庞大的系统。
铁板一块式monolithic系统是坏的
什么是铁板一块monolithic系统,最简单定义就是,你如果拿出来一部分,整体就会运行失败,每个部分连接到其他部门,相互依存。这个词也用来指一块整石头。
这个词语来自古希腊,建筑直接在洛矶山的悬崖上凿成,由于直接雕刻整个山,他们是无法修复的,城市最终陷入下降。软件系统的复杂性随着时间推移,难以修复和延伸,成本不断提高。
铁板一块式的软件产生的开发流程和方法危害更大,因为系统有这么多依赖,你必须关注如何让开发者在改变它们时非常小心,大量精力用于防止代码失败。从瀑布到敏捷,都是为了铁板一块式的软件服务,都是为了让软件变得越来越大。
模块化系统是好的
作为软件开发者,应该努力避免建立铁板式系统,那就是建立模块化系统,当一个部分丢失时,整个系统还是可以运行。虽然像集装箱那样建立软件的模块化是一个很艰难的过程,但是我们知道这是处理复杂性的唯一方法。
对象是地狱
为实现模块化系统,面向对象范式受到推崇,其实对象比你想象中的要相差很多,他们来自天真的数学观点,是一种纯柏拉图的东西,以相同的属性和特征划分对象,表面上看合理,实际你在打破了现实世界的真实面貌,现实世界是混乱,甚至都打破了数学世界。请问集合是包含自身还是不包含自身呢(banq注:罗素的逻辑悖论)。
对象的最终弱点是,他们只是促成了向铁板式庞大系统发展,对象只是一个系统需要的袋袋,什么都可以往里面装,你有属性,私有和公有,你有方法,也许覆盖了其父类,你也可以有状态。
有太多的东西可以装入对象,结果一个巨大的类包含了最纠结最痛苦的大量逻辑。
NodeJs的模式是简单的
有一个例子认为计算斐波纳契数是CPU密集型,而Node.js只有一个线程,那么计算斐波纳契数的性能是可怕的。你可以使用异步委派到到操作系统,使用processes 过程而不是线程处理,为了避免CPU密集型的计算,你需要将计算任务放入队列,然后异步处理它们。
线程是出了名的难,Node.js的胜利就是避免了它们,你的代码变得易懂。
有一个问题是在javascript中如何实现单例,实际上在现实中很少会碰到这种问题,因为模块已经帮你照看一切,最好的方式是你使用Node.js建立一个Server,通过网络和其他部分通信。
NodeJS确实需要你学习一些新模式,主要是回调模式,回调函数的签名有一个规律:如果有错误发生,第一个对象是错误对象,否则,第一个参数是空的,第二个总是返回的结果。
回调函数自然地来自Node.js的事件处理循环, JavaScript最初用来处理浏览器中用户界面事件,现在非常适合处理服务器端事件果。
当你开始使用Node.js的第一件事就是创建回调(像意大利面条)。你结束了大量的缩进代码,使用回调内嵌回调。经过一些练习,你很快学会使用命名良好的函数结构化你的代码,包括异步模块库。
Node.js的另一个重大的模式是流,已经被编写成API,让你轻松 简洁操作和转换数据,你使用管道将数据从一个流接至另外一个恶瘤,你可以读写全双工的数据流。
以正确的方式思考
编程语言会应当让我在一个正确的层次去思考,可惜大多数语言在此惨遭失败。编程语言在我们思考复杂性过程中成为我们的羁绊,最终发生抽象泄漏(http://www.jdon.com/46006)。
我们应该改变到以面向行动为导向的看待世界方式,这样才能建立好一大型系统,为什么设计模式会失败?因为他们使用静态的概念表达世界,而世界并不是这样,我们的大脑也不是这样工作的。
比如我们开始一个系统总是从用例开始,这是和静止的实体无关的,如果是初学者肯定首先编写一段面向过程的代码,然后才建立一些数据结构,我们现在可以遵循这种大脑自然思考方式上做得更好。
什么是新的设计模式?在我们为客户开发的项目中,我们使用了两个主要方式:微服务和模式匹配。
(banq注:之前已经节省了不少翻译,到这里才进入主题)
微服务Micro-Services
我们可以用生物细胞作为灵感构建健壮的可扩展的系统。生物细胞具有许多有趣的性质。它们体积小,单一用途。
我们不是建立一个铁板式的100 000行的代码库,建设100个小型服务,每个服务有100行代码。弗雷德·乔治(程序员无政府状态的发明者)是这种方法的最大支持者之一,称这些小程序为微服务。
每个微服务执行一个非常有限的任务。这有很好的效果,他们很容易验证。您一眼就能看到他们,测试与否都不重要的。在人的方面,这也意味着这种代码很容易改写,甚至使用不同的语言也是这样。如果一个初级工程师写不好微服务实现,你可以把它扔掉,并重写。微服务易于更换。微服务之间通过发送消息相互通信。您可以直接通过内部HTTP发送这些消息,或者使用消息队列应对大规模。
微服务易于扩展和伸缩,能够达到更精细的粒度级别。目前我们还没有发现所有这些过程的管理过于繁重。
一般来说,你可以使用监控工具来确保服务保持正常运行。一个服务死了处理就变得相对简单。你会有一个重要的服务运行多个实例,然后很快重新启动。如果一些奇怪的事情发生了,也还是重新启动。事实上,这可以让你的系统变得非常强大,可以防止各种腐败现象的积聚。
微服务让你部署任何系统都很容易。刚开始更换一些服务,看看会发生什么。回滚是微不足道的 - 重新启动回归旧版本。微服务也让您的开发团队可伸缩,无论是在个人和团队。个人的大脑更容易和微服务一起工作,因为考虑的范围是如此之小,并且很少有副作用。您可以专心于当前的用例。如果扩展到团队也是很容易,纳入新的服务,知晓会有团队成员之间的一些依赖和堵塞。
最后,微服务以软件的独立单元让你映射到你的用例。他们让你考虑发生了什么。这超越了对象概念的范围。
模式匹配
模式匹配可以让我们在一个合适水平思考,模式匹配以消息为核心,服务之间的消息需要发现一个路径以便到达正确的目标服务,模式匹配越简单越好。当然消息可能并不包括所有的属性,这是使用切面关注比较方便,比如记录所有有关保存数据的消息,只是在这些消息出现时抓取,作为日志项目加入,然后继续发送这个消息,你可以加入权限 缓存等等机制(AOP),所有这些不会影响服务。
一个案例是用户注册,你可能有一个基本注册服务,用来保存用户资料到数据库,但是你要发送一个欢迎Email,或者做其他一些逻辑,你并不能继承这个基本类,你只要继承用户注册的消息即可。
微服务和模式匹配能够很容易使用Node.js实现,这个工具包是Seneca(http://senecajs.org/)