什么是微服务?
微服务是在多个独立却又相互联系的服务且拥有其自己的进程和资源的软件设计中最新的术语之一。这种方式有别于典型的客户端-服务端应用设计。通常的客户端-服务端应用包含一个或多个客户端,一个包括全部领域数据和逻辑的后端,以及一个允许客户端访问后端和它的功能的API。
微服务正在代替经典的庞大的后端服务。
在一个微服务架构中,被描述成庞大的后端会被一系列分布的服务取而代之。这种设计允许更好的职责分离,更轻松的维护,在为各个服务选择技术时更高的伸缩性,以及更简单的可扩展性和容错性。与此同时,复杂的分布式系统有一系列的挑战。他们需要处理大量的竟态条件(race conditions),更难进行调试因为不能轻易定位问题到某个单一的服务,而是分布在很多服务。如果为构建这样一个系统所付出的努力没有遵循最佳实践时,你会发现自己如同置身于火海之中而不能自拨。必须对服务的有效负载契约(payload contracts)投以特别的关注,因为某一个服务的变化可能会影响到全部的客户端,从而影响全部后端的服务体系。
这些考虑全部都是重要的,但让我们假设你已经把他们都考虑过了。现在你想要的就是找到一种构建你自己微服务后端的方式。那么让我们直奔主题吧。
如何搭建微服务架构
目前有很多种搭建微服务的方式,在这次教程中我们将关注于代理架构(broker architecture)。
代理架构
代理架构是可以把你的服务相互联系起来的方式之一。
代理架构是可以把你的服务相互联系起来的方式之一。在这里,全部的服务围绕着一个消息服务,即代理商(broker),并且全部都与它连接。服务发送消息给知道随后需要转发这些消息给其他哪些服务的代理商。这种方式,服务不需要保持其他服务的信息。相反,他们依赖于代理商来保管全部的消息,代理商则允许他们各自独立且只关注特别的领域。代理商也可以在接收者关闭时保存消息,允许发送者和接收者不需要强制同时启动,因此允许更高级别的隔离。当然,这种解决方案也是有缺点的因为既然全部的通讯都需要经过代理商很快就会成为瓶颈,同样代理商也会成为你后端的单点失败故障。然而,有一些缓解这些问题的方式。其中一种方式就是并行运行多个代理商实例,以允许更好的系统容错性。另一种方式就是使用别的架构。备选的架构不同于我们在这次教程中实现的架构,不是使用代理商,也不是使用截然不同的代理架构,也不是使用如HTTP这些不同的消息协议。
服务之间的通讯
在这次教程中,我们将使用ZeroMQ来处理服务和代理商之间的通讯。
ZeroMQ提供了一个处理通过随机运输的多部分异步消息的协议抽象层(protocol abstraction layer)。在服务和代理商之间使用ZeroMQ进行消息传递的好处偏离了本次教程的主题,所以我们在这里不再进行深入的研究,但如果你想知道更多,可以通过Quora 文章了解更多。如果你对找到其他能让你的服务可以相互沟通的方法感兴趣的话,我建议你看下代理商vs无代理商的文章。
构建微服务体系
此文章将会引导你完成创建微服务体系所需要的全部步骤。我们的系统将会包含一个代理商和一个服务。我们也会使用一个很小的客户端脚本来测试对服务套件的调用,但请记住客户端的代码可以轻易在任何地方使用。
那么,让我们开始构建吧。
开搞
首先,确保你已经有了需要运行代理商和服务的全部东西。第一,在你的机器上开始下载和安装Node.js,ZeroMQ和Git。如果你使用OSX,每个都有homebrew包,而且大部分的linux贡献中也都有这些软件安装包,所以应该不会有什么问题。Windowns的用户可以使用上面提供的下载链接。
运行代理商
在安装全部必须的依赖后,让我们把代理商运行起来。在这次教程中,我们使用作为ZMQ Service Oriented Suite其中一部分且用Node.js实现的代理商。你可以在GitHub上找到它的代码和文档。为了运行代理商,首先克隆代理商引导程序到你的机器。此仓库是使用以上代理商类库的引导程序。注意,这一步不是必须的因为原始的类库本身是可以运行的,但两者的区别是在引导程序里你可以改变默认的配置。
那么,首先,使用以下的Git命令把项目下载到你的机器:
$ git clone git@github.com:dadah/zmq-broker-bootstrap.git
做完后,切换到刚创建的目录:
$ cd zmq-broker-bootstrap
现在安装包依赖:
$ npm install
代理商现在准备好了。为了运行你的代理商,执行以下命令:
$ bin/zss-broker run
你可以在config/目录下为每个环境找到配置文件。这是默认的开发配置:
{
"broker": {
"backend": "tcp://127.0.0.1:7776",
"frontend": "tcp://127.0.0.1:7777"
},
"log": {
"consolePlugin": {
"level": "debug"
}
}
}
backend参数定义了代理商后端和前端的ip:port地址。后端地址是代理商从服务接收请求和回复用的,而前端地址则是接收和发送给服务客户端用的。你也可以通过改变log.consolePlugin.level来设置日记级别。可以的值是trace,debug,info,warn和error,决定了代理商将会输出的日记信息的数量。
运行服务
在启动了代理商后,是时候开发你的第一个Ruby微服务了。从打开一个新的控制台开始。然后,创建一个保存你的服务的目录并接着去到此目录。在本次教程中,我们将使用Ruby客户端和ZMQ SOA套件。这里有一个可用的“Hello world”服务向导,让我们用它来把我们第一个服务运行起来。
去到你的服务目录并克隆此向导仓库:
$ git clone git@github.com:dadah/zmq-service-suite-ruby-bootstrap.git
进入新建的目录:
$ cd zmq-service-suite-ruby-bootstrap
安装全部的依赖:
$ bundle install
为了启动服务,运行以下命令:
$ bin/zss-service run
很好!你已经把你第一个服务弄好并运行了起来。
如果你去到运行代理商的控制窗口,你会看到以下这样的输出:
2015-12-15 16:45:05 | INFO | BROKER - Async Broker is waiting for messages...
2015-12-15 16:45:14 | DEBUG | BACKEND - received from: hello-word#aaa65374-8585-410a-a41d-c8a5b024553b rid: 76f50741-913a-43b9-94b0-36d8f7bd75b1
2015-12-15 16:45:14 | DEBUG | BACKEND - routing from: hello-word#aaa65374-8585-410a-a41d-c8a5b024553b rid: 76f50741-913a-43b9-94b0-36d8f7bd75b1 to SMI.UP request...
#部分内容略。。。
2015-12-15 16:45:16 | DEBUG | BACKEND - routing from: hello-word#aaa65374-8585-410a-a41d-c8a5b024553b rid: b3044c24-c823-4394-8204-1e872f30e909 to SMI.HEARTBEAT request...
2015-12-15 16:45:16 | DEBUG | BACKEND - reply to: hello-word#aaa65374-8585-410a-a41d-c8a5b024553b rid: b3044c24-c823-4394-8204-1e872f30e909 with status: 200
这些日记意味着代理商已经识别到了一个新服务的存在并且正在接收它的心跳消息。每一秒,此服务都会发送一个心跳消息给代理商,所以它知道服务实例是起来的了。
消费服务
现在我们有了运行的服务,那么如何使用它呢?
在启动仓库里,有一个你可以用来测试“Hello World”服务的小型客户端。简单地打开一个新控制窗口或者标签,并去到你的服务目录。一旦你进入到那后,运行以下命令:
$ bin/zss-client
你应该会看一些类似这样的东西:
15-49-15 16:49:54 | INFO | ZSS::CLIENT - Request 90a88081-3485-45b6-91b3-b0609d64592a sent to HELLO-WORD:*#HELLO/WORLD with 1.0s timeout
15-49-15 16:49:54 | INFO | ZSS::CLIENT - Received response to 90a88081-3485-45b6-91b3-b0609d64592a with status 200
"Hello World"
如果你去到运行服务的控制窗口,你会看到:
Started hello-word daemon...
15-45-15 16:45:14 | INFO | ZSS::SERVICE - Starting SID: 'HELLO-WORD' ID: 'hello-word#aaa65374-8585-410a-a41d-c8a5b024553b' Env: 'development' Broker: 'tcp://127.0.0.1:7776'
15-49-15 16:49:54 | INFO | ZSS::SERVICE - Handle request for HELLO-WORD:*#HELLO/WORLD
15-49-15 16:49:54 | INFO | ZSS::SERVICE - Reply with status: 200
Good!你刚刚启动并消费了你的“Hello World”服务。然而,这还不是我们想要做的。我们要的是构建我们的服务。继续前进!
下一篇:[译] 一步步教你:如何在Ruby搭建微服务架构(下)
本文翻译作者为:dogstar,发表于开源中国个人博客;欢迎转载,但请注明出处,谢谢!