一、Eureka简介
Eureka是一项基于REST(代表性状态转移)的服务,主要在AWS云中用于定位服务,以实现负载均衡和中间层服务器的故障转移。我们称此服务为Eureka Server。Eureka还带有一个基于Java的客户端组件Eureka Client,它使与服务的交互更加容易。客户端还具有一个内置的负载均衡器,可以执行基本的循环负载均衡。在Netflix,更复杂的负载均衡器将Eureka包装起来,以基于流量,资源使用,错误条件等多种因素提供加权负载均衡,以提供出色的弹性。
Git地址:https://github.com/Netflix/eureka
服务治理
在传统的rpc远程调用框架中,管理每个服务于服务之间依赖关系比较复杂,所以需要使用服务治理,管理服务与服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册
Spring Cloud封装了Netflix公司开发的Eureka模块来实现服务治理
服务注册
Eureka采用了CS的设计架构,Eureka Server作为服务注册功能的服务器,它是服务注册中心,而系统中的其他服务,使用Eureka的客户端连接到Eureka Server并维持心跳连接。这样系统的维护人员就可以通过Eureka Server来监控系统中各个微服务是否正常运行。在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信息,比如服务地址、通讯地址等以别名方式注册到注册中心上,另一方(消费者|服务提供者),以该别名的方式去注册中心上获取实际的服务通讯地址,然后在实现本地RPC调用RPC远程调用框架核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念)。在任何rpc远程框架中,都会有一个注册中心(存放服务地址相关信息(接口地址))
二、Eureka两组件
Eureka Server
Eureka Server提供服务注册服务,各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。
Eureka Client
Eureka Client通过注册中心进行访问是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳。Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)
三、Eureka架构
说明:
Register(服务注册):把自己的IP和端口注册给Eureka。
Renew(服务续约):发送心跳包,每30秒发送一次。告诉Eureka自己还活着。
Cancel(服务下线):当provider关闭时会向Eureka发送消息,把自己从服务列表中删除。防止consumer调用到不存在的服务。
Get Registry(获取服务注册列表):获取其他服务列表。
Replicate(集群中数据同步):eureka集群中的数据复制与同步。
Make Remote Call(远程调用):完成服务的远程调用。
四、单机版Eureka Server
五、集群版Eureka Server
注册中心作为微服务架构中的核心功能,其重要性不言而喻。在实际生产中,都会去搭建应用的集群来保证服务高可用。Eureka Server注册中心集群中每个节点都是平等的,集群中的所有节点同时对外提供服务的发现和注册等功能。同时集群中每个Eureka Server节点又是一个微服务,也就是说,每个节点都可以在集群中的其他节点上注册当前服务。又因为每个节点都是注册中心,所以节点之间可以相互注册当前节点中已注册的服务,并发现其他节点中已注册的服务。
搭建步骤
1、创建三个单机版的Eureka Server项目,分别为
test-springcloud-eureka-server8761
test-springcloud-eureka-server8762
test-springcloud-eureka-server8763
2、编辑项目test-springcloud-eureka-server8761的application.yml配置文件
1 # 端口 2 server: 3 port: 8761 4 5 spring: 6 application: 7 name: cloud-eureka-server 8 9 # Eureka配置 10 eureka: 11 instance: 12 # eureka服务端的实例名称 13 hostname: eureka8761.com 14 client: 15 # false表示不向注册中心注册自己 16 register-with-eureka: false 17 # false表示自己端就是注册中心,职责就是维护服务实例,并不需要去检查服务 18 fetch-registry: false 19 # 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址 20 service-url: 21 # 集群模式:设置服务注册中心地址,指向其他注册中心 22 defaultZone: http://eureka8762.com:8762/eureka,http://eureka8763.com:8763/eureka
同理配置其他2个节点的配置文件,不同地方有以下三点
# 端口 server.port # 实例主机名称 eureka.instance.hostname # server-url eureka.client.server-url.defaultZone
3、更改主机的映射,hosts 文件
127.0.0.1 eureka8761.com 127.0.0.1 eureka8762.com 127.0.0.1 eureka8763.com
4、启动三个注册中心,使用地址:http://eureka8761.com:8761/,访问8761节点
同理,可以使用http://eureka8762.com:8762/,http://eureka8763.com:8763/,访问另外2个节点
5、Eureka Client 客户端,在向集群模式Eureka注册的时候,注册地址是:
http://eureka8761.com:8761/eureka,http://eureka8762.com:8762/eureka,http://eureka8763.com:8763/eureka
同时向三个节点注册
1 eureka: 2 client: 3 # 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址 4 service-url: 5 defaultZone: http://eureka8761.com:8761/eureka,http://eureka8762.com:8762/eureka,http://eureka8763.com:8763/eureka
六、Eureka Server安全认证
Eureka Server作为Spring Cloud中的服务注册中心,如果可以任意访问的话,那么其安全性太低。所以Spring Cloud中也有为Eureka Server提供安全认证的方式。可以使用spring-boot-starter-security组件来为Eureka Server增加安全认证。
1、新增security的POM依赖:
1 <!-- spring boot security安全认证启动器 --> 2 <dependency> 3 <groupId>org.springframework.boot</groupId> 4 <artifactId>spring-boot-starter-security</artifactId> 5 </dependency>
2、修改application.yml配置文件,增加安全认证信息、用户名密码、修改连接地址
1 spring: 2 application: 3 name: cloud-eureka-server 4 security: 5 user: 6 name: root 7 password: 123456 8 9 # Eureka配置 10 eureka: 11 client: 12 service-url: 13 # 集群模式:设置服务注册中心地址,指向其他注册中心 14 defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@eureka8762.com:8762/eureka,http://${spring.security.user.name}:${spring.security.user.password}@eureka8763.com:8763/eureka 15 16 17 #安全认证信息 18 security: 19 basic: 20 enabled: true
完整配置如下:
1 # 端口 2 server: 3 port: 8761 4 5 spring: 6 application: 7 name: cloud-eureka-server 8 security: 9 user: 10 name: root 11 password: 123456 12 13 # Eureka配置 14 eureka: 15 instance: 16 # eureka服务端的实例名称 17 hostname: eureka8761.com 18 client: 19 # false表示不向注册中心注册自己 20 register-with-eureka: false 21 # false表示自己端就是注册中心,职责就是维护服务实例,并不需要去检查服务 22 fetch-registry: false 23 # 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址 24 service-url: 25 # 集群模式:设置服务注册中心地址,指向其他注册中心 26 defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@eureka8762.com:8762/eureka,http://${spring.security.user.name}:${spring.security.user.password}@eureka8763.com:8763/eureka 27 28 29 #安全认证信息 30 security: 31 basic: 32 enabled: true
3、增加安全认证的配置类,WebSecurityConfig.java
由于新版的Spring Security启用csrf防护后,会对post、delete、put等请求进行安全校验。过程是,请求里必须携带crfs的tocken,如果请求里不带有tocken时,服务器会认为该请求非法,请求就会被拒绝。不关闭,可能导致服务无法在注册中心注册
1 @EnableWebSecurity 2 @Configuration 3 public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 4 5 @Override 6 protected void configure(HttpSecurity http) throws Exception { 7 8 // Spring Security启用csrf防护后,会对post、delete、put等请求进行安全校验。 9 // 过程是,请求里必须携带crfs的tocken,如果请求里不带有tocken时,服务器会认为该请求非法,请求就会被拒绝。 10 // 默认开启,关闭csrf过滤 11 http.csrf().disable(); 12 13 http 14 .authorizeRequests() 15 .anyRequest().authenticated() 16 .and() 17 .formLogin().and() 18 .httpBasic(); 19 } 20 21 }
4、重启Eureka Server服务,使用地址:http://eureka8761.com:8761/login,进行访问
需要登录,输入用户名/密码:root/123456
5、Eureka Client客户端,修改配置,连接增加用户名和密码
1 # 端口 2 server: 3 port: 8001 4 5 spring: 6 application: 7 name: cloud-payment-service 8 security: 9 user: 10 name: root 11 password: 123456 12 13 eureka: 14 client: 15 # 表示将自己注册进Eureka Server默认为true 16 register-with-eureka: true 17 # 是否从Eureka Server抓去已有的注册信息,默认是true 18 fetch-registry: true 19 # 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址 20 service-url: 21 defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@eureka8761.com:8761/eureka,http://${spring.security.user.name}:${spring.security.user.password}@eureka8762.com:8762/eureka
6、重启项目,打开Eureka注册中心,查看是否注册成功
七、Eureka自我保存模式
如果Eureka服务器检测到数量超过预期的注册客户端已以不正当的方式终止了它们的连接,并且同时正等待逐出,则它们将进入自我保存模式。这样做是为了确保灾难性的网络事件不会清除eureka注册表数据,并将其传播到下游的所有客户端。
服务保护模式
服务保护模式(自我保护模式):一般情况下,微服务在Eureka上注册后,会每30秒发送心跳包,Eureka通过心跳来判断服务时候健康,同时会定期删除超过90秒没有发送心跳服务。
导致Eureka Server接收不到心跳包的可能:一是微服务自身的原因,二是微服务与Eureka之间的网络故障。通常微服务的自身的故障只会导致个别服务出现故障,一般不会出现大面积故障,而网络故障通常会导致Eureka Server在短时间内无法收到大批心跳。虑到这个区别,Eureka设置了一个阀值,当判断挂掉的服务的数量超过阀值时,Eureka Server认为很大程度上出现了网络故障,将不再删除心跳过期的服务。
那么这个阀值是多少呢?Eureka Server在运行期间,会统计心跳失败的比例在15分钟内是否低于85%,如果低于85%,Eureka Server则任务是网络故障,不会删除心跳过期服务。
这种服务保护算法叫做Eureka Server的服务保护模式。
这种不删除的,90秒没有心跳的服务,称为无效服务,但是还是保存在服务列表中。如果Consumer到注册中心发现服务,则Eureka Server会将所有好的数据(有效服务数据)和坏的数据(无效服务数据)都返回给Consumer。
服务保护模式的存在必要性
因为同时保留"好数据"与"坏数据"总比丢掉任何数据要更好,当网络故障恢复后,Eureka Server会退出"自我保护模式"。
Eureka还有客户端缓存功能(也就是微服务的缓存功能)。即便Eureka Server集群中所有节点都宕机失效,微服务的Provider和Consumer都能正常通信。
微服务的负载均衡策略会自动剔除死亡的微服务节点(Robbin)。
只要Consumer不关闭,缓存始终有效,直到一个应用下的所有Provider访问都无效的时候,才会访问Eureka Server重新获取服务列表。
关闭服务保护模式
可以通过全局配置文件来关闭服务保护模式,商业项目中不推荐关闭服务保护,因为网络不可靠很容易造成网络波动、延迟、断线的可能。如果关闭了服务保护,可能导致大量的服务反复注册、删除、再注册。导致效率降低。在商业项目中,服务的数量一般都是几十个,大型的商业项目中服务的数量可能上百、数百,甚至上千:
1 eureka: 2 server: 3 # 是否开启自我保护模式,默认是true 4 enable-self-preservation: false 5 # 扫描失效服务的时间间隔。单位 毫秒。 默认值 60 * 1000 6 eviction-interval-timer-in-ms: 1000
优雅关闭服务(优雅停服)
在Spring Cloud中,可以通过HTTP请求的方式,通知Eureka Client优雅停服,这个请求一旦发送到Eureka Client,那么Eureka Client会发送一个shutdown请求到Eureka Server,Eureka Server接收到这个shutdown请求后,会在服务列表中标记这个服务的状态为down,同时Eureka Client应用自动关闭。这个过程就是优雅停服。
如果使用了优雅停服,则不需要再关闭Eureka Server的服务保护模式。
1、在Eureka Client中增加新的依赖actuator
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-actuator</artifactId> 4 </dependency>
2、Eureka Client默认不开启优雅停服功能,需要在全局配置文件中新增如下内容
1 # 开启应用关闭端口 2 management.endpoint.shutdown.enabled=true 3 # 暴露shutdown的web端口
3、发起shutdown请求:
必须通过POST请求向Eureka Client发起一个shutdown请求。请求路径为:http://ip:port/shutdown。可以通过任意技术实现,如:HTTPClient、form表单,AJAX等。
建议使用优雅停服方式来关闭Application Service/Application Client服务。
八、Eureka 的常用配置项
1、通用配置
1 spring.application.name=xxxxxxxxxxxxx :应用名称配置,将会出现在 Eureka 注册中心 Application 列 2 server.port=8701 :应用端口,默认值为 8761 3 eureka.instance.hostname= server1 :服务注册中心应用实例主机名 4 eureka.instance.ip-address=127.0.0.1 :应用实例ip 5 eureka.instance.prefer-ip-address=false :客户端向注册中心注册时,相较于 hostname 是否有限使用 ip。在服务中心注册后,鼠标放到服务的 Status 列的链接上,无需点击,左下角能看出配置的变化。 6 eureka.instance.environment=dev :该实例的环境配置 7 eureka.client.register-with-eureka=false :是否将自己注册到 Eureka 注册中心。单机情况下的 Eureka Server 不需要注册,集群的 Eureka Server 以及 Eureka Client 需要注册。默认值 true 8 eureka.client.fetch-registry=false :是否需要从注册中心检索获取服务的注册信息。单机情况下的 Eureka Server 不需要获取。集群的 Eureka Server 以及 Eureka Client 需要获取。默认值 true 9 eureka.client.service-url.defaultZone= http://${spring.security.user.name}:${spring.security.user.password}@server1:8081/eureka/ :Eureka 服务的地址信息,中间的占位符为安全认证开启时使用,如果 Eureka Server 为集群状态,则逗号分隔,依次书写即可。
2、Eureka Server 配置
1 eureka.server.enable-self-preservation = false :是否开启自我保护模式,eureka server默认在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%,如果低于 85%,Eureka Server 会将这些实例保护起来,让这些实例不会过期,但是在保护期内如果服务刚好这个服务提供者非正常下线了,此时服务消费者就会拿到一个无效的服务实例,此时会调用失败。默认 true 2 eureka.server.eviction-interval-timer-in-ms=10000 :扫描失效服务的时间间隔。单位 毫秒。 默认值 60 * 1000 3 security.basic.enabled=true :开启 Eureka 安全认证 4 spring.security.user.name=root :安全认证用户名 5 spring.security.user.password=123456 :安全认证密码
3、Eureka Client 配置
1 eureka.client.registry-fetch-interval-seconds=30 :客户端获取服务注册信息时间间隔,单位 秒。默认 30 2 eureka.instance.appname=eureka-client :服务名,默认取 spring.application.name 配置值,如果没有则为 unknown 3 eureka.instance.lease-expiration-duration-in-seconds=90 :服务的失效时间,失效的服务将被注册中心删除。时间间隔为最后一次注册中心接收到的心跳时间。单位 秒,默认 90 4 eureka.instance.lease-renewal-interval-in-seconds=30 :应用实例给注册中心发送心跳的间隔时间,用于表明该服务实例可用。单位 秒。默认30 5 eureka.client.eureka-server-connect-timeout-seconds=5 :client 连接 Eureka 注册中心的超时时间,单位 秒,默认 5 6 eureka.client.eureka-server-read-timeout-seconds=8 :client 对 Eureka 服务器读取信息的超时时间,单位 秒,默认 8 7 eureka.client.eureka-connection-idle-timeout-seconds=30 :client 连接 Eureka 服务端后空闲等待时间,单位 秒,默认 30 8 eureka.client.eureka-server-total-connections=200 :client 到 所有Eureka 服务端的连接总数,默认 200 9 eureka.client.eureka-server-total-connections-per-host=50 :client 到 Eureka 单服务端的连接总数,默认 50