说明:SpringBoot 版本-2.1.2.RELEASE,Eureka版本-2.1.0.RELEASE。
以下内容纯属个人见解,不一定正确,如有发现理解错误地方,望不吝指教,不胜感激。
一、Eureka服务端注意事项
- 添加Eureka服务端依赖:
<!-- eureka 服务端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
- 必须在启动类上添加
@EnableEurekaServer
注解,否则在浏览器上访问不到Eureka管理页面,并且客户端也不会注册成功。
二、Eureka单机配置
单机版须在配置文件中指定配置:
eureka:
client:
# 是否在Eureka注册。没有该配置,则单机版启动会报错。
register-with-eureka: false
# 是否从Eureka中获取注册信息。没有该配置,则单机版启动会报错。
fetch-registry: false
# 可选配置
service-url:
# 默认注册地址,注意不能写成default-zone,否则将不生效。
# 原因是Eureka有默认的defaultZone配置,端口为8761。
# 详情参见:org.springframework.cloud.netflix.eureka.EurekaClientConfigBean类的serviceUrl属性初始化代码块
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
三、Eureka集群配置
以3个节点集群为例,端口分别为8080、8081、8082,样例如下:
- eureka-server-01节点配置:
# eureka-server-01 配置
spring:
application:
# 应用名称。
# 为了便于管理和维护,需要将集群内的所有节点都设置为一样的应用名称。
name: spring-cloud-eureka-server
server:
# 端口
port: 8080
eureka:
client:
service-url:
# 默认注册地址,注意不能写成default-zone,否则将不生效。
# 原因是Eureka有默认的defaultZone配置,端口为8761。
# 详情参见:org.springframework.cloud.netflix.eureka.EurekaClientConfigBean类的serviceUrl属性初始化代码块
defaultZone: http://localhost:8081/eureka/,http://localhost:8082/eureka/
- eureka-server-02节点配置:
# eureka-server-02 配置
spring:
application:
# 为了便于管理和维护,需要将集群内的所有节点都设置为一样的应用名称。
name: spring-cloud-eureka-server
server:
# 端口
port: 8081
eureka:
client:
service-url:
# 这里必须将所有非本节点都列出来。
defaultZone: http://localhost:8080/eureka/,http://localhost:8082/eureka/
- eureka-server-03节点配置:
同上
三、Eureka服务端安全认证
- 添加security安全认证依赖:
<!-- security安全认证依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
- 配置文件添加用户名和密码配置:
spring:
......
security:
user:
# 用户名。集群时候可以分别对多个Eureka Server配置不同的用户名,不推荐。
name: admin
# 密码。集群时候可以分别对多个Eureka Server配置不同的用户名,不推荐。
password: admin
eureka:
client:
......
service-url:
# > 这段注释很重要 <
# > 这段注释很重要 <
# > 这段注释很重要 <
# 重要的事情说3遍
# --------------------------------------------------------
# defaultZone改为"http://[user:password@]localhost:8080/eureka/"格式。
# 其中:
# "user"为用户名,可自定义。
# "password"为密码,可自定义。
# "@"为连接符,固定格式。
# --------------------------------------------------------
# 在SpringBoot(版本:2.1.2.RELEASE) + SpringCloud(版本:Greenwich.RELEASE)中(别的版本没试过):
# []包裹的内容在单机模式下为可选配置(不配置好像没有什么影响)。
# 但是,在集群中则必须配置为别的Eureka Server的用户名和密码。
# 单机如果要配置的话,配置的是本Eureka Server的用户名密码。
# 集群模式配置的是对方的用户名密码,有可能和自己不一样。
defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@localhost:8081/eureka/
- 关闭csrf检验(不关闭则客户端将不能正常注册到服务端)。
新版的security默认启用了csrf检验
解决步骤:
- 在 Eureka Server 项目中,增加存放配置的专用包目录;
- 添加一个继承 WebSecurityConfigurerAdapter 的类;
- 在类上添加 @EnableWebSecurity 注解;
- 覆盖父类的 configure(HttpSecurity http) 方法,关闭掉 csrf,至此大工告成。
/**
* 关闭csrf检验
* @author liangdl
*
*/
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
super.configure(http);
}
}
四、自我保护
默认情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将会注销该实例(默认90秒)。但是当网络分区故障发生时,微服务与Eureka Server之间无法正常通信,以上行为可能变得非常危险了——因为微服务本身其实是健康的,此时本不应该注销这个微服务。
Eureka通过“自我保护模式”来解决这个问题——当Eureka Server节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。一旦进入该模式,Eureka Server就会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后,该Eureka Server节点会自动退出自我保护模式。
综上,自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留),也不盲目注销任何健康的微服务。使用自我保护模式,可以让Eureka集群更加的健壮、稳定。
开发环境为了调试方便,可以关闭,生产环境不建议关闭。
- Eureka 服务端配置
......
# Eureka 服务端配置
eureka:
server:
# 关闭保护机制,以确保注册中心将不可用的实例正确剔除
enable-self-preservation: false
# (代表是5秒,单位是毫秒,清理失效服务的间隔 )
eviction-interval-timer-in-ms: 5000
......
- Eureka 客户端配置
......
eureka:
instance:
# 每间隔10s,向服务端发送一次心跳,证明自己依然"存活"
lease-renewal-interval-in-seconds: 10
# 告诉服务端,如果我20s之内没有给你发心跳,就代表我"死"了,将我踢出掉。
lease-expiration-duration-in-seconds: 20
......
五、健康检查
健康检查在服务端和客户端均可配置
- 添加健康检查依赖
<!-- 健康检查 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 添加配置
SpringCloud 默认开启info和health两项,可以手动配置多个。
# 开启健康检查项
management:
endpoints:
web:
exposure:
# "*"表示开启所有健康检查项,也可以指定具体类型,多个用逗号分割。
include: "*"
部分可选配置项:
info: 显示任意的应用信息
health: 展示应用的健康信息
metrics: 展示当前应用的指标信息 true
mappings: 显示所有@RequestMapping路径的整理列表
trace: 显示trace信息(默认为最新的一些HTTP请求)
beans: 显示一个应用中所有Spring Beans的完整列表
- 访问
SpringCloud 2.x中,在访问地址中加了"/actuator",目的是方便安全控制。
// 应用信息
http://localhost:8080/actuator/info
// 健康信息
http://localhost:8080/actuator/health
......
六. 安全控制
健康检查的信息里面包含很多敏感信息,如果没有访问权限的控制,那么应用程序也有很大的风险。
默认情况下,安全认证不只是针对健康检查,而是针对整个系统。
- 添加安全认证依赖
<!-- 安全认证 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
- 添加配置
spring:
security:
user:
# 用户名
name: admin
# 密码
password: admin
- 对部分url做安全认证
添加以上配置后,访问所有请求都将经过安全认证(登录)。那么就会导致服务注册也需要安全认证,可以过滤部分地址需要安全认证。
/**
* 认证Web路径配置<br>
* 参考:http://www.mamicode.com/info-detail-2375708.html
* @author liangdl
*
*/
@Configuration
@EnableWebSecurity
public class ActuatorWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// 特定请求需要认证(健康检查)
.antMatchers("/actuator/*")
.authenticated()
// 剩余请求不需要认证,如果不设置这个,那么所有调用的url都需要认证。
.antMatchers("/*")
.permitAll()
.and()
.formLogin();
}
}
提示: 可能需要web依赖(未测试)
<!-- spring-web依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
七、附录
- 完整的Eureka 服务端
pom.xml
笔者的测试代码没有在服务器端做健康检查配置,所以不包含健康检查依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.vvlin</groupId>
<artifactId>sc-eureka</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>sc-eureka</name>
<description>Spring Cloud Eureka Demo</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<!-- eureka 服务端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!-- security安全认证依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
</project>
- 完整的Eureka 服务端
application.yml
笔者的测试代码没有在服务器端做健康检查配置,所以不包含健康检查配置
spring:
application:
# 应用名称
name: sc-eureka-server
security:
user:
name: admin
password: admin
server:
# 端口
port: 8080
eureka:
# instance:
# # 使用ip地址访问
# prefer-ip-address: true
server:
# 关闭保护机制,以确保注册中心将不可用的实例正确剔除
enable-self-preservation: false
# (代表是5秒,单位是毫秒,清理失效服务的间隔 )
eviction-interval-timer-in-ms: 5000
client:
# 是否在Eureka注册。没有该配置,则单机版启动会报错。
register-with-eureka: false
# 是否从Eureka中获取注册信息。没有该配置,则单机版启动会报错。
fetch-registry: false
# 可选配置
service-url:
# 默认注册地址,注意不能写成default-zone,否则将不生效。
# 原因是Eureka有默认的defaultZone配置,端口为8761。
# 详情参见:org.springframework.cloud.netflix.eureka.EurekaClientConfigBean类的serviceUrl属性初始化代码块
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
defaultZone: http://localhost:8080/eureka/
# defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@localhost:8081/eureka/
网友评论