Painless migration Eureka, Config to the Nacos

I. Overview

Recently the company was doing assembly technology upgrade, you need the original registry Eureka, Configuration Center Spring Cloud Config replaced Nacos, mainly due to the following:

1. Spring Cloud Netflix Eureka projects announced closed-source

This important announcement Spring Cloud, meaning that, with the development of technology, end-use Eureka users will be faced with the problem of migration registration center .

2. Nacos more

<1> in the service registration, Nacos achieve almost all the features supported by the Eureka;

<2> on the configuration management, Nacos Config includes all the features supported;

<3> Nacos console provides the UI, makes it easier to service management, configuration management;

It can be understood as, Nacos = Spring Cloud Eureka + Spring Cloud Config, but more powerful.

Therefore, this article will explore: how to  "zero code" way, using the Eureka, Config application to migrate to Nacos.

Two. Nacos Introduction and Key Features Display

       Nacos by providing a simple-to-use dynamic service discovery, service configuration, shared services and infrastructure management services to help customers in the native cloud era, in all private cloud, public cloud or hybrid cloud and other cloud environments, better constructed, delivery, manage their own micro-service platform, faster multiplexing and business services, faster delivery of business value of innovation, so as to win the market users. The following is an overview of FIG Nacos:

Sentence summary is, Nacos provides service management, configuration management, multi-environment management, follow-up will also support rights management and other modules. See detailed functions of the examiner on Nacos network.

III. Implementation process

1. preparation

<1> combing list of services to be migrated

All current micro-services need to be migrated, organize the list of services (easy to post retroactive, to avoid leakage change);

<2> the components used to determine the version

版本依赖选型,需要参考官方Wiki:

https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

另外,Hibernate-Validator版本低于5.X.X时,Nacos-Client报错;

最终,确定的版本情况如下:

2. Nacos 部署

完成了前期准备,下一步便是Nacos的部署。这里采用集群部署的方式,保证Nacos集群高可用。

部署方式采用官方推荐的方式。物理架构如下图所示:

其中,Nacos节点为无状态节点。因此,只通过域名指定轮询访问其中一台即可保证高可用。

<1> Nacos安装

本次使用的Nacos版本为1.1.4,需要三台机器,每台机器都执行同样的安装操作;

1~ 初始化数据库

初始化SQL脚本为 nacos-mysql.sql,文件位于nacos/conf目录下。初始化的表共有11个,如下图所示:

2~ Nacos下载

下载地址:https://github.com/alibaba/nacos/releases/tag/1.1.4

3~ Nacos安装与配置

解压 nacos-server-1.1.4.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

4~ 启动

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

<2> Nginx配置

       因为状态都保存在数据库,因此Nacos是无状态节点,配置Nginx时,只通过域名指定轮询访问其中一台即可保证高可用,配置如下所示:

upstream nacos{
        server 10.0.112.64:8848;
        server 10.0.112.65:8848;
        server 10.0.112.66:8848;
}
server {
        listen       8848;
        server_name  10.0.17.115;
        location / {
            proxy_pass http://nacos;
            proxy_set_header Host $http_host;
        }
}

<3> 验证

通过域名(或者IP端口)的方式访问,出现如下界面,证明部署成功。

3. 配置多环境隔离

Nacos通过命名空间的形式,实现了环境的逻辑隔离。通过不同的命名空间,隔离了不同环境。

登录Nacos控制台,新增命名空间即可。例如需要开发环境和生产环境,则新增 dev,pro 两个命名空间即可。

4. 服务注册与发现

<1> 引入依赖

建议通过父pom的方式引入,避免parent的方式。依赖如下:

    <!-- mvn依赖管理 -->
    <dependencyManagement>
        <dependencies>
            <!-- spring boot -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

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

            <!-- spring cloud alibaba dependencies -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${alibaba-spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

在子项目中直接引入即可:

        <!-- nacos discovery -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

同时去掉Eureka的依赖:spring-cloud-starter-netflix-eureka-client

<2> 配置替换

只需要在配置中去掉Eureka的配置,改为Nacos的配置即可。

spring.cloud.nacos.discovery.server-addr=10.0.17.115:8848

<3> 加上注解

在启动类上加上 @EnableDiscoveryClient 即可。

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

5. 服务配置管理

<1> 引入依赖

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

        <!-- nacos config -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

同时去掉 Config 的依赖。

<2> 配置替换

同服务注册与发现,只需要在配置中去掉Config的配置,改为Nacos的配置即可。

spring.cloud.nacos.config.server-addr=10.0.17.115:8848

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

四. 存在的问题

在实施的过程中,我们也遇到了一些问题:

1. 多环境管理的做法

我们既然在Nacos配置了多环境隔离,那么服务自然也支持多环境隔离,因此我们的做法是:

首先,我们配置了多个配置文件,如下所示:

boostrap.yml 为公用配置,boostrap-xx.yml 作为不同环境的区分,boostrap-xx.yml 内容如下:

spring:
  cloud:
    nacos:
      discovery:
        namespace: 0ec603e3-261f-4705-8530-60093f0c8309
      config:
        namespace: 0ec603e3-261f-4705-8530-60093f0c8309

可以看到,通过namespace区分不同的环境。最终应用启动时,通过 spring.profiles.active 指定环境即可。

2. 配置的实时生效

Nacos支持客户端配置的自动更新,因此,这里提供三种方法实现配置的自动更新(任一种均可):

<1> 通过@Configuration注解指定的配置类, 且在类上加上@RefreshScope

<2> 通过@Value注解注入的属性,且在类上加上@RefreshScope

<3> 通过ConfigurableApplicationContext

@Autowired
private ConfigurableApplicationContext applicationContext;

applicationContext.getEnvironment().getProperty("user.name")

这样,我们在修改配置的同时,配置也会实时在各个客户端生效。

3. Nacos权重配置不生效,且服务无法秒级下线

       经过测试发现,Nacos的权限配置不生效。经过查阅资料,最终通过自定义负载均衡器解决,它是一个基于权重的自定义Nacos负载均衡器,并将Ribbon使用的负载均衡策略由轮询改为它。实现过程如下:

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.DynamicServerListLoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 基于权重的自定义负载均衡器
 * @author zz
 * @date 2019/12/5 13:55
 **/
@Slf4j
public class NacosWeightLoadBalancerRule extends AbstractLoadBalancerRule {

    @Override
    public Server choose(Object o) {
        DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
        String name = loadBalancer.getName();
        try {
            Instance instance = discoveryProperties.namingServiceInstance().selectOneHealthyInstance(name);
            log.info("select instance:{}", instance);
            return new NacosServer(instance);
        } catch (NacosException ee) {
            log.error("select instance error! message:", ee);
        } catch (Exception e) {
            log.error("select instance error! message:", e);
        }
        return null;
    }

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {
    }

    @Autowired
    private NacosDiscoveryProperties discoveryProperties;
import com.netflix.loadbalancer.IRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Ribbon配置
 * @author zz
 * @date 2019/12/5 14:14
 **/
@Configuration
public class RibbonConfig {

    @Bean
    public IRule getRibbonRule() {
        return new NacosWeightLoadBalancerRule();
    }

}

这样,在Nacos进行权重变更时,客户端也能及时根据变更,进行正确的负载。

4. Feign的 @RequestBody 无法继承

看下面的例子,第一个为Feign客户端,第二个为服务端的Controller

@FeignClient("user")
public interface UserApi {
    
    @RequestMapping("/saveUser")
    public String saveUser(@RequestBody User user);
}
@RestController
public class UserController implements UserApi{
    @Override
    public String saveUser(User user) {
        return userService.save(user);
    }
}

通1过测试发现,使用该 Feign 客户端去调用的时候,报错:FeignException:status 404。而且发现服务端收到的参数均为null。

原因及解决:UserController无法继承UserApi的@RequestBody属性。因此,最笨的方法就是在UserController上加上@RequestBody,除此之外,另一种优雅的做法是,实现一个定制化的Processor,修改supportParameter的判断方法。判断到为Spring Cloud定义的接口,并且是自定义对象时,使用@RequestBody相同的内容转换器。

    @Override
    public boolean supportsParameter(MethodParameter parameter)
    {
        if (AnnotatedElementUtils.hasAnnotation(parameter.getContainingClass(), FeignClient.class) && isCustomizedType(parameter.getParameterType())) {
            return true;
        }
        return super.supportsParameter(parameter);
    }

五. 改造带来的收益

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

1. 经济价值
我们替换了旧的配置和注册中心,目前开发测试共有5套环境,每套环境的配置和注册中心都部署集群的话,需要部署5*2*2=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 一定会在微服务体系上走得更远,走得更好。

七. 参考资料

Nacos官网:https://nacos.io/

扩展Ribbon支持Nacos权重的三种方式:https://www.jianshu.com/p/6b6cf891ac6a

 

发布了21 篇原创文章 · 获赞 23 · 访问量 1万+

Guess you like

Origin blog.csdn.net/qq_15898739/article/details/104004188