目录
(2)修改订单服务cloud-consumer-order80
② 在resources下,新建文件:bootstrap.yml
③ 在 consul 的 ui 中创建 config 文件夹
④ 在 config 下创建二级文件夹,表示该微服务的不同开发环境
⑤ 在每个文件夹下,创建一个文件(key),名为 data。
六、Consul服务注册和发现
1.基本介绍
Question1:Consul是什么?
Consul是一款开源的分布式服务发现与配置管理系统,由HashiCorp公司使用Go语言开发。
官方:http://consul.io/
Question2:为什么不使用Eureka了?
① Eureka 停更了,不在开发新版本了
② Eureka 对初学者不友好,有自我保护机制
③ 我们希望注册中心能够从项目中分离出来,单独运行(解耦),而 Eureka 做不到这一点
Question3:Consul能干什么?
① 服务发现:提供HTTP和DNS两种发现方式
② 健康检测:支持多种方式,HTTP、TCP、Docker、Shell脚本定制化监控
③ KV存储:Key、Value的存储方式
④ 多数据中心:Consul支持多数据中心
⑤ 可视化WEB界面
2.下载运行
注意:下载对应的版本(adm64版本的就是x86_64版本的,386就是x86_32版本的)
安装目录下输入cmd,弹出命令行窗口:
输入命令:consul --version,检查是否安装成功
输入命令:consul agent -dev,以开发模式启动
访问 8500 端口,访问 Consul 首页:localhost:8500
3.服务注册与发现
需求说明:将前面单体服务中的支付模块、订单模块注册到 Consul 中
(1)支付服务provider8001注册进consul
步骤:
① 该模块的 pom 文件中引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
② 该模块的 yaml 配置文件编写配置
spring:
application:
# 当前服务名
name: cloud-payment-service
cloud:
consul:
host: localhost
port: 8500
discovery:
#配置当前服务注册到里面使用的名字
service-name: ${spring.application.name}
③ 启动类加上 @EnableDiscoveryClient 注解,开启服务发现功能
@SpringBootApplication
@MapperScan("com.mihoyo.cloud.mapper") //import tk.mybatis.spring.annotation.MapperScan;
@EnableDiscoveryClient
public class Main8001 {
public static void main(String[] args) {
SpringApplication.run(Main8001.class, args);
}
}
④ 启动 8001 服务,查看 consul 控制台:
(2)修改订单服务cloud-consumer-order80
步骤:
① 该模块的 pom 文件中引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
② 该模块的 yaml 配置文件编写配置
spring:
application:
name: cloud-consumer-order
####Spring Cloud Consul for Service Discovery
cloud:
consul:
host: localhost
port: 8500
discovery:
prefer-ip-address: true #优先使用服务ip进行注册
service-name: ${spring.application.name}
③ 启动类加上 @EnableDiscoveryClient 注解,开启服务发现功能
@SpringBootApplication
@EnableDiscoveryClient
public class Main80
{
public static void main(String[] args)
{
SpringApplication.run(Main80.class,args);
}
}
④ 修改 controller
//服务注册中心上的微服务名称
public static final String PaymentSrv_URL = "http://cloud-payment-service";
⑤ 启动 80 服务,查看 consul 控制台:
⑥ 测试访问地址:http://localhost/consumer/pay/get/1
很显然,全局异常处理机制捕获到了异常:
原因:
当你把服务注册到Consul时,Consul充当了服务发现的角色,它会记录服务实例的信息(例如IP地址和端口),然后其他微服务可以通过查询Consul来获取这些服务实例的信息。
RestTemplate 并不具备从服务发现平台(如Consul)动态获取服务实例信息的能力。它会仅仅处理你直接提供的URL(如http://localhost:8080
)。
⑦ 给 RestTemplate 组件加上 @LoadBalanced 注解
@Configuration
public class RestTemplateConfig
{
@Bean
@LoadBalanced
public RestTemplate restTemplate()
{
return new RestTemplate();
}
}
分析:
Consul 作为服务注册与发现平台,确实具有服务发现的能力。但 RestTemplate 本身并不知道如何与 Consul 进行交互,它只会处理你提供的字符串。它不会知道这个地址是不是微服务的名称,也不会知道如何去Consul中查找对应的服务实例。
所以即使你已将 ip 和端口号注册进 consul,但 RestTemplate 还是认为你设置的 url = "http://cloud-payment-service" 是通过硬编码的方式。因此,RestTemplate 是找不到该 url 的。
但加上 @LoadBalanced 后,SpringCloud 会让 RestTemplate 具有服务发现和负载均衡的功能。这意味着,当你传递一个服务名称(如 http://order-service
)给 RestTemplate 时,它会自动知道这是一个微服务的名称,而不是一个硬编码的IP地址。
@LoadBalanced 会让 SpringCloud 通过服务发现机制(如Consul)查找这个服务的可用实例,然后根据负载均衡策略(如轮询等)选择一个实例进行访问。
运行结果:
4.CAP
(1)CAP理论
CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个。
因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三 大类:
CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
CP - 满足一致性,分区容忍性的系统,通常性能不是特别高。
AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。
(2)三个注册中心异同点
组件名 | 语言 | CAP | 服务健康检查 | 对外暴露接口 | SpringCloud 集成 |
---|---|---|---|---|---|
Eureka | Java | AP | 可配支持 | HTTP | 已集成 |
Consul | Go | CP | 支持 | HTTP/DNS | 已集成 |
Zookeeper | Java | CP | 支持 | 客户端 | 已集成 |
Ⅰ. AP 架构(Eureka)
当网络分区出现后,为了保证可用性,系统B可以返回旧值,保证系统的可用性。
当数据出现不一致时,虽然A, B上的注册信息不完全相同,但每个Eureka节点依然能够正常对外提供服务,这会出现查询服务信息时如果请求A查不到,但请求B就能查到。如此保证了可用性但牺牲了一致性
结论:违背了一致性 C 的要求,只满足可用性和分区容错,即AP。
Ⅱ. CP 架构 (Zookeeper/Consul)
当网络分区出现后,为了保证一致性,就必须拒接请求,否则无法保证一致性。Consul 遵循CAP原理中的 CP 原则,保证了强一致性和分区容错性,且使用的是 Raft 算法,比 zookeeper 使用的Paxos 算法更加简单。虽然保证了强一致性,但是可用性就相应下降了。
例如服务注册的时间会稍长一些,因为 Consul 的 raft 协议要求必须过半数的节点都写入成功才认为注册成功 ;在leader挂掉了之后,重新选举出leader之前会导致Consul 服务不可用。
结论:违背了可用性 A 的要求,只满足一致性和分区容错,即CP 。
5.分布式配置中心(服务配置)
(1)功能介绍
问题说明:
系统拆分之后,会产生大量的微服务。每个微服务都有其对应的配置文件 yml。如果其中的某个配置项发生了修改,一个一个微服务修改会很麻烦。因此一套集中式的、动态的配置管理设施是必不可少的。从而实现一次修改,处处生效。
例如:给班里同学通知下节课不上了
麻烦的方法:一个个发送消息
简单的方法:直接在班级群 @所有人
结论:
所以,consul 优于 Eureka,不仅式因为它符合 CP 原则,而且因为 consul 同时支持服务注册和分布式配置中心,而 Eureka 不支持分配式配置中心。
(2)方法实现步骤:
需求:通用全局配置信息,直接注册进 Consul 服务器,从 Consul 获取。
(注意:既然从 Consul 获取自然要遵守 Consul 的配置规则要求。)
① 给对应的模块添加服务配置的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
② 在resources下,新建文件:bootstrap.yml
说明:
① bootstrap.yml和applicaiton.yml一样都是配置文件。applicaiton.yml是用户级,bootstrap.yml 是系统级的,优先级更加高
② Spring Cloud会创建一个“Bootstrap Context”,作为Spring应用的Application Context的父上下文。初始化的时候,Bootstrap Context负责从外部源加载配置属性并解析配置。这两个上下文共享一个从外部获取的 Environment。
③ Bootstrap属性有高优先级,默认情况下,它们不会被本地配置覆盖。
④ bootstrap.yml 比application.yml先加载的
注意:
application.yml 和 bootstrap.yml 可以共存:
bootstrap.yml 主要用于配置应用启动时所需的外部依赖和环境(配置服务注册和发现的客户端、配置中心的地址等)
application.yml 用于业务逻辑相关的配置(数据库连接、消息队列、线程池设置等)
bootstrap.yml:
spring:
application:
name: cloud-payment-service
####Spring Cloud Consul for Service Discovery
cloud:
consul:
host: localhost
port: 8500
discovery:
#配置当前服务注册到里面使用的名字
service-name: ${spring.application.name}
config:
enabled: true #是否开启配置中心
format: yaml #配置文件格式,这里用的yaml
profile-separator: "-" #例如: service-provider和dev中间的符号 用-就是service-provider-dev
data-key: data #默认的值就是data 是config的key 写上方便阅读
prefix: config #默认的值就是config 是配置的前缀 写上方便阅读
application.yml:
server:
port: 8001
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db2024?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
password: 123456
# ========================mybatis===================
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.mihoyo.cloud.entities
configuration:
map-underscore-to-camel-case: true
③ 在 consul 的 ui 中创建 config 文件夹
打开consul 的 ui 界面,找到 key-value,点击右上角的 create,创建文件夹(名为:config)
注意: