欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

搭建 Spring Cloud Eureka Server 高可用注册中心集群

程序员文章站 2022-06-12 15:31:48
...

什么是注册中心

Eureka Server 在微服务中承担的角色是服务注册中心,也是最最基础的核心设施之一。从“Eureka”单词的含义“我找到了!我发现了!”可以看出,其实 Eureka 就是用来实现服务注册、服务发现的工具,和 dubbo 这类的分布式服务治理框架类似。各种独立的微服务将自己注册到 Eureka Server,Eureka Client 则提供了服务发现的能力。

本文目的

Eureka的特点在于可以相互注册,形成高可用注册中心集群。这篇文章记录一下本地搭建两个 Eureka Server 注册中心,让他们互相注册自己到对方的服务中心,最后创建一个名为 hello-service 的微服务,将它们注册到注册中心。

开发环境

  • IntelliJ IDEA 2018.1.6
  • Maven-3.5.3
  • JDK8
  • spring cloud版本:Finchley.RELEASE
  • spring-boot-starter版本:2.0.3.RELEASE

准备工作

由于是本地在同一台机器上模拟搭建两个注册中心,需要修改 HOSTS 文件,这里以 Win10 系统为例,HOSTS 文件的路径在 C:\Windows\System32\drivers\etc

在末尾追加内容如下,表示访问 eureka-server1 和 eureka-server2 时,等于访问 127.0.0.1:

127.0.0.1 eureka-server1
127.0.0.1 eureka-server2

第1步:搭建注册中心1

在IDEA创建工程,取名为 cat-spring-cloud-eureka-server-1,通过Spring初始化工具,添加 eureka server 依赖(这里就不贴图演示了):

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>

    <groupId>me.zebe</groupId>
    <artifactId>cat-spring-cloud-eureka-server-1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>cat-spring-cloud-eureka-server-1</name>
    <description>pring Cloud Eureka 注册中心1</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <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>Finchley.RELEASE</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</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>

</project>

application.yml

server:
  port: 20001
eureka:
  instance:
    # eureka-server1 是一个别名,需要在 hosts 文件里面将其映射为 127.0.0.1
    hostname: eureka-server1
  client:
    serviceUrl:
      # 将自身反注册到eureka-server2,利用相互注册,形成高可用注册中心集群
      defaultZone: http://eureka-server2:20002/eureka/
    # 将当前服务注册中心本身也作为服务注册到别的服务注册中心(eureka-server2)
    register-with-eureka: true
    # 不将当前服务注册中心本身也作为服务注册到别的服务注册中心(如设为false,则 eureka-server2 中,unavailable-replicas 会包含此注册中心)
    # register-with-eureka: false

应用启动器类

package me.zebe.cat.spring.cloud.eureka.server;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
 * Spring Cloud Eureka 注册中心1
 *
 * @author Zebe
 */
@EnableEurekaServer
@SpringBootApplication
public class CatSpringCloudEurekaServer1Application {

    /**
     * 运行入口
     * @param args 运行参数
     */
    public static void main(String[] args) {
        SpringApplication.run(CatSpringCloudEurekaServer1Application.class, args);
        System.out.println("Spring Cloud Eureka 注册中心1 -> 已启动。");
    }
}

运行该类,启动时会抛出异常,提示找不到 eureka-server2,这是因为 eureka-server2 我们没有启动,不用管它。

第2步:搭建注册中心2

第二个注册中心和第一个注册中心没有本质上的区别,只不过是换了运行端口和注册地址。将第二个工程取名为 cat-spring-cloud-eureka-server-2

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>

    <groupId>me.zebe</groupId>
    <artifactId>cat-spring-cloud-eureka-server-2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>cat-spring-cloud-eureka-server-2</name>
    <description>pring Cloud Eureka 注册中心2</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <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>Finchley.RELEASE</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</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>

</project>

application.yml

server:
  port: 20002
eureka:
  instance:
    # eureka-server2 是一个别名,需要在 hosts 文件里面将其映射为 127.0.0.1
    hostname: eureka-server2
  client:
    serviceUrl:
      # 将自身反注册到eureka-server1,利用相互注册,形成高可用注册中心集群
      defaultZone: http://eureka-server1:20001/eureka/
    # 将当前服务注册中心本身也作为服务注册到别的服务注册中心(eureka-server1)
    register-with-eureka: true
    # 不将当前服务注册中心本身也作为服务注册到别的服务注册中心(如设为false,则 eureka-server1 中,unavailable-replicas 会包含此注册中心)
    # register-with-eureka: false

应用启动器类

package me.zebe.cat.spring.cloud.eureka.server;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
 * Spring Cloud Eureka 注册中心2
 *
 * @author Zebe
 */
@EnableEurekaServer
@SpringBootApplication
public class CatSpringCloudEurekaServer2Application {

    /**
     * 运行入口
     * @param args 运行参数
     */
    public static void main(String[] args) {
        SpringApplication.run(CatSpringCloudEurekaServer2Application.class, args);
        System.out.println("Spring Cloud Eureka 注册中心2 -> 已启动。");
    }
}

运行该类,只要 hosts 文件里面按照配置里面修改好了,启动时就不会报异常了。

第3步:启动注册中心

先启动注册中心1,忽略报错信息,然后再启动注册中心2。分别访问 http://127.0.0.1:20001http://127.0.0.1:20002
可以看到两个注册中心已经互相注册,配置文件的注释里面已经写清楚了如何观察。

注册中心1
搭建 Spring Cloud Eureka Server 高可用注册中心集群

注册中心2
搭建 Spring Cloud Eureka Server 高可用注册中心集群

第4步:制作快速启动脚本(非必需)

将这两个注册中心工程,分别用Maven打包成JAR文件,然后写好批处理文件,后面就可以一健启动了,比如我为这两个应用写了批处理文件,如下所示:

  • 01 一健启动 Eureka 注册中心-1 运行在 20001.cmd
  • 02 一健启动 Eureka 注册中心-2 运行在 20002.cmd

内容参考:

title EurekaServer1-20001
java -jar cat-spring-cloud-eureka-server-1-0.0.1-SNAPSHOT.jar
title EurekaServer2-20002
java -jar cat-spring-cloud-eureka-server-2-0.0.1-SNAPSHOT.jar

强烈建议写为批处理文件,因为如果要本地搭建为服务学习环境,注册中心是首先要启动的基础设施。

第5步:编写 HELLO-SERVICE 微服务

创建工程,取名为 cat-spring-cloud-hello-service。该工程很简单,需要依赖于 eureka client 来实现服务发现,注意需要引用 starter-web 提供WEB访问功能。

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>

    <groupId>me.zebe</groupId>
    <artifactId>cat-spring-cloud-hello-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>cat-spring-cloud-hello-service</name>
    <description>Spring Cloud Hello-Service 服务实现</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <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>Finchley.RELEASE</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- spring-boot-starter-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>
            <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>

</project>

application.yml

server:
  port: 8001
spring:
  application:
    name: hello-service
eureka:
  client:
    serviceUrl:
      # 如果这里只配置一个服务注册中心 eureka-server1,那么当 eureka-server1 挂掉,服务便无法注册上去
      # defaultZone: http://eureka-server1:20001/eureka/
      # 因此,通常的做法是,将注册中心的地址写成多个(用逗号隔开时,不要有空格,不然可能会报解析错误)
      defaultZone: http://eureka-server1:20001/eureka/,http://eureka-server1:20002/eureka/
    # 将当前服务注册到eureka服务注册中心,这样消费者就可以发现服务
    register-with-eureka: true
    # 如果设置为false,则不会注册到服务中心
    #register-with-eureka: false

应用启动器类

package me.zebe.cat.spring.cloud.service.hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 * Spring Cloud {Hello-Service} 服务提供者
 *
 * @author Zebe
 */
@EnableEurekaClient
@SpringBootApplication
public class CatSpringCloudEurekaHelloServiceApplication {

    /**
     * 运行入口
     * @param args 运行参数
     */
    public static void main(String[] args) {
        SpringApplication.run(CatSpringCloudEurekaHelloServiceApplication.class, args);
        System.out.println("Spring Cloud Eureka {Hello-Service} 服务提供者 -> 已启动。");
    }
}

服务提供控制器类

package me.zebe.cat.spring.cloud.service.hello;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * {Hello-Service} 服务提供者控制器
 *
 * @author Zebe
 */
@RestController
public class HelloServiceController {

    @Value("${server.port}")
    private int port;

    /**
     * Hello
     * @return 返回字符串
     */
    @GetMapping("/hello")
    public String hello() {
        // 返回值里面显示当前的端口号,这样可以用来测试单个服务节点挂掉之后的运行情况
        return "{Hello} From " + port;
    }

}

启动该服务,观察注册中心,可以看到服务注册成功。到此为止,一个简单的微服务注册例子就完成了。

服务运行截图

搭建 Spring Cloud Eureka Server 高可用注册中心集群

搭建 Spring Cloud Eureka Server 高可用注册中心集群