Spring Cloud 服务治理

本文将介绍微服务领域中的服务治理理论,并说明 Nacos 基本概念及其使用方法。

一、微服务相互调用问题

假设有微服务 A 和微服务 B,每个微服务均是一个由若干节点组成的集群,微服务 A 希望调用微服务 B。

一种做法是:

增加负载均衡层,它维护一个 KVMap,K 为微服务的虚 IP 地址,V 为微服务的节点列表。当微服务希望相互调用时,应该访问负载均衡层,并携带虚 IP 地址以指定目标微服务。负载均衡层接收到请求后,通过负载均衡的方式将请求转发到目标微服务的某个节点中。

显然,这种做法需要额外维护负载均衡层,维护节点列表。假设应用由大量微服务组成,运维压力将会非常庞大。

二、服务治理

1. 什么是服务治理?

针对应用集群的相互调用问题,Spring Cloud 引入了服务治理理论。

具体来说:

  • 微服务相互调用时,不希望通过额外中间层,而是双方直连,因此提供了服务注册、服务发现两项机制
  • 考虑到节点可能发生异常,提供了异常容错机制

2. 服务注册和服务发现

具体来说:

  • 有一个中心化的注册中心,他是服务节点信息的管理者
  • 服务注册:当微服务节点启动,它应该将自己的信息注册到注册中心中
  • 服务发现:每隔一段时间,节点从注册中心获取节点列表
  • 服务调用:当节点希望访问其它服务时,根据本地负载均衡策略,从服务的节点列表中选取某个节点,发起服务调用

3. 异常容错

考虑节点可能因为故障导致无法正常工作,针对这一问题,业界通用的解决方案是 “心跳检查”,具体来说:

  • 所有的节点都需要每隔一段时间向注册中心发送心跳信息

  • 如果节点持续发送心跳信息,则一切正常;

    如果注册中心在一段时间内没有收到某个节点的心跳消息,会将其标记为下线状态,并从服务节点列表中剔除

  • 如果节点关闭或重启,它应该主动发送一条 “下线” 指令给注册中心,以便注册中心将节点下线

三、Nacos - 服务治理

1. 什么是 Nacos?

Nacos 是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

2. 基本概念

(1) 领域模型

Nacos 领域模型描述了微服务与节点之间的关系。

领域模型从上到下分为服务、集群、实例三层,如图所示:

(2) 数据模型

Nacos 的数据模型包含三个层级结构,如下:

  • Namespace:命名空间;可以通过它来区分开发环境、生产环境等;默认为 public
  • Group:分组;默认为 DEFAULT_GROUP
  • Service ID:服务 ID

通过 Namespace + Group + Service ID,可以定位到某一个微服务。

例如,通过 Production.A.orderService 定位到生产环境下 A 分组的订单服务

3. 示例 - 服务注册

(1) 添加依赖

1
2
3
4
5
6
7
<dependencies>
<!-- Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>

(2) 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
spring:
cloud:
nacos:
discovery:
# 命名空间
namespace: dev
# 分组
group: myGroup
# 服务ID
service: Mall-Product
# Nacos地址 [可以配置多个,逗号分隔]
server-addr: localhost:8848
# 心跳时间间隔,时间单位是ms
heart-beat-interval: 5000
# 超过一定时间未收到心跳就标记为不健康,默认为15s
heart-beat-timeout: 20000
# 是否在启动时读取服务列表缓存 [若true,则会在本地文件中保存服务列表,在启动时读取]
naming-load-cache-at-start: false
# 向注册中心注册服务,默认为true [如果只消费服务,不作为服务提供方,可以设置成false以减少开销]
register-enabled: true

(3) 启动项目

项目启动后,将会自动向 Nacos 注册,并发送心跳信息。

4. 示例 - 服务发现

(1) 添加依赖

服务发现往往搭配客户端负载均衡,这里采用 Nacos + Loadbalancer 的组合

1
2
3
4
5
6
7
8
9
10
11
12
13
<dependencies>
<!-- Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

<!-- 负载均衡 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
</dependencies>

(2) 配置 HTTP 客户端

RestTemplate 和 WebClient 是 Spring 提供的两个用于访问 HTTP 服务的客户端。如果希望为 HTTP 客户端开启负载均衡功能,只需在注册 HTTP 客户端时添加 @LoadBalanced 注解即可。

具体来说:

  • RestTemplate:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @Configuration
    public class RestTemplateConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
    return new RestTemplate();
    }

    }
  • WebClient:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @Configuration
    public class WebClientConfig {

    @Bean
    @LoadBalanced
    public Builder register() {
    return WebClient.builder();
    }

    }

(3) 发出请求

传入 uri 时,无需指定具体 IP 和端口,只需说明服务名即可。

Nacos 会通过服务发现机制获取到目标服务的所有节点列表,负载均衡过滤器会从列表中选取一个节点进行调用,整个流程对开发人员都是透明、无感知的。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Resource
private Builder webClientBuilder;

@PostMapping("/list")
public List<Order> list() {
return webClientBuilder
.build()
.post()
.uri("http://Mall-Order/order/list")
.retrieve()
.bodyToMono(new ParameterizedTypeReference<List<Order>>(){})
.block();
}

参考

  • Spring Cloud 微服务项目实战