阅读背景:

Spring-Cloud笔记03:服务注册中心Eureka Server的简单配置、访问控制配置以及高可用配置

来源:互联网 

[超级链接:Spring-Cloud学习序章]


翻译:Eureka [juəˈri:kə] 我发现了==>服务注册中心,服务提供者

本章主要对服务注册中心Eureka组件进行学习,包括三个层次:

  • 简单配置:简单的服务注册中心Eureka Server与服务提供者Eureka Client
  • 高可用配置:高可用的服务注册中心Eureka Server
  • 认证配置:带安全认证的服务注册中心Eureka Server

1.简单配置

1.1.创建主工程

创建主工程spring-cloud-demo,如何创建参考:Spring-Cloud笔记02:IDEA中构建多模块的Maven项目

spring-cloud-demopom.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!--主项目信息-->
    <groupId>pers.hanchao</groupId>
    <artifactId>spring-cloud-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--微服务信息-->
    <modules>
        <!--注册中心示例 Eureka -->
        <module>eureka-server</module>
        <module>eureka-hi</module>
    </modules>

    <!--Spring Boot版本-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <!--编码、java版本、Spring Cloud版本-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR1</spring-cloud.version>
        <docker.image.prefix>hanchao5272</docker.image.prefix>
    </properties>

    <!--基础的Spring Boot/Cloud依赖-->
    <dependencies>
        <!--服务监视器组件-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--服务注册与发现组件-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
        </dependency>
        <!--web组件-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--测试组件-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <!--Spring Cloud的版本序列,代表了一些列组件的默认版本-->
            <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>

    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
</project>

1.2.创建服务注册中心

1.2.1.创建子模块

创建子模块eureka-server,如何创建参考:[Spring-Cloud笔记02:IDEA中构建多模块的Maven项目]

1.2.2.编辑pom.xml

编辑pom.xml,如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>pers.hanchao.springclouddemo</groupId>
    <artifactId>eureka-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>eureka-server</name>
    <description>Demo project for Spring Cloud Eureka Server</description>

    <parent>
        <groupId>pers.hanchao</groupId>
        <artifactId>spring-cloud-demo</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

</project>

说明:对于服务注册中心来说,必不可少的组件是spring-cloud-starter-eureka-server,继承自主工程。

1.2.3.添加注解@EnableEurekaServer

在启动类EurekaServerApplication上添加注解@EnableEurekaServer,标识这是一个服务注册中心。

@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

1.2.4.编辑配置文件

默认生成的配置文件是application.properties,我习惯性将其重命名为application.yml,配置如下:

# 端口号
server:
  port: 8761
# 服务注册相关配置
eureka:
  # 服务实例主机名
  instance:
    hostname: localhost
  # 服务提供者配置
  client:
    # 不进行注册(当服务注册中心是单点而非高考用时的配置方式)
    registerWithEureka: false
    # 不获取注册信息(当服务注册中心是单点而非高考用时的配置方式)
    fetchRegistry: false
    # 服务注册中心地址
    serviceUrl:
      defaultZone: http://${security.user.name}:${server.port}/eureka/

注意:

  • registerWithEureka: false表示当前服务注册中心不在其他服务注册中心进行注册。
  • fetchRegistry: false表示当前服务注册中心不获取其他服务注册中心的注册信息。
  • 以上两个配置,只有在当服务注册中心是单点配置时才如此配置,因为单点情况下这两个值必然为false。

1.2.5.启动服务注册中心

启动服务注册中心,在浏览器访问https://localhost:8761/,如下:

观察Instances currently registered with Eureka部分,可以发现,目前没有可用的实例,表示还没有服务提供者注册到当前的服务注册中心。

1.3.创建服务提供者

1.3.1.创建子模块

创建子模块eureka-hi,如何创建参考:[Spring-Cloud笔记02:IDEA中构建多模块的Maven项目]

1.3.2.编辑pom.xml

编辑pom.xml,如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>pers.hanchao.springclouddemo</groupId>
    <artifactId>eureka-hi</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>eureka-hi</name>
    <description>Demo project for Spring Cloud Eureka Client</description>

    <parent>
        <groupId>pers.hanchao</groupId>
        <artifactId>spring-cloud-demo</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

</project>

说明:对于服务提供者来说,必不可少的组件是spring-cloud-starter-eureka-server,继承自主工程。

1.3.3.添加注解@EnableEurekaServer

在启动类EurekaHiApplication上添加注解@EnableEurekaClient,标识这是一个服务提供者。

@RestController
@EnableEurekaClient
@SpringBootApplication
public class EurekaHiApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaHiApplication.class, args);
    }

    /** 获取端口号 */
    @Value("${server.port}")
    String port;

    /** * 定义一个简单接口 * @param name * @return */
    @GetMapping("/hi/{name}")
    public String home(@PathVariable String name){
        return "hi " + name + ",I am from port :" + port;
    }
}

上述java类中,还进行了以下编码:

  • 添加@RestController,相当于@Controller+@ResponseBody,标识这个类对外提供Restful风格的HTTP接口服务。
  • 通过注解@Value获取配置文件application.yml中的配置。
  • 通过注解@GetMapping("/hi")对外提供一个GET类型的接口。
  • 通过注解@PathVariable来获取路径上的参数,从而形成RESTful风格的请求路径。

1.3.4.编辑配置文件

默认生成的配置文件是application.properties,我习惯性将其重命名为application.yml,配置如下:

# 服务端口号
server:
  port: 8763
# 服务名称,即serviceId
spring:
  application:
    name: service-hi
# 服务注册与发现相关配置
eureka:
  client:
    # 服务注册地址
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

1.3.5.启动服务提供者

启动服务eureka-hi,再次在浏览器访问https://localhost:8761/,如下:

观察Instances currently registered with Eureka部分,可以发现,目前已经存在一个SERVICE-HI的服务。
说明Eureka Client确实注册到了Eureka Server中心。

在浏览器访问https://localhost:8763/hi/david,得到如下结果:

说明Eureka Client确实能够提供RESTful风格的服务。

1.4.网络拓扑图

简单的服务注册中心Eureka Server与服务提供者Eureka Client的网络拓扑图,可以总结如下:

这种配置方式有以下致命缺陷:

  • 当成千上万的服务提供者都向它单节点的服务注册中心进行注册时,它的负载是非常高的。
  • 一旦这个单节点的服务注册中心挂掉,则所有服务提供者的注册信息都将变得不可用。

2.高可用配置

所谓高可用,就是将微服务集群化,当其中一个节点挂掉之后,其他的节点还能够提供正常的功能。

高可用配置,可以在前一章节的基础上进行修改。

为了便于区分,本人重新创建了eureka-server-haeureka-hi-ha服务,其配置过程与前面章节一致。

2.1.修改Eureka Server的application.yml

先上Eureka Server的application.yml配置文件:

---
# 高可用节点1的配置
server:
  port: 8771
spring:
  # 节点1的标签
  profiles: peer1
  # 服务名保持一致
  application:
    name: eureka-ha
eureka:
  instance:
    hostname: peer1
  client:
    # 进行注册(高可用配置、默认配置)
    # registerWithEureka: true
    # 获取注册信息(高可用配置、默认配置)
    # fetchRegistry: true
    serviceUrl:
      # 节点1向节点2/3进行服务注册
      defaultZone: http://peer2:8772/eureka/,http://peer3:8773/eureka/

---
# 高可用节点2的配置
server:
  port: 8772
spring:
  # 节点2的标签
  profiles: peer2
  # 服务名保持一致
  application:
    name: eureka-ha
eureka:
  instance:
    hostname: peer2
  client:
    # 进行注册(高可用配置、默认配置)
    # registerWithEureka: true
    # 获取注册信息(高可用配置、默认配置)
    # fetchRegistry: true
    serviceUrl:
      # 节点2向节点1/3进行服务注册
      defaultZone: http://peer1:8771/eureka/,http://peer3:8773/eureka/

---
# 高可用节点3的配置
server:
  port: 8773
spring:
  # 节点3的标签
  profiles: peer3
  # 服务名保持一致
  application:
    name: eureka-ha
eureka:
  instance:
    hostname: peer3
  client:
    # 进行注册(高可用配置、默认配置)
    # registerWithEureka: true
    # 获取注册信息(高可用配置、默认配置)
    # fetchRegistry: true
    serviceUrl:
      # 节点3向节点1/2进行服务注册
      defaultZone: http://peer1:8771/eureka/,http://peer2:8772/eureka/

说明:

  • yml文件中,通过---来区分多个文件,减少配置文件个数。
  • 高可用配置中,每个节点的端口号不同。
  • 高可用配置中,所有节点的服务名相同,即spring.application.name相同。
  • 高可用配置中,默认情况下,registerWithEureka: truefetchRegistry: true
  • 高可用配置中的节点,需要向除此节点之外的节点进行服务注册。
  • 高可用配置中,设置了每个节点的标签spring.profiles,通过此标签来区分到底启动哪个配置页。
  • 配置文件中,全部采用驼峰命名

2.3.分别启动服务注册中心的三个节点

Run/Debug Configurations界面中,配置程序参数为--spring.profiles.active=peer1

然后运行,以此来启动节点1的服务,配置如下图所示。

分别配置--spring.profiles.active=peer2--spring.profiles.active=peer3来启动另外两个服务。

在本例中,三个节点的port分别是8771、8772、8773,访问https://localhost:8771/,如下:

依次访问https://localhost:8772/https://localhost:8773/,结果类似。

2.3.修改Eureka Client的application.yml

修改Eureka Client的配置文件。

# 服务地址
server:
  port: 8783
# 服务名称
spring:
  application:
    name: service-hi-ha
eureka:
  client:
    serviceUrl:
      # 这里只需要执行其中一个服务注册中心节点即可
      defaultZone: http://peer1:8771/eureka/

注意:

  • 这里只需要执行其中一个服务注册中心节点即可,因为其注册信息时可以各节点之间复制的。

2.4.高可用测试

启动eureka-hi-ha,然后刷新https://localhost:8771/,发现注册中心多了一个SERVICE-HI-HA服务。

关闭服务节点peer1,再次访问https://localhost:8771/,发现服务不可用,表示节点1真的宕机了。

访问https://localhost:8772/或者https://localhost:8773/,发现服务可用如下:

注意:

  • peer1节点并没有立即从服务列表中消失,这是因为服务注册中心通过心跳来检测服务是否存活。
  • 服务宕机之后,服务并不会马上从服务注册中心注销。
  • 只有当超过规定时间还未检测到服务时,才会注销服务。
  • 虽然peer1节点挂掉了,但是eureka-hi-ha的注册信息在其他注册中心节点还是存在的。

2.5.网络拓扑图

高可用的服务注册中心Eureka Server与服务提供者Eureka Client的网络拓扑图,可以总结如下:

当前其中任意节点宕机之后,其他节点上还保存着所有的服务注册信息。

3.认证配置

无论前面的简单配置,还是高可用配置,都存在一个很低级的安全问题,那就是谁都可以进行服务注册。

为了解决这个问题,可以通过安全认证组件security来进行配置。

本章节以1.简单配置章节为基础进行修改。

3.1.修改Eureka Server

修改pom.xml

添加security组件:

<dependencies>
    <!--添加安全认证-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
</dependencies>

修改application.yml

# 端口号
server:
  port: 8761
# 安全认证
security:
  # 开启基本安全认证
  basic:
    enabled: true
  # 设置用户名密码
  user:
    name: admin
    password: admin
# 服务注册相关配置
eureka:
  # 服务实例主机名
  instance:
    hostname: localhost
  # 服务提供者配置
  client:
    # 不进行注册(当服务注册中心是单点而非高考用时的配置方式)
    registerWithEureka: false
    # 不获取注册信息(当服务注册中心是单点而非高考用时的配置方式)
    fetchRegistry: false
    # 服务注册中心地址
    serviceUrl:
      # 无安全认证的配置
      # defaultZone: https://${eureka.instance.hostname}:${server.port}/eureka/
      # 安全认证的配置
      defaultZone: https://${security.user.name}:${security.user.password}@${eureka.instance.hostname}:${server.port}/eureka/

3.2.修改Eureka Client

无需修改pom.xml

修改application.yml

# 服务端口号
server:
  port: 8763
# 服务名称,即serviceId
spring:
  application:
    name: service-hi
# 服务注册与发现相关配置
eureka:
  client:
    # 服务注册地址
    serviceUrl:
      # 无安全认证的配置
      # defaultZone: https://localhost:8761/eureka/
      # 安全认证配置
      defaultZone: http://admin:admin@localhost:8761/eureka/

3.3.安全认证测试

第一次测试:

依次启动服务eureka-servereureka-hi,在浏览器访问:https://localhost:8761/,会出现以下输入框:

输入用户名admin和密码admin之后,进入注册中心。在注册中心,发现了SERVICE-HI已经注册中心。


第二次测试:

关闭所有服务,关闭浏览器,修改Eureka Client的application.yml,将defaultZone还原成https://localhost:8761/eureka/

依次启动服务eureka-servereureka-hi,在浏览器访问:https://localhost:8761/,重新弹出安全认证输入框。

输入用户名admin和密码admin之后,进入注册中心。在注册中心,发现了SERVICE-HI不在注册中心。

查看eureka-hi的启动日志,发现报错:

2018-06-03 23:07:22.261  INFO 17504 --- [           main] com.netflix.discovery.DiscoveryClient    : Getting all instance registry info from the eureka server
2018-06-03 23:07:22.341  WARN 17504 --- [           main] c.n.d.s.t.d.RetryableEurekaHttpClient    : Request execution failure with status code 401; retrying on another server if available
2018-06-03 23:07:22.341 ERROR 17504 --- [           main] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_SERVICE-HI/DESKTOP-4J0FACQ:service-hi:8763 - was unable to refresh its cache! status = Cannot execute request on any known server

com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server
    at com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient.execute(RetryableEurekaHttpClient.java:111) ~[eureka-client-1.6.2.jar:1.6.2]
    at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.getApplications(EurekaHttpClientDecorator.java:134) ~[eureka-client-1.6.2.jar:1.6.2]
    at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$6.execute(EurekaHttpClientDecorator.java:137) ~[eureka-client-1.6.2.jar:1.6.2]
    ...

经测试,简单的安全认证配置成功。


分享到: