1 Eureka

1.1 什么是Eureka注册中心

EurekaNetflix开发的服务发现组件, 本身是一个基于 REST的服务。
Spring Cloud将它集成在其子项目 spring-cloud-netflix 中, 以实现 Spring Cloud 的服务注册于发现, 同时还提供了负载均衡故障转移等能力。

1.2 Eureka注册中心三种角色

1.2.1 Eureka Server

通过 Register、 Get、 Renew 等接口提供服务的注册和发现。

1.2.2 Application Service (Service Provider)

服务提供方:把自身的服务实例注册到 Eureka Server

1.2.3 Application Client (Service Consumer)

服务调用方:通过 Eureka Server 获取服务列表, 消费服务

1.3 原理图

在这里插入图片描述
Register(服务注册): 把自己的 IP 和端口注册给 Eureka
Renew(服务续约): 发送心跳包, 每 30 秒发送一次。 告诉 Eureka 自己还活着。
Cancel(服务下线): 当 provider 关闭时会向 Eureka 发送消息, 把自己从服务列表中删除。 防止 consumer 调用到不存在的服务。
Get Registry(获取服务注册列表): 获取其他服务列表。
Replicate(集群中数据同步)eureka 集群中的数据复制与同步。
Make Remote Call(远程调用): 完成服务的远程调用。

1.4 Eureka 特点

  • 可用性(AP原则)Eureka 在设计时就紧遵AP原则,Eureka的集群中,只要有一台Eureka还在,就能保证注册服务可用,只不过查到的信息可能不是最新的(不保证强一致性)。
  • 去中心化架构Eureka Server 可以运行多个实例来构建集群,不同于 ZooKeeper选举 leader 的过程,Eureka Server 采用的是Peer to Peer 对等通信。这是一种去中心化的架构,无 master/slave 之分,每一个 Peer 都是对等的。节点通过彼此互相注册来提高可用性,每个节点需要添加一个或多个有效的 serviceUrl 指向其他节点。每个节点都可被视为其他节点的副本。
  • 请求自动切换:在集群环境中如果某台Eureka Server宕机,Eureka Client 的请求会自动切换到新的Eureka Server节点上,当宕机的服务器重新恢复后,Eureka会再次将其纳入到服务器集群管理之中。
  • 节点间操作复制:当节点开始接受客户端请求时,所有的操作都会在节点间进行复制操作,将请求复制到该 Eureka Server 当前所知的其它所有节点中。
  • 自动注册&心跳:当一个新的 Eureka Server 节点启动后,会首先尝试从邻近节点获取所有注册列表信息,并完成初始化。Eureka Server 通过 getEurekaServiceUrls() 方法获取所有的节点,并且会通过心跳契约的方式定期更新。
  • 自动下线:默认情况下,如果 Eureka Server 在一定时间内没有接收到某个服务实例的心跳(默认周期为30秒),Eureka Server 将会注销该实例(默认为90秒, eureka.instance.lease-expiration-duration-in-seconds 进行自定义配置)。
  • 保护模式:当 Eureka Server 节点在短时间内丢失过多的心跳时,那么这个节点就会进入自我保护模式。

除了上述特点,Eureka还有一种自我保护机制,如果在15分钟内超过 85% 的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:

  • Eureka不再从注册表中移除因为长时间没有收到心跳而过期的服务;
  • Eureka仍然能够接受新服务注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)
  • 当网络稳定时,当前实例新注册的信息会被同步到其它节点中。

1.5 Eureka工作流程

了解完 Eureka 核心概念,自我保护机制,以及集群内的工作原理后,我们来整体梳理一下Eureka的工作流程:

  1. Eureka Server 启动成功,等待服务端注册。在启动过程中如果配置了集群,集群之间定时通过 Replicate 同步注册表,每个Eureka Server都存在独立完整的服务注册表信息。
  2. Eureka Client 启动时根据配置的 Eureka Server 地址去注册中心注册服务。
  3. Eureka Client 会每 30sEureka Server发送一次心跳请求,证明客户端服务正常。
  4. Eureka Server 90s 内没有收到 Eureka Client 的心跳,注册中心则认为该节点失效,会注销该实例。
  5. 单位时间内 Eureka Server 统计到有大量的Eureka Client没有上送心跳,则认为可能为网络异常,进入自我保护机制,不再剔除没有上送心跳的客户端。
  6. Eureka Client 心跳请求恢复正常之后,Eureka Server 自动退出自我保护模式。
  7. Eureka Client 定时全量或者增量从注册中心获取服务注册表,并且将获取到的信息缓存到本地。
  8. 服务调用时,Eureka Client 会先从本地缓存找寻调取的服务。如果获取不到,先从注册中心刷新注册表,再同步到本地缓存。
  9. Eureka Client 获取到目标服务器信息,发起服务调用。
  10. Eureka Client 程序关闭时向 Eureka Server 发送取消请求,Eureka Server 将实例从注册表中删除。

Eureka 为了保障注册中心的高可用性,容忍了数据的非强一致性,服务节点间的数据可能不一致,Client-Server 间的数据可能不一致。比较适合跨越多机房、对注册中心服务可用性要求较高的使用场景。

2 CAP原理

点击了解CAP理论

3 eureka优雅停服

3.1 Eureka自我保护

3.1.1 自我保护的条件

一般情况下, 微服务在Eureka上注册后, 会每30秒发送心跳包,Eureka通过心跳来判断服务是否健康, 同时会定期删除超过90秒没有发送心跳服务。

3.1.2 Eureka Server收不到微服务的心跳

  • 是微服务自身的原因
  • 是微服务与 Eureka 之间的网络故障,通常(微服务的自身的故障关闭)只会导致个别服务出现故障, 一般不会出现大面积故障, 而(网络故障)通常会导致Eureka Server在短时间内无法收到大批心跳。
    考虑到这个区别,Eureka设置了一个阀值, 当判断挂掉的服务的数量超过阀值时,Eureka Server 认为很大程度上出现了网络故障, 将不再删除心跳过期的服务。

3.1.3 eureka阀值

  • 15 分钟之内是否低于85%
  • Eureka Server 在运行期间,会统计心跳失败的比例在 15 分钟内是否低于 85%这种算法叫做 Eureka Server 的自我保护模式

3.2 为什么需要eureka自我保护

  • 因为同时保留好数据坏数据总比丢掉任何数据要更好, 当网络故障恢复后,这个 Eureka节点会退出自我保护模式
  • Eureka还有客户端缓存功能(也就是微服务的缓存功能)。 即便 Eureka 集群中所有节点都宕机失效, 微服务的 ProviderConsumer都能正常通信。
  • 微服务的负载均衡策略会自动剔除死亡的微服务节点

3.3 关闭自我保护

修改 Eureka Server 配置文件

#关闭自我保护:true 为开启自我保护, false 为关闭自我保护
eureka.server.enableSelfPreservation=false
#清理间隔(从服务列表删除无用服务的时间间隔,单位:毫秒, 默认是 60*1000)
eureka.server.eviction.interval-timer-in-ms=60000

3.4 优雅停服

环境:springboot:2.1.3 springcloud:Greenwich.SR5

3.4.1 不需要在Eureka Server中配置关闭自我保护

3.4.2 添加actator的坐标依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

3.4.3 修改properties文件

###### 优雅停服######
##启用 shutdown
management.endpoint.shutdown.enabled=true
# 暴露所有端点
management.endpoints.web.exposure.include=*
#禁用密码验证
management.endpoints.shutdown.sensitive=false

3.4.4 发送关闭服务的URL请求

post请求

public static String doPost(String url,Map<String,String> param)  {
		//创建HTTPClient对象
		CloseableHttpClient httpClient = HttpClients.createDefault();
		String resultString = "";
		CloseableHttpResponse response = null;
		try{
			//创建httpget请求
			HttpPost httpPost = new HttpPost(url);
			if(MapUtils.isNotEmpty(param)) {
				List<NameValuePair> paramList= new ArrayList<>();
				param.forEach((a,b)->paramList.add(new BasicNameValuePair(a,b)));
				//模拟表单
				UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(paramList,"utf-8");
				//UrlEncodedFormEntity 来设置 body,消息体内容类似于“KEY1=VALUE1&KEY2=VALUE2&...
				httpPost.setEntity(formEntity);
			}
			//执行请求
			response = httpClient.execute(httpPost);
			if(response.getStatusLine().getStatusCode()==200) {
				System.out.println("========成功========");
				resultString = EntityUtils.toString(response.getEntity(),"utf-8");
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				if(response!=null)response.close();
				httpClient.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return resultString;
	}

main方法发送

public static void main(String[] args) throws Exception {
		String url ="http://127.0.0.1:9080/actuator/shutdown";
		//该 url 必须要使用 dopost 方式来发送
		HttpClientUtil.doPost(url,null);
	}

main方法发送后,就可以在本地看到启动的服务自己就关闭了,也可以在服务注册管理页面查看

4 eureka的安全认证

4.1 在Eureka Server中添加 security 包

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

4.2 修改Eureka Server配置文件

#开启 http basic 的安全认证 没有用 需要通过下面方法来关闭或开启
#spring.security.basic.enabled=true
spring.security.user.name=user
spring.security.user.password=123456
 # 修改访问集群节点的 url
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka2:8761/eureka/

4.3 修改微服务的配置文件添加访问注册中心的用户名与密码

spring.application.name=eureka-provider
server.port=9090
#设置服务注册中心地址, 指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
#启用 shutdown
management.endpoints.shutdown.enabled=true
#禁用密码验证
management.endpoints.shutdown.sensitive=false

4.4 关闭csrf认证

Spring Cloud 2.0 以上的security默认启用了csrf检验,要在eurekaServer端配置securitycsrf检验为false

@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable(); //关闭csrf
        //开启认证  若注释掉,就关闭认证了
        http.authorizeRequests().anyRequest().authenticated().and().httpBasic(); 
    }
}
Logo

云原生社区为您提供最前沿的新闻资讯和知识内容

更多推荐