EUREKA原理总结

Eureka高可用架构

https://github.com/Netflix/eureka/wiki/Eureka-at-a-glance

 

 

 

上图中主要的名称说明:

  • Register:EurekaClient注册(Http请求)到EurekaServer,EurekaClient会发送自己元数据(ip,port,主页等),EurekaServer会将其添加到服务注册列表Map
  • Renew:EurekaClient默认每30秒发送心跳(timer定时任务,发送Http请求)到EurekaServer续约,向EurekaServer证明其活性,EurekaServer将EurekaClient心跳中的时间戳参数已有服务列表中对应的该服务的时间戳进行比较,不相等就更新对应的服务列表;如果EurekaServer 90秒都没收到某个EurekaClient的续约,并且没有进入保护模式,就会将该服务从服务列表将其剔除(Eviction)
  • Get Registry:EurekaClient默认每30秒从EurekaServer获取服务注册列表,并且会与自身本地已经缓存过的服务列表进行比较合并,有点像本地仓库从git仓库进行git pull
  • Cancel:EurekaClient服务的下线
  • Make Remote Call:EurekaClient服务间进行远程调用,比如通过RestTemplate+Ribbon或Fegin
  • us-east-1c:美国东海岸EurekaServer
  • Replicate:EurekaServer集群节点之间数据(主要是服务注册列表信息)同步

 

 

 

Eureka源码 

1. 是纯正的 servlet 应用,需构建成war包部署
2. 使用了 Jersey 框架(如注解@POST、@Consumers)实现自身的 RESTful HTTP接口
3. peer之间的同步服务的注册全部通过 HTTP 协议实现
4. 定时任务(发送心跳续约、定时清理过期服务Eviction节点同步等)通过 JDK 自带的 Timer 实现
5. 内存缓存使用Google的guava包实现

EurekaServer初始化

由于是Servlet应用,所以Eureka需要通过servlet的相关监听器 ServletContextListener 嵌入到 Servlet 的生命周期中。EurekaBootStrap 类实现了该接口,在servlet标准的contextInitialized()方法中完成了EurekaServer初始化工作:

/*** Initializes Eureka, including syncing up with other Eureka peers and publishing the registry.** @see* javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)*/@Overridepublic void contextInitialized(ServletContextEvent event) {try {initEurekaEnvironment();initEurekaServerContext();ServletContext sc = event.getServletContext();sc.setAttribute(EurekaServerContext.class.getName(), serverContext);} catch (Throwable e) {logger.error("Cannot bootstrap eureka server :", e);throw new RuntimeException("Cannot bootstrap eureka server :", e);}}

EurekaBootStrap实现了ServletContextListener接口,重写了contextInitialized方法;
initEurekaEnvironment主要做的是读取配置信息,设置eureka的数据中心datacenter和环境environment;
initEurekaServerContext主要是初始化servlet代码如下:
protected void initEurekaServerContext() throws Exception {...//省略代码
   PeerAwareInstanceRegistry registry;if (isAws(applicationInfoManager.getInfo())) {...//省略代码,如果是AWS的代码} else {registry = new PeerAwareInstanceRegistryImpl(eurekaServerConfig,eurekaClient.getEurekaClientConfig(),serverCodecs,eurekaClient);}PeerEurekaNodes peerEurekaNodes = getPeerEurekaNodes(registry,eurekaServerConfig,eurekaClient.getEurekaClientConfig(),serverCodecs,applicationInfoManager);}

 

与Spring Cloud结合的胶水代码

Eureka是一个纯正的Servlet应用,而Spring Boot使用的是嵌入式Tomcat, 因此就需要一定的胶水代码让Eureka跑在Embedded Tomcat中。

这部分工作是在 EurekaServerBootstrap 中完成的。

与上面提到的EurekaBootStrap相比,它的代码几乎是直接将原生代码copy过来的,虽然它并没有继承 ServletContextListener, 但是相应的生命周期方法都还在,然后添加了@Configuration注解使之能被Spring容器感知:
原生的 EurekaBootStrap 类实现了标准的ServletContextListener接口,Spring CloudEurekaServerBootstrap没有实现servlet接口,但是保留了接口方法的完整实现。

在类EurekaServerInitializerConfiguration中实现了 ServletContextAware(拿到了tomcat的ServletContext对象)、SmartLifecycle(Spring容器初始化该bean时会调用相应生命周期方法):

 

@Configuration
@CommonsLog
public class EurekaServerInitializerConfigurationimplements ServletContextAware, SmartLifecycle, Ordered {
}

 

在 start() 方法中:

eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);

SpringCloud中,Spring容器初始化该组件时,Spring调用其生命周期方法start()从而触发了Eureka启动:

@Overridepublic void start() {new Thread(new Runnable() {@Overridepublic void run() {try {eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext); // 调用 servlet 接口方法手工触发启动log.info("Started Eureka Server");// ... ...
                }catch (Exception ex) {// Help!log.error("Could not initialize Eureka servlet context", ex);}}}).start();}

 

重要的代码入口

1. com.netflix.appinfo.InstanceInfo类封装了服务注册所需的全部信息
2. Eureka Client探测本机IP是通过org.springframework.cloud.commons.util.InetUtils工具类实现的
3. com.netflix.eureka.resources.ApplicationResource类相当于Spring MVC中的控制器,是服务的注册查询功能的代码入口点

一个服务启动后最长可能需要2分钟时间才能被其它服务感知到

 当一个服务A启动后,首先需要注册到某个EurekaServer集群节点上,已经注册到EurekaServer上的服务B此时想要Make Remote Call服务A,最长可能要等两分钟,这是因为三处缓存一处延迟

 

1.  Eureka Client对已经获取到的本地的注册信息也做了30s缓存。

即服务通过eureka客户端第一次查询服务注册信息会请求EurekaServer,然后会将请求返回的结果缓存,下次再调用时就不会真正向Eureka发起HTTP请求了,直接查询本地的服务注册信息

 
 

2. 负载均衡组件Ribbon也有30s缓存

Ribbon会从Eureka Client本地获取服务列表,然后将结果缓存30s

 

3. EurekaServer对HTTP响应做了缓存。在EurekaServer的”控制器”类 ApplicationResource的109行可以看到有一行

String payLoad = responseCache.get(cacheKey);
的调用,该代码所在的getApplication()方法的功能是响应客户端查询某个服务信息的HTTP请求:
String payLoad = responseCache.get(cacheKey); // 从cache中拿响应数据if (payLoad != null) {logger.debug("Found: {}", appName);return Response.ok(payLoad).build();
} else {logger.debug("Not Found: {}", appName);return Response.status(Status.NOT_FOUND).build();
}

responseCache引用的是ResponseCache类型,该类型是一个接口,其get()方法首先会去缓存中查询数据,如果没有则生成数据返回(即真正去查询注册列表),且缓存的有效时间为30s

也就是说,客户端拿到Eureka的响应并不一定是即时的,大部分时候只是缓存信息。

 

 

4. 如果你并不是在Spring Cloud环境下使用这些组件(Eureka, Ribbon),你的服务一启动(不是启动完成)并不会马上向Eureka注册,而是需要等到第一次发送心跳请求时才会注册

心跳请求的发送间隔也是30s。(Spring Cloud对此做了修改,服务启动后会马上注册)

 
Eureka保护机制

https://www.cnblogs.com/theRhyme/p/10058988.html

 

 

Eureka比Zookeeper好在哪里

Zookeeper保证CP

注册中心需求分析及关键设计考量: https://www.cnblogs.com/theRhyme/p/10130714.html

当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接down掉不可用。

也就是说,服务注册功能对可用性的要求要一致性

但是zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。

在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。

Eureka保证AP

Eureka优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。

而Eureka的客户端在向某个Eureka注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。

除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
1. Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务
2. Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)
3. 当网络稳定时,当前实例新的注册信息会被同步到其它节点中

因此, Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪。

就算Eureka节点一个都不可用,还有缓存的服务列表,如EurekaClient本地的服务列表。

 

 

Service Health Check

 

使用 ZooKeeper 作为服务注册中心时,服务的健康检测常利用 ZooKeeper 的 Session 活性 Track机制 以及结合 Ephemeral ZNode的机制,简单而言,就是将服务的健康监测绑定在了 ZooKeeper 对于 Session 的健康监测上,或者说绑定在TCP长链接活性探测上了。

 

这在很多时候也会造成致命的问题,ZK 与服务提供者机器之间的TCP长链接活性探测正常的时候,该服务就是健康的么?答案当然是否定的!注册中心应该提供更丰富的健康监测方案,服务的健康与否的逻辑应该开放给服务提供方自己定义,而不是一刀切搞成了 TCP 活性检测!

 

健康检测的一大基本设计原则就是尽可能真实的反馈服务本身的真实健康状态,否则一个不敢被服务调用者相信的健康状态判定结果还不如没有健康检测。

 

 

 

参考来源:

https://blog.csdn.net/forezp/article/details/73017664

https://blog.csdn.net/neosmith/article/details/53131023

https://yq.aliyun.com/articles/601745?spm=a2c4e.11153940.blogcont604028.19.6daf2a38OLvUBo

转载于:https://www.cnblogs.com/theRhyme/p/10313299.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/463548.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux下安装oracle 11g R2

Linux环境配置 [c-sharp]view plaincopy OS:Fedora 15 DB:Oracle 11gR2 将Oracle安装到home/oracle_11目录 配置过程:本文来自Oracle官方文档网上资料 Oracle官方文档:http://www.oracle.com/pls/db112/homepage 1. 以root用户登录到Linux 2. 检查机器…

通俗理解数字签名,ssl数字证书和https

前言 最近在开发关于PDF合同文档电子签章的功能,大概意思就是在一份PDF合同上签名,盖章,使其具有法律效应。签章有法律效应必须满足两个条件: 能够证明签名,盖章者是谁,无法抵赖PDF合同在签章后不能被更改在…

linux 性能分析工具——perf

最近需要对linux下的开发的数据库应用程序进行性能调试,找到了该篇文章,保存下来为了以后便于查找,这篇是转载的perf文章,后续还有vtune相关的文章。 转载:https://blog.csdn.net/u014608280/article/details/8026571…

红外遥控

红外遥控简介红外遥控是一种无线、非接触控制技术,具有抗干扰能力强,信息传输可靠,功耗低,成本低,易实现等显著优点,被诸多电子设备特别是家用电器广泛采用,并越来越多的应用到计算机系统中。由于红外线遥控不具有像无线电遥控那样穿过障碍物去控制被控对象的能力,所…

使用jQuery Mobile移动开发框架将博客网站快速转化为Mobile网站

日期:2012-7-12 来源:GBin1.com 在线演示 jQuery Mobile是一个非常不错的移动端网站应用的解决方案,很多网站都使用jQuery Mobile来生成Mobile手机端的移动网站应用,在过去的GBin1博客文章中,我们曾经使用jQuery Mob…

NVLink技术及影响解析

1繁华的背面 最新GPU架构Pascal,能自己开上舞台的Audi A7,超过700名与会专家学者及技术人员,近百场学术会议和科研分享,连续两晚的happy hour、酒会和GTC Party……在一片喧嚣和欢乐当中,2014年度的GTC大会降下了帷幕。…

2022年结束了

在去年这个时候,我刚好也写了一篇这样的文章。再往前是2020年的总结年终了,肿一下斗转星移,我的这个公众号也陪伴着我经过了4年的时间,明年后,我也正式进入35岁程序员的行列,随时会受到命运对我的锤炼。庆幸…

STL容器之deque

双端队列&#xff1b;序列式容器(deque/vector)&#xff1b;底层分段连续 支持从双端进行插入和删除&#xff1b; 综合了vector和list的优点&#xff1b; 插入、删除、查找的平均时间复杂度都是O(1) 部分deque的操作如下&#xff1a; #include <stdlib.h> #include …

varnish-cache使用

Varnish Cache是一个web加速软件&#xff0c;用作web服务加速的反向代理&#xff0c;与Squid不同的是它建立在较新的系统内核调用上&#xff0c;并且主要是使用内存作为缓存&#xff0c;它现有的使用者有facebook等&#xff0c;据使用者反馈&#xff0c;其与Squid相比&#xff…

2020年文章汇总

据悉&#xff0c;深圳某工程师沦为C语言笔试枪手修改cmdline 把内存改成512MB上拉电阻的作用剖析C语言是如何画出这样的三角形的c语言画谢宾斯基三角形Linux字符设备驱动实例哦&#xff0c;这是桶排序回答一个微信好友的创业问题Linux-C编程 / 多线程 / 如何终止某个线程&#…

2018年文章汇总

Android ANR 实例分析Linux kernel计算某段代码运行时间Linux Kernel 发展和内核特点C/C函数指针与指针函数(二)老王带你理解算法复杂度O(1),O(N),O(N^2)Android NDK Tombstone/Crash 分析堆和栈的区别&#xff08;转过无数次的文章&#xff09;C语言scanf-周末杂想C语言-scanf…

Angular CLI的简单使用(1)

参考地址: https://v2.angular.cn/docs/ts/latest/cli-quickstart.html Angular CLI是一个命令行界面工具&#xff0c;它可以创建项目、添加文件以及执行一大堆开发任务&#xff0c;比如测试、打包和发布。 1. 请先在终端/控制台窗口中运行命令 node -v 和 npm -v, 如下图,没有…

在没有数据集的情况下使用数据表

使用数据适配器填充数据表 View Code using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Data.SqlClient;namespace PopDataTable {class Program{static void Main(string[] args){string connString…

2019年文章汇总

要不要去培训机构深造一下&#xff1f;我一个37岁的程序员朋友Linux内核中的GPIO系统整理的免费资料&#xff0c;帮你年后跳槽C语言&#xff0c;字符串指针做函数参数书籍推荐过年回家抢票攻略C语言&#xff0c;函数不可返回指向栈内存的指针你还会写这段C51程序吗&#xff1f;…

linux下修改max_user_processes和open_file的最大值

从事分布式服务器开发工作的都会遇到&#xff0c;linux下open_file的值默认是1024&#xff1b;max user processes的值默认是4096&#xff0c;在实际用于中&#xff0c;这两个值严重不足&#xff0c;常常需要调整这两个值。默认配置如下&#xff1a; 可以通过以下两种方式修改&…

IP SLA的路径控制

一、定义SLA 服务水平协议&#xff08;简称&#xff1a;SLA&#xff0c;全称&#xff1a;service level agreement&#xff09;是在一定开销下为保障服务的性能和可靠性&#xff0c;服务提供商与用户间定义的一种双方认可的协定。通常这个开销是驱动提供服务质量的主要因素。简…

【linux】linux系统中常见配置文件及目录说明

1.配置文件/proc/sys/fs/file-nr 里文件里显示三个数字 [rootlocalhost logs]# cat /proc/sys/fs/file-nr 2112 0 2100000已分配文件句柄的数目 已使用文件句柄的数目 文件句柄的最大数目 上面第二项的值为0表示分配的文件…

ptmalloc,tcmalloc和jemalloc内存分配策略研究

转载&#xff1a;https://cloud.tencent.com/developer/article/1173720 操作系统内存布局 各种malloc的内存分配管理方式离不开操作系统的内存布局策略。 32位经典内存布局 32位系统下经典内存布局如上&#xff0c;程序起始的1GB地址为内核空间&#xff0c;接下来是向下增长…

Tcmalloc

Tcmalloc Ptmalloc在性能上还是存在一些问题的&#xff0c;比如不同分配区&#xff08;arena&#xff09;的内存不能交替使用&#xff0c;比如每个内存块分配都要浪费8字节内存等等&#xff0c;所以一般倾向于使用第三方的malloc。 Tcmalloc是Google gperftools里的组件之一。…

JVM自动内存管理机制——Java内存区域(下)

一、虚拟机参数配置 在上一篇《Java自动内存管理机制——Java内存区域&#xff08;上&#xff09;》中介绍了有关的基础知识&#xff0c;这一篇主要是通过一些示例来了解有关虚拟机参数的配置。 1、Java堆参数设置 a&#xff09;下面是一些简单的使用参数 其中最后一个是一个运…