eureka技术分享


推荐阅读:Java小白进阶架构师学习路线


上一篇文章《微服务零基础入门教学》,详细的介绍了微服务的大背景以及微服务架构的演进,我们还对各种解决微服务的方案进行了分析,今天就让我们正式开始微服务的实战环节:注册中心

我打算将迄今为止常见的八种注册中心逐一展开介绍,首先讲解第一个大家最为熟知的注册中心——Eureka

注册中心之Eureka

    • 一、Eureka的基础知识
    • 二、Eureka的交互流程与原理
    • 三、搭建Eureka注册中心
      • 1、搭建Eureka服务中心
      • 2、服务注册中心管理后台
    • 四、服务注册到Eureka注册中心
      • 1、商品服务注册
      • 2、订单服务注册
    • 五、Eureka中的自我保护
    • 六、Eureka中的元数据
    • 七、Eureka高可用集群
      • 1、搭建 Eureka Server高可用集群
      • 2、服务注册到Eureka Server集群
    • 八、Eureka中的常见问题
      • 1、服务注册慢
      • 2、服务节点剔除问题
      • 3、监控页面显示ip
    • 九、Eureka配置合集
      • 1、Eureka Server常用配置
      • 2、Eureka Client 常用配置
      • 3、Eureka Instance常用配置



一、Eureka的基础知识

Eureka是Netflix开发的服务发现框架,SpringCloud将它集成在自己的子项目spring-cloud-netflix中,实现SpringCloud的服务发现功能。

eureka技术分享_第1张图片
上图简要描述了Eureka的基本架构,由3个角色组成:

  1. Eureka Server
    提供服务注册和发现
  2. Service Provider
    服务提供方将自身服务注册到Eureka,从而使服务消费方能够找到
  3. Service Consumer
    服务消费方从Eureka获取注册服务列表,从而能够消费服务

二、Eureka的交互流程与原理

eureka技术分享_第2张图片

图是来自Eureka官方的架构图,大致描述了Eureka集群的工作过程。图中包含的组件非常多,可能比较难以理解,我们用通俗易懂的语言解释一下:

  • Application Service 相当于本书中的服务提供者,Application Client相当于服务消费者;
  • Make Remote Call,可以简单理解为调用RESTful API;
  • us-east-1c、us-east-1d等都是zone,它们都属于us-east-1这个region;

由图可知,Eureka包含两个组件:Eureka Server 和 Eureka Client,它们的作用如下:

  • Eureka Client是一个Java客户端,用于简化与Eureka Server的交互;
  • Eureka Server提供服务发现的能力,各个微服务启动时,会通过Eureka Client向Eureka Server进行注册自己的信息(例如网络信息),Eureka Server会存储该服务的信息;
  • 微服务启动后,会周期性地向Eureka Server发送心跳(默认周期为30秒)以续约自己的信息。如果Eureka Server在一定时间内没有接收到某个微服务节点的心跳,Eureka Server将会注销该微服务节点(默认90秒);
  • 每个Eureka Server同时也是Eureka Client,多个Eureka Server之间通过复制的方式完成服务注册表的同步;
  • Eureka Client会缓存Eureka Server中的信息。即使所有的Eureka Server节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者。

综上,Eureka通过心跳检测、健康检查和客户端缓存等机制,提高了系统的灵活性、可伸缩性和可用性。


三、搭建Eureka注册中心

1、搭建Eureka服务中心

(1) 创建shop_eureka_server子模块
在 shop_parent 下创建子模块 shop_eureka_server
(2) 引入maven坐标

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

(3) 配置application.yml

server:
 port: 8761
eureka:
 instance:
   hostname: localhost
 client:
   registerWithEureka: false  
   fetchRegistry: false
   serviceUrl:
     defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
	registerWithEureka: 是否将自己注册到Eureka服务中,本身就是所有无需注册
	fetchRegistry : 是否从Eureka中获取注册信息
	serviceUrlEureka: 客户端与Eureka服务端进行交互的地址

(4) 配置启动类
在 cn.itcast.eureka 下创建启动类 EurekaServerApplication

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
	public static void main(String[] args) {
		SpringApplication.run(EurekaServerApplication.class, args);
 	}
}

EnableEurekaServer : 激活Eureka Server端配置

2、服务注册中心管理后台

打开浏览器访问http://localhost8761即可进入EurekaServer内置的管理控制台,显示效果如下
eureka技术分享_第3张图片


四、服务注册到Eureka注册中心

1、商品服务注册

(1) 商品模块中引入坐标
在 shop_service_product 的pom文件中添加eureka client的相关坐标

<dependencies>
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
    dependency>
dependencies>

(2) 配置application.yml文件
在工程的 application.yml 中添加Eureka Server的主机地址

eureka:
 client:
   serviceUrl: # eureka server的路径
     defaultZone: http://localhost:8761/eureka/
 instance:
   prefer-ip-address: true #使用ip注册

(3) 修改启动类添加服务注册注解

@SpringBootApplication
//@EnableDiscoveryClient
//@EnableEurekaClient
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
 }
}

从Spring Cloud Edgware版本开始, @EnableDiscoveryClient 或 @EnableEurekaClient 可省略。只需加上相关依赖,并进行相应配置,即可将微服务注册到服务发现组件上。

2、订单服务注册

和商品微服务一样,只需要引入坐标依赖,在工程的 application.yml 中添加Eureka Server的主机地址即可

(1) 订单模块中引入坐标
在 shop_service_product 的pom文件中添加eureka client的相关坐标

<dependencies>
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
    dependency>
dependencies>

(2) 配置application.yml文件
在工程的 application.yml 中添加Eureka Server的主机地址

eureka:
 client:
   serviceUrl: # eureka server的路径
     defaultZone: http://localhost:8761/eureka/
 instance:
   prefer-ip-address: true #使用ip注册

(3) 修改启动类添加服务注册注解

@SpringBootApplication
//@EnableDiscoveryClient
//@EnableEurekaClient
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
 }
}

从Spring Cloud Edgware版本开始, @EnableDiscoveryClient 或 @EnableEurekaClient 可省略。只需加上相关依赖,并进行相应配置,即可将微服务注册到服务发现组件上。

五、Eureka中的自我保护

微服务第一次注册成功之后,每30秒会发送一次心跳将服务的实例信息注册到注册中心。通知 Eureka Server 该实例仍然存在。如果超过90秒没有发送更新,则服务器将从注册信息中将此服务移除。

Eureka Server在运行期间,会统计心跳失败的比例在15分钟之内是否低于85%,如果出现低于的情况(在单机调试的时候很容易满足,实际在生产环境上通常是由于网络不稳定导致),Eureka Server会将当前的实例注册信息保护起来,同时提示这个警告。保护模式主要用于一组客户端和Eureka Server之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)验证完自我保护机制开启后,并不会马上呈现到web上,而是默认需等待 5 分钟(可以通eureka.server.wait-time-in-ms-when-sync-empty 配置),即 5 分钟后你会看到下面的提示信息:

eureka技术分享_第4张图片
如果关闭自我保护
通过设置 eureka.enableSelfPreservation=false 来关闭自我保护功能。


六、Eureka中的元数据

Eureka的元数据有两种:标准元数据和自定义元数据。

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

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

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class RestTemplateTest {
	@Autowired
	private DiscoveryClient discoveryClient;
	@Test
	public void test() {
	//根据微服务名称从注册中心获取相关的元数据信息
	List<ServiceInstance> instances = discoveryClient.getInstances("shop-service-product");
		for (ServiceInstance instance : instances) {
			System.out.println(instance);
		 }
	 }
}

七、Eureka高可用集群

Eureka Client会定时连接Eureka Server,获取注册表中的信息并缓存到本地。微服务在消费远程API时总是使用本地缓存中的数据。因此一般来说,即使Eureka Server发生宕机,也不会影响到服务之间的调用。但如果Eureka Server宕机时,某些微服务也出现了不可用的情况,Eureka Server中的缓存若不被刷新,就可能会影响到微服务的调用,甚至影响到整个应用系统的高可用。因此,在生成环境中,通常会部署一个高可用的Eureka Server集群。

Eureka Server可以通过运行多个实例并相互注册的方式实现高可用部署,Eureka Server实例会彼此增量地同步信息,从而确保所有节点数据一致。事实上,节点之间相互注册是Eureka Server的默认行为。
eureka技术分享_第5张图片

1、搭建 Eureka Server高可用集群

1、修改本机host属性

127.0.0.1 eureka1
127.0.0.1 eureka2

2、修改 shop_eureka_server 工程中的yml配置文件,添加如下配置属性

#指定应用名称
spring:
 application:
   name: shop-eureka-server
---
#执行peer1的配置信息
spring:
 profiles: eureka1
server:
 port: 8761
eureka:
 instance:
   hostname: eureka1
 client:
   service-url:
     defaultZone: http://eureka2:8762/eureka
---
#执行peer2的配置信息
spring:
 profiles: eureka2
server:
 port: 8762
eureka:
 instance:
   hostname: eureka2
 client:
   service-url:
     defaultZone: http://eureka1:8761/eureka

在配置文件中通过连字符(—)将文件分为三个部分,第一部分为应用名称,第二部分和第三部分是根据不同的profiles选项动态添加,可以在IDEA启动时进行激活配置

eureka技术分享_第6张图片

使用IDEA启动历次EurekaServerApplicaion分别激活eureka1和eureka2配置。访问http://eureka1:8761和http://eureka1:8762/。会发现注册中心 SHOP-EUREKA-SERVER 已经有两个节点,并且registered-replicas (相邻集群复制节点)中已经包含对方。
eureka技术分享_第7张图片

2、服务注册到Eureka Server集群

如果需要将微服务注册到Eureka Server集群只需要修改yml配置文件即可

eureka:
 client:
   serviceUrl:
     defaultZone: http://eureka1:8761/eureka/,http://eureka1:8761/eureka/

以商品微服务为例,修改defaultZone配置添加多个Eureka Server的地址

八、Eureka中的常见问题

1、服务注册慢

默认情况下,服务注册到Eureka Server的过程较慢。SpringCloud官方文档中给出了详细的原因
在这里插入图片描述

大致含义:服务的注册涉及到心跳,默认心跳间隔为30s。在实例、服务器、客户端都在本地缓存中具有相同的元数据之前,服务不可用于客户端发现(所以可能需要3次心跳)。可以通过配置eureka.instance.leaseRenewalIntervalInSeconds (心跳频率)加快客户端连接到其他服务的过程。在生产中,最好坚持使用默认值,因为在服务器内部有一些计算,他们对续约做出假设。

2、服务节点剔除问题

默认情况下,由于Eureka Server剔除失效服务间隔时间为90s且存在自我保护的机制。所以不能有效而迅速的剔除失效节点,这对开发或测试会造成困扰。解决方案如下:

Eureka Server:
配置关闭自我保护,设置剔除无效节点的时间间隔

eureka:
 instance:
   hostname: eureka1
 client:
   service-url:
     defaultZone: http://eureka2:8762/eureka
 server:
   enable-self-preservation: false  #关闭自我保护
   eviction-interval-timer-in-ms: 4000 #剔除时间间隔,单位:毫秒

Eureka Client:
配置开启健康检查,并设置续约时间

eureka:
 client:
   healthcheck: true #开启健康检查(依赖spring-boot-actuator)
   serviceUrl:
     defaultZone: http://eureka1:8761/eureka/,http://eureka1:8761/eureka/
 instance:
   preferIpAddress: true
   lease-expiration-duration-in-seconds: 10 #eureka client发送心跳给server端后,续约到期时间(默认90秒)
   lease-renewal-interval-in-seconds: 5 #发送心跳续约间隔

3、监控页面显示ip

在Eureka Server的管控台中,显示的服务实例名称默认情况下是微服务定义的名称和端口。为了更好的对所有服务进行定位,微服务注册到Eureka Server的时候可以手动配置示例ID。配置方式如下:

eureka:
 instance:
   instance-id: ${spring.cloud.client.ip-address}:${server.port}
#spring.cloud.client.ip-address:获取ip地址

在这里插入图片描述

九、Eureka配置合集

1、Eureka Server常用配置

eureka:
  server:
    #服务端开启自我保护模式
    enable-self-preservation: true
    #扫描失效服务的间隔时间(单位毫秒,默认是60*1000)即60秒
    eviction-interval-timer-in-ms: 60000
    #间隔多长时间,清除过期的 delta 数据
    delta-retention-timer-interval-in-ms: 0
    #是否开启请求频率限制器
    rate-limiter-enabled: false
    #请求频率限制器
    rate-limiter-burst-size: 10
    #请求频率的平均值
    rate-limiter-full-fetch-average-rate: 100
    #是否对标准的client进行频率请求限制。如果是false,则只对非标准client进行限制
    rate-limiter-throttle-standard-clients: false
    #注册服务、拉取服务列表数据的请求频率的平均值
    rate-limiter-registry-fetch-average-rate: 500
    #设置信任的client list
    rate-limiter-privileged-clients: Collections.emptySet()
    #在设置的时间范围类,期望与client续约的百分比。
    renewal-percent-threshold: 0.85
    #多长时间更新续约的阈值
    renewal-threshold-update-interval-ms: 900000
    #对于缓存的注册数据,多长时间过期
    response-cache-auto-expiration-in-seconds: 180
    #多长时间更新一次缓存中的服务注册数据
    response-cache-update-interval-ms: 30000
    #缓存增量数据的时间,以便在检索的时候不丢失信息
    retention-time-in-m-s-in-delta-queue: 180000
    #当时间戳不一致的时候,是否进行同步
    sync-when-timestamp-differs: true
    #是否采用只读缓存策略,只读策略对于缓存的数据不会过期。
    use-read-only-response-cache: true
    
    #============== server node 与 node 之间关联的配置 ==============#

    #发送复制数据是否在request中,总是压缩
    enable-replicated-request-compression: false
    #指示群集节点之间的复制是否应批处理以提高网络效率。
    batch-replication: false
    #允许备份到备份池的最大复制事件数量。而这个备份池负责除状态更新的其他事件。可以根据内存大小,超时和复制流量,来设置此值得大小
    max-elements-in-peer-replication-pool: 10000
    #允许备份到状态备份池的最大复制事件数量
    max-elements-in-status-replication-pool: 10000
    #多个服务中心相互同步信息线程的最大空闲时间
    max-idle-thread-age-in-minutes-for-peer-replication: 15
    #状态同步线程的最大空闲时间
    max-idle-thread-in-minutes-age-for-status-replication: 15
    #服务注册中心各个instance相互复制数据的最大线程数量
    max-threads-for-peer-replication: 20
    #服务注册中心各个instance相互复制状态数据的最大线程数量
    max-threads-for-status-replication: 1
    #instance之间复制数据的通信时长
    max-time-for-replication: 30000
    #正常的对等服务instance最小数量。-1表示服务中心为单节点。
    min-available-instances-for-peer-replication: -1
    #instance之间相互复制开启的最小线程数量
    min-threads-for-peer-replication: 5
    #instance之间用于状态复制,开启的最小线程数量
    min-threads-for-status-replication: 1
    #instance之间复制数据时可以重试的次数
    number-of-replication-retries: 5
    #eureka节点间间隔多长时间更新一次数据。默认10分钟。
    peer-eureka-nodes-update-interval-ms: 600000
    #eureka服务状态的相互更新的时间间隔。
    peer-eureka-status-refresh-time-interval-ms: 0
    #eureka对等节点间连接超时时间
    peer-node-connect-timeout-ms: 200
    #eureka对等节点连接后的空闲时间
    peer-node-connection-idle-timeout-seconds: 30
    #节点间的读数据连接超时时间
    peer-node-read-timeout-ms: 200
    #eureka server 节点间连接的总共最大数量
    peer-node-total-connections: 1000
    #eureka server 节点间连接的单机最大数量
    peer-node-total-connections-per-host: 10
    #在服务节点启动时,eureka尝试获取注册信息的次数
    registry-sync-retries: 0
    #在服务节点启动时,eureka多次尝试获取注册信息的间隔时间
    registry-sync-retry-wait-ms:
    #当eureka server启动的时候,不能从对等节点获取instance注册信息的情况,应等待多长时间。
    wait-time-in-ms-when-sync-empty: 0

2、Eureka Client 常用配置


eureka:
  client:
    #该客户端是否可用
    enabled: true
    #实例是否在eureka服务器上注册自己的信息以供其他服务发现,默认为true
    register-with-eureka: false
    #此客户端是否获取eureka服务器注册表上的注册信息,默认为true
    fetch-registry: false
    #是否过滤掉,非UP的实例。默认为true
    filter-only-up-instances: true
    #与Eureka注册服务中心的通信zone和url地址
    service-url: 
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
    #client连接Eureka服务端后的空闲等待时间,默认为30 秒
    eureka-connection-idle-timeout-seconds: 30
    #client连接eureka服务端的连接超时时间,默认为5秒
    eureka-server-connect-timeout-seconds: 5
    #client对服务端的读超时时长
    eureka-server-read-timeout-seconds: 8
    #client连接all eureka服务端的总连接数,默认200
    eureka-server-total-connections: 200
    #client连接eureka服务端的单机连接数量,默认50
    eureka-server-total-connections-per-host: 50
    #执行程序指数回退刷新的相关属性,是重试延迟的最大倍数值,默认为10
    cache-refresh-executor-exponential-back-off-bound: 10
    #执行程序缓存刷新线程池的大小,默认为5
    cache-refresh-executor-thread-pool-size: 2
    #心跳执行程序回退相关的属性,是重试延迟的最大倍数值,默认为10
    heartbeat-executor-exponential-back-off-bound: 10
    #心跳执行程序线程池的大小,默认为5
    heartbeat-executor-thread-pool-size: 5
    # 询问Eureka服务url信息变化的频率(s),默认为300秒
    eureka-service-url-poll-interval-seconds: 300
    #最初复制实例信息到eureka服务器所需的时间(s),默认为40秒
    initial-instance-info-replication-interval-seconds: 40
    #间隔多长时间再次复制实例信息到eureka服务器,默认为30秒
    instance-info-replication-interval-seconds: 30
    #从eureka服务器注册表中获取注册信息的时间间隔(s),默认为30秒
    registry-fetch-interval-seconds: 30
    # 获取实例所在的地区。默认为us-east-1
    region: us-east-1
    #实例是否使用同一zone里的eureka服务器,默认为true,理想状态下,eureka客户端与服务端是在同一zone下
    prefer-same-zone-eureka: true
    # 获取实例所在的地区下可用性的区域列表,用逗号隔开。(AWS)
    availability-zones:
      china: defaultZone,defaultZone1,defaultZone2
    #eureka服务注册表信息里的以逗号隔开的地区名单,如果不这样返回这些地区名单,则客户端启动将会出错。默认为null
    fetch-remote-regions-registry:
    #服务器是否能够重定向客户端请求到备份服务器。 如果设置为false,服务器将直接处理请求,如果设置为true,它可能发送HTTP重定向到客户端。默认为false
    allow-redirects: false
    #客户端数据接收
    client-data-accept:
    #增量信息是否可以提供给客户端看,默认为false
    disable-delta: false
    #eureka服务器序列化/反序列化的信息中获取“_”符号的的替换字符串。默认为“__“
    escape-char-replacement: __
    #eureka服务器序列化/反序列化的信息中获取“$”符号的替换字符串。默认为“_-”
    dollar-replacement: "_-"
    #当服务端支持压缩的情况下,是否支持从服务端获取的信息进行压缩。默认为true
    g-zip-content: true
    #是否记录eureka服务器和客户端之间在注册表的信息方面的差异,默认为false
    log-delta-diff: false
    # 如果设置为true,客户端的状态更新将会点播更新到远程服务器上,默认为true
    on-demand-update-status-change: true
    #此客户端只对一个单一的VIP注册表的信息感兴趣。默认为null
    registry-refresh-single-vip-address:
    #client是否在初始化阶段强行注册到服务中心,默认为false
    should-enforce-registration-at-init: false
    #client在shutdown的时候是否显示的注销服务从服务中心,默认为true
    should-unregister-on-shutdown: true

3、Eureka Instance常用配置

eureka:
  instance:
    #应用名,首先获取spring.application.name的值,如果取值为空,则取默认unknown。
    appname: unknown
    #应用组名
    appGroupName: null
    #实例注册到Eureka上时,是否立刻开启通讯。有时候应用在准备好服务之前需要一些预处理。
    instanceEnabledOnit: false
    #非安全的端口
    nonSecurePort: 80
    #安全端口
    securePort: 443
    #是否开启非安全端口通讯
    nonSecurePortEnabled: true
    #是否开启安全端口通讯
    securePortEnabled: false
    #实例续约更新间隔时间
    leaseRenewalIntervalInSeconds: 30
    #实例超时/过期时间,表示最大leaseExpirationDurationInSeconds秒后没有续约,Server就认为他不可用了,随之就会将其剔除。
    leaseExpirationDurationInSeconds: 90
    #虚拟主机名,首先获取spring.application.name的值,如果取值为空,则取默认unknown。
    virtualHostName: unknown
    #注册到eureka上的唯一实例ID,不能与相同appname的其他实例重复。
    instanceId: ${spring.application.name}:${server.port}
    #安全虚拟主机名,首先获取spring.application.name的值,如果取值为空,则取默认unknown。
    secureVirtualHostName: unknown
    #实例元数据,可以供其他实例使用。比如spring-boot-admin在监控时,获取实例的上下文和端口。
    metadataMap: new HashMap();
    #实例部署的数据中心。如AWS、MyOwn。
    dataCenterInfo: new MyDataCenterInfo(DataCenterInfo.Name.MyOwn);
    #实例的IP地址
    ipAddress: null
    #实例状态页相对url
    statusPageUrlPath: "/actuator/info"
    #实例状态页绝对URL
    statusPageUrl: null
    #实例主页相对URL
    homePageUrlPath: "/"
    #实例主页绝对URL
    homePageUrl: null
    #实例健康检查相对URL
    health-check-url-path: "/actuator/health"
    #实例健康检查绝对URL
    healthCheckUrl: null
    #实例安全的健康检查绝对URL
    secureHealthCheckUrl: null
    #配置属性的命名空间(Spring Cloud中被忽略)
    namespace: "eureka"
    #主机名,不配置的时候将根据操作系统的主机名来获取
    hostname: null
    #是否优先使用IP地址作为主机名的标识
    preferIpAddress: false


推荐阅读:Java小白进阶架构师学习路线


你可能感兴趣的:(深入浅出,百炼成仙,eureka,微服务,spring,cloud,注册中心)