初探微服务架构
本文内容
前言
在前面两篇文章中,讲解了什么是微服务,何时进行服务拆分,拆分后会到来什么问题等。
这篇文章将带你走进微服务架构,看看它的各个组成部分,主要的几个基本组件如下:
- 服务描述;
- 注册中心;
- 服务框架;
- 服务监控;
- 服务追踪;
- 服务治理。
一次微服务之间的调用流程如下:
- 服务提供者 按照一定格式的服务描述,向注册中心注册服务,声明自己能提供哪儿服务以及服务所在的地址是什么,完成服务发布;
- 服务消费者向注册中心发起请求,查询要调用服务的地址,然后 按照约定好的通信协议发起请求 即可得到结果;
在服务调用过程中:
- 服务的请求耗时、调用次数等指标会被服务追踪组件记录下来,用于故障问题的定位;
- 如果发现请求量过大、出现调用失败等情况,则将通过服务降级、熔断、重试等服务治理手段保证系统的可用性。
微服务架构的模块图:
1. 服务描述
要调用服务,首先要解决的就是 如何对外描述该服务,描述信息包括 服务名、调用所需的参数、调用使用什么传输方式、如何解析结果 等等。
常用的服务描述方式有 RESTful API、XML 配置和 IDL 文件(Interface Definition Language)三种。
1.1 RESTful API
RESTful API 通常用于 HTTP/HTTPS 协议的服务描述,常用 Wiki 或 Swagger 进行管理。
比如下面这个用 Swagger 进行管理的 RESTful API:
因为 HTTP 是一个常用、公开的协议,对于服务消费者来说没有任何学习成本,所以可以非常方便的供他人使用,适用于 跨业务平台之间的服务,比如 不同业务部门之间的服务调用,或提供给外网的服务。
1.2 XML 配置
XML 配置多用在 RPC 协议的服务描述,通过 *.xml
文件来定义服务的接口名、参数等信息。
比如下面这个 XML 配置方式的服务描述:
服务消费者 想要引用服务,也需要维持一份对等的 XML 配置文件,因此这种方式 对代码入侵比较高,XML 配置有变更时,服务提供者和消费者都需要更新,适合公司 内部联系比较紧密的业务之间采用。
1.3 IDL 文件
IDL(Inteface Definition Language)文件通常用作 Thrift、gRPC 这类跨语言的服务调用,gRPC 就是通过 Protobuf 文件来定义服务的接口名、参数等信息。
下面是一个 Protobuf 文件的示例,helloword.proto
定义了一个接口 SayHello 方法,它的请求参数是 HelloRequest,它的返回值是 HelloReply:
// The greeter service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
利用 protoc 插件可以自动生成服务端的代码,支持多种语言,下面是生成的 Java 示例代码:
private class GreeterImpl extends GreeterGrpc.GreeterImplBase {
@Override
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
@Override
public void sayHelloAgain(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
HelloReply reply = HelloReply.newBuilder().setMessage("Hello again " + req.getName()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
protoc 插件也能自动生成 Client 端(调用者)的代码:
public void greet(String name) {
logger.info("Will try to greet " + name + " ...");
HelloRequest request = HelloRequest.newBuilder().setName(name).build();
HelloReply response;
// 忽略 try-catch 代码
response = blockingStub.sayHello(request);
logger.info("Greeting: " + response.getMessage());
response = blockingStub.sayHelloAgain(request);
logger.info("Greeting: " + response.getMessage());
}
gRPC 的服务描述是 使用 proto 文件来定义接口,接着使用 protoc 插件来自动生成不同语言的服务端和客户端代码,从而具备跨语言服务调用的能力。
需要注意的是,在描述接口定义时,IDL 文件需要对接口的名称、参数、返回值都进行详细的定义,因此 IDL 文件方式不太适用于接口信息经常变化的情况。
2. 注册中心
解决了服务描述后,能定义好接口了,那么这些接口服务如何被调用者发现进行调用呢?接着就要解决 服务的发布和订阅 问题了。
所以我们需要一个 注册中心,用于 记录服务提供者的所提供的服务及地址,调用者在调用时从注册中心中查询对应的服务地址,然后发起请求即可。
一般的注册中心的工作流程如下:
- 服务提供者根据发布配置文件向注册中心注册服务;
- 服务消费者根据其配置文件在注册中心订阅自己所需的服务;
- 注册中心将返回服务提供者的地址列表给服务消费者;
- 当服务提供者有变化时(如节点更新),注册中心将更变通知给消费者。
流程如下:
3. 服务框架
在有了注册中心后,就可以获取地址调用服务了,但是在调用服务之前,还需要解决下面几个问题:
- 服务采用什么协议通信?是采用四层 TCP/UDP 协议,还是采用七层 HTTP 协议,还是采用 RPC 相关协议?
- 数据采用什么方式传输?有同步、异步、单连接传输、多路复用等。
- 数据采用什么格式压缩?通常都需要对实体进行压缩,减少网络传输的数据量,以加速传输时间。常见的有 JSON 序列化、Protobuf 序列化等。
这就需要一个 微服务服务框架 来解决,比如 SpringCloudAlibaba Dobbo、SpringCloud Feign 等。
4. 服务监控
当微服务多起来的时候,为了掌握每个服务的健康情况,是否能正常提供服务。通常需要一个 服务监控组件,它包含三个流程:
- 指标收集:把一次服务调用的请求耗时、成功与否等信息收集起来,给数据处理中心进行分析;
- 数据处理:从上一步中得到数据后,就可以计算每秒服务请求量、平均耗时、成功率等指标;
- 数据展示:数据经过收集分析处理后,需要通过友好的界面展示出来,方便观看,一般是展示到一个 Dashboard 面板上。
5. 服务追踪
当调用链路较长时,就需要 记录服务调用过程中的每层链路情况,以便进行问题追踪和故障定位。
服务追踪 的大致工作原理如下:
服务消费者发起调用时,会生成一个 requestid,随着请求参数一起传递给服务提供者;
服务提供者收到请求后,需要记录下 requestid,然后处理请求。如果 该服务提供者需要请求其他服务,那么重复第一步,将两个 requestid 都向下传递。
最后请求完成后,根据最开始生产的 requestid,就能串联所有节点,达到服务追踪的目的。
6. 服务治理
服务监控和服务追踪能发现问题所在,而要解决问题,就得靠 服务治理 了。
服务治理:通过一系列的手段来保证服务在意外情况下也能正常调用。
在微服务架构中,常见的意外情况有如下几种:
- 单机故障:当遇到集群中的某一台机器故障时,服务治理可以 自动移除故障机器,保证业务不受影响;
- 单 IDC(互联网数据中心)故障:在某些极端情况下,例如施工挖断光缆、自然灾害导致机房被摧毁,都将导致单 IDC 故障,服务治理可以 自动切换故障 IDC 的流量到其他正常的 IDC 下;
- 某微服务不可用:当调用的某个服务不可用时,服务治理可以进行 服务熔断,使服务能正常的返回结果,而避免增加该服务的压力,使其能尽快恢复;
还有一些服务治理的其他手段,比如 服务降级、服务限流、自动扩缩容 等。
7. 总结
可以发现,引入微服务后,需要考虑各种各样的问题,只有你都清楚每个问题的解决方案后,才能进一步实施微服务。
因此,我们接下来需要搞明白上面所提到的一些微服务基本组件:
- 服务描述;
- 注册中心;
- 服务框架;
- 服务监控;
- 服务追踪;
- 服务治理。