My Name is YangYang
Eureka简介
在微服务架构中往往会有一个注册中心,每个微服务都会向注册中心去注册自己的地址及端口信息,注册中心维护着服务名称与服务实例的对应关系。每个微服务都会定时从注册中心获取服务列表,同时汇报自己的运行情况,这样当有的服务需要调用其他服务时,就可以从自己获取到的服务列表中获取实例地址进行调用,Eureka实现了这套服务注册与发现机制。
搭建Eureka注册中心
使用IDEA来创建SpringCloud应用
Eureka分为注册和发现,所以需要创建Server模块和Client模块,简单些讲实际项目中Eureka作为注册Server模块,其他子服务属于Client模块。
- 创建一个eureka-server模块,并使用Spring Initializer初始化一个SpringBoot项目
- 填写应用信息
- 选择你需要的SpringCloud组件进行创建
- 添加Pom.xml依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
- 在启动类上添加@EnableEurekaServer注解来启用Euerka注册中心功能
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
- 在配置文件application.yml中添加Eureka注册中心的配置
server:
port: 8001 #指定运行端口
spring:
application:
name: eureka-server #指定服务名称
eureka:
instance:
hostname: localhost #指定主机地址
client:
fetch-registry: false #指定是否要从注册中心获取服务(注册中心不需要开启)
register-with-eureka: false #指定是否要注册到注册中心(注册中心不需要开启)
server:
enable-self-preservation: false #关闭保护模式
使用IDEA的Run Dashboard来运行SpringCloud应用
- 打开Run Dashboard,默认情况下,当IDEA检查到你的项目中有SpringBoot应用时,会提示你开启,如果你没开启,可以用以下方法开启。
- 运行SpringCloud应用
- 运行完成后访问地址 http://localhost:8001/ 可以看到Eureka注册中心的界面
搭建Eureka客户端
- 新建一个eureka-client模块,并在pom.xml中添加如下依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- 在启动类上添加@EnableDiscoveryClient注解表明是一个Eureka客户端
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args);
}
}
- 在配置文件application.yml中添加Eureka客户端的配置
server:
port: 8101 #运行端口号
spring:
application:
name: eureka-client #服务名称
eureka:
client:
register-with-eureka: true #注册到Eureka的注册中心
fetch-registry: true #获取注册实例列表
service-url:
defaultZone: http://localhost:8001/eureka/ #配置注册中心地址
- 运行Eureka-Client
- 查看注册中心http://localhost:8001/ 发现Eureka客户端已经成功注册
Eureka原理图
-
库存服务注册原理图
-
eureka底层实现是使用concurrentHashMap,图中为eureka的实现原理可以很清楚的理解,其中有个多级缓存,服务每隔30s发送一个心跳。
-
注册到服务注册中心,接着立马同步到readwith缓存中,接着30s同步到readonly缓存中,然后服务每隔30s拉取注册表即可调用注册中的服务。
-
服务下线是在eureka中有个每隔60s的定时检查,然后从readwith中剔除,30s后再从readonly中剔除,再会去被拉取。
-
从中可以看出时间还是比较长的,当在生产环境中还是要优化一下的,服务的发现还是比较慢的。
-
服务的实例是如何从服务中心剔除的:eureka server 要求client端定时进行续约,也就是发送心跳,来证明该服务实例还存活,是健康的,是可以调用的。
-
如果租约超过一定的时间没有进行续约操作,eureka server端会主动的剔除,这一点即心跳模式。
Eureka参数含义
配置 | 含义 | 默认值 |
---|---|---|
eureka.client.enabled | 是否启用Eureka Client 默认值:true | true |
eureka.client.register-with-eureka | 表示是否将自己注册到Eureka Server 默认值:true | true |
eureka.client.fetch-registry | 表示是否从Eureka Server获取注册的服务信息默认值:true | true |
eureka.client.serviceUrl.defaultZone | 配置Eureka Server地址,用于注册服务和获取服务默认值:http://localhost:8761/eureka | http://localhost:8761/eureka |
eureka.client.registry-fetch-interval-seconds | 默认值为30秒,即每30秒去Eureka Server上获取服务并缓存默认值:30 | 30 |
eureka.instance.lease-renewal-interval-in-seconds | 向Eureka Server发送心跳的间隔时间,单位为秒,用于服务续约默认值:30 | 30 |
eureka.instance.lease-expiration-duration-in-seconds | 定义服务失效时间,即Eureka Server检测到Eureka Client木有心跳后(客户端意外下线)多少秒将其剔除默认值:90 | 90 |
eureka.server.enable-self-preservation | 用于开启Eureka Server自我保护功能默认值:true | true |
eureka.client.instance-info-replication-interval-seconds | 更新实例信息的变化到Eureka服务端的间隔时间,单位为秒默认值:30 | 30 |
eureka.client.eureka-service-url-poll-interval-seconds | 轮询Eureka服务端地址更改的间隔时间,单位为秒。默认值:300 | 300 |
eureka.instance.prefer-ip-address | 表示使用IP进行配置为不是域名默认值:false | false |
eureka.client.healthcheck.enabled | 默认Erueka Server是通过心跳来检测Eureka Client的健康状况的,通过置为true改变Eeureka Server对客户端健康检测的方式,改用Actuator的/health端点来检测。默认值:false | false |
Eureka常用配置
eureka:
server:
wait-time-in-ms-when-sync-empty: 0 #在eureka服务器获取不到集群里对等服务器上的实例时,需要等待的时间,单机默认0
shouldUseReadOnlyResponseCache: true #eureka是CAP理论种基于AP策略,为了保证强一致性关闭此切换CP 默认不关闭 false关闭
enable-self-preservation: false #关闭服务器自我保护,客户端心跳检测15分钟内错误达到80%服务会保护,导致别人还认为是好用的服务
eviction-interval-timer-in-ms: 6000 #清理间隔(单位毫秒,默认是60*1000)5秒将客户端剔除的服务在服务注册列表中剔除#
response-cache-update-interval-ms: 3000 #eureka server刷新readCacheMap的时间,注意,client读取的是readCacheMap,这个时间决定了多久会把readWriteCacheMap的缓存更新到readCacheMap上 #eureka server刷新readCacheMap的时间,注意,client读取的是readCacheMap,这个时间决定了多久会把readWriteCacheMap的缓存更新到readCacheMap上默认30s
response-cache-auto-expiration-in-seconds: 180 #eureka server缓存readWriteCacheMap失效时间,这个只有在这个时间过去后缓存才会失效,失效前不会更新,过期后从registry重新读取注册服务信息,registry是一个ConcurrentHashMap。
instance:
prefer-ip-address: true
instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${spring.application.instance_id:${server.port}}
hostname: 127.0.0.1
lease-renewal-interval-in-seconds: 30 # 续约更新时间间隔(默认30秒),eureka客户端向服务端发送心跳的时间间隔
lease-expiration-duration-in-seconds: 90 # 续约到期时间(默认90秒)
client:
#注册到其他eureka
registerWithEureka: false
fetchRegistry: false #为true时,可以启动,但报异常:Cannot execute request on any known server ,是否从eureka服务端获取注册信息,消费者需要配置true
register-with-eureka: false #表示是否将服务注册到Eureka服务端,由于自身就是Eureka服务端,所以设置为false;
fetch-registry: false #表示是否从Eureka服务端获取服务信息,因为这里只搭建了一个Eureka服务端,并不需要从别的Eureka服务端同步服务信息,所以这里设置为false;
instance-info-replication-interval-seconds: 10 #更新实例信息的变化到Eureka服务端的间隔时间,单位为秒
registry-fetch-interval-seconds: 30 #从eureka服务端获取注册信息的间隔时间
eureka-service-url-poll-interval-seconds: 300 #轮询Eureka服务端地址更改的间隔时间,单位为秒。
service-url:
defaultZone: http://lee:lee@${eureka.instance.hostname}:${server.port}/eureka/
Eureka必须优化参数
eureka.server.responseCacheUpdateIntervalMs = 3000 #eureka server刷新readCacheMap的时间,注意,client读取的是readCacheMap,这个时间决定了多久会把readWriteCacheMap的缓存更新到readCacheMap上 默认30s
eureka.client.registryFetchIntervalSeconds = 30000 #从eureka服务端获取注册信息的间隔时间
eureka.client.leaseRenewalIntervalInSeconds = 30 # 续约更新时间间隔(默认30秒),eureka客户端向服务端发送心跳的时间间隔
eureka.server.evictionIntervalTimerInMs = 60000 #清理间隔(单位毫秒,默认是60*1000)5秒将客户端剔除的服务在服务注册列表中剔除#
eureka.instance.leaseExpirationDurationInSeconds = 90 90 # 续约到期时间(默认90秒)
- 服务发现的时效性变成秒级,几秒钟可以感知服务的上线和下线 这样eurek server差不多就优化好了,我们再优化下client端。
spring:
application:
name: api-gateway
cloud:
config:
discovery:
enabled: true
service-id: CONFIG
profile: dev
eureka:
client:
service-url:
defaultZone: http://lee:lee@127.0.0.1:8080/eureka
registry-fetch-interval-seconds: 5 #eureka client刷新本地缓存时间,默认30
instance:
hostname: 127.0.0.1
instance-id: 127.0.0.1:9000
lease-expiration-duration-in-seconds: 7 #Eureka服务端在收到最后一次心跳之后等待的时间上限,单位为秒,超过则剔除(客户端告诉服务端按照此规则等待自己),默认90
lease-renewal-interval-in-seconds: 5 #Eureka客户端向服务端发送心跳的时间间隔,单位为秒(客户端告诉服务端自己会按照该规则),默认30
Eureka与Zookeeper的区别
CAP,C是一致性,A是可用性,P是分区容错性。
-
zk是有一个leader节点会接受数据,然后同步到其他的节点,一但leader挂了,要重新选举leader,这个过程为了保证C,就牺牲了A,不接用一段时间,但是一个leader选举好了,就可以继续写数据了,保证一致性,即CP
-
eureka是peer模式,可能还没同步数据过去,结果自己就死了,此时还是可以继续从别的eureka机器上拉取注册表,但是可能看到的就不是最新的数据了,但是保证了可用性A,即AP。
转载:https://blog.csdn.net/awiner/article/details/106600222