希望长大对我而言,是可以做更多想做的事,而不是被迫做更多不想做的事...... 首页 spring cloud注册中心之Eureka 丁D 学无止境 2020-04-21 13:43 55119已阅读 spring cloud Eureka 注册中心 摘要本文讲解的是spring cloud的注册中心Eureka。 ### 什么是注册中心? 随着微服务的盛行,越来越多的应用,开始拆成一个一个的服务,服务之间相互依赖,那么内部的服务是怎么相互调用的。 例如:服务A部署在3个服务器上,3个实例有不同的ip地址。然后服务B依赖服务A,需要调用服务A。 在没有注册中心的情况下。我们可能是服务A前面架设了一个nginx ![](/upload/2BD5FA21-C116-4ef0-AF8C-7E5A2F0C3821.png) 这样做服务B就可以只访问nginx的地址,然后转发到3个实例。 但是随着docker容器的盛行。ip地址已经不在固定,经常发生变化。这样的话我们就需要部署的时候手工去修改nginx的配置文件,或者使用脚本去更新配置文件,然后reload。 现在我们引入注册中心,只需要将服务注册到注册中心,然后网关等从注册中心获取实例的信息,实现动态路由。 ### 注册中心需要的功能 #### 服务注册 理论上来说 服务在启动的时候,就应该调用eureka server的api(register方法)进行注册。 对于java 服务可以使用 eureka client封装的api去调用server的api进行注册 对于spring cloud的应用 基于spring boot的自动配置,已经自动帮我们注册服务了 #### 服务下线 Cancel(服务下线);Eureka client 会发送 下线请求给 Eureka server ,Eureka server 就会将 这个 client 的实例从注册列表中剔除;发送下线请求代码如下: DiscoveryManager.getInstance().shutdownComponent() #### 服务剔除 正常来说服务在关系应用的时候,应该通过钩子或者生命周期的回调方法去调用eureka server的de-register来删除自身的信息。 但是为了解决服突然挂掉或其他情况没有及时删除自身的信息,eureka server要求client定时发送心跳(30s),来证明服务还存活,如果超过一定时间没有进行续约(90s),server就会认为该服务不健康自动剔除。 #### 服务租约 Eureka client 会向 Eureka server 每隔30秒发送心跳;续约的目的是通知 Eureka server 自己代表的实例是处于存活状态;如果 Eureka server 90 秒内 未收到 续约心跳,就会将这个实例从服务列表中剔除;官方建议是不要修改续约间隔,原因是服务器要使用这些信息去确认 Eureka server 与 Eureka client 之间的交流是否存在广泛传播的问题; ### 数据一致性问题 作为注册中心,是不可能是单点的,一定是集群化,那么集群中eureka每个节点是如何进行数据同步的? 一般来说:分布式系统中,数据副本的复制方式一般分为主从复制或对等复制(peer to peer) **eureka使用的是对等复制** 主从复制:就好像mysql主从,写都写在主节点,然后由主节点复制给其他从节点,这样主节点的写压力大,但是从节点可以分担读压力 对等复制:任何节点都可以接受写请求和读请求.然后副本间进行数据更新;但副本间数据同步时可能产生数据冲突; Eureka Server也是一个Client,在启动时,通过请求其中一个节点(Server),将自身注册到Server上,并获取注册服务信息; 每当Server信息变更后(client发起注册,续约,注销请求),就将信息通知给其他Server,来保持数据同步; 在执行同步(复制)操作时,可能会有数据冲突,是通过lastDirtyTimestamp,最近一次变更时间来保证是最新数据; 客户端维护这一个Eureka Server不可用列表和可用列表,当有请求的时候,会从可用列表中获取一个地址,进行请求,失败按顺序换下一个地址 为了防止每个Eureka client按配置文件配置的顺序来请求,导致请求server不均衡,client有个定时任务,每隔5分钟重新刷新并随机化Eureka Server的列表。 peer-peer复制不一定成功,所以server之间还可以通过hearbeat来修复 ### AP优于CP 分布式系统中有3个特性(CAP) Consistency:数据一致性,多个副本的情况下,可能由于网络,机器故障等问题导致,有的副本写入成功,有的失败,造成副本之间数据不一致,满足一致性要求对数据更新操作成功之后,多个副本要保持一致。 Availability:在任何时候对集群进行读写,集群要能正常响应,在一定的延时内完成 Partition Tolerance:分区容忍性,整个集群被分割多个无法相互通信的分区是,集群要仍然可用。 由于网络是不可控的,所以网络分区是客观存在,不可避免的。所以系统需要具备分区容忍性。在这个前提下设计只能在AP和CP之间选择。 **zookeeper可以说是cp的 但是也不能说是强一致性的**,,因为客户端提交一个写请求,只要过半的节点写成功就返回,这时有个读请求刚好读到没有同步的节点, 这个时候就读不到新的数据,如果需要强一致性,需要读取数据的时候先执行一下sync,即先向主节点同步一下数据。。 但是在网络分区的情况下,主节点,不在non-quorum分区,这个分区的读写请求都会报错,不可用无法满足Availability的特性 而且在选主节点的时候zk集群不可用 **eureka选择满足Availability,所以他是ap的,**节点之间并不是强一致性的,设计者认为注册中心,保留可用及过期的数据总比丢掉可用的数据好。 ### 自我保护 为了防止,偶尔的网络抖动或者,短暂的网络不可用,造成误判,导致清空服务实例的注册信息,这会严重影响Eureka的可用性(availability),所以引入了自我保护策略 eureka client和server端之前有个租约,client要定时发送心跳维持这个租约,表示自己还活着,eureka通过当注册的实例数,去计算每分钟应该从应用接收到的心跳数,如果1分钟接收的心跳数小于指定的阈值,就禁止定时任务剔除失效的实例。 eureka.server.enable-self-preservation = false 阈值可以通过eureka.server.renewal-percent-threshold来设置 。设置小于0.5 即0.49默认是0.85 ### 常见问题 **为什么服务下线了,eureka server接口返回的信息还会存在?** 情况一: 应用异常挂掉,没有告诉eureka server要下线该服务的实例信息,这就需要靠定时清除任务去剔除(evictionTask) 调整evictionTask的调度频率。。默认是1分钟调整为5s 情况二: 应用告诉了eureka server要下线该服务的实例信息,,但是由于eureka server的rest api有 response cache。因此需要等待缓存过期才能呢更新 response cache的问题,可以根据情况禁止readonlyCacheMap或者调整过期时间 情况三: 开启了自我保护,导致不会因过期而被剔除。 **为什么服务上线了,eureka client不能及时获取到? ** 针对新服务上线client获取不及时,在测试环境可以适当提供client端拉取server注册信息的频率,比如将默认的30s改成5s ### Eureka高可用 多台Eureka相互注册即可 ### 实例 ``` package com.ding; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; //服務註冊中心 @SpringBootApplication @EnableEurekaServer public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class, args); } } ``` ``` server: port: 10088 eureka: instance: hostname: localhost client: registerWithEureka: false #自己就是注册中心,不用注册自己 fetchRegistry: false #要不要去注册中心获取其他服务的地址 serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ spring: application: name: cloud-eurka ``` ``` 4.0.0 spring-cloud cloud-parent 0.0.1-SNAPSHOT spring-cloud cloud-eureka 0.0.1-SNAPSHOT cloud-eureka http://maven.apache.org org.springframework.cloud spring-cloud-starter-netflix-eureka-server ``` 很赞哦! (2) 上一篇:spring cloud服务间调用之feign 下一篇:CAS+Springboot单点登录 目录 点击排行 Elasticsearch6.3.2之x-pack redis哨兵 2019-07-09 22:05 Redis+Twemproxy+HAProxy+Keepalived 2019-07-12 17:20 GC优化策略和相关实践案例 2019-10-10 10:54 JVM垃圾回收器 2019-10-10 10:23 标签云 Java Spring MVC Mybatis Ansible Elasticsearch Redis Hive Docker Kubernetes RocketMQ Jenkins Nginx 友情链接 郑晓博客 佛布朗斯基 凉风有信 MarkHoo's Blog 冰洛博客 南实博客 Rui | 丁D Java研发工程师 生活可以用「没办法」三个字概括。但别人的没办法是「腿长,没办法」、「长得好看,没办法」、「有才华,没办法」。而你的没办法,是真的没办法。 请作者喝咖啡