聊聊SpringBoot使用Nacos进行服务注册发现与配置管理问题

 更新时间:2022年01月19日 11:02:01   作者:Throwable  
Nacos支持基于DNS和基于RPC的服务发现(可以作为springcloud的注册中心)、动态配置服务(可以做配置中心)、动态 DNS 服务。本文重点给大家介绍SpringBoot使用Nacos进行服务注册发现与配置管理,感兴趣的朋友一起看看吧

前提

最近由于业务发展,需要调研一套完善和主流的基础架构,进行中台化(微服务)的实施,考虑到技术栈切换到SOFAStack。既然整个体系都切换到蚂蚁金服的技术栈,那么自然考虑一些基础组件如服务注册发现、配置管理等都切换为阿里的技术栈。考虑到目前比较热的服务发现组件是Nacos,需要调研SpringBoot服务接入Nacos的可行性,为以后强制要求新服务使用SOFAStack + Nacos的技术栈进行服务开发打下基础。

Nacos简介

Nacos英文全称Dynamic Naming and Configuration Service,Na为naming/nameServer即注册中心,co为configuration即注册中心,service是指该注册/配置中心都是以服务为核心。服务在nacos是一等公民

下面的简介来源于Nacos的官网:

Nacos致力于帮助您发现、配置和管理微服务。Nacos提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。

Nacos帮助您更敏捷和容易地构建、交付和管理微服务平台。Nacos是构建以服务为中心的现代应用架构(例如微服务范式、云原生范式)的服务基础设施。

Nacos地图:

Nacos生态图:

Nacos提供的发展地图来看,它基本提供了目前微服务实施中一些核心问题:监控、服务发现注册、配置灰度发布、配置回滚等等。另外,它在生态上能够融入目前主流的K8SDockerSpringCloudConsulZookeeper等等(有点像屏蔽底层细节,只需少量配置就可以切换底层架构的实现),这一点十分重要。目前Nacos在阿里云上提供了商用版本(记得有前辈说过开源的终极目标就是商用,大概如此)。如果在项目中使用的是SpringCloud全家桶,引入Nacos以及它和SpringCloud之间的胶水层,可以完全替代Eureka组件的功能,替代和强化部分Spring Cloud Config的功能。

Nacos服务部署

Nacos-Server部署相对简单,它的发布版本见Github的Releases页面。下载完成后进行解压,Windows系下启动Nacos-Server只需进入解压后的${解压目录}\nacos\bin目录,执行startup.cmd即可,服务启动成功的结果如下:

单机模式在不修改配置的前提下直接启动,使用的是内存数据库,重启后数据会被清空。如果需要数据持久化,则需要建立数据库,具体的步骤是:

  • 建表的脚本在${解压目录}\nacos\conf目录下,见schema.sqlnacos-mysql.sql两个文件。
  • 自行通过建表的脚本建立数据库。
  • 需要指定数据库,则需要修改${解压目录}\nacos\conf\application.properties,在文件的尾部追加数据源的连接配置,下面是官方给出的多数据源的例子:
# 需要确保多个数据源的用户名和密码一致
db.num=2
db.url.0=jdbc:mysql://11.162.196.16:3306/nacos_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.url.1=jdbc:mysql://11.163.152.9:3306/nacos_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=nacos_devtest
db.password=nacos

测试获取已经注册的服务:

λ curl -X GET http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=nacos.naming.serviceName
{"hosts":[],"name":"DEFAULT_GROUP@@nacos.naming.serviceName","clusters":""}

访问http://127.0.0.1:8848/nacos即可打开Nacos-Console,初始的登录账号和密码都是nacos

更多运维部署相关的内容见文档运维指南中的一节。

SpirngBoot应用使用Nacos作为注册中心

SpringBoot应用使用Nacos作为注册中心需要引入依赖nacos-discovery-spring-boot-starter,笔者编写本文的时候(2020-01-01),该依赖的最新版本为0.2.4,对应于SpringBoot的版本为2.0.3.RELEASE,引入如下依赖:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.0.3.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.boot</groupId>
        <artifactId>nacos-discovery-spring-boot-starter</artifactId>
        <version>0.2.4</version>
    </dependency>
</dependencies>

为了方便起见,笔者把控制器、服务注册的代码都写在启动类ProvideApplication中:

@RestController
@SpringBootApplication(scanBasePackages = "club.throwable.provide")
public class ProvideApplication implements CommandLineRunner {

    @NacosInjected
    private NamingService namingService;

    @Value("${spring.application.name}")
    private String applicationName;

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

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

    @GetMapping(path = "/hello")
    public String hello(@RequestParam(name = "name") String name) {
        return String.format("%s say hello!", name);
    }

    @Override
    public void run(String... args) throws Exception {
        // 通过Naming服务注册实例到注册中心
        namingService.registerInstance(applicationName, "127.0.0.1", serverPort);
    }
}

配置文件application-provide.properties内容如下:

spring.application.name=provide-service
server.port=9092
nacos.discovery.server-addr=127.0.0.1:8848

使用spring.profiles.active=provide启动ProvideApplication,启动成功后用浏览器打开Nacos-Console

暂时可知服务的提供方已经注册成功。接着编写服务的消费方代码,引入的最小依赖和服务提供方完全一致,编写启动类ConsumeApplication如下:

@SpringBootApplication(scanBasePackages = "club.throwable.consume")
public class ConsumeApplication implements CommandLineRunner {

    @NacosInjected
    private NamingService namingService;

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

    @Override
    public void run(String... args) throws Exception {
        // 根据服务名从注册中心获取一个健康的服务实例
        Instance instance = namingService.selectOneHealthyInstance("provide-service");
        // 这里只是为了方便才新建RestTemplate实例
        RestTemplate template = new RestTemplate();
        String url = String.format("http://%s:%d/hello?name=throwable", instance.getIp(), instance.getPort());
        String result = template.getForObject(url, String.class);
        System.out.println(String.format("请求URL:%s,响应结果:%s", url, result));
    }
}

消费服务的配置文件application-consume.properties内容如下:

spring.application.name=consume-service
server.port=9091
nacos.discovery.server-addr=127.0.0.1:8848

使用spring.profiles.active=consume启动ConsumeApplicationCommandLineRunner执行完毕后控制台打印:

请求URL:http://127.0.0.1:9092/hello?name=throwable,响应结果:throwable say hello!

这种方式使用起来会感觉模板代码比较多,不够简洁。如果在SpringCloud体系中,结合Feign客户端则可以省略这些模板代码。

SpirngBoot应用使用Nacos管理配置

如果使用Nacos进行配置管理,则需要引入nacos-config-spring-boot-starter依赖,笔者编写本文的时候(2020-01-01),该依赖的最新版本为0.2.4

<dependency>
    <groupId>com.alibaba.boot</groupId>
    <artifactId>nacos-config-spring-boot-starter</artifactId>
    <version>0.2.4</version>
</dependency>

新建一个启动类ConfigApplication如下:

@RestController
@NacosPropertySource(dataId = "example", autoRefreshed = true)
@SpringBootApplication(scanBasePackages = "club.throwable.config")
public class ConfigApplication {

    @NacosValue(value = "${counter:0}", autoRefreshed = true)
    public Long counter;

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

    @GetMapping(path = "/get")
    public String get() {
        return String.format("Counter value:%d", counter);
    }
}

笔者定义了一个长整型的计数器,设置了autoRefreshed(自动刷新)为true,新建一个配置文件application-config.properties

spring.application.name=config-service
server.port=9093
nacos.config.server-addr=127.0.0.1:8848

使用spring.profiles.active=config启动ConfigApplication,启动成功后通过CURL调用下面的接口:

λ curl -X GET http://127.0.0.1:9093/get
Counter value:0

接着通过Nacos-Console添加一个配置:

点击发布按钮后再次调用接口:

λ curl -X GET http://127.0.0.1:9093/get
Counter value:10086

可见计数器的值已经动态刷新。配置项里面还有很多高级配置如:指定配置生效的服务、Beta发布等等,可以按照合适的场景进行设置。

另外,Nacos Server提供Open API从而可以使用HTTP客户端就可以轻松进行配置查询、配置更新发布等操作(目前这些API没有做鉴权,社区也有人曾提出这样会引发安全性问题,Nacos官方已经立项在后续新版本中加入鉴权的功能,目前建议屏蔽或者仅允许内网访问这些Open API):

小结

本文只是简单介绍了SpringBoot中使用Nacos作为注册中心以及进行配置管理。Nacos项目Github仓库当前(2020-01-01)的star数已经接近10000,社区也十分活跃,Issues和交流群的响应都十分迅速。加之Netflix的部分开源产品如EurekaHystrix等已经停止迭代,但Nacos还在飞速迭代,甚至已经在阿里云衍生出商业版本,所以笔者认为Nacos值得使用,在相对熟悉它的大部分特性之后会付之于生产环境中使用。

参考资料:

Nacos文档

本文的Demo项目:

spring-boot-nacos

下一篇博文会介绍一下SOFAStack中基于SOFABootSOFARpc以及Nacos等组件作为基础架构搭建一套微服务的详细过程。

到此这篇关于SpringBoot使用Nacos进行服务注册发现与配置管理的文章就介绍到这了,更多相关SpringBoot服务注册与配置管理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 在Java和PostgreSQL枚举之间转换的通用方法

    在Java和PostgreSQL枚举之间转换的通用方法

    枚举类型(enum)是一种方便的数据类型,允许我们指定一个常量列表,对象字段或数据库列可以设置为该列表中的值,在本文中,我将回顾处理Java和PostgreSQL枚举转换的通用方法,需要的朋友可以参考下
    2023-10-10
  • Spring Cloud Eureka高可用配置(踩坑记录)

    Spring Cloud Eureka高可用配置(踩坑记录)

    在进行Eureka高可用配置时,控制台一直出现“......”的错误,但是在浏览器中输入地址:peer1:8761 却是可正常运行,这篇文章主要介绍了Spring Cloud踩坑之Eureka高可用配置,需要的朋友可以参考下
    2023-08-08
  • 使用Jmeter进行http接口测试的实践

    使用Jmeter进行http接口测试的实践

    本文主要针对http接口进行测试,使用Jmeter工具实现。文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • SpringBoot集成cache缓存的实现

    SpringBoot集成cache缓存的实现

    日常开发中,缓存是解决数据库压力的一种方案,本文记录springboot中使用cache缓存。需要的朋友们下面随着小编来一起学习学习吧
    2021-06-06
  • Java源码解析LinkedList

    Java源码解析LinkedList

    今天小编就为大家分享一篇关于Java源码解析LinkedList,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • Java线程池复用线程的秘密你知道吗

    Java线程池复用线程的秘密你知道吗

    这篇文章主要为大家详细介绍了Java线程池复用线程的秘密,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望您能够多多关注

    2022-03-03
  • Java实例化一个抽象类对象的方法教程

    Java实例化一个抽象类对象的方法教程

    大家都知道抽象类无法实例化,就无法创建对象。所以下面这篇文章主要给大家介绍了关于Java实例化一个抽象类对象的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧。
    2017-12-12
  • 基于Properties类操作.properties配置文件方法总结

    基于Properties类操作.properties配置文件方法总结

    这篇文章主要介绍了Properties类操作.properties配置文件方法总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • 详解SpringBoot中@ConditionalOnClass注解的使用

    详解SpringBoot中@ConditionalOnClass注解的使用

    这篇文章主要和大家详细介绍一下springboot中@ConditionalOnClass注解的用法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2022-08-08
  • Java多线程实战之交叉打印的两种方法

    Java多线程实战之交叉打印的两种方法

    今天小编就为大家分享一篇关于Java多线程实战之交叉打印的两种方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-02-02

最新评论