一、为什么要引入服务注册中心
(1)为什么引入
微服务硬编码 IP / 端口的核心问题总结
- 环境变更敏感:当支付微服务的 IP 或端口修改时,订单微服务必须同步修改所有调用该支付服务的代码或配置,否则将无法正常通信
- 无法实现负载均衡:若支付微服务部署了多个实例(如 3 台服务器),订单微服务硬编码固定 IP 只能访问其中一台,无法自动将请求分散到多个实例,导致部分服务器压力过大,另一部分闲置
- 扩展维护困难:当系统需要增加微服务实例(如新增 2 台支付服务器)时,硬编码的方式需要手动修改所有订单微服务的配置,操作繁琐且容易遗漏
解决方案方向
- 服务注册与发现:使用工具(如 Eureka、Consul)自动管理服务的 IP 和端口,调用方无需硬编码
- 负载均衡:结合 Ribbon、Nginx 等工具,自动将请求分发到多个微服务实例
- 配置中心:通过集中配置管理(如 Nacos、Apollo)动态更新服务地址,减少手动修改
(2)对照大纲
二、为什么不再使用传统老牌的Eureka
(1)Eureka停更进维
(2)Eureka对初学者不友好
(3)注册中心独立且和微服务解耦
目前主流服务中心,希望单独隔离出来而不是作为一个独立微服务嵌入到系统中
- 按照Netflix的之前的思路,注册中心Eureka也是作为一个微服务且需要程序员自己开发部署
- 实际情况,希望微服务和注册中心分离解耦,注册中心和业务无关的,不要混为一谈
- 提供类似tomcat一样独立的组件,微服务注册上去使用,是个成品
(4)阿里巴巴Nacos的崛起
Service discovery and configuration management
三、consul简介
(1)是什么
- consul官网地址Consul by HashiCorp
- What is Consul?
- 禁止使用问题:
- 条款链接:
- 放心用:
- 条款链接:
- spring consul:Spring Cloud Consul
(2)能干嘛
- 服务发现:提供HTTP和DNS两种发现方式
- 健康监测:支持多种方式,HTTP、TCP、Docker、Shell脚本定制化监控
- KV存储:key、value的存储方式
- 多数据中心:Consul支持多数据中心
- 可视化Web界面
(3)去哪下
Install | Consul | HashiCorp Developer
(4)怎么玩
- 网址:Spring Cloud Consul
- 两大作用:
四、安装并运行consul
(1)官网下载
(2)下载完成后只有一个cosul.exe文件,对应全路径下查看版本号信息
(3)使用开发模式启动
- consul agent -dev
- 通过以下地址可以访问Consul的首页:http://localhost:8500
- 结果页面
五、服务注册与发现
(1)服务提供者8001
5.1.1支付服务provider8001注册进consul
5.1.2POM
在原来POM文件的基础上,加上:
<!--SpringCloud consul discovery -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
配置来源:Quick Start :: Spring Cloud Consul
5.1.3YML
####Spring Cloud Consul for Service Discovery
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}
5.1.4主启动
添加@EnableDiscoveryClient,开启服务发现
5.1.5启动8001并查看consul控制台
(2)服务消费者80
5.2.1修改微服务cloud-consumer-order80
5.2.2POM
<!--SpringCloud consul discovery -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
5.2.3YML

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.4主启动类
5.2.5Controller
5.2.6启动80并查看consul控制台
5.2.7访问测试地址
- 访问http://localhost:80/consumer/pay/get/10
- 结果如何:
- 一个bug
- java.net.UnknownHostException: cloud-payment-service
5.2.8配置修改RestTemplateConfig
(3)三个注册中心异同点
5.3.1CAP
- C(Consistency):强一致性
- A(Availability):可用性
- P(Partition Tolerance):分区容错性
5.3.2经典CAP图
- 最多只能同时较好的满足两个
- CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求
- 因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三 大类:
- CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大
- CP - 满足一致性,分区容忍性的系统,通常性能不是特别高
- AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些
(1)AP(Eureka)
- 当网络分区出现后,为了保证可用性,系统B可以返回旧值,保证系统的可用性
- 当数据出现不一致时,虽然A, B上的注册信息不完全相同,但每个Eureka节点依然能够正常对外提供服务,这会出现查询服务信息时如果请求A查不到,但请求B就能查到。如此保证了可用性但牺牲了一致性结论:违背了一致性C的要求,只满足可用性和分区容错,即AP
(2)CP(Zookeeper/Consul)
- 当网络分区出现后,为了保证一致性,就必须拒接请求,否则无法保证一致性
- Consul 遵循CAP原理中的CP原则,保证了强一致性和分区容错性,且使用的是Raft算法,比zookeeper使用的Paxos算法更加简单。虽然保证了强一致性,但是可用性就相应下降了,例如服务注册的时间会稍长一些,因为 Consul 的 raft 协议要求必须过半数的节点都写入成功才认为注册成功 ;在leader挂掉了之后,重新选举出leader之前会导致Consul 服务不可用。结论:违背了可用性A的要求,只满足一致性和分区容错,即CP
六、服务配置与刷新
(1)分布式系统面临的→配置问题
微服务架构下,由于服务拆分导致大量独立服务实例,每个服务都需配置信息。集中式动态配置管理可解决重复配置问题,例如统一管理各服务相同的数据库配置,当主机迁移时只需修改一处即可全局生效
(2)官网说明
(3)服务配置案例步骤
6.3.1需求
- 通用全局配置信息,直接注册进Consul服务器,从Consul获取
- 既然Consul获取自然要遵守Consul的配置规则要求
6.3.2修改cloud-provider-payment8001
6.3.3POM
<!--SpringCloud consul config-->
<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>
6.3.4YML
(1)配置规则说明
(2)新增配置文件bootstrap.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: profile-separator: '-' # default value is ",",we update '-' format: YAML # config/cloud-payment-service/data # /cloud-payment-service-dev/data # /cloud-payment-service-prod/data
(3)application.yml
6.3.5consul服务器key/value配置填写
(1)参考规则
(2)创建config文件夹,以/结尾
(3)config文件夹下分别创建其它三个文件夹,以/结尾
(4)在上述三个文件夹下分别创建data内容,data不再是文件夹
6.3.6controller
@Value("${server.port}")
private String port;
@GetMapping(value = "/pay/get/info")
private String getInfoByConsul(@Value("${atguigu.info}") String atguiguInfo){
return "atguiguInfo:" + atguiguInfo + ",port:" + port;
}
6.3.7测试
(4)动态刷新案例步骤
6.4.1问题
接上一步,我们在consul的dev配置分支修改了内容,马上访问,结果无效
6.4.2步骤
- @RefreshScope主启动类添加
- bootstrap.yml修改下(只为教学,实际别改)spring.cloud.consul.config.watch.wait-time
- 测试:
(5)思考
- 截至到这,服务配置和动态刷新全部通过,假设我重启Consul,之前的配置还在吗?
- 试试(之前的配置不在了)