前言

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

1、硬编码

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

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

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

2、外部化配置文件

Spring项目经常会在resoures目录下放很多配置文件,各个环境对应不同的配置文件,通过SVN管理

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

劣势:系统庞大时,配置文件很多,多人开发,配置格式不统一,维护麻烦;敏感配置不需要暴露给开发人员,降低风险,但开发经常要和运维沟通怎么修改配置,沟通不恰当容易引发生产事故;而且,如果应用部署在多台机器,对运维来说,修改配置也是非常头疼的事情(当然也可以引入NFS系统来解决一部分问题)

3、数据库

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

优势:可以灵活管理配置,无需重启服务

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

4、配置中心

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

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

劣势:引入组件,增加系统风险;如果是中途切换成配置中心,也会增加研发接入成本;配置中心也需要保证高可用,否则容易造成大面积影响

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

  • 做人做事,要知道自己几斤几两

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

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

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

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

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

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

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上,欢迎下载学习

参考资料

Nacos系列:基于Nacos的配置中心的更多相关文章

  1. Nacos系列:Nacos的三种部署模式

    三种部署模式 Nacos支持三种部署模式 1.单机模式:可用于测试和单机使用,生产环境切忌使用单机模式(满足不了高可用) 2.集群模式:可用于生产环境,确保高可用 3.多集群模式:可用于多数据中心场景 ...

  2. Spring Cloud Config(三):基于JDBC搭建配置中心

    1.简介 本文主要内容是基于jdbc搭建配置中心,使应用从配置中心读取配置信息并成功注册到注册中心,关于配置信息表结构仅供参考,大家可以根据具体需要进行扩展. 2.Config Server 搭建 2 ...

  3. Nacos系列:Nacos的Java SDK使用

    Maven依赖 Nacos提供完整的Java SDK,便于配置管理和服务发现及管理,以 Nacos-0.8.0 版本为例 添加Maven依赖: <dependency> <group ...

  4. Spring Cloud Config(二):基于Git搭建配置中心

    1.简述 本文选用Git作为配置仓库,新建两个环境的配置文件夹,dev 和 test,文件夹中分别存放 Config Client 端的配置文件,目录结构如下: ├ ─ ─ dev └ ─ ─ con ...

  5. Spring Boot实战系列(7)集成Consul配置中心

    本篇主要介绍了 Spring Boot 如何与 Consul 进行集成,Consul 只是服务注册的一种实现,还有其它的例如 Zookeeper.Etcd 等,服务注册发现在微服务架构中扮演这一个重要 ...

  6. Nacos - 阿里开源配置中心

    配置中心相信大家都有听过,zookeeper.apollo等等都是配置中心的代表,但大部分都是JAVA系为主的,笔者主要开发语言使用的是Golang当然也有类似于ETCD这样的组件,但是并不方便管理也 ...

  7. 学习一下 SpringCloud (六)-- 注册中心与配置中心 Nacos、网关 Gateway

    (1) 相关博文地址: 学习一下 SpringCloud (一)-- 从单体架构到微服务架构.代码拆分(maven 聚合): https://www.cnblogs.com/l-y-h/p/14105 ...

  8. 配置中心的设计-nacos vs apollo

    简介 前面我们分析了携程的 apollo(见 详解apollo的设计与使用),现在再来看看阿里的 nacos. 和 apollo 一样,nacos 也是一款配置中心,同样可以实现配置的集中管理.分环境 ...

  9. SpringCloud实战 | 第三篇:SpringCloud整合Nacos实现配置中心

    前言 随着eureka的停止更新,如果同时实现注册中心和配置中心需要SpringCloud Eureka和SpringCloud Config两个组件;配置修改刷新时需要SpringCloud Bus ...

  10. Nacos配置中心交互模型是 push 还是 pull ?你应该这么回答

    本文案例收录在 https://github.com/chengxy-nds/Springboot-Notebook 大家好,我是小富- 对于Nacos大家应该都不太陌生,出身阿里名声在外,能做动态服 ...

随机推荐

  1. python项目1:自动解压并删除压缩包

    目的:实现压缩包的自动解压及删除. 思路:获取压缩包 > 解压 > 删除压缩包 代码实现:此处代码实现前提为.py文件和压缩包在同一文件夹 # 导入需要的包 import os impor ...

  2. Linux-3.0.8 input subsystem代码阅读笔记

    先乱序记录一下阅读Linux input subsystem代码的笔记. 在input device driver的入口代码部分,需要分配并初始化input device结构,内核提供的API是inp ...

  3. WordPress数据结构分析

    WordPress仅仅用了10 个表:wp_comments, wp_links, wp_options, wp_postmeta, wp_posts, wp_term_relationships, ...

  4. NLP文本相似度

    NLP文本相似度 相似度 相似度度量:计算个体间相似程度 相似度值越小,距离越大,相似度值越大,距离越小 最常用--余弦相似度:​ 一个向量空间中两个向量夹角的余弦值作为衡量两个个体之间差异的大小 余 ...

  5. 1042.D Petya and Array 前缀 + 树状数组

    11.19.2018 1042.D Petya and ArrayNew Point: 前缀 + 树状数组 :树状数组逐个维护前缀个数 Describe: 给你一个数组,一个标记数,问你有多少区间[l ...

  6. js操作bom和dom

    Bom 概念 BOM : Browser Object Model 浏览器对象模型,描述与浏览器进行交互的方法和接 口, ECMAscript是javascript的核心,但如果要在web中使用jav ...

  7. 安装Nodejs、npm、Less

    最近学习到Bookstrap的时候需要用到less这门预处理的CSS语言.其中需要将less文件转换成css文件.记录一下,方便自己以后查找. 安装Nodejs和npm 1:到https://node ...

  8. C/C++中宏定义#pragma once与 #ifndef的区别

    为了避免同一个文件被include多次,我们可以通过以下两种方式来进行宏定义: 1. #ifndef方式2. #pragma once方式 在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两 ...

  9. Javascript高级编程学习笔记(67)—— 事件(11)HTML5事件

    DOM规范没有涵盖所有浏览器支持的所有事件 而许多浏览器出于满足用户需求,或解决特殊问题的目的,实现了一些自定义事件 HTML5列出了浏览器应该支持的所有事件,这里只讨论得到浏览器完善支持的事件(并非 ...

  10. Eclipse 中构建 Maven 项目的完整过程 - 动态 Web 项目

    进行以下步骤的前提是你已经安装好本地maven库和eclipse中的maven插件了(有的eclipse中已经集成了maven插件) 一.Maven项目的新建 1.鼠标右键---->New--- ...