04-Consul服务注册与发现
1.为什么要引入服务注册中心
1.1 原因
public static final String PAYMENT_SRV_URL = "http://localhost:8001";//硬编码
微服务所在的IP地址和端口号硬编码到订单微服务中,会存在非常多的问题
(1)如果订单微服务和支付微服务的IP地址或者端口号发生了变化,则支付微服务将变得不可用,需要同步修改订单微服务中调用支付微服务的IP地址和端口号。
(2)如果系统中提供了多个订单微服务和支付微服务,则无法实现微服务的负载均衡功能。
(3)如果系统需要支持更高的并发,需要部署更多的订单微服务和支付微服务,硬编码订单微服务则后续的维护会变得异常复杂。
所以,在微服务开发的过程中,需要引入服务治理功能,实现微服务之间的动态注册与发现,从此刻开始我们正式进入SpringCloud实战。
1.2 注册中心在SpringCloud体系的位置
2.为什么不再使用Eureka
2.1 Enreka停更维护
https://github.com/Netflix/eureka/wiki
2.2 注册中心独立且和微服务功能解耦
目前主流服务中心,希望单独隔离出来而不是作为一个独立微服务嵌入到系统中。
按照Netflix
之前的思路,注册中心Eureka也是作为一个微服务且需要程序员自己开发部署(cloud2020
的教程,eureka需要单独引入依赖,做为一个服务启动)。
实际情况,希望微服务和注册中心分离解耦,注册中心和业务无关的,不要混为一谈。提供类似tomcat一样独立的组件,微服务注册上去使用,是个成品。
.3 阿里巴巴Nacos的崛起
一个集成了Service discovery and configuration management的独立组件。在配置文件的持久化上,使用起来比Consul要简单。后面教程会讲解到。
3.Consul简介
3.1 是什么
3.1.1 consul官网地址
3.1.2 What is Consul?
Consul 是一套开源的分布式服务发现和配置管理系统,由HashiCorp
公司用Go语言开发。
提供了微服务系统中的服务治理、配置中心、控制总线等功能。这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建全方位的服务网格,总之Consul提供了一种完整的服务网格解决方案。它具有很多优点。包括: 基于raft协议,比较简洁; 支持健康检查, 同时支持HTTP
和DNS
协议支持跨数据中心的 WAN集群,提供图形界面 跨平台,支持 Linux、Mac、Windows。
https://developer.hashicorp.com/consul/docs/intro
3.1.3 禁止使用问题
HashiCorp是一家非常知名的基础软件提供商,很多人可能没听过它的名字,但是其旗下的6款主流软件,Terraform、Consul、Vagrant、Nomad、Vault,Packer 相信不少程序员都听说或使用过,尤其是Consul使用者不尽其数。截止目前为止,从HashiCorp官网上的声明来看,开源项目其实还是“安全”的,被禁用的只是Vault企业版(并且原因是Vault产品目前使用的加密算法在中国不符合法规,另一方面是美国出口管制法在涉及加密相关软件上也有相应规定。因此这两项原因使得HashiCorp不得不在声明中说明风险)而非其他所有开源产品(Terraform、Consul等)。因此,大家可以暂时放下心来,放心使用!
3.1.4 Spring Cloud Consul
https://docs.spring.io/spring-cloud-consul/reference/index.html
3.2 能干嘛
3.2.1 服务发现
提供HTTP和DNS两种发现方式。
3.2.2 健康检测
支持多种方式,HTTP,TCP,Docker,Shell脚本定制化监控。
3.2.3 KV存储
Key,Value的存储方式。
3.2.4 多数据中心
Consul多数据中心
3.2.5 可视化WEB界面
3.3 下载地址
https://developer.hashicorp.com/consul/install
3.4 快速开始
https://docs.spring.io/spring-cloud-consul/reference/quickstart.html
4.下载并运行Consul
下载,注意选择版本,和对应操作系统,以及如果是,Windows下的CPU架构。
找到下载文件,移动到合适的目录,解压即可,因为是一个可执行的consul.exe文件
#查看版本信息,注意在consul.exe目录下执行
D:\Develop\consul>consul -version
开发者模式启动
D:\Develop\consul>consul agent -dev
通过http://localhost:8500,访问页面
5.服务注册与发现
5.1 服务提供者8001
支付服务provider8001注册进consul
5.1.1 引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
<exclusions>
<!--这个因为包含了多余的日志依赖,这个是排除的。否则控制台,会有警告信息。-->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
为什么这么引入,见官网。
5.1.2 配置文件修改
spring:
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}
5.1.3 主启动
@EnableDiscoveryClient注解,开启服务发现(作为一个服务,注册到consul,也可以从consul中,获取其他服务的ip和端口信息)。
5.2 服务消费者80
5.2.1 引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
<exclusions>
<!--这个因为包含了多余的日志依赖,这个是排除的。否则控制台,会有警告信息。-->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
5.2.2 修改配置
server:
port: 8080
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}
5.2.3 主启动
@EnableDiscoveryClient注解,开启服务发现。
5.2.4 Controller类修改
@RestController
@RequestMapping("/consumer")
public class OrderController {
//public static final String PAYMENT_SRV_URL = "http://localhost:8001";//硬编码
public static final String PAYMENT_SRV_URL = "http://cloud-payment-service";//服务注册中心上的微服务名称
@Resource
private RestTemplate restTemplate;
...
}
5.2.5 启动测试
略
5.2.6 修改RestTemplateConfig类
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced//新增的,因为注册中心 ,必须要有负载均衡。
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
5.3 注册中心异同点
5.3.1 CAP理论
C:Consistency(强一致性)
A:Availablility(可用性)
P:Partition tolerance(分区容错性)
5.3.2 经典CAP图
中间件,一般能支持CAP中的两项特性,就不错了。
5.3.3 AP(Eureka/Nacos)
AP架构
当网络分区出现后,为了保证可用性,系统B可以返回旧值,保证系统的可用性。
当数据出现不一致时,虽然A, B上的注册信息不完全相同,但每个Eureka节点依然能够正常对外提供服务,这会出现查询服务信息时如果请求A查不到,但请求B就能查到。如此保证了可用性但牺牲了一致性结论:违背了一致性C的要求,只满足可用性和分区容错,即AP。
5.3.4 CP(Zookerper/Consul)
CP架构
当网络分区出现后,为了保证一致性,就必须拒接请求,否则无法保证一致性,Consul 遵循CAP原理中的CP原则,保证了强一致性和分区容错性,且使用的是Raft算法,比zookeeper使用的Paxos算法更加简单。虽然保证了强一致性,但是可用性就相应下降了,例如服务注册的时间会稍长一些,因为 Consul 的 raft 协议要求必须过半数的节点都写入成功才认为注册成功 ;在leader挂掉了之后,重新选举出leader之前会导致Consul 服务不可用。结论:违背了可用性A的要求,只满足一致性和分区容错,即CP。
6.服务配置与刷新
6.1 分布式系统面临的->配置问题
微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务。由于每个服务都需要必要的配置信息才能运行,所以一套集中式的、动态的配置管理设施是必不可少的。比如某些配置文件中的内容大部分都是相同的,只有个别的配置项不同。就拿数据库配置来说吧,如果每个微服务使用的技术栈都是相同的,则每个微服务中关于数据库的配置几乎都是相同的,有时候主机迁移了,我希望一次修改,处处生效。
当下我们每一个微服务自己带着一个application.yml,上百个配置文件的管理....../(ㄒoㄒ)/~~
6.2 官网说明
Consul可作为注册中心和配置中心。
作为配置中心介绍。
6.3 服务使用配置中心
既然可以使用全局配置信息,直接注册进Consul服务器,从Consul获取。但是要遵守Consul的配置规则要求。
6.3.1 引入依赖
<!--SpringCloud consul config-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
为什么需要引入注册中心,和bootstrap依赖。见官网
6.3.2 修改配置
Consul配置规则说明
You can change the data key using spring.cloud.consul.config.data-key
.可以使用该属性key修改配置文件和其分组间使用的分隔符。
例如Consul中默认','作为分隔符,application,dev.yml 设置了属性为'-' ,就可以使用该方式,application-dev.yml。
新增bootstrap.yml配置文件
applicaiton.yml
是用户级的资源配置项。
bootstrap.yml
是系统级的,优先级更加高。
Spring Cloud会创建一个“Bootstrap Context”,作为Spring应用的Application Context
的父上下文。初始化的时候,Bootstrap Context
负责从外部源加载配置属性并解析配置。这两个上下文共享一个从外部获取的Environment
。
Bootstrap
属性有高优先级,默认情况下,它们不会被本地配置覆盖。 Bootstrap context
和Application Context
有着不同的约定,所以新增了一个bootstrap.yml
文件,保证Bootstrap Context
和Application Context
配置的分离。
applicaiton.yml
文件改为bootstrap.yml
,这是很关键的或者两者共存。因为bootstrap.yml
是比applicaiton.yml
先加载的。bootstrap.yml
优先级高于applicaiton.yml
。yml
和properties
只是文件名后缀,以及配置是,相同前缀的key是否省略不同(写法上),优先级方面无区别。
6.3.3 配置文件内容
bootstrap.yml
spring:
application:
name: cloud-payment-service
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}
config:
profile-separator: '-' # default value is ",",we update '-'
format: YAML
applicaiton.yml
server:
port: 8001
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3307/db2024?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: xxx
password: xxx
profiles:
active: # 多环境配置加载内容dev/prod,不写就是默认default配置
# ========================mybatis===================
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.atguigu.cloud.entities
configuration:
map-underscore-to-camel-case: true
6.3.4 consul服务器Key/Value配置填写
1.参考规则
config/cloud-payment-service/data //没写就是默认default
config/cloud-payment-service-dev/data
config/cloud-payment-service-prod/data
2.创建config文件夹,以/结尾
打开,consul的web管理界面,Key/value菜单,Create按钮新建即可。
3.在config文件夹下创建其他3个文件夹,以/结尾
4.在上述3个文件夹下分别创建data内容,data不再是文件夹
6.3.5 测试配置中心配置的方法
@Value("${server.port}")
private String port;
@GetMapping(value = "/get/info")
private String getInfoByConsul(@Value("${info}") String info) {//要和data文件中写入的配置信息相同
return "Info: " + info + "\t" + "port: " + port;
}
通过修改application.yml里面的激活配置部分,进行内容的验证。
6.3.6 测试
略
6.3.7 使用ConfigUtil静态获取系统配置的类
一般情况下,开发时,都会使用一个工具类静态的获取系统配置,见博文。
6.4 动态刷新
在周阳老师视频中,修改了data中的配置内容,不会立刻刷洗,但是我学习,操作过程中,会自动刷新,且不用配置或者,在主启动类上加@RefreshScope
注解。
周洋老师视频中,需要在主启动类,加@RefreshScope
注解,修改spring.cloud.consul.config.watch.wait-time
配置,改项配置默认值是55秒。
6.5 思考
存在问题,在Key/Value新增的配置,在consul重启后,就没了。Consul的配置持久化...
只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。