第 3 章 – 服务治理
服务治理可以说是微服务架构中最为核心和基础的模块,它主要用来实现各个微服务实例的自动化注册与发现。为什么我们在微服务架构中那么需要服务治理模块呢?
在最初开始构建微服务系统的时候可能服务并不多,我们可以通过做一些静态配置来完成服务的调用。比如,有两个服务 A 和 B,其中服务 A 需要调用服务 B 来完成一个业务操作时,为了实现服务 B 的高可用,不论采用服务端负载均衡还是客户端负载均衡,都需要手工维护服务 B 的具体实例清单。
但是随着业务的发展,系统功能越来越复杂,相应的微服务应用也不断增加,我们的静态配置就会变得越来越难以维护。并且面对不断发展的业务,我们的集群规模、服务的位置、服务的命名等都有可能发生变化,如果还是通过手工维护的方式,那么极易发生错误或是命名冲突等问题。同时,对于这类静态内容的维护也必将消耗大量的人力。
为了解决微服务架构中的服务实例维护问题,产生了大量的服务治理框架和产品。这些框架和产品的实现都围绕着服务注册与服务发现机制来完成对微服务应用实例的自动化管理。
目标:
在本章中,您将学习:
- 构建服务注册中心
- 服务注册与服务发现
常见方案
Netflix Eureka
Spring Cloud Eureka,它既包含了服务端组件,也包含了客户端组件,并且服务端与客户端均采用 Java 编写,所以 Eureka 主要适用于通过 Java 实现的分布式系统,或是与 JVM 兼容语言构建的系统。但是,由于 Eureka 服务端的服务治理机制提供了完备的 RESTful API,所以它也支持将非 Java 语言构建的微服务应用纳入 Eureka 的服务治理体系中来。
zookeeper
ZooKeeper 是一个开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 Hbase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。ZooKeeper 的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
Consult
Consul 是一个服务网格(微服务间的 TCP/IP,负责服务之间的网络调用、限流、熔断和监控)解决方案,它是一个分布式的,高度可用的系统,而且开发使用都很简便。它提供了一个功能齐全的控制平面,主要特点是:服务发现、健康检查、键值存储、安全服务通信、多数据中心。
Spring Cloud Alibaba Nacos
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
方案对比
服务治理的方案不一而论,现将主流的技术框架进行横向比对:
从上面的对比可以知道,Nacos 作为服务发现中心具备更多的功能支持,且从长远来看 Nacos 在以后的版本会支持 SpringCloud+K8s 的组合,填补两者的鸿沟,在两套体系下可以采用同一套服务发现和配置管理的解决方案,这将大大的简化使用和维护成本.本节课程将以 Nacos 为例,讲解服务治理的相关概念.
服务治理
在服务治理框架中,通常都会构建一个注册中心,每个服务单元向注册中心登记自己提供的服务,将主机与端口号、版本号、通信协议等一些附加信息告知注册中心,注册中心按服务名分类组织服务清单。
搭建 Nacos 服务
Nacos 的安装和使用都非常简单.下面我们就在 Windows 系统上搭建一个 Nacos 服务吧.
1.下载安装包
在 Nacos 的 GitHub 页面,提供有下载链接,可以下载编译好的 Nacos 服务端或者源代码:
GitHub 主页:https://github.com/alibaba/nacos
GitHub 的 Release 下载页:https://github.com/alibaba/nacos/releases
如图所示: Windows 系统下载对应的 zip 压缩包即可.
2.解压
将 nacos-server-2.1.0.zip 解压到任意非中文目录,此处将其解压到 D 盘的 develop 目录下:
目录说明:
- bin:启动脚本
- conf:配置文件
3.修改端口
Nacos 的默认端口是 8848,如果你电脑上的其它进程占用了 8848 端口,请先尝试关闭该进程。如果无法关闭占用 8848 端口的进程,也可以进入 nacos 的 conf 目录,修改配置文件中的端口:
修改其中的内容:
4.启动
启动非常简单,进入 bin 目录,结构如下:
然后执行命令即可:
当前目录下,打开 cmd 黑窗口,执行 windows 命令:
1 |
startup.cmd -m standalone |
(以单实例本机启动)。
也可以打开 startup.cmd, 修改
set MODE="cluster
为set MODE="standalone"
,然后执行startup.cmd
。
启动成功界面如下:
5.访问
在浏览器中访问 Console 给出的 URL: http://192.168.1.4:8848/nacos/index.html ,Nacos 默认的账号密码都是 nacos 。
登录成功:
本章节,我们通过两个简单的微服务模块来了解 Nacos 是如何进行服务注册和发现.
- 服务提供者
- 服务消费者
注册服务提供者
现在我们已经成功构建了两个微服务业务模块,接下来我们尝试将这两个业务模块加入 Nacos 的服务治理体系中去.服务之间通过 HTTP 协议进行通信,所以当我们使用 Nacos 进行管理的时候,Nacos 也需要知道相关的信息,比如 IP,端口号等。
1. 添加依赖
由于 Spring Cloud Alibaba 是新加入 Spring Cloud 的组件,所以没有在 spring-cloud-dependencies 里面,我们需要在项目的父工程 pom.xml 文件中加入如下依赖管理:
1 2 3 4 5 6 7 |
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.2.5.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> |
2. 添加 Nacos 的客户端依赖
在上一节,我们已经搭建了 Nacos 服务,而想将我们的应用注册到 Nacos 中,我们还需要在模块中添加 Nacos 的客户端依赖。现在将依赖添加到其中一个模块的 pom.xml 文件中:
1 2 3 4 5 |
<!-- nacos客户端依赖包 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> |
3. 添加 Nacos 地址
引入以上依赖之后,我们就可以在 application.yml 文件中配置相关信息,将服务注册到 Nacos 中。
在服务治理框架中,通常都会构建一个注册中心,每个服务单元向注册中心登记自己提供的服务,将主机与端口号、版本号、通信协议等一些附加信息告知注册中心,注册中心按服务名分类组织服务清单。
所以我们需要配置本服务的服务名以及 nacos 的服务端地址信息,如下:
1 2 3 4 5 6 |
spring: application: name: orderservice #注册到注册中心的服务名称 cloud: nacos: server-addr: localhost:8848 #nacos 服务端地址 |
4. 启动测试
重启当前应用,观察 nacos 控制台服务管理下的服务列表菜单,注册成功则会将该应用实例显示在列表中。
按照以上步骤,我们可以将另一个服务也注册到 Nacos 中,注册成功后,可以在 Nacos 中看到两条服务信息.
服务发现与消费
通过上面的内容介绍与实践,己经搭建起了微服务架构中的核心组件——服务注册中心。同时,还对两个业务模块做了改造。通过简单的配置,使该程序注册到 Nacos 注册中心上,成为该服务治理体系下的服务。
现在我们己经有了服务注册中心和服务提供者,服务消费者,下面就来尝试让服务消费者完成两个目标,发现服务以及消费服务。我们通过构建一个简单的示例,看看在 Nacos 的服务治理体系下如何实现服务的发现与消费。
1.添加@LoadBalanced 注解
在没有将服务交由 Nacos 管理之前,我们通过简单的 RestTemplate 对象的方法即可模拟 HTTP 请求,而现在我们将使用服务名代替传统的 IP+端口号的这种 URL,并且实现简单的负载均衡(负载均衡的内容我们将在之后的章节详细介绍).
在声明 RestTemplate 的地方添加注解:
1 2 3 4 5 6 7 8 9 |
/** * 在容器中注册 RestTemplate 方便项目内调用 * @return */ @Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); } |
2.使用服务名
在发送请求的时候,使用服务名替换掉原 IP+端口。服务消费方 Controller 关键代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
@RestController @RequestMapping("order") public class OrderController { @Autowired private OrderService orderService; @Autowired private RestTemplate restTemplate; @GetMapping("{orderId}") public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) { // 根据id查询订单并返回 Order order = orderService.queryOrderById(orderId); //通过RestTemplate查询用户信息 使用服务名代替ip和端口号 String url = "http://userservice/user/"+order.getUserId(); User forObject = restTemplate.getForObject(url, User.class); //封装返回的数据 order.setUser(forObject); return order; } } |
3.测试
当以上步骤完成之后,我们就构建了一个简单但完整的
服务消费方->注册中心->服务提供方
的这样一个简单体系。当我们使用浏览器访问一个服务的时候,该服务内部如何去调用其他服务能力接口的整个过程我们是感知不到的。所以我们像以前一样正常访问即可.
如果测试通过,我们将得到包含两个模块数据的结果集,如下所示案例:
如果希望查询到的 User 实例包含配置文件中的端口信息, 可以这样修改 userservcie
模块 中的 UserController
类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@Slf4j @RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @Value("${server.port}") private String serverPort; @GetMapping("/{id}") public User queryById(@PathVariable("id") Long id) { User user = userService.queryById(id); user.setServerPort(serverPort); return user; } } |
4.如何启动多个服务提供方
在上面的案例中,我们只启动了一个服务提供方,如果我们想要启动多个服务提供方,并且让服务消费方能够负载均衡的访问到这些服务提供方,那么我们需要做一些额外的配置.
- 首先修改运行配置, 开启允许并行运行
- 准备多个配置文件,并且修改端口号使其各互不冲突, 然后修改运行配置的 active profile 为不同的配置方案, 启动多个服务:
- 也可以
直接修改运行配置中的 VM options,添加-Dserver.port=XXXX
,
其中 XXXX 为不同的端口号, 分别启动多个服务.
- 找到现有的运行配置服务, 选择复制配置后修改配置文件或者端口设置, 通过不同的运行配置来启动多个服务.
- 当同时运行 2 个或者多个 springboot 服务时, 可以
alt+8
打开服务列表, 添加 SpringBoot 的配置类型, 可以方便的统一管理多个服务.
- 在 Nacos 运行的运行的情况下可以查看到服务列表, 包括服务的名称, 实例数量, 以及服务的运行状态.
Q: Nacos 服务注册中心的作用是什么?
A: 服务注册中心是一个服务的注册表, 用于存储服务提供方的信息, 以便服务消费方能够找到服务提供方, 从而实现服务的调用.
搭建 Eureka 服务
pom.xml
1 2 3 4 5 |
<!--eureka服务端--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> |
application.yml
1 2 3 4 5 6 7 8 9 10 |
server: port: 10086 # 服务端口 #将Eureka服务注册到Eureka注册中心上,方便以后做集群管理 spring: application: name: eurekaserver # eureka的服务名称 eureka: client: service-url: # eureka的地址信息, 如果搭建Eureka集群则需要配置多个地址, 以逗号分隔, 交叉注册 defaultZone: http://127.0.0.1:10086/eureka |
运行 Eureka 服务, 查看可视化界面
启用 Eureka 客户端
user 和 order 模块:
1 2 3 4 5 6 |
@MapperScan("com.niit.user.mapper") @SpringBootApplication @EnableEurekaClient // for uereka public class MainApplication { ... } |
application.yml
1 2 3 4 5 |
# Eureka 的地址信息 eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka |
Q: Nacos 的服务注册中心和 Eureka 的服务注册中心有什么区别?
A: Nacos 的服务注册中心和 Eureka 的服务注册中心都是用于存储服务提供方的信息, 但是 Nacos 的服务注册中心是一个更加完善的服务注册中心, 它不仅仅是一个服务注册中心, 还是一个配置中心, 服务发现中心, 以及服务管理中心.
活动 3.1
使用 Nacos 实现服务调用
练习问题
- 下面哪个选项不是常见的服务治理方案?
a. Netflix Eureka
b. Zookeeper
c. Spring Cloud Alibaba Nacos
d. Spring Boot Application答案
d
- 我们在使用 Spring Cloud Alibaba Nacos 作为注册中心,可以在发送请求的时候,使用服务名替换掉原 IP+端口。
a. 错误
b. 正确答案
b
- 下面哪条命令是在本机以单实例启动 Nacos 服务?
a. startup.cmd -m standalone
b. startup.cmd -f standalone
c. startup.exe -m standalone
d. startup.cmd答案
a
- 下面哪个是 Nacos 注册中心的客户端依赖?
a. spring-cloud-starter-alibaba-nacos-config
b. spring-cloud-starter-alibaba-nacos-discovery
c. spring-cloud-alibaba-starter-nacos-discovery
d. spring-cloud-alibaba-nacos-starter-discovery答案
b
小结
在本章中,您学习了:
- 服务治理的常见方案
- 搭建 Nacos 服务
- 注册服务提供者
- 服务发现与消费
Views: 4