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 ...
随机推荐
- Codeforces 453E - Little Pony and Lord Tirek(二维线段树+ODT)
Codeforces 题目传送门 & 洛谷题目传送门 一道难度 *3100 的 DS,而且被我自己搞出来了! 不过我终究还是技不如人,因为这是一个 \(n\log^2n\) + 大常数的辣鸡做 ...
- intent.getSerializableExtra(转)
Activity之间通过Intent传递值,支持基本数据类型和String对象及它们的数组对象byte.byte[].char.char[].boolean.boolean[].short.short ...
- R语言与医学统计图形-【21】ggplot2标题
ggplot2绘图系统--标题 在期刊杂志中,需要设置的图形标题并不多. 除了图形标题,还有坐标轴标题(标签).图例标题.脚注等. 标题函数:ggtitle,labs 坐标轴标题函数:xlab,yla ...
- halt
halt命令用来关闭正在运行的Linux操作系统.halt命令会先检测系统的runlevel,若runlevel为0或6,则关闭系统,否则即调用shutdown来关闭系统. 语法 halt(选项) 选 ...
- Oracle-with c as (select ......) 实现多次调用子查询结果
with c as (select a.trandt,sum(a.tranam) tranam from tran a group by a.trandt ) #将子查询抽取出来,以后可以直接重 ...
- 22-reverseString-Leetcode
思路:so easy class Solution { public: string reverseString(string s) { int n = s.size(); for(int i=0;i ...
- WebRTC网页打开摄像头并录制视频
前面我们能打开本地摄像头,并且在网页上看到摄像头的预览图像. 本文我们使用MediaRecorder来录制视频.在网页上播放录制好的视频,并能提供下载功能. html 首先创建一个html界面,放上一 ...
- A Child's History of England.1
A Child's History of England, by Charles Dickens (狄更斯) CHAPTER I ANCIENT ENGLAND AND THE ROMANS If y ...
- 大数据学习day19-----spark02-------0 零碎知识点(分区,分区和分区器的区别) 1. RDD的使用(RDD的概念,特点,创建rdd的方式以及常见rdd的算子) 2.Spark中的一些重要概念
0. 零碎概念 (1) 这个有点疑惑,有可能是错误的. (2) 此处就算地址写错了也不会报错,因为此操作只是读取数据的操作(元数据),表示从此地址读取数据但并没有进行读取数据的操作 (3)分区(有时间 ...
- Web安全学习二
目录 常见漏洞攻防 SQL注入 注入分类 按技巧分类 按获取数据的方式分类 注入检测 权限提升 数据库检测 绕过技巧 CheatSheet SQL Server Payload MySQL Paylo ...