跳至主要內容

初探微服务架构

AruNi_Lu微服务架构基础约 2332 字大约 8 分钟

本文内容

前言

在前面两篇文章中,讲解了什么是微服务,何时进行服务拆分,拆分后会到来什么问题等。

这篇文章将带你走进微服务架构,看看它的各个组成部分,主要的几个基本组件如下:

  • 服务描述;
  • 注册中心;
  • 服务框架;
  • 服务监控;
  • 服务追踪;
  • 服务治理。

一次微服务之间的调用流程如下:

  1. 服务提供者 按照一定格式的服务描述,向注册中心注册服务,声明自己能提供哪儿服务以及服务所在的地址是什么,完成服务发布;
  2. 服务消费者向注册中心发起请求,查询要调用服务的地址,然后 按照约定好的通信协议发起请求 即可得到结果;

在服务调用过程中:

  • 服务的请求耗时、调用次数等指标会被服务追踪组件记录下来,用于故障问题的定位;
  • 如果发现请求量过大、出现调用失败等情况,则将通过服务降级、熔断、重试等服务治理手段保证系统的可用性。

微服务架构的模块图:

img

1. 服务描述

要调用服务,首先要解决的就是 如何对外描述该服务,描述信息包括 服务名、调用所需的参数、调用使用什么传输方式、如何解析结果 等等。

常用的服务描述方式有 RESTful API、XML 配置和 IDL 文件(Interface Definition Language)三种。

1.1 RESTful API

RESTful API 通常用于 HTTP/HTTPS 协议的服务描述,常用 Wiki 或 Swagger 进行管理

比如下面这个用 Swagger 进行管理的 RESTful API:

img

因为 HTTP 是一个常用、公开的协议,对于服务消费者来说没有任何学习成本,所以可以非常方便的供他人使用,适用于 跨业务平台之间的服务,比如 不同业务部门之间的服务调用,或提供给外网的服务

1.2 XML 配置

XML 配置多用在 RPC 协议的服务描述,通过 *.xml 文件来定义服务的接口名、参数等信息。

比如下面这个 XML 配置方式的服务描述:

img

服务消费者 想要引用服务,也需要维持一份对等的 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. 注册中心

解决了服务描述后,能定义好接口了,那么这些接口服务如何被调用者发现进行调用呢?接着就要解决 服务的发布和订阅 问题了。

所以我们需要一个 注册中心,用于 记录服务提供者的所提供的服务及地址,调用者在调用时从注册中心中查询对应的服务地址,然后发起请求即可。

一般的注册中心的工作流程如下:

  1. 服务提供者根据发布配置文件向注册中心注册服务
  2. 服务消费者根据其配置文件在注册中心订阅自己所需的服务
  3. 注册中心将返回服务提供者的地址列表给服务消费者
  4. 当服务提供者有变化时(如节点更新),注册中心将更变通知给消费者

流程如下:

img

3. 服务框架

在有了注册中心后,就可以获取地址调用服务了,但是在调用服务之前,还需要解决下面几个问题:

  • 服务采用什么协议通信?是采用四层 TCP/UDP 协议,还是采用七层 HTTP 协议,还是采用 RPC 相关协议?
  • 数据采用什么方式传输?有同步、异步、单连接传输、多路复用等。
  • 数据采用什么格式压缩?通常都需要对实体进行压缩,减少网络传输的数据量,以加速传输时间。常见的有 JSON 序列化、Protobuf 序列化等。

这就需要一个 微服务服务框架 来解决,比如 SpringCloudAlibaba Dobbo、SpringCloud Feign 等。

4. 服务监控

当微服务多起来的时候,为了掌握每个服务的健康情况,是否能正常提供服务。通常需要一个 服务监控组件,它包含三个流程:

  • 指标收集:把一次服务调用的请求耗时、成功与否等信息收集起来,给数据处理中心进行分析;
  • 数据处理:从上一步中得到数据后,就可以计算每秒服务请求量、平均耗时、成功率等指标;
  • 数据展示:数据经过收集分析处理后,需要通过友好的界面展示出来,方便观看,一般是展示到一个 Dashboard 面板上。

5. 服务追踪

当调用链路较长时,就需要 记录服务调用过程中的每层链路情况,以便进行问题追踪和故障定位。

服务追踪 的大致工作原理如下:

  • 服务消费者发起调用时,会生成一个 requestid,随着请求参数一起传递给服务提供者;

  • 服务提供者收到请求后,需要记录下 requestid,然后处理请求。如果 该服务提供者需要请求其他服务,那么重复第一步,将两个 requestid 都向下传递

  • 最后请求完成后,根据最开始生产的 requestid,就能串联所有节点,达到服务追踪的目的。

6. 服务治理

服务监控和服务追踪能发现问题所在,而要解决问题,就得靠 服务治理 了。

服务治理:通过一系列的手段来保证服务在意外情况下也能正常调用

在微服务架构中,常见的意外情况有如下几种:

  • 单机故障:当遇到集群中的某一台机器故障时,服务治理可以 自动移除故障机器,保证业务不受影响;
  • 单 IDC(互联网数据中心)故障:在某些极端情况下,例如施工挖断光缆、自然灾害导致机房被摧毁,都将导致单 IDC 故障,服务治理可以 自动切换故障 IDC 的流量到其他正常的 IDC 下
  • 某微服务不可用:当调用的某个服务不可用时,服务治理可以进行 服务熔断,使服务能正常的返回结果,而避免增加该服务的压力,使其能尽快恢复;

还有一些服务治理的其他手段,比如 服务降级、服务限流、自动扩缩容 等。

7. 总结

可以发现,引入微服务后,需要考虑各种各样的问题,只有你都清楚每个问题的解决方案后,才能进一步实施微服务。

因此,我们接下来需要搞明白上面所提到的一些微服务基本组件:

  • 服务描述;
  • 注册中心;
  • 服务框架;
  • 服务监控;
  • 服务追踪;
  • 服务治理。
上次编辑于: