Node.js微服务实践(一)

什么是微服务

微服务是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每一个微服务仅关注于完成一件任务并很好地完成该任务。在全部状况下,每一个任务表明着一个小的业务能力。
微服务的概念源于2014年3月Martin Fowler所写的一篇文章“Microservices”(http://martinfowler.com/articles/microservices.html)。javascript

尽管“微服务”这种架构风格没有精确的定义,但其具备一些共同的特性,如围绕业务能力组织服务、自动化部署、智能端点、对语言及数据的“去集中化”控制等等。微服务架构的思考是从与总体应用对比而产生的。html

一般,在一家公司随着业务需求的增加为逐步发展(天然增加)的过程当中,前期每每是以单块架构的方式来组织系统的。由于对于软件的初期构建来讲,单块架构的方式是最容易且最高效的。可是若干年(甚至是几个月)后,受限于前期既有单块软件系统内部耦合性,再向该系统加新功能变得愈来愈艰难。java

单块软件

企业应用,由于服务于众多业务需求,所以会有些特定的软件应用提供许多功能,而通常惯例是把这些功能都堆在单个单片应用中。例如,ERP,CRM和其余各类软件系统被规划构建为具备数百个功能的总体。这种带坑应用一经部署,在日后的故障排除、扩展和升级场景中就是一场接一场的恶梦了。node

面向服务架构(SOA)旨在经过引入“服务”的概念来克服以上的限制,“服务”是从应用程序提供的相似功能中提取出来的聚合和分组。所以,使用SOA,软件应用程序就会被设计为“粗粒度”服务的组合。然而,SOA中服务的范围很是普遍,这又引出了复杂而庞大的服务与一大堆操做(功能)以及复杂无比的消息格式和标准(如WS *标准)。数据库

image

多数状况下,SOA中的服务彼此独立,只不过它们与全部其余服务一块儿部署在相同的运行时间里(只需考虑将部署到同一个Tomcat实例中的多个Web应用)。和单片软件应用相似,这些服务经过积累各类功而具备随时间推移的习惯。图1是一个很是好的一个单片架构的例子,显示了包括多个服务的零售软件应用,全部这些服务都能部署到同一应用程序。express

说了那么多,你们是否是有点不明因此?我总结了一些重点,如下就是基于单快软件架构的应用程序的一些特性概括:npm

  • 单片应用程序被设计、开发和部署为单个单元。
  • 单片应用相对复杂,致使维护,升级和新特性困难重重。
  • 难以用单片架构来实践敏捷开发和交付方法。
  • 想更新某部分,极可能要从新部署整个应用。
  • 规模需求冲突的状况下,若想作单点扩展,要作好多倍资源甚至推倒重来的准备(例如,想给A服务更多CPU,B服务可能要重作,也可能要补两三倍memory)
  • 可靠性:一个不稳定的服务能够拖慢整个应用性能。
  • 难创新:采用新技术和框架很是困难,由于全部的功能必须创建在均匀的技术/框架上。

面向微服务的架构

面向微服务的架构拥有一些特质。任意规模的大中型公司若是想让自身IT系统保持弹性,并但愿随时均可以对系统规模进行伸缩的话,一定会对这些特质趋之若鹜。编程

为何面向微服务的架构更好

微服务架构(MSA)的基础是将单片应用做为一套小型和独立服务来开发,这些服务都在本身的空间独立开发、部署和运行。在微服务体系结构的大多数定义中,它广泛被解释为将巨大的可用服务隔离成一套独立服务的过程。api

可是面向微服务的架构并是不工程的圣杯。弹性、可组合性以及灵活性是面向微服务架构设计的关键原则。若是不遵照你将失去一个完美的解决方案,并最终在单块应用分拆多台机器上时遇到大量的问题。服务器

不足之处

事无绝对,微服务也会有几下问题:

  • 网络延迟:微服务具备分布式的特性,从而无可避免地会存在网络延迟
  • 运维负担:更多的服务器也意味着须要更多的维护工做
  • 最终一致性:在一个对事务性要求较高的系统中,考虑到实现的局限性,各个节点在某一时间内可能会出现数据不一致

关键设计原则

通常来讲,咱们能够肯定一下设计原则:

  • 单一责任原则(SRP):为微服务提供有限和重点突出的业务范围,有助于咱们知足开发和提供服务的敏捷性。
  • 在微服务的设计阶段,咱们应该找到各服务的边界,并将其与业务能力(也称为域驱动设计中的有界环境 )保持一致。
  • 微服务设计要确保敏捷/独立开发和部署服务的丝滑稳定。
  • 咱们的重点应该放在微服务的范围上,而不是使服务更"小"。服务的大小应该是指所需的范围大小,以促进给定的业务能力。
  • 与SOA中的服务不一样,给定的微服务应该具备不多的操做/功能和简单的消息格式。
  • 随着时间的推移,首先开始具备相对普遍的服务边界,重构到较小的服务界限(基于业务需求),这是一个很好的作法。

关键的好处

如今咱们看几项关键的好处。

弹性

维基百科将弹性定义为系统处理变化的能力。我对弹性的理解是在问题被解决后系统从异常状态或者压力期中优雅的恢复,同时又不会影响系统性能的能力。

这虽然看上去很简单,可是在构建面向微服务软件的时候,问题源会因为系统的分布式特性而被放大,有时很难防止全部的异常状况。

弹性是从错误中优雅回复的能力。可是一样也为系统带来了新的复杂度:若是一个微服务出现了问题,咱们可否防止系统的常规故障?理想状况下,咱们应该以这样一种方式来构建服务:仅对服务响应进行降级而非让系统出现常规故障,即便这样作也并不容易。

可伸缩性

现在各大公司的一个通病是系统存在可伸缩性的问题。一般,这些问题并不涉及应用的每一层次或全部子系统。每每只有个别子系统或服务会明显鳗鱼其他部分,一旦没有处理好容量问题就会致使整个应用发生故障。

下图描述了如何对微服务进行扩展(扩展成两个邮件服务)的,同时又不牵扯系统的其他部分:

image
image

技术的多样性

软件世界每几个月就出更新系统。新语言进入业界成为某类系统事实标准的节奏片刻位停。

  • Golang:因其结合了强大的性能与优雅简洁的语法而成为当前一种趋势,任何只要拥有一门编程语言经验的人均可以在几天学会它。
  • Java:自从Sping Boot 发布之后,他成为在编写敏捷服务方面至关有吸引力的技术栈。
  • DJango:是一款强大且可用于编写微服务的Python的框架,与Ruby on Raile 很是类似。
  • Node.js:利用了著名的JavaScript 的优点,建立了一个新的服务端技术栈,从而改变了工程师们编写新软件的方式。

那么,将这些语言的技术栈结合起来会有什么问题吗?平心而论,这是一个优点:咱们能够选择合适的工具来作相对应的工做。只要待集成的技术是标准化的,面向微服务的架构即可以帮你实现这一点。

下图展现了微服务是如何隐藏数据的存取逻辑的,两个服务在存取数据方面共用同一个通讯点,从而能很好地互相解耦:

image

Node.js 并非一门适合执行并行任务的语言。针对那些处于压力之下的微服务来讲,咱们能够选择一门更适合的语言来进行开发,好比 Erlang,从而能够以一种更加优雅的方式来管理并发。

可替换性

可替换性是指替换系统中某个组件而不影响系统行为的一种能力。
当咱们在讨论软件的时候,可替换性每每是与低耦合密不可分的。在编写微服务的时候不能讲内部逻辑暴露给调用服务,服务实现对客户端来讲是透明的,客户端只须要了解的只有接口。

独立性

全部服务应该都是独立的,他们经过接口进行交互。除了协定确认接口这一环节以外,不一样的工程师团队能够在无需交流的状况下完成对服务的开发。

易于部署

微服务应当易于部署,缘由以下:

  • 少许的业务逻辑,致使更易于部署。
  • 微服务是自治的工做单元,因此升级一个服务对于复杂的系统来讲是一个局部可控的问题。无需从新部署整个系统。
  • 微服务架构中的基础设施和配置都应该尽量的自动化(如 Docker 来部署微服务)。

SOA 与微服务的比较

面向微服务架构(SOA)与微服务架构很是想象的。那么他们之间的区别究竟是什么呢?

微服务是细粒度的 SOA 组件。换句话说,某个单个SOA组件能够拆成多个微服务,而这些微服务经过分工协做,能够提供与原SOA组件相同级别的功能,以下图:

image

微服务与 SOA 之间的另外一个不一样之处是服务互联和编写服务时所使用的技术。而另外一方面,微服务推崇执行的标准(例如 HTTP)倒是人民普遍了解并共同使用的。咱们能够经过选择合适的语言或者工做来构建某个组件(微服务),进而得到 技术多样性 提到的关键好处。

除了技术栈和服务规模以外,在SOA于微服务之间还有一个更大的区别:领域模型。在一个机遇微服务的软件中,每一个微服务应该在本地存储自身管理数据,并将领域模型分别隔离到单个服务中。而在面向SOA的软件中,数据每每存储在单个大型的数据库中,服务之间会共享领域模型。

为何选择 Node.js

Node.js 是一门新型技术栈,对于不少人而言,它仅仅只是一个趋势,离做为解决问题的实际工具还欠点火候。

让咱们来看重点看看 Node.js 。 Node.js 是用来构建面向微服务的架构的绝佳选择,缘由以下:

  • 学习门槛低(若是想要精通仍是有必定门槛的)
  • 易于扩展
  • 对测试友好
  • 易于部署
  • 能够经过 npm 进行依赖管理
  • 有着大量与主流标准协议相集成的库

API 聚合

API 聚合是一项用于将不一样功能(插件、方法等)组合成一个接口的高级技术。例子:

const express = require('express');
const app = express();

app.get('/sayhello', function (req, res) {
  res.send('Hello World!');
});
app.get('/saygoodbye', function(req, res) {
  res.send('Bye bye!');
}

const server = app.listen(3000, function () {

  let host = server.address().address;
  let port = server.address().port;

  console.log('Example app listening at http://%s:%s', host, port);

});

前面的例子使用了 Express, 这是一个在Node.js技术栈中广为流行的 Web 框架。该框架一样也是围绕API聚合来构建的。

让咱们来看下 第四行和第七行。在这些代码里,开发者注册了两个方法。当某人以 GET 请求的方式分别请求 URL:/sayhello 和 /saygoodbye 时,这两个对应的方法将被执行。在该例子中,该接口就是一个在3000端口上监听的app。

小结

在本文中你了解一些面向微服务的架构的关键好处,好比能够为相应的服务选择合适的语言(语言多样性);以及一些可能会加剧咱们负担的误区,好比如何有面向微服务的架构分布式特性而带来的运维方面开销。

最后,咱们讨论了 Node.js 是用来构建微服务的强大工具,以及如何经过利用像 API 聚合这样的技术来从 JavaScript 获益,从而构建出高质量的软件组件。

相关文章
相关标签/搜索