Eureka 用户认证
连接到 eureka 的时候需要带上连接的用户名和密码。
我们需要对之前写的Eureka的服务端,和客户端进行改造。
服务端及我们的 注册中心(springcloud-eureka),客户端 包含我们的 服务提供者(springcloud-provider)和服务消费者(springcloud-consumer)。
eureka 服务端改造
认证依赖引入
<!--security安全认证框架:身份验证和访问控制-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
代码配置 关闭CSRF
@EnableWebSecurity
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//关闭csrf
http.csrf().disable();
//开启认证:URL格式登录必须是httpBasic
http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
}
}
application.yml 配置文件修改
# 设置登录用户名和密码
spring:
security:
user:
name: admin
password: admin
#开启 basic 校验
security:
basic:
enabled: true
启动注册中心浏览器访问地址,需要用户名密码才能访问
Eureka 客户端改造
连接 eureka 注册中心的时候要带上用户名密码
eureka:
client: #将客户端注册到 eureka 服务列表内
service-url:
defaultZone: http://admin:admin@eureka8763:8763/eureka/ #注册中心地址 添加用户密码admin:admin@
关于关闭CSRF的说明
加入了安全认证模块后,默认会开启 CSRF 跨站脚本攻击。
新版(Spring Cloud 2.0 以上)的security默认启用了csrf检验。对下面这样的访问会拦截:
http://admin:admin@192.168.1.1
如果不关闭csrf,eureka客户端连接不上服务端,启动报Cannot execute request on any known server的错误。
服务续约保活
- 客户端启需要隔段时间发送一次心跳给 eureka 服务端来证明自己还活着,当 eureka 服务端收到这个心跳请求后才会知道客户端还活着,才会维护该客户端的服务列表信息。
- 一旦因为某些原因导致客户端没有按时发送心跳给 eureka 服务端,这时候 eureka 服务端可能会认为你这个客户端已经挂了,它就有可能把该服务从服务列表中删除掉。
- Eureka Server 自我保护模式默认开启,在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%,如果低于 85%,Eureka Server 会将这些实例保护起来,让这些实例不会过期。
有关续约保活的客户端配置
eureka:
client:
#表示eureka client间隔多久去拉取服务注册信息,默认为30秒
registry-fetch-interval-seconds: 30
instance:
#服务续约,心跳的时间间隔
lease-renewal-interval-in-seconds: 30
#从前一次发送心跳时间起,90秒没接受到新的心跳,则剔除服务
lease-expiration-duration-in-seconds: 90
服务端配置
eureka:
server:
#自我保护模式,当出现出现网络分区、eureka在短时间内丢失过多客户端时,会进入自我保护模式,即一个服务长时间没有发送心跳,eureka也不会将其删除,默认为true
enable-self-preservation: true
#Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%,如果低于 85%,Eureka Server 会将这些实例保护起来
renewal-percent-threshold: 0.85
#eureka server清理无效节点的时间间隔,默认60000毫秒,即60秒
eviction-interval-timer-in-ms: 60000
自我保护的意义
Eureka 的自我保护模式是有意义的,该模式被激活后,它不会从注册列表中剔除因长时间没收到心跳的服务,而是等待修复,直到心跳恢复正常之后,它自动退出自我保护模式。这种模式旨在避免因网络分区故障导致服务不可用的问题。
例如,两个客户端实例 C1 和 C2 的连通性是良好的,但是由于网络故障,C2 未能及时向 Eureka 发送心跳续约,这时候 Eureka 不能简单的将 C2 从注册表中剔除。因为如果剔除了,C1 就无法从 Eureka 服务器中获取 C2 注册的服务,但是这时候 C2 服务是可用的。
自我保护存在的问题
在保护期内如果服务刚好这个服务提供者非正常下线了,此时服务消费者就会拿到一个无效的服务实例,此时会调用失败,对于这个问题需要服务消费者端要有一些容错机制,如重试,断路器等。
Eureka 健康检测
默认情况下,Eureka使用客户端心跳来确定客户端是否启动。
但是有的情况下,虽然服务连接是好的,但是有可能这个服务的某些接口不是正常的,可能由于需要连接 Redis,mongodb 或者 DB 有问题导致接口调用失败,所以理论上服务虽然能够正常调用,但是它不是一个健康的服务。所以我们就有必要对这种情况做自定义健康检测。
我们在springcloud-provider中实现自定义的HealthCheckHandler。
依赖引入:
<!--spring-boot监控模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
配置开启健康检测
eureka:
client:
healthcheck:
enabled: true #健康检测
自定义健康检测代码实现
我们可以在 health 方法里面去连接数据库或者redis,如果连接异常了则返回 DOWN,如果没异常则返回 UP,这个 health 方法每隔一段时间被调用一次。
@Configuration
public class ProviderHealthIndicator implements HealthIndicator {
public static int i = 0;
@Override
public Health health() {
boolean isHealth = true;
/*业务判断逻辑 可以连接数据库、redis等设置isHealth的值*/
//******************* 模拟判断 第三次判断之后 返回false
i++;
if(i>2){
isHealth = false;
}
System.out.println("I"+i+";"+isHealth);
//*************模拟判断END************************
if(isHealth) {
return new Health.Builder(Status.UP).build();
} else {
return new Health.Builder(Status.DOWN).build();
}
}
}
启动后状态为UP
当helth方法被调用三次后,状态变为DOWN
服务下线
比如有些情况是服务主机意外宕机了,也就意味着服务没办法给 eureka 心跳信息了,但是
eureka 在没有接受到心跳的情况下依然维护该服务 90s,在这 90s 之内可能会有客户端调用
到该服务,这就可能会导致调用失败。所以我们必须要有一个机制能手动的立马把宕机的服
务从 eureka 服务列表中清除掉,避免被服务调用方调用到。
查看服务列表
接口地址:http://localhost:8763/eureka/apps
使用postman调用接口,返回两个服务
服务下线的接口
接口:http://localhost:8763/eureka/apps/CONSUMER/localhost:consumer:8082
我们把consumer这个服务下线。
用postman调用这个接口使服务下线
再次调用获取服务列表接口发现只有一个服务了,下线成功