SpringBoot项⽬使⽤Nacos作为配置中⼼
前置条件:jdk、SpringBoot项⽬、Nacos、Linux服务器(可⽆)
具体版本:jdk11、SpringBoot 2.3.5.RELEASE、Nacos 2.0.3、Centos 6
⽬标:SpirngBoot项⽬使⽤Nacos作为配置中⼼动态管理项⽬配置
相关问题及解答参考本⽂末尾
原⽂⾸发:,个⼈博客⽹站。
前⾔
使⽤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配置
根据官⽅⽂档——,在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中使⽤,但是配置更加繁琐。可以参考
Nacos配置
启动Nacos
对于本⽂中的环境,即单个Spirng Boot⾮分布式集的项⽬⽽⾔,Nacos需要以单机的形式启动。
在Windows下修改/nacos/bin⽬录下的d脚本⽂件,将其中的 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
需要注意的是,在以上配置中,有个别配置需要注意,关于此问题,参看
测试代码
参看,编写如下测试类(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 in 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.ateBeanInstance(AbstractAutowireCapableBeanFactory.java:1206) ~[spring-beans-5.3.2.jar:5.3.2]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.alibaba.fig.binder.NacosBootConfigurationPropertiesBinder]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/ 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.fig.binder.NacosBootConfigurationPropertiesBinder.<init>(NacosBootConfigurationPropertiesBinder.java:51) ~[nacos-config-spring-boot-autoconfigure-0.2.7.jar:0.2.7]
wInstance0(Native Method) ~[na:1.8.0_181]
wInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_181]
wInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_181]
at wInstance(Constructor.java:423) ~[na:1.8.0_181]
springboot框架的作用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.t.properties.ConfigurationBeanFactoryMetadata
at java.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,从官⽅下载安装包后,解压到/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也可能失败,参考,需要将启动脚本startup.sh中的如下配置进⾏替换
JAVA_OPT_EXT_FIX="-dirs=${JAVA_HOME}/jre/lib/ext:${JAVA_HOME}/lib/ext"
替换为
JAVA_OPT="${JAVA_OPT} -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作为配置中⼼,动态管理配置完成。
参考资料
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论