摘自:https://www.cnblogs.com/mrhelloworld/p/eureka.html
服务注册中心是服务实现服务化管理的核心组件,类似于目录服务的作用,主要用来存储服务信息,譬如提供者 url 串、路由信息等。服务注册中心是微服务架构中最基础的设施之一。
在微服务架构流行之前,注册中心就已经开始出现在分布式架构的系统中。Dubbo 是一个在国内比较流行的分布式框架,被大量的中小型互联网公司所采用,它提供了比较完善的服务治理功能,而服务治理的实现主要依靠的就是注册中心。
什么是注册中心
注册中心可以说是微服务架构中的“通讯录”,它记录了服务和服务地址的映射关系。在分布式架构中,服务会注册到这里,当服务需要调用其它服务时,就到这里找到服务的地址,进行调用。
举个现实生活中的例子,比如说,我们手机中的通讯录的两个使用场景:
当我想给张三打电话时,那我需要在通讯录中按照名字找到张三,然后就可以找到他的手机号拨打电话。—— 服务发现
李四办了手机号并把手机号告诉了我,我把李四的号码存进通讯录,后续,我就可以从通讯录找到他。—— 服务注册
通讯录 —— ?什么角色(提示:服务注册中心)
总结:服务注册中心的作用就是服务的注册和服务的发现。
常见的注册中心
- Netflix Eureka
- Alibaba Nacos
- HashiCorp Consul
- Apache ZooKeeper
- CoreOS Etcd
- CNCF CoreDNS
特性 | Eureka | Nacos | Consul | Zookeeper |
---|---|---|---|---|
CAP | AP | CP + AP | CP | CP |
健康检查 | Client Beat | TCP/HTTP/MYSQL/Client Beat | TCP/HTTP/gRPC/Cmd | Keep Alive |
雪崩保护 | 有 | 有 | 无 | 无 |
自动注销实例 | 支持 | 支持 | 不支持 | 支持 |
访问协议 | HTTP | HTTP/DNS | HTTP/DNS | TCP |
监听支持 | 支持 | 支持 | 支持 | 支持 |
多数据中心 | 支持 | 支持 | 支持 | 不支持 |
跨注册中心同步 | 不支持 | 支持 | 支持 | 不支持 |
SpringCloud集成 | 支持 | 支持 | 支持 | 支持 |
为什么需要注册中心
了解了什么是注册中心,那么我们继续谈谈,为什么需要注册中心。在分布式系统中,我们不仅仅是需要在注册中心找到服务和服务地址的映射关系这么简单,我们还需要考虑更多更复杂的问题:
- 服务注册后,如何被及时发现
- 服务宕机后,如何及时下线
- 服务如何有效的水平扩展
- 服务发现时,如何进行路由
- 服务异常时,如何进行降级
- 注册中心如何实现自身的高可用
这些问题的解决都依赖于注册中心。简单看,注册中心的功能有点类似于 DNS 服务器或者负载均衡器,而实际上,注册中心作为微服务的基础组件,可能要更加复杂,也需要更多的灵活性和时效性。所以我们还需要学习更多 Spring Cloud 微服务组件协同完成应用开发。
注册中心解决了什么问题
- 服务管理
- 服务的依赖关系管理
什么是 Eureka 注册中心
Eureka 是 Netflix 开发的服务发现组件,本身是一个基于 REST 的服务。Spring Cloud 将它集成在其子项目 Spring Cloud Netflix 中,实现 Spring Cloud 的服务注册与发现,同时还提供了负载均衡、故障转移等能力。
Eureka 注册中心三种角色
Eureka Server
通过 Register、Get、Renew 等接口提供服务的注册和发现。
Application Service(Service Provider)
服务提供方,把自身的服务实例注册到 Eureka Server 中。
Application Client(Service Consumer)
服务调用方,通过 Eureka Server 获取服务列表,消费服务。
Eureka 入门案例
创建项目
我们创建聚合项目来讲解 Eureka,首先创建一个 pom 父工程。
添加依赖
pom.xml
注册中心 eureka-server
在刚才的父工程下创建 eureka-server
注册中心的项目。
创建项目
添加依赖
pom.xml
配置文件
application.yml
此时如果直接启动项目是会报错的,错误信息:com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused: connect
,这是因为 Eureka 默认开启了将自己注册至注册中心和从注册中心获取服务注册信息的配置,如果该应用的角色是注册中心并是单节点的话,要关闭这两个配置项。
启动类
EurekaServerApplication.java
访问
访问:http://localhost:8761/
高可用 Eureka 注册中心
注册中心 eureka-server
创建项目
在刚才的父工程下再创建一个 eureka-server02
注册中心的项目,如果是多机器部署不用修改端口,通过 IP 区分服务,如果在一台机器上演示需要修改端口区分服务。
添加依赖
pom.xml
配置文件
集群配置下,注册中心需要相互注册实现信息的同步。
eureka-server 的 application.yml
eureka-server02 的 application.yml
启动类
启动类不变,启动两个 server。
访问
访问:http://localhost:8761/ 或者 http://localhost:8762/ 都出现如下图说明互相注册成功。
Status
显示方式为默认值,如果想要清晰可见每个服务的 IP + 端口需要通过以下配置来实现。
显示 IP + 端口
一个普通的 Netflix Eureka 实例注册的 ID 等于其主机名(即,每个主机仅提供一项服务)。 Spring Cloud Eureka 提供了合理的默认值,定义如下:spring.cloud.client.hostname:spring.cloud.client.hostname:{spring.application.name}:\({spring.application.instance_id:\){server.port}}},也就是:主机名:应用名:应用端口。
我们也可以可以自定义进行修改:
服务提供者 service-provider
创建项目
在刚才的父工程下创建一个 service-provider
服务提供者的项目。
添加依赖
pom.xml
配置文件
application.yml
实体类
Product.java
编写服务
ProductService.java
ProductServiceImpl.java
控制层
ProductController.java
该项目我们可以通过单元测试进行测试,也可以直接通过 url 使用 postman 或者浏览器来进行测试。
启动类
ServiceProviderApplication.java
注册中心
访问注册中心,可以看到用户服务已经注册至注册中心。
服务消费者 service-consumer
创建项目
在刚才的父工程下创建一个 service-consumer 服务消费者的项目。
添加依赖
pom.xml
配置文件
application.yml
实体类
Product.java
Order.java
消费服务
OrderService.java
对于服务的消费我们这里讲三种实现方式:
- DiscoveryClient:通过元数据获取服务信息
- LoadBalancerClient:Ribbon 的负载均衡器
- @LoadBalanced:通过注解开启 Ribbon 的负载均衡器
DiscoveryClient
Spring Boot 不提供任何自动配置的RestTemplate
bean,所以需要在启动类中注入 RestTemplate
。
OrderServiceImpl.java
LoadBalancerClient
OrderServiceImpl.java
@LoadBalanced
启动类注入 RestTemplate
时添加 @LoadBalanced
负载均衡注解,表示这个 RestTemplate
在请求时拥有客户端负载均衡的能力。
OrderServiceImpl.java
控制层
OrderController.java
访问
访问:http://localhost:9090/order/1
Eureka 架构原理
- Register(服务注册):把自己的 IP 和端口注册给 Eureka。
- Renew(服务续约):发送心跳包,每 30 秒发送一次,告诉 Eureka 自己还活着。如果 90 秒还未发送心跳,宕机。
- Cancel(服务下线):当 Provider 关闭时会向 Eureka 发送消息,把自己从服务列表中删除。防止 Consumer 调用到不存在的服务。
- Get Registry(获取服务注册列表):获取其他服务列表。
- Replicate(集群中数据同步):Eureka 集群中的数据复制与同步。
- Make Remote Call(远程调用):完成服务的远程调用。
CAP 原则
CAP 原则又称 CAP 定理,指的是在一个分布式系统中具有以下其中两个特性:
- Consistency (一致性)
- Availability (可用性)
- Partition tolerance(分区容错性)
CAP 由 Eric Brewer 在 2000 年 PODC 会议上提出。该猜想在提出两年后被证明成立,成为我们熟知的 CAP 定理。CAP 三者不可兼得。
特性 | 定理 |
---|---|
Consistency | 也叫做数据原子性,系统在执行某项操作后仍然处于一致的状态。在分布式系统中,更新操作执行成功后所有的用户都应该读到最新的值,这样的系统被认为是具有强一致性的。等同于所有节点访问同一份最新的数据副本。 |
Availability | 每一个操作总是能够在一定的时间内返回结果,这里需要注意的是"一定时间内"和"返回结果"。一定时间内指的是,在可以容忍的范围内返回结果,结果可以是成功或者是失败。 |
Partition tolerance | 在网络分区的情况下,被分隔的节点仍能正常对外提供服务(分布式集群,数据被分布存储在不同的服务器上,无论什么情况,服务器都能正常被访问)。 |
取舍策略
CAP 三个特性只能满足其中两个,那么取舍的策略就共有三种:
- CA without P:如果不要求P(不允许分区),则C(强一致性)和A(可用性)是可以保证的。但放弃 P 的同时也就意味着放弃了系统的扩展性,也就是分布式节点受限,没办法部署子节点,这是违背分布式系统设计的初衷的。
- CP without A:如果不要求A(可用),相当于每个请求都需要在服务器之间保持强一致,而P(分区)会导致同步时间无限延长(也就是等待数据同步完才能正常访问服务),一旦发生网络故障或者消息丢失等情况,就要牺牲用户的体验,等待所有数据全部一致了之后再让用户访问系统。设计成 CP 的系统其实不少,最典型的就是分布式数据库,如 Redis、HBase 等。对于这些分布式数据库来说,数据的一致性是最基本的要求,因为如果连这个标准都达不到,那么直接采用关系型数据库就好,没必要再浪费资源来部署分布式数据库。
- AP without C:要高可用并允许分区,则需放弃一致性。一旦分区发生,节点之间可能会失去联系,为了高可用,每个节点只能用本地数据提供服务,而这样会导致全局数据的不一致性。典型的应用就如某米的抢购手机场景,可能前几秒你浏览商品的时候页面提示是有库存的,当你选择完商品准备下单的时候,系统提示你下单失败,商品已售完。这其实就是先在 A(可用性)方面保证系统可以正常的服务,然后在数据的一致性方面做了些牺牲,虽然多少会影响一些用户体验,但也不至于造成用户购物流程的严重阻塞。
总结
现如今,对于多数大型互联网应用的场景,主机众多、部署分散,而且现在的集群规模越来越大,节点只会越来越多,所以节点故障、网络故障是常态,因此分区容错性也就成为了一个分布式系统必然要面对的问题。那么就只能在 C 和 A 之间进行取舍。但对于传统的项目就可能有所不同,拿银行的转账系统来说,涉及到金钱的对于数据一致性不能做出一丝的让步,C 必须保证,出现网络故障的话,宁可停止服务,可以在 A 和 P 之间做取舍。
总而言之,没有最好的策略,好的系统应该是根据业务场景来进行架构设计的,只有适合的才是最好的。
Eureka 自我保护
启动自我保护条件
一般情况下,服务在 Eureka 上注册后,会每 30 秒发送心跳包,Eureka 通过心跳来判断服务是否健康,同时会定期删除超过 90 秒没有发送心跳的服务。
有两种情况会导致 Eureka Server 收不到微服务的心跳
- 微服务自身的原因
- 微服务与 Eureka 之间的网络故障
自我保护模式
Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%,如果低于 85%,Eureka Server 会将这些实例保护起来,让这些实例不会过期,同时提示一个警告。这种算法叫做 Eureka Server 的自我保护模式。
为什么要启动自我保护
- 因为同时保留"好数据"与"坏数据"总比丢掉任何数据要更好,当网络故障恢复后,这个 Eureka 节点会退出"自我保护模式"。
- Eureka 还有客户端缓存功能(也就是微服务的缓存功能)。即使 Eureka 集群中所有节点都宕机失效,微服务的 Provider 和 Consumer 都能正常通信。
- 微服务的负载均衡策略会自动剔除死亡的微服务节点。
如何关闭自我保护
注册中心配置自我保护
Eureka 优雅停服
配置了优雅停服以后,将不需要 Eureka Server 中配置关闭自我保护。本文使用 actuator 实现。
添加依赖
服务提供者添加 actuator 依赖
配置文件
服务提供者配置度量指标监控与健康检查
优雅停服
使用 POST 请求访问:http://localhost:7070/actuator/shutdown 效果如下
Eureka 安全认证
添加依赖
注册中心添加 security 依赖
配置文件
注册中心配置安全认证
修改访问集群节点的 url
注册中心的配置文件
服务提供者的配置文件
服务消费者的配置文件
过滤 CSRF
Eureka 会自动化配置 CSRF 防御机制,Spring Security 认为 POST, PUT, and DELETE http methods 都是有风险的,如果这些 method 发送过程中没有带上 CSRF token 的话,会被直接拦截并返回 403 forbidden。
官方给出了解决的方法,具体可以参考 spring cloud issue 2754,里面有大量的讨论,这里提供两种解决方案。
首先注册中心配置一个 @EnableWebSecurity
配置类,继承 org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
,然后重写 configure
方法。
方案一
使 CSRF 忽略 /eureka/**
的所有请求
方案二
保持密码验证的同时禁用 CSRF 防御机制
访问
使用配置好的用户名和密码登录以后可看到注册中心界面,启动服务提供者和服务消费者,功能正常使用,至此 Eureka 注册中心所有的知识点就讲解结束了。
大家可以通过 分类
查看更多关于 Spring Cloud
的文章。
本文采用 知识共享「署名-非商业性使用-禁止演绎 4.0 国际」许可协议
。
✍️ 本章节到这里就结束了,喜欢的话就点赞 加转发吧。
关注 哈喽沃德先生
,学习更多 IT 技术 ~
__EOF__
出 处:https://www.cnblogs.com/mrhelloworld
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:署名 - 非商业性使用 - 禁止演绎,协议普通文本 | 协议法律文本。
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
https://mrhelloworld.com
https://mrhelloworld.cn