SpringCloud 2.x Eureka 服务端

2019-02-20  本文已影响0人  单v纯微笑

说明:SpringBoot 版本-2.1.2.RELEASE,Eureka版本-2.1.0.RELEASE。

以下内容纯属个人见解,不一定正确,如有发现理解错误地方,望不吝指教,不胜感激。

一、Eureka服务端注意事项
  1. 添加Eureka服务端依赖:
<!-- eureka 服务端依赖 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
  1. 必须在启动类上添加 @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,样例如下:

  1. 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/
  1. 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/
  1. eureka-server-03节点配置:
    同上

三、Eureka服务端安全认证
  1. 添加security安全认证依赖:
<!-- security安全认证依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
  1. 配置文件添加用户名和密码配置:
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/
  1. 关闭csrf检验(不关闭则客户端将不能正常注册到服务端)。

新版的security默认启用了csrf检验
解决步骤:

  1. 在 Eureka Server 项目中,增加存放配置的专用包目录;
  2. 添加一个继承 WebSecurityConfigurerAdapter 的类;
  3. 在类上添加 @EnableWebSecurity 注解;
  4. 覆盖父类的 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集群更加的健壮、稳定。

开发环境为了调试方便,可以关闭,生产环境不建议关闭。

  1. Eureka 服务端配置
......
# Eureka 服务端配置
eureka:
    server:
        # 关闭保护机制,以确保注册中心将不可用的实例正确剔除
        enable-self-preservation: false
        # (代表是5秒,单位是毫秒,清理失效服务的间隔 )
        eviction-interval-timer-in-ms: 5000
......
  1. Eureka 客户端配置
......
eureka:
    instance:
        # 每间隔10s,向服务端发送一次心跳,证明自己依然"存活"
        lease-renewal-interval-in-seconds: 10
        # 告诉服务端,如果我20s之内没有给你发心跳,就代表我"死"了,将我踢出掉。
        lease-expiration-duration-in-seconds: 20
......

五、健康检查

健康检查在服务端和客户端均可配置

  1. 添加健康检查依赖
<!-- 健康检查 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  1. 添加配置
    SpringCloud 默认开启info和health两项,可以手动配置多个。
# 开启健康检查项
management:
    endpoints:
        web:
            exposure:
                # "*"表示开启所有健康检查项,也可以指定具体类型,多个用逗号分割。
                include: "*"

部分可选配置项:
info: 显示任意的应用信息
health: 展示应用的健康信息
metrics: 展示当前应用的指标信息 true
mappings: 显示所有@RequestMapping路径的整理列表
trace: 显示trace信息(默认为最新的一些HTTP请求)
beans: 显示一个应用中所有Spring Beans的完整列表

  1. 访问

SpringCloud 2.x中,在访问地址中加了"/actuator",目的是方便安全控制。

// 应用信息
http://localhost:8080/actuator/info
// 健康信息
http://localhost:8080/actuator/health
......

六. 安全控制

健康检查的信息里面包含很多敏感信息,如果没有访问权限的控制,那么应用程序也有很大的风险。
默认情况下,安全认证不只是针对健康检查,而是针对整个系统。

  1. 添加安全认证依赖
<!-- 安全认证 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
  1. 添加配置
spring:
    security:
        user:
            # 用户名
            name: admin
            # 密码
            password: admin
  1. 对部分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>

七、附录

笔者的测试代码没有在服务器端做健康检查配置,所以不包含健康检查依赖

<?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>


笔者的测试代码没有在服务器端做健康检查配置,所以不包含健康检查配置

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/
上一篇下一篇

猜你喜欢

热点阅读