V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hansonwang99
V2EX  ›  程序员

Spring Cloud Eureka Server 高可用之:在线扩容

  •  
  •   hansonwang99 ·
    hansonwang99 · 2018-10-19 07:16:26 +08:00 · 2349 次点击
    这是一个创建于 2238 天前的主题,其中的信息可能已经有所发展或是发生改变。

    本文共 1591 字,阅读大约需要 6 分钟 !


    概述

    业务微服务化以后,我们要求服务高可用,于是我们可以部署多个相同的服务实例,并引入负载均衡机制。而微服务注册中心作为微服务化系统的重要单元,其高可用也是非常必要的,因此在生产中我们可能需要多个微服务注册中心实例来保证服务注册中心的稳定性。本文就以 Eureka 微服务注册中心为例,来实践一下如何 在线扩充 Eureka Server 实例来保证 微服务注册中心的高可用性!

    注: 本文首发于 My Personal Blog,欢迎光临 小站

    本文内容脑图如下:

    本文内容脑图


    原理与实验流程介绍

    我们欲模拟如下过程:

    • 首先启动一个 eureka-server 实例( eureka-server-1 )

    • 再启动一个 eureka-client 实例( eureka-client-1 )并注册到 eureka-server-1 中

    • 接下来我们启动第二个 eureka-server 实例:eureka-server-2,并且让已启动的 eureka-server-1 和 eureka-client-1 在不重启的情况下来感知到 eureka-server-2 的加入

    • 同理我们可以在启动第三个 eureka-server 实例:eureka-server-3,并且让已启动的 eureka-server-1、eureka-server-2 和 eureka-client-1 在不重启的情况下来感知到 eureka-server-3 的加入

    • 更多 eureka-server 实例的加入原理完全相同,不再赘述

    这样一来我们便实现了微服务注册中心的动态在线扩容!

    而如何才能让已启动的服务能够在不重启的情况下来感知到新的 eureka-server 的加入呢?

    为此我们引入 Spring Cloud Config 配置中心 config-server,并将 eureka-server 和 eureka-client 服务的配置文件由 config-server 进行统一管理,这样一来对配置文件的修改如果可以通过某种机制来通知已启动的服务,那么问题便迎刃而解了!

    我们给出整个过程的原理图如下:

    实验原理图

    接下来我们来实践这整个过程!


    基础工程搭建

    • 创建一个 config-server 工程

    pom 中关键依赖如下:

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-config-server</artifactId>
            </dependency>
    

    主类添加相应注解:

    @SpringBootApplication
    @EnableConfigServer
    public class ConfigServerApplication {
      ...
    }
    

    bootstrap.yml 配置文件如下:

    spring:
      application:
        name: config-server
      cloud:
        config:
          server:
            git:
              uri: https://github.com/hansonwang99/xxxx
              username: xxxx
              password: xxxx
    server:
      port: 1115
    

    该 yml 配置很重要,其连接了预先准备好的 git 仓库,后续 eureka-server 和 eureka-client 的配置文件都是存于该 git 仓库中的!

    • 创建一个 eureka-server 工程

    pom 中关键依赖如下:

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
            </dependency>
    

    主类添加相应注解:

    @SpringBootApplication
    @EnableEurekaServer
    public class EurekaServerApplication {
      ...
    }
    
    

    bootstrap.yml 重要配置如下:

    spring:
      application:
        name: eureka-server
      cloud:
        config:
          uri: http://localhost:1115
    

    注意该 yml 中关于 spring cloud config 的配置同样非常重要,因为此 eureka-server 需要从 config-server 中拉取配置!

    最后我们还需要添加一个 controller 便于测试:

    @RestController
    @RequestMapping("/test")
    public class TestController {
    
        @Autowired
        EurekaClientConfigBean eurekaClientConfigBean;
    
        @GetMapping("/eureka-service-info")
        public Object getEurekaServerUrl(){
            return eurekaClientConfigBean.getServiceUrl();
        }
    }
    

    这个 Rest Controller 接口的意图很简单:打印出当前到底有多少个 eureka-server 实例在提供服务(从而可以直观的判断出 eureka-server 的扩容是否已经成功)

    • 创建一个 eureka-client 工程

    pom 中关键依赖如下:

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
            </dependency>
    

    主类添加相应注解:

    @SpringBootApplication
    @EnableDiscoveryClient
    public class EurekaClientApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(EurekaClientApplication.class, args);
        }
    }
    

    bootstrap.yml 重要配置如下:

    spring:
      application:
        name: eureka-client
      cloud:
        config:
          uri: http://localhost:1115
    

    这里基本同上面 eureka-server 的配置,不再赘述

    同样,我们也在 eureka-client 中添加一个 controller 便于测试:

    @RestController
    @RequestMapping("/test")
    public class TestController {
    
        @Autowired
        EurekaClientConfigBean eurekaClientConfigBean;
    
        @GetMapping("/eureka-service-info")
        public Object getEurekaServerUrl(){
            return eurekaClientConfigBean.getServiceUrl();
        }
    }
    

    三个工程的创建到此完毕!下来我们来依次启动各个工程

    • 首先启动 config-server 工程

    • 然后用 peer1 配置文件来启动 第一个 eureka server,指令如下:

    mvn spring-boot:run -Dspring.profiles.active=peer1
    

    启动过程的开始打印出如下信息,一目了然:

    用 peer1 配置文件来启动第一个 eureka server

    当然这个 peer1 配置文件实际物理存在于 git 仓库之上:

    peer1 配置文件的配置

    • 接下来我们启动 eureka_client 工程,指令如下:
    mvn spring-boot:run -Dspring.profiles.active=peer1
    

    其依然需要通过 spring cloud config 去 git 仓库拉取 eureka-client 的 peer1 配置文件,这一点从 eureka-client 的启动过程中也能看到:

    启动 eureka-client

    • 接下来我们用浏览器访问仅存在的一个 eureka-server 微服务注册中心,可以看到有服务已经注册上去了:

    微服务注册中心

    既然 config-server / eureka-server / eureka-client 三个服务已经启动了,那么接下来我们来测试一下:

    浏览器访问 eureka-client 的 Rest 接口:localhost:1114/test/eureka-service-info

    访问 eureka-client 的 Rest 接口

    同理,浏览器访问 eureka-server 的 Rest 接口:localhost:1111/test/eureka-service-info

    访问 eureka-server 的 Rest 接口

    OK,一切正常,但目前微服务注册中心仅一个 eureka-server 实例,下来我们来 在线动态扩容微服务注册中心实例


    扩充一次 Eureka Server

    接下来我们再用 peer2 配置文件来 启动第二个 eureka server,指令如下:

    mvn spring-boot:run -Dspring.profiles.active=peer2
    

    启动完毕后,浏览器访问微服务注册中心第一个实例 eureka-server-1:localhost:1111/ 发现第二个微服务注册中心实例 eureka-server-2 已经成功启动并加入

    第二个微服务注册中心实例 eureka-server-2 已经成功启动并加入

    为了让已启动的 eureka-client 和 eureka-server-1 能在线感知到 eureka-server-2 的加入,此时我们需要修改两个地方:

    • 修改 Git 上 eureka-client 的配置文件:
    server:
      port: 1114
    
    spring:
      application:
        name: eureka-client
    
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:1111/eureka/,http://localhost:1112/eureka/  # 此处改为包含两个 eureka-server
    
    • 修改 Git 上第一个 eureka-server ( eureka-server-1 )的配置文件:
    server:
      port: 1111
    
    spring:
      application:
        name: eureka-server
    eureka:
      instance:
        hostname: localhost
        preferIpAddress: true
      client:
        registerWithEureka: true
        fetchRegistry: true
        serviceUrl:
          defaultZone: http://localhost:1112/eureka/ # 此处改为第二个 eureka-server 地址
      server:
          waitTimeInMsWhenSyncEmpty: 0
          enableSelfPreservation: false
    

    Git 仓库里配置文件的修改完毕并不能触发已启动的 eureka-client 和 eureka-server-1 在线更新,我们还需要向 eureka-client 服务和 eureka-server-1 服务来 POST 两个请求来激活刚才所修改的配置:

    POST localhost:1111/actuator/refresh  // 激活 eureka-client 服务的配置
    POST localhost:1114/actuator/refresh // 激活 eureka-server-1 服务的配置
    

    POST 请求一旦发出,我们从控制台里能直观看到更新配置文件的详情:

    POST 触发更新配置文件

    配置文件更新完毕,浏览器再次访问 eureka-client 的 Rest 接口:localhost:1114/test/eureka-service-info

    浏览器再次访问 eureka-client 的 Rest 接口


    再扩充一次 Eureka Server

    接下来还可以再用 peer3 配置文件来启动第三个 eureka server 加入高可用微服务注册中心集群,过程和上面类似,此处不再赘述!当然更多 eureka-server 实例的扩充原理也相同。


    后记

    由于能力有限,若有错误或者不当之处,还请大家批评指正,一起学习交流!



    5 条回复    2019-05-21 18:38:12 +08:00
    zealzz
        1
    zealzz  
       2018-10-19 08:38:36 +08:00 via Android
    概括一下楼主实现原理:
    1、Eureka server 的配置存放在 git 上,通过 SpringCloud Config 加载配置
    2、修改 git 上的配置,增加一个 Eureka server,refresh 配置问价
    ourslay
        2
    ourslay  
       2018-10-19 09:18:10 +08:00 via Android
    可以设置 Web hook 自动刷新 config server 的配置
    hansonwang99
        3
    hansonwang99  
    OP
       2018-10-19 10:23:50 +08:00
    多谢楼上大神指导
    saximoer
        4
    saximoer  
       2018-10-19 10:31:10 +08:00
    貌似还可以通过 web hook 刷新 config server 通过 spring bus 让其他项目自动更新配置
    不需要去每一个 eureka-server 上手动刷新
    zhuwd
        5
    zhuwd  
       2019-05-21 18:38:12 +08:00 via iPhone
    请问有没有不借助配置中心实现动态扩容的方法
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3377 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 11:56 · PVG 19:56 · LAX 03:56 · JFK 06:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.