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 ...
随机推荐
- CF1592F2 Alice and Recoloring 2
目前在看贪心/构造/DP 杂题选做,发现一道非常不错的结论题,具有启发意义. 先说明如下结论 结论一:如何怎么样都不会使用二和三操作 证明: 二三操作显然可以通过两次一操作达到,而其操作费用大于两次一 ...
- [ARC101C] Ribbons on Tree
神仙的容斥题与神仙的树形DP题. 首先搞一个指数级的做法:求总的.能够覆盖每一条边的方案数,通过容斥可以得到\(\text{ans}=\sum\limits_E{(-1)^{|E|}F(E)}\).其 ...
- python的包与模块
win +R d
- 安卓手机添加系统证书方法(HTTPS抓包)
目录 1. 导出证书(以Charles为例) 2. 安卓证书储存格式 3. 将导出的证书计算hash值 4. 生成系统系统预设格式证书文件 5. 上传证书 安卓7.0以后,安卓不信任用户安装的证书,所 ...
- perl 转置矩阵
这里提供一个转置矩阵的perl脚本,R语言中的t()函数同样也能实现转置 1 use strict; 2 3 open A,"$ARGV[0]"; 4 5 my %ha; 6 my ...
- Excel-数据分列的多种方法实现
2.数据->分列 (数据格式统一的精准分列)<=> 手动快捷键ctrl+E+等待 ("模糊模仿""分列)<=> 用函数实现(精准分列) 用函 ...
- 19.Happy Number-Leetcode
Write an algorithm to determine if a number is "happy". A happy number is a number defined ...
- deque、queue和stack深度探索(上)
deque是可双端扩展的双端队列,蓝色部分就是它的迭代器类,拥有四个指针,第一个cur用来指向当前元素,first指向当前buffer头部,last指向当前buffer尾部,node指向map自己当前 ...
- GO瞬间并发数控制
var wg2 sync.WaitGroup wg2.Add(nums) xc :=0 parallelNum := plt.MaxParallel var waitCount int32 = 0 f ...
- css实现项目中的加载动画
// =========================================第一个动画 <template> <!-- 这个组件用于 页面下滑到底部时 展示加载动画 -- ...