Eureka元数据详解

Eureka的元数据有两种:标准元数据和自定义元数据。标准元数据:主机名、IP地址、端⼝号等信息,这些信息都会被发布在服务注册表中,用于服务之间的调用。
自定义元数据:可以使用eureka.instance.metadata-map配置,符合KEY/VALUE的存储格式。这些元数据可以在远程客户端中访问。

  1. instance:
  2. prefer-ip-address: true
  3. metadata-map:
  4. # 自定义元数据(kv自定义)
  5. cluster: cl1
  6. region: rn1

可以在程序中可以使用DiscoveryClient 获取指定微服务的所有元数据信息

  1. @Autowired
  2. private DiscoveryClient discoveryClient;
  3. @Autowired
  4. private RestTemplate restTemplate;
  5. @Test
  6. public void testInstanceMetadata() {
  7. // 从EurekaServer获取指定微服务实例
  8. List<ServiceInstance> instances = discoveryClient.getInstances("lagou-service-resume");
  9. for (int i = 0; i < instances.size(); i++) {
  10. // 循环打印每个微服务实例的元数据信息
  11. ServiceInstance serviceInstance = instances.get(i);
  12. System.out.println(serviceInstance);
  13. }
  14. }

1、元数据展示

image.png

2、获取元数据有何用?

客户端通过远程调用的方式来获取元数据,实现信息传递?

Eureka客户端详解

服务提供者(也是Eureka客户端)要向EurekaServer注册服务,并完成服务续约等工作

1、服务注册详解(服务提供者)

1)当我们导入了eureka-client依赖坐标,配置Eureka服务注册中心地址
2)服务在启动时会向注册中心发起注册请求,携带服务元数据信息
3)Eureka注册中心会把服务的信息保存在Map中。

2、服务续约详解(服务提供者)

服务每隔30秒会向注册中心续约(心跳)一次(也称为报活),如果没有续约,租约在 90秒后到期,然后服务会被失效。每隔30秒的续约操作我们称之为心跳检测 往往不需要我们调整这两个配置

  1. #向Eureka服务中心集群注册服务
  2. eureka:
  3. instance:
  4. # 租约续约间隔时间,默认30秒
  5. lease-renewal-interval-in-seconds: 30
  6. # 租约到期,服务时效时间,默认值90秒,服务超过90秒没有发送心跳,
  7. EurekaServer会将服务从列表移除
  8. lease-expiration-duration-in-seconds: 90

3、获取服务列表详解(服务消费者)

每隔30秒服务会从注册中心中拉取一份服务列表,这个时间可以通过配置修改。往 往不需要我们调整

  1. #向Eureka服务中⼼集群注册服务
  2. eureka:
  3. client:
  4. # 每隔多久拉取⼀次服务列表
  5. registry-fetch-interval-seconds: 30

1)服务消费者启动时,从 EurekaServer服务列表获取只读备份,缓存到本地
2)每隔30秒,会重新获取并更新数据
3)每隔30秒的时间可以通过配置eureka.client.registry-fetch-interval-seconds修改

4、Eureka服务端详解

服务下线
1)当服务正常关闭操作时,会发送服务下线的REST请求给EurekaServer。
2)服务中心接受到请求后,将该服务置为下线状态

失效剔除

Eureka Server会定时(间隔值是eureka.server.eviction-interval-timer-in-ms,默 认60s)进行检查,如果发现实例在在一定时间(此值由客户端设置的 eureka.instance.lease-expiration-duration-in-seconds定义,默认值为90s)内没有收到心跳,则会注销此实例

自我保护

服务提供者 —> 注册中心定期的续约(服务提供者和注册中心通信),假如服务提供者和注册中心之间的网络有点问题,不代表服务提供者不可用,不代表服务消费者无法访问服务提供者 如果在15分钟内超过85%的客户端节点都没有正常的心跳,那么Eureka就认为客户 端与注册中心出现了网络故障,Eureka Server自动进行自我保护机制。
image.png
当处于自我保护模式时
1)不会剔除任何服务实例(可能是服务提供者和EurekaServer之间网络问题),保证了大多数服务依然可用
2)Eureka Server仍然能够接受新服务的注册和查询请求但是不会被同步到其它节点上,保证当前节点依然可用,当网络稳定时,当前Eureka Server新的注册信息才会被同步到其它节点中
3)在Eureka Server过程中通过eureka.server.enable-self-preservation配置可用关停自我保护,默认值是打开

  1. eureka:
  2. server:
  3. enable-self-preservation: false # 关闭⾃我保护模式(缺省为打开)

经验:建议生产环境打开自我保护机制

Eureka核心源码剖析

1、 Eureka Server启动过程

A、入口

其入口就是SpringCloud充分利用了SpringBoot的自动装配的特点。可以看到eureka-server的jar包,发现在META-INF下面有配置文件spring.factories 这个文件是固定的,里面就是一些SpringBoot对其实现自动装配的一些类
springboot应用启动时, 会加载EurekaServerAutoConfiguration自动配置类
image.png

1、eurekaController
2、peerAwareInstanceRegistry 依靠于peerEurekaNodes的辅助
peerEurekaNodes里面有start()方法,方法里面有更新的方法updatePeerEurekaNodes()
3、eurekaServerContext服务的上下文有一个DefaultEurekaServerContext类,里面有一个initialize() 方法。用于启动peerEurekaNodes的start的。
4、eurekaServerBootstrap后续启动要用此对象
5、jerseyFilterRegistration是一个reset框架,帮助发布接口服务

实例化的
1、在EurekaServerInitializerConfiguration中有一个 start() ,里面有一个上下文实例化contextInitialized(),里面还有这initEurekaServerContext(),里面有着对非ioc容器的实例化_initialize,注册统计_syncUp(统计有没有,没有就远程把信息拿过来,在自己这里注册到列表中),其里面有调用到register,
_2、_com.netflix.eureka.registry.InstanceRegistry#openForTraffic,除了syncUp,还有openForTraffic。里面有一个super.postInit();,调用了定时器renewsLastMin.start();具体是调用EvictionTask方法进行的。

发布任务的
org.springframework.cloud.netflix.eureka.server.EurekaServerAutoConfiguration#jerseyFilterRegistration
它也依赖jerseyApplication,来发布资源的

服务注册
com.netflix.eureka.resources.ApplicationResource#addInstance, 服务注册接口(接受客户端注册服务 )addInstance方法,里面是调用register进行注册的,里面还有调用父类注册的super.registe,同时也把该注册的实例信息同步到其他节点replicateToPeers,其里面还调用了一个replicateInstanceActionsToPeers,根据情况选择相对的操作。

服务端接受客户端续约
这个续约是对具体的对象而言,所以找到资源里面的实例,com.netflix.eureka.resources.InstanceResource#renewLease,有调用renew方法,里面还有replicateToPeers去同步到其他方法,其里面又是调用replicateInstanceActionsToPeers, 复制Instance实例操作到其它节点 ,与replicateToPeers同层的还有一个super.renew(),通过调用leaseToRenew.renew();重新更新时间

######
客户端注册服务
入口
image.png
1)读取配置文件注入到容器
EurekaInstanceConfigBean

2)启动时从EurekaServer获取服务实例信息
EurekaClient里面返回的是CloudEurekaClient,其里面还调用super(。。),其父类是DiscoveryClient方法,里面还调用了this(applicationInfoManager。。。)构造器,还继续中信息中心获取信息列表,if (clientConfig.shouldFetchRegistry() && !fetchRegistry(false)) ,fetchRegistry从服务中心拿到本地缓存getApplications();

3)注册信息到EurekaServer(addInstance)
其里面有一个register(),就是用来注册自己的, 还继续调用register,底层使用Jersey客户端进行远程请求。

4)开启一些定时任务(心跳续约,刷新本地服务缓存列表)
还是在DiscoveryClient类中有任务方法,initScheduledTasks,里面有对cacheRefresh,heartbeat等处理的,
cacheRefresh调用CacheRefreshThread(),里面调refreshRegistry,heartbeat调用HeartbeatThread(),调用renew()进行续约,还有更新时间。续约是先拉去列表信息,如果没有自己就继续注册一个进去,
服务下架
直接在EurekaClientConfiguration#eurekaClient方法上,点进去,shutdown,调用了unregister();,调用底层jersey进行,发送请求,准备下线咯。

……下载源码,写注释比较好