SpringBoot项目使用Nacos作为配置中心
前置条件:jdk、SpringBoot项目、Nacos、Linux服务器(可无)
具体版本:jdk11、SpringBoot 2.3.5.RELEASE、Nacos 2.0.3、Centos 6
目标:SpirngBoot项目使用Nacos作为配置中心动态管理项目配置
相关问题及解答参考本文末尾
原文首发:chenetchen.ltd,个人博客网站。
前言
使用SringBoot框架开发的项目,虽然免去了在Tomcat上的配置,可以将项目打成jar包后在服务器上发布,但是如果需要修改配置文件,需要停下项目,使用vim打开jar包修改配置文件,然后重启项目。
过程不免繁杂,而且需要启停项目,需要专业人员在服务器上操作。在之前的工作中,学习到的JMX,可以动态获取或修改参数,但是JMX的主要作用是用于监控,而不是作为一个配置,且调用JMX连接也麻烦,学习成本较大,使用JMX查看并管理参数需要使用到jconsole工具,也存在学习成本,一样需要专业人员来操作。
于是乎,回想起之前学习的分布式组件中,Nacos进入了我的选择范围
Nacos
Nacos是阿里旗下的一款开源软件,支持服务注册与发现、配置管理以及微服务管理的组件。Nacos的目标是为了取代过去常用的注册中心(Zookeeper、Eureka等),以及配置中心(Spring Cloud Config等)。Nacos集成了注册中心和配置中心的功能。
基于此,虽然是SpirngBoot项目,服务注册与发现用不上,但是可以使用Nacos配置中心的功能,对项目的配置文件进行动态管理。
SpringBoot使用Nacos
Maven配置
根据官方文档——Nacos Spring Boot 快速开始,在Spirng Boot项目的Maven中引入nacos-config-spring-boot-starter依赖
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>${latest.version}</version>
</dependency>
需要注意的是,网上对于Spring Boot项目使用的Nacos依赖是哪一个,存在错误的版本,相当一部分的帖子和博客,提到的是spring-cloud-starter-alibaba-nacos-discovery和spring-cloud-starter-alibaba-nacos-config,虽然这两个也能在Spring Boot中使用,但是配置更加繁琐。可以参考SpringBoot整合nacos实现配置中心(配置动态更新)
Nacos配置
启动Nacos
对于本文中的环境,即单个Spirng Boot非分布式集群的项目而言,Nacos需要以单机的形式启动。
在Windows下修改/nacos/bin目录下的startup.cmd脚本文件,将其中的 set MODE="cluster"修改为 set MODE="standalone",即可实现Nacos的单机启动。
配置管理
Nacos启动成功后(本文默认在测试情况下都在Windows环境下单机启动Nacos,保持默认配置),访问 localhost:8848/nacos,使用naocs/nacos登录Nacos平台。
在左侧的配置管理中点击配置列表,再点击右侧页面主体列表上方的加号按钮,添加配置,Data Id为 test,分组默认,格式选择properties,配置内容为
useLocalCache=true
发布成功后,返回。
项目配置
Nacos配置
项目配置有两种方法,一种是使用注解,在SpringBoot项目的主启动类上使用
@NacosPropertySource(dataId = "test", autoRefreshed = true)
dataId:Nacos中配置的配置ID
autoRefreshed:开启自动刷新
另一种方式是使用配置文件,因为前文中提到了Spring Boot中使用的是nacos-config-spring-boot-starter,而非Cloud中难道依赖,所以此处是无法使用bootstrap配置文件的(如要使用bootstrap配置,需要引入cloud相关的配置文件),直接在application配置文件中配置好nacos相关的配置。
nacos:
config:
type: yaml
server-addr: 127.0.0.1:8848
context-path: nacos
data-id: test
auto-refresh: true
bootstrap:
enable: true
需要注意的是,在以上配置中,有个别配置需要注意,关于此问题,参看SpringBoot2集成nacos(一)
测试代码
参看Nacos官方提供的demo,编写如下测试类(SpringBoot项目需要引入web依赖)
@Controller
public class Test {
@NacosValue(value = "${useLocalCache:false}", autoRefreshed = true)
private boolean useLocalCache;
@RequestMapping(value = "/get", method = RequestMethod.GET)
@ResponseBody
public boolean get() {
return useLocalCache;
}
}
启动项目(如果配置文件中——Nacos配置和项目配置中均未指定项目端口,且80端口被占用,需要注意添加额为项目端口配置,server.prot=xxx,配置在Nacos或application配置文件中均可)
访问/get测试,返回为true即表示SpringBoot项目正确获取Nacos中的配置。
版本问题
如果上方的基本流程一切顺利,那么恭喜你没有遇到版本问题;如果Nacos启动失败、项目启动失败、获取不到值等,那么接下来的部分应该可以解决你的问题。
SpirngBoot和Nacos Spring Boot
首先是SpringBoot的版本和Nacos的pom文件版本,此问题一般出现在项目启动失败,这是因为SpringBoot的版本和nacos-config-spring-boot-starter的版本问题。一般会出现如下错误:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'nacosConfigurationPropertiesBinder': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.alibaba.boot.nacos.config.binder.NacosBootConfigurationPropertiesBinder]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:315) ~[spring-beans-5.3.2.jar:5.3.2]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:296) ~[spring-beans-5.3.2.jar:5.3.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1356) ~[spring-beans-5.3.2.jar:5.3.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1206) ~[spring-beans-5.3.2.jar:5.3.2]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.alibaba.boot.nacos.config.binder.NacosBootConfigurationPropertiesBinder]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:225) ~[spring-beans-5.3.2.jar:5.3.2]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:117) ~[spring-beans-5.3.2.jar:5.3.2]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:311) ~[spring-beans-5.3.2.jar:5.3.2]
... 20 common frames omitted
Caused by: java.lang.NoClassDefFoundError: org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata
at com.alibaba.boot.nacos.config.binder.NacosBootConfigurationPropertiesBinder.<init>(NacosBootConfigurationPropertiesBinder.java:51) ~[nacos-config-spring-boot-autoconfigure-0.2.7.jar:0.2.7]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_181]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_181]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_181]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_181]
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:212) ~[spring-beans-5.3.2.jar:5.3.2]
... 22 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_181]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_181]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) ~[na:1.8.0_181]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_181]
... 28 common frames omitted
错误提示创建名为'nacosConfigurationPropertiesBinder'的bean失败。这是因为nacos-config-spring-boot-starter支持的SpringBoot版本比项目当前使用的版本低,而SpringBoot在2.4之后删掉了ConfigurationBeanFactoryMetadata,需要将SpringBoot的版本降级到2.3.x。
Nacos Spring Boot和JDK
是的,没错,JDK此处也插了一脚,是可能存在JDK的版本问题的。
在JDK11的的情况下,nacos-config-spring-boot-starter版本过低,项目启动不过抛出异常,但是访问测试代码时,无法获取Nacos配置中心中配置的值。
经由网友@yvioo测试,在JDK11下,使用nacos-config-spring-boot-starter版本为0.2.7及以上,可以成功获取Nacos配置中心的值(我测试的时候依旧为未成功获取),建议使用0.2.10版本。
部署项目到Linux上
经过上方的一系列测试,SpringBoot项目已经能完整的获取Nacos配置中心中值,现在,需要将环境部署到Linux服务器上使用。
Linux安装Nacos
相信网上关于在Linux上部署Nacos的教程数不胜数了,但是大部分的教程在我眼里还是不够细致,并没有提到各种各样的bug,在经由我八哥小王子的测试下,果不其然触发了各式各样的bug,为此,下文中不过多描述如何安装nacos,而是如何解决bug。
简单概述一下Linux安装Nacos,从官方下载nacos.tar.gz安装包后,解压到/usr/local目录下,便安装成功了,一切顺利的话,像Windows下修改启动模式,从集群修改为单机后,直接 ./startup.sh -m standalone即可启动Nacos了。
Java环境问题
Nacos启动失败,首先排查一下Java环境,Nacos实际上为jar包,需要使用Java来启动。
如果熟悉shell脚本,可以看到在nacos/bin目录下的startup.sh脚本中,是有获取Java环境的。
[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=$JAVA_HOME/java/jdk-11.0.11
[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/java
[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/opt/taobao/java
[ ! -e "$JAVA_HOME/bin/java" ] && unset JAVA_HOME
首先可以先使用命令 echo $JAVA_HOME 查看在/etc/profile中定义的JAVA_HOME路径,对比Nacos启动脚本中获取的JAVA_HOME路径。
JDK11问题
是的,没错,JDK11的问题又来了,在JDK11的环境下启动Nacos也可能失败,参考Linux下使用JDK11部署Nacos启动报错:Could not find or load main class,需要将启动脚本startup.sh中的如下配置进行替换
JAVA_OPT_EXT_FIX="-Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${JAVA_HOME}/lib/ext"
替换为
JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${JAVA_HOME}/lib/ext"
echo "$JAVA $JAVA_OPT_EXT_FIX ${JAVA_OPT}"
替换为
echo "$JAVA ${JAVA_OPT}"
echo "$JAVA $JAVA_OPT_EXT_FIX ${JAVA_OPT}" > ${BASE_DIR}/logs/start.out 2>&1 &
nohup "$JAVA" "$JAVA_OPT_EXT_FIX" ${JAVA_OPT} nacos.nacos >> ${BASE_DIR}/logs/start.out 2>&1 &
替换为
echo "$JAVA ${JAVA_OPT}" > ${BASE_DIR}/logs/start.out 2>&1 &
nohup $JAVA ${JAVA_OPT} nacos.nacos >> ${BASE_DIR}/logs/start.out 2>&1 &
即可成功启动。
JVM内存问题
替换完后,进行启动,此时应该已经可以成功启动了,ps -ef|grep nacos命令也能成功看到nacos的pid,但是当你访问服务器的nacos地址时,发现无法请求(默认排除了端口占用,防火墙未开放端口等问题),且重新使用ps命令查看,会发现nacos自动停止了。
这是因为nacos2.0版本,在配置文件中默认指定了jvm的大小。同样是在Nacos的启动脚本startup.sh文件中。
#===========================================================================================
# JVM Configuration
#===========================================================================================
if [[ "${MODE}" == "standalone" ]]; then
JAVA_OPT="${JAVA_OPT} -Xms512m -Xmx512m -Xmn256m"
JAVA_OPT="${JAVA_OPT} -Dnacos.standalone=true"
else
if [[ "${EMBEDDED_STORAGE}" == "embedded" ]]; then
JAVA_OPT="${JAVA_OPT} -DembeddedStorage=true"
fi
JAVA_OPT="${JAVA_OPT} -server -Xms2g -Xmx2g -Xmn1g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${BASE_DIR}/logs/java_heapdump.hprof"
JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages"
fi
if [[ "${FUNCTION_MODE}" == "config" ]]; then
JAVA_OPT="${JAVA_OPT} -Dnacos.functionMode=config"
elif [[ "${FUNCTION_MODE}" == "naming" ]]; then
JAVA_OPT="${JAVA_OPT} -Dnacos.functionMode=naming"
fi
其中的JAVA_OPT="${JAVA_OPT} -Xms512m -Xmx512m -Xmn256m"一行指定了JVM的初始容量和最大容量。
-Xms: 设定程序启动时占用内存大小
-Xmx: 设定程序运行期间最大可占用的内存大小
-Xmn:新生代大小
针对Linux系统容量手动修改即可成功启动。
JAVA_OPT="${JAVA_OPT} -Xms100m -Xmx256m -Xmn200m"
至此,SpirngBoot项目使用Nacos作为配置中心,动态管理配置完成。
参考资料
SpringBoot项目使用Nacos作为配置中心的更多相关文章
- Nacos(四):SpringCloud项目中接入Nacos作为配置中心
前言 通过前两篇文章: Nacos(二):Nacos与OpenFeign的对接使用 Nacos(三):SpringCloud项目中接入Nacos作为注册中心 相信大家已经对Nacos作为注册中心的基本 ...
- Nacos系列:基于Nacos的配置中心
前言 在看正文之前,我想请你回顾一下自己待过的公司都是怎么管理配置的,我想应该会有以下几种方式: 1.硬编码 没有什么配置不配置的,直接写在代码里面,比如使用常量类 优势:对开发友好,开发清楚地知道代 ...
- java架构之路-(微服务专题)feign的基本使用和nacos的配置中心
上次回归: 上次我们说了ribbon的基本使用,包括里面的内部算法,算法的细粒度配置,还有我们自己如何实现我们自己的算法,主要还是一些基本使用的知识,还不会使用ribbon的小伙伴可以回去看一下上一篇 ...
- nacos作为配置中心动态刷新@RefreshScope添加后取值为null的一个问题
之前springboot项目常量类如下形式: @Component @RefreshScope//nacos配置中心时添加上 public class Constants { @Value(" ...
- 程序员你是如何使用Nacos作为配置中心的?
假如你使用的是spring-cloud-alibaba微服务技术栈 单个服务独有配置文件 即去除应用程序的状态,配置统一外部化管理,方便进行水平的伸缩. 集成步骤: 假如我有一个应用app-desig ...
- 使用nacos作为配置中心统一管理配置
基础环境 引入所需依赖包 <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>s ...
- ******可用 SpringBoot 项目打包分开lib,配置和资源文件
spring-boot多模块打包后,无法找到其他模块中的类https://blog.csdn.net/Can96/article/details/96172172 关于SpringBoot项目打包没有 ...
- Nacos作为配置中心时,多个服务共用一个dataId的配置
写在前面 本文是对我之前一篇文章<Spring Cloud+nacos+Feign,实现注册中心及配置中心>的补充.此文章中简单写了如何将Nacos作为配置中心.在使用配置中心时,我们会遇 ...
- SpringCloud项目中使用Nacos作为配置中心
参考:https://blog.csdn.net/qq_33619378/article/details/96991237 Nacos-server启动 这里就不说了 新建配置 在Nacos-Serv ...
随机推荐
- Python技法1:变长和定长序列拆分
Python中的任何序列(可迭代的对象)都可以通过赋值操作进行拆分,包括但不限于元组.列表.字符串.文件.迭代器.生成器等. 元组拆分 元组拆分是最为常见的一种拆分,示例如下: p = (4, 5) ...
- 妹子始终没搞懂OAuth2.0,今天整合Spring Cloud Security 一次说明白!
大家好,我是不才陈某~ 周二发了Spring Security 系列第一篇文章,有妹子留言说看了很多文章,始终没明白OAuth2.0,这次陈某花了两天时间,整理了OAuth2.0相关的知识,结合认证授 ...
- 洛谷 P4240 - 毒瘤之神的考验(数论+复杂度平衡)
洛谷题面传送门 先扯些别的. 2021 年 7 月的某一天,我和 ycx 对话: tzc:你做过哪些名字里带"毒瘤"的题目,我做过一道名副其实的毒瘤题就叫毒瘤,是个虚树+dp yc ...
- Codeforces 796E - Exam Cheating(dp)
Codeforces 题目传送门 & 洛谷题目传送门 当被数据结构搞自闭的 tzc 信心满满地点开一道 *2400 的 dp 题时-- 却发现自己不会做?! 这足以证明蒟蒻 dp 之菜/dk/ ...
- GO 语言使用copy 拷贝切片的问题
使用copy,直接改变原片的值,而不是先创建一个副本.
- centos yum安装mongodb,php扩展
一,安装mongodb,php扩展 ? 1 [root@localhost ~]# yum install php-pecl-mongo mongodb mongodb-devel mongodb-s ...
- c/c++在线编译Output Limit Exceeded(OLE)错误
提示输出错误,有如下两个可能情况: 1. 不符合题目给出的输出格式,自己输出了多余的内容或者格式不正确 2. 输入数据的时候,未考虑到输入错误的情况 针对2,有如下的例子: 错误的情况: 1 int ...
- 云原生时代,为什么基础设施即代码(IaC)是开发者体验的核心?
作者 | 林俊(万念) 来源 |尔达 Erda 公众号 从一个小故事开始 你是一个高级开发工程师. 某天,你自信地写好了自动煮咖啡功能的代码,并在本地调试通过.代码合并入主干分支后,你准备把服务发布到 ...
- c学习 - 第八章:函数
8.7 数组作函数的参数 1.数组元素作函数的参数--值传递,单向传递 2.数组名做函数的参数--地址传送 (1)实参:数组名做实参,传递的是数组首元素的地址 (2)形参:使用同类型的数组名或指针变量 ...
- GO并发相关
锁的使用 注意要成对,重点是代码中有分支或者异常返回的情况,这种情况要在异常返回前先释放锁 mysqlInstanceLock.Lock() slaveHostSql := "show sl ...