Nacos系列:基于Nacos的配置中心

前言

在看正文以前,我想请你回顾一下本身待过的公司都是怎么管理配置的,我想应该会有如下几种方式:html

一、硬编码java

没有什么配置不配置的,直接写在代码里面,好比使用常量类git

优点:对开发友好,开发清楚地知道代码须要用到什么配置github

劣势:涉及秘钥等敏感配置直接暴露给开发人员,不安全;若是想修改配置必须从新发版,比较麻烦web

二、外部化配置文件spring

Spring项目常常会在resoures目录下放不少配置文件,各个环境对应不一样的配置文件,经过SVN管理数据库

优点:配置文件外部化,支持多环境配置管理,修改配置只需重启服务,无需发版segmentfault

劣势:系统庞大时,配置文件不少,多人开发,配置格式不统一,维护麻烦;敏感配置不须要暴露给开发人员,下降风险,但开发常常要和运维沟通怎么修改配置,沟通不恰当容易引起生产事故;并且,若是应用部署在多台机器,对运维来讲,修改配置也是很是头疼的事情(固然也能够引入NFS系统来解决一部分问题)api

三、数据库安全

配置信息存储在数据库中,灵活修改

优点:能够灵活管理配置,无需重启服务

劣势:界面不友好,配置没有版本管理,一旦出现问题,回滚或定位问题都比较麻烦;此外,数据库必需要保证高可用,避免所以而形成生产故障

四、配置中心

微服务基础架构体系中的一个不可或缺的基础组件

优点:集中化管理,敏感配置可控;多版本存储,方便追溯;界面友好,修改配置一键发布;即便面对多集群也能从容应对,十分淡定

劣势:引入组件,增长系统风险;若是是中途切换成配置中心,也会增长研发接入成本;配置中心也须要保证高可用,不然容易形成大面积影响

以上几种管理配置文件的方式,我想都会有公司在用,不要由于配置中心有诸多优势,就盲目引进项目中,我以为应该遵照如下两个原则:

  • 作人作事,要知道本身几斤几两

释义:没深刻研究过的技术,就不要随便拿到公司项目中来试水啦,恐怕到时候坑够你填的,要否则就是你有信心玩得转它。

  • 杀只鸡而已,你拿牛刀来作甚?

释义:小团队小项目选择简单的配置管理方式就行了,要什么配置中心,纯属没事找事。

总而言之,咱们必须从实际出发,实事求是,选择适合本身的技术栈。

关于为何须要有配置中心,我推荐一篇文章给你看,讲得比较透彻:《微服务架构为何须要配置中心?》

另外,我以为对开发自己来讲,是宁愿本身管理本身代码的配置的,交给运维老是会有各类各样的问题,至于敏感配置,说实话,开发人员要真想作点“坏事”,那拦得住吗?可是,从公司的角度来说,把服务器的配置管理交给运维同事是符合常理的,系统须要稳定且安全地运行,这是对客户的负责,从这一方面去思考,这么作是合情合理的。

Okay,我就啰嗦到这里吧,下面正式介绍Nacos做为配置中心是怎么使用的。

Nacos 结合 Spring

添加 maven 依赖:

<dependency>
    <groupId>com.alibaba.nacos</groupId>
    <artifactId>nacos-spring-context</artifactId>
    <version>${nacos-spring-context.version}</version>
</dependency>
复制代码

使用 @EnableNacosConfig 开启 Nacos Spring 的配置管理功能

@Configuration
@EnableNacosConfig(globalProperties = @NacosProperties(serverAddr = "127.0.0.1:8848"))
@NacosPropertySource(dataId = "nacos.spring.config", autoRefreshed = true)
public class NacosConfig {
}
复制代码

其中:

@Configuration:Spring的注解,配置应用上下文
@EnableNacosConfig:Nacos的注册,启用 Nacos Spring 的配置管理服务
@NacosProperties:全局和自定义Nacos属性的统一注解
@NacosPropertySource:加载数据源
globalProperties:全局 Nacos 属性
serverAddr:Nacos Server服务器地址
dataId:配置的数据集ID
autoRefreshed:是否开启配置动态更新
复制代码

再写一个Controller类,来验证Nacos的配置管理功能,代码以下:

package com.learn.nacos;

import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.alibaba.nacos.api.exception.NacosException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping(value = "config")
public class NacosConfigController {
     @NacosInjected
     private ConfigService configService;

     @NacosValue(value = "${useLocalCache:false}", autoRefreshed = true)
     private boolean useLocalCache;

     @RequestMapping(value = "/get", method = RequestMethod.GET)
     @ResponseBody
     public boolean get() {
         return useLocalCache;
     }

     @RequestMapping(method = RequestMethod.GET)
     @ResponseBody
     public ResponseEntity<String> publish(@RequestParam String dataId, @RequestParam(defaultValue = "DEFAULT_GROUP") String group, @RequestParam String content) throws NacosException {
         boolean result = configService.publishConfig(dataId, group, content);
         if (result) {
             return new ResponseEntity<String>("Success", HttpStatus.OK);
         }
         return new ResponseEntity<String>("Fail", HttpStatus.INTERNAL_SERVER_ERROR);
     }
}
复制代码

该Controller类提供了两个HTTP接口 读取配置:http://127.0.0.1:8080/config/get 发布配置:http://127.0.0.1:8080/config?dataId=XXX&content=XXX

发布配置还能够经过 Nacos Open API:curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=XXX&group=XXX&content=XXX 发布配置,你也能够用Postman工具模拟POST请求进行配置发布,我这里主要是为了方便验证问题,采用了这种方式。

在验证以前,请先确保 Nacos Server 已经启动,Nacos Server 的安全及启动方式详见:《Nacos系列:欢迎来到Nacos的世界!》

启动Tomcat,观察Console控制台

20:50:13.646 [RMI TCP Connection(5)-127.0.0.1] WARN com.alibaba.nacos.spring.core.env.AnnotationNacosPropertySourceBuilder - There is no content for NacosPropertySource from dataId[nacos.spring.config] , groupId[DEFAULT_GROUP] , properties[{encode=${nacos.encode:UTF-8}, namespace=${nacos.namespace:}, contextPath=${nacos.context-path:}, endpoint=${nacos.endpoint:}, serverAddr=${nacos.server-addr:}, secretKey=${nacos.secret-key:}, accessKey=${nacos.access-key:}, clusterName=${nacos.cluster-name:}}].

20:50:17.825 [RMI TCP Connection(5)-127.0.0.1] INFO com.alibaba.nacos.spring.context.event.LoggingNacosConfigMetadataEventListener - Nacos Config Metadata : dataId='nacos.spring.config', groupId='DEFAULT_GROUP', beanName='nacosConfig', bean='null', beanType='class com.learn.nacos.NacosConfig', annotatedElement='null', xmlResource='null', nacosProperties='{serverAddr=127.0.0.1:8848, encode=UTF-8}', nacosPropertiesAttributes='{encode=${nacos.encode:UTF-8}, namespace=${nacos.namespace:}, contextPath=${nacos.context-path:}, endpoint=${nacos.endpoint:}, serverAddr=${nacos.server-addr:}, secretKey=${nacos.secret-key:}, accessKey=${nacos.access-key:}, clusterName=${nacos.cluster-name:}}', source='org.springframework.core.type.classreading.AnnotationMetadataReadingVisitor@66e4d430', timestamp='1550753413647'
复制代码

咱们先经过http://127.0.0.1:8080/config?dataId=nacos.spring.config&content=useLocalCache=true发布一个dataId为nacos.spring.config且配置内容为useLocalCache=true的配置集,观察Nacos控制台的变化

再经过http://127.0.0.1:8080/config/get读取配置

而后在Nacos控制台将useLocalCache的值改成false,并发布配置

再次访问http://127.0.0.1:8080/config/get

Nacos 结合 Spring Boot

添加 Starter 依赖:

<dependency>
    <groupId>com.alibaba.boot</groupId>
    <artifactId>nacos-config-spring-boot-starter</artifactId>
    <version>0.2.1</version>
</dependency>
复制代码

注意:版本 0.2.x.RELEASE 对应的是 Spring Boot 2.x 版本,版本 0.1.x.RELEASE 对应的是 Spring Boot 1.x 版本。

application.properties中添加以下配置信息:

nacos.config.server-addr=127.0.0.1:8848
复制代码

添加NacosConfigApplication启动类

@SpringBootApplication
@NacosPropertySource(dataId = "nacos.springboot.config", autoRefreshed = true)
public class NacosConfigApplication {
     public static void main(String[] args) {
         SpringApplication.run(NacosConfigApplication.class, args);
     }
}
复制代码

若是你看过个人上一篇文章:《Nacos系列:基于Nacos的注册中心》,那么你应该知道 Spring Boot 实现方式和 Spring 的没太大差异,因此我就再也不细说了,请参考个人源码示例或者官网资料学习。

这里说下我在学习过程当中遇到的一个问题,在application.properties添加配置文件的时候,不当心将nacos.config.server-addr写成了nacos.discovery.server-addr,结果启动项目时,一直报错:

ERROR 9028 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

------

APPLICATION FAILED TO START

------

Description:

client error: invalid param. null

Action:

please check your client configuration
复制代码

刚开始一直找不到缘由,后面跟着官网代码示例复核,才发现是配置问题致使的,呵呵哒,本身给本身挖坑。

后语

我挺喜欢Nacos的,既然作服务发现和管理,又能作配置管理,这二者本质没多大区别,Nacos把这二者统一块儿来,一箭双雕,我以为没什么很差,要否则你引入了Zookeeper做为注册中心,还要引入Apollo做为配置中心,无故增长学习成本。就像以前听音乐,我通常用网易云音乐就好,后面由于搞了版权的事,不得不下载了虾米和QQ音乐,我就听个歌而已,手机里装了三个APP,你说,这叫什么事儿?

示例源码

  • Nacos + Springlearn-nacos-spring-config
  • Nacos + Spring Bootlearn-nacos-springboot-config

代码已上传至码云Github上,欢迎下载学习

参考资料

相关文章
相关标签/搜索