【JAVA企业级开发】给公司两个分布式技术组件Netflix-Eureka,SpringCloud-Config做零代码无痛人流迁移手术,并且技术组件更换为Alibaba-Nacos。

一级目录

二级目录

三级目录

一. 概述

最近公司在做组件的技术升级,需要将原有注册中心 Eureka,配置中心 Spring Cloud Config 替换为 Nacos,主要原因如下:

1. Spring Cloud Netflix Eureka项目宣布闭源

Spring Cloud的这一重要宣布,意味着,随着技术的发展,最终使用Eureka的用户都会面临注册中心迁移的问题。

2. 原生的SpringCloud-config以为以Git作为存储介质的硬伤

①Git的权限控制是个坑

Git的权限管理是说控制用户能不能Push或者Delete分支,或者能不能Push代码,而不是能不能访问某个目录的文件。
对目录和文件的可读是Git的最基本要求,不可能做到针对目录级别的不可读。
因此如果直接使用,会出现这样一种情形

②不同团队之间可以互看对方配置!

于是,可能会有如下情形发生

A团队同事A:“小B,这个地方不懂怎么配?”
A团队同事B:“去看看B团队的配置,直接贴过来。”
然后B团队就会发现自己的中间件里总是会多出一些莫名奇妙的数据!

当然,你可以禁止研发直接登陆Git改配置。然后呢,基于Git研发一套配置管理系统,在上面做权限控制,但是又有几个公司这么做呢?因为,这可能带来第二个问题。

③粒度问题

将配置信息放在Git中,有一个致命问题:粒度太粗了!
你每次对一条配置发生crud的操作,其带来的影响是整个文件发生变动。如果将来我们需要对某条配置做灰度发布,基于Git来做是比较麻烦的,注意了,我没说不能做,只是比较麻烦。

那么,当时我们最理想的存储介质就是数据库,将配置信息放在数据库里有两个好处

基于数据库开发一套配置管理系统,显然比基于git来开发容易的多!

将配置放在数据库里,每条配置对应数据库的表中的一条记录。这么做粒度够细,针对某些重要的配置,做灰度发布,实现起来就容易很多。

因此,我们采用数据库作为存储介质。庆幸的是,这一点在Spring-Cloud-Config中是支持的。在该组件下,只需要设置

spring.profiles.active=jdbc

就能够激活jdbc模式。
但是我们很快发现了一个更大的问题,也正是因为这个问题,我们不得以需要进行改写Spring-Cloud-Config。

④Spring-Cloud-Config的刷新机制是个坑!

因为一个配置中心应该要能够做到,配置发生改动的时候,项目能够自动感知,自动更新配置才对。在Spring-Cloud-Config中,这套机制是借助一些代码仓库(SVN、Github等)提供的Webhook机制加上Spring-Cloud-Bus来实现的。
在Webhook中配置一个回调地址,刷新流程如下图所示:
在这里插入图片描述
OK,那么问题又来了!
(1)配置数据放在数据库中,数据库里没有Webhook这种东西啊,怎么做到实时刷新?
(2)Spring-Cloud-Config的这套刷新机制依赖于消息总线,依赖于消息队列,存在延迟的情况!且依赖于消息队列的可用性,系统的复杂度大大增加。如果生产环境上消息队列出问题了,我们的刷新功能就会受到影响!

3. Nacos更强

<1> 在服务注册上,Nacos 几乎实现了 Eureka 所支持的所有特性;

<2> 在配置管理上,Nacos 具备 Config 所支持的所有功能;

<3> Nacos 提供了控制台UI,便于更方便地进行服务管理,配置管理;

可以理解为,Nacos = Spring Cloud Eureka + Spring Cloud Config,但是其功能更强大。

因此,本文将探讨:如何以 “零代码” 的方式,将使用 Eureka,Config 的应用迁移到 Nacos 上。

二Nacos

在这里插入图片描述

Nacos=Netflix-Eureka+SpringCloud-Config

nacos地址
https://github.com/alibaba/nacos/releases/tag/1.3.2

三服务注册中心无痛迁移过程

1关于 eureka和nacos的服务注册中心

eureka实例规模在很大的时候才会出现性能瓶颈,所以服务在规模合适的情况下其性能不会存在问题,
一般情况下可以使用eureka1.0作为注册中心使用,满足业务使用即可。
nacos在一般项目性能上与EURKA相当,在伸缩性和扩展性来看Nacos支持跨注册中心同步及大数量级的
集群;nacos中包含了配置中心,在源码中可以看到在客户端维护了一个长轮询的任务,会通过安全监听
通知变更的内容定拉取发生变更的配置信息。

eureka的数据同步采取的是去除中心化,每个节点都持有全量数据,新增的数据可以往任
意一个节点写入,然后由这个节点向其他节点传播达到一致性。
nacos使用一个数据同步中间件,Nacos-Sync用来做数据同步中心服务。

2组件版本关系前期准备

在这里插入图片描述

3安装 NacosServer高可用 集群代替EurekaServer高可用集群

nacosserver不像eureka一样,可以通过依赖的方式引入到项目中,并且可以整合在项目中配置运行,因为nacos(eureka+springcloudConfig)整体的体积较大,所以需要单独下载部署,微服务模块使用开发过程中需要删除eurekaserver的集群模块。
在这里插入图片描述

①解压 nacos-server-1.3.0.tar.gz。

②修改application.properties,文件位于nacos/conf目录下,修改文件中的数据库配置。

spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://10.0.17.21:3306/registry?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=123456

③修改cluster.conf,文件位于nacos/conf目录下,配置集群节点的信息(IP端口形式)。

#it is ip
#example
10.0.112.64:8848
10.0.112.65:8848
10.0.112.66:8848

④启动

进入nacos/bin目录下,通过 sh startup.sh 启动 nacos 即可。

4修改服务提供者模块

①依赖

eureka client依赖

  <!--springcloud的Finchley.SR2版本新的eureka客户端依赖-->
        <<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

nacos client依赖

 <!--nacos客户端依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

②配置

eureka

#注意不要忘了/eureka/后缀,设置与eureka-server的交互地址
eureka.client.service-url.defaultZone= http://eurekaserver1:9001/eureka/,http://eurekaserver2:9002/eureka/,http://eurekaserver3:9003/eureka/
#eureka的健康检查机制开关
eureka.client.healthcheck.enabled=true
#自我保护机制
#eureka.server.enable-self-preservation=false
#自我保护机制关闭之后的配置,告诉服务端,如果你N秒之后还没有接受到我发送的心跳,就代表我"死"了,将我的服务踢出掉。
#eureka.instance.lease-expiration-duration-in-seconds=36
#设置每隔多少秒给服务中心发送一次心跳,证明自己还活着
#eureka.instance.lease-renewal-interval-in-seconds=6
#springcloudconfig的配置中心开关,SpringCloud默认启动的时候是会先加载bootstrap.properties或bootstrap.yml配置文件,如果没有的话,则会远程从http://localhost:8888获取配置,然后才会加载到application.yml,properties文件。
spring.cloud.config.enabled=false

nacos

#springcloudconfig的配置中心开关,SpringCloud默认启动的时候是会先加载bootstrap.properties或bootstrap.yml配置文件,如果没有的话,则会远程从http://localhost:8888获取配置,然后才会加载到application.yml,properties文件。
spring.cloud.config.enabled=false
spring.cloud.nacos.discovery.server-addr=localhost:8848
spring.cloud.nacos.config.server-addr=localhost:8848

③启动类,更换注解即可

@EnableEurekaClient》》》》》》@EnableDiscoveryClient

eureka
package fengbo;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * Created by @author LiuChunhang on 2020/7/14.
 */

@MapperScan(basePackages = "fengbo.dao")
@EnableTransactionManagement
@SpringBootApplication
@EnableEurekaClient

public class AccountClientApp {
    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(AccountClientApp.class);
        springApplication.setBannerMode(Banner.Mode.OFF);
        springApplication.run(args);
    }
}

nacos

package fengbo;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * Created by @author LiuChunhang on 2020/7/14.
 */

@MapperScan(basePackages = "fengbo.dao")
@EnableTransactionManagement
@SpringBootApplication
/*@EnableEurekaClient*/
@EnableDiscoveryClient
public class AccountClientApp {
    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(AccountClientApp.class);
        springApplication.setBannerMode(Banner.Mode.OFF);
        springApplication.run(args);
    }
}

5修改服务消费者模块

①依赖

eureka client依赖

  <!--springcloud的Finchley.SR2版本新的eureka客户端依赖-->
        <<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

nacos client依赖

 <!--nacos客户端依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

②配置

eureka

#禁止自己当做服务注册,微服务消费者只消费服务,不像注册中心注册,如果加网关组件的话,必须开启自注册,消费者供网关消费
#eureka.client.register-with-eureka=false
#指定向哪些eurekaserver注册
eureka.client.service-url.defaultZone=http://eurekaserver3:9003/eureka/,http://eurekaserver2:9002/eureka/,http://eurekaserver1:9001/eureka/

nacos

#springcloudconfig的配置中心开关,SpringCloud默认启动的时候是会先加载bootstrap.properties或bootstrap.yml配置文件,如果没有的话,则会远程从http://localhost:8888获取配置,然后才会加载到application.yml,properties文件。
spring.cloud.config.enabled=false

spring.cloud.nacos.discovery.server-addr=localhost:8848
spring.cloud.nacos.config.server-addr=localhost:8848

③ 启动类,更换注解即可

eureka

package fengbo;

import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import ribbonbalance.IndividualBalance;

/**
 * Created by @author LiuChunhang on 2020/7/21.
 */
@SpringBootApplication
@EnableEurekaClient
/**此注解的属性用于服务定制化负载均衡,且负载均衡配置类不能在@ComponentScan所扫描的当前包下以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,也就是说我们达不到特殊化定制的目的了。*/
@RibbonClient(name = "accountprovider",configuration = IndividualBalance.class)
@EnableFeignClients(basePackages = "fengbo.service")
public class AccountSystem {
    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(AccountSystem.class);
        application.setBannerMode(Banner.Mode.OFF);
        application.run(args);
    }
}

nacos

package fengbo;

import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import ribbonbalance.IndividualBalance;

/**
 * Created by @author LiuChunhang on 2020/7/21.
 */
@SpringBootApplication
@EnableDiscoveryClient
/**此注解的属性用于服务定制化负载均衡,且负载均衡配置类不能在@ComponentScan所扫描的当前包下以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,也就是说我们达不到特殊化定制的目的了。*/
@RibbonClient(name = "accountprovider",configuration = IndividualBalance.class)
@EnableFeignClients(basePackages = "fengbo.service")
public class AccountSystem {
    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(AccountSystem.class);
        application.setBannerMode(Banner.Mode.OFF);
        application.run(args);
    }
}

6服务中心测试

①下载,解压缩,执行命令部署Nacos

https://github.com/alibaba/nacos/releases
在这里插入图片描述

         ,--.
       ,--.'|
   ,--,:  : |                                           Nacos
,`--.'`|  ' :                       ,---.               Running in stand alone mode, All function modules
|   :  :  | |                      '   ,'\   .--.--.    Port: 8848
:   |   \ | :  ,--.--.     ,---.  /   /   | /  /    '   Pid: 11836
|   : '  '; | /       \   /     \.   ; ,. :|  :  /`./   Console: http://192.168.1.34:8848/nacos/index.html
'   ' ;.    ;.--.  .-. | /    / ''   | |: :|  :  ;_
|   | | \   | \__\/: . ..    ' / '   | .; : \  \    `.      https://nacos.io
'   : |  ; .' ," .--.; |'   ; :__|   :    |  `----.   \
|   | '`--'  /  /  ,.  |'   | '.'|\   \  /  /  /`--'  /
'   : |     ;  :   .'   \   :    : `----'  '--'.     /
;   |.'     |  ,     .-./\   \  /            `--'---'
'---'        `--`---'     `----'

2020-08-13 16:23:07,306 INFO Bean 'org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration' of type [org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration$$EnhancerBySpringCGLIB$$d877e6a8] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

2020-08-13 16:23:07,646 INFO Bean 'objectPostProcessor' of type [org.springframework.security.config.annotation.configuration.AutowireBeanFactoryObjectPostProcessor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

2020-08-13 16:23:07,656 INFO Bean 'org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler@73a8da0f' of type [org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

2020-08-13 16:23:07,657 INFO Bean 'org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration' of type [org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration$$EnhancerBySpringCGLIB$$fd4c895a] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

2020-08-13 16:23:07,679 INFO Bean 'methodSecurityMetadataSource' of type [org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

2020-08-13 16:23:08,951 INFO Tomcat initialized with port(s): 8848 (http)

2020-08-13 16:23:09,510 INFO Root WebApplicationContext: initialization completed in 8928 ms

2020-08-13 16:23:17,205 INFO Initializing ExecutorService 'applicationTaskExecutor'

2020-08-13 16:23:17,423 INFO Adding welcome page: class path resource [static/index.html]

2020-08-13 16:23:18,434 INFO Creating filter chain: Ant [pattern='/**'], []

2020-08-13 16:23:18,640 INFO Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@ecf9fb3, org.springframework.security.web.context.SecurityContextPersistenceFilter@60d84f61, org.springframework.security.web.header.HeaderWriterFilter@41c07648, org.springframework.security.web.csrf.CsrfFilter@52c8295b, org.springframework.security.web.authentication.logout.LogoutFilter@2575f671, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@324dcd31, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@433ffad1, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@2d35442b, org.springframework.security.web.session.SessionManagementFilter@781e7326, org.springframework.security.web.access.ExceptionTranslationFilter@77b21474]

2020-08-13 16:23:19,012 INFO Exposing 2 endpoint(s) beneath base path '/actuator'

2020-08-13 16:23:19,062 INFO Initializing ExecutorService 'taskScheduler'

2020-08-13 16:23:19,297 INFO Tomcat started on port(s): 8848 (http) with context path '/nacos'

2020-08-13 16:23:19,307 INFO Nacos Log files: D:\AlibabaNacos\logs

2020-08-13 16:23:19,309 INFO Nacos Log files: D:\AlibabaNacos\conf

2020-08-13 16:23:19,310 INFO Nacos Log files: D:\AlibabaNacos\data

2020-08-13 16:23:19,310 INFO Nacos started successfully in stand alone mode. use embedded storage

②出现如下界面,证明部署成功。

在这里插入图片描述
账号,密码都是 nacos

7服务发现调用测试

启动已经配置好的服务提供者,然后登录到nacosserver,见如下界面,则证明服务提供者配置与nacos的注册中心成功!
在这里插入图片描述
负载均衡调用微服务测试
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这样子,就完成了服务注册与发现调用的改造。

四服务配置中心无痛人流迁移过程

1服务提供者和消费者更换依赖

在前面的基础上,直接引入下面依赖即可:

 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
 </dependency>

同时去掉 SpringCloudConfig 的客户端依赖:

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

2服务提供者和消费者更换配置

#Nacos配置中心URL
spring.cloud.nacos.config.server-addr=localhost:8848

同时去掉 SpringCloudConfig 的配置

spring.cloud.config.enabled=false
spring.cloud.config.config.server.git=XXXX

这样子,服务就加入了Nacos配置中心。

五. 改造带来的收益

改造完成后,经过多轮测试,最终成功投产到生产环境。经过一段时间的验证,我们发现Nacos还是很香的。

1. 经济价值

我们替换了旧的配置和注册中心,目前开发测试共有5套环境,每套环境的配置和注册中心都部署集群的话,需要部署522=20个节点,现在只需要部署3个节点,即可实现高可用。这为我们省下了一笔机器的花销。

2. 实用价值

<1> 服务管理: 随时随地上下线应用,随时随地修改权重。
<2> 配置管理: 高效管理配置,支持修改对比,回滚配置,并且记录修改记录。

要知道,这两个功能,在Eureka均需要二次开发,这对中小企业来说,不够友好。而Nacos天然地支持服务,配置管理。

3. 其他价值

使用Nacos后,我们的应用完美融入了微服务生态。我们知道,Eureka和Config在融入云原生方面存在很大欠缺(虽然有解决方案,但较为繁琐)。而Nacos则不同,它天然地融入云原生中,据官方消息,Nacos将为融入Service Mesh做出更大改进。

六. 总结

经过上述改造,服务得以顺利地从 Eureka,Config 迁移到 Nacos 上,后续在微服务生态上能发挥更好的价值。

下面做个简单的总结:

  1. Spring Cloud Alibaba 实现了Spring Cloud服务注册规范,这使得开发者能够无痛地迁移 Eureka 到 Nacos;

  2. 在功能上,Nacos = Eureka + Nacos;

  3. 在生态上,Nacos亲近开发者,无论是对dubbo,SpringCloud还是k8s的兼容,深得人心;

因此,可以相信,随着技术的演进, Nacos 一定会在微服务体系上走得更远,走得更好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

牵牛刘先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值