[toc]
**推荐理由**
> 这篇博文很关键的一点是把nacos的管理分为单租户和多租户的概念,提出两种环境隔离的思路。这样把两种管理方式做了很好的理论解释,不至于在使用的时候左右为难。
# 一、前言
前景回顾:
- [Nacos(五):多环境下如何“读取”Nacos中相应环境的配置](https://www.larscheng.com/config-profile/)
- [Nacos(四):SpringCloud项目中接入Nacos作为配置中心](https://www.larscheng.com/config-service/)
现如今,在微服务体系中,一个系统往往被拆分为多个服务,每个服务都有自己的配置文件,然后每个系统往往还会准备开发环境、测试环境、正式环境
我们来说算一算,假设某系统有10个微服务,那么至少有10个配置文件吧,三个环境(dev\test\prod),那就有30个配置文件需要进行管理。
这么多的配置文件,要修改一个或者多个的时候,稍有不慎可能就会出现改错了、不生效…等等问题。
**那么如果引入Nacos作为配置中心后,如何有效的进行配置文件的管理和不同环境间的隔离区分呢?**
> 别担心,Namespace可以帮助我们进行多环境下的管理和隔离
有了上一篇文章的介绍,本文主要从以下几个方面介绍:
- Namespace是什么
- Namespace如何进行配置和服务的管理、隔离
- 创建和获取NamespaceID
- Namespace实施方案1
- Namespace实施方案2
# 二、如何进行配置和服务的管理、隔离
## Namespace
Nacos引入了命名空间(Namespace)的概念来进行`多环境配置和服务`的管理及隔离
Namespace也是官方推荐的多环境支持方案。
当我们的服务达到一定的数量,集中式的管理许多服务会十分不便,
那我们可以将这些具有相同特征或属性的服务进行分组管理,服务对应的配置也进行分组隔离
这里的`分组`就是`Namespace`的概念,将服务和配置纳入相同的Namespace进行管理
不同Namespace下的服务和配置之间就隔离开来
## 创建和获取NamespaceID
NamespaceId值是在配置文件配置时必须要填入的配置项,所以需要我们先创建Namespace和Id,步骤如下:
nacos 的控制台左边功能栏看到有一个`命名空间`的功能,点击就可以看到`新建命名空间` 的按钮
新建成功后,可以在命名空间列表中查看到你所创建的Namespace和他生成的ID值
这里只是讲解创建步骤,本文继续延用Nacos(五)中创建的`DEV、TEST`
[![img](https://img-blog.csdnimg.cn/img_convert/ae643a2f3f6efb2ffd512936aec8f476.png)](https://cdn.jsdelivr.net/gh/larscheng/myImg//blogImg/Nacos/20190723175908.png)
## Namespace实施方案1
Nacos给出了两种Namespace的实践方案
- 面向一个租户
- 面向多个租户
方案1主要说明一下面向一个租户
从一个租户(用户)的角度来看,如果有多套不同的环境,那么这个时候可以根据指定的环境来创建不同的 namespce,以此来实现多环境的隔离。
例如,你可能有dev,test和prod三个不同的环境,那么使用一套 nacos 集群可以分别建以下三个不同的 namespace。如下图所示:
[![方案1](https://img-blog.csdnimg.cn/img_convert/9998ef08a02f9eb73df3bdc10fa6a408.png)](https://cdn.jsdelivr.net/gh/larscheng/myImg//blogImg/Nacos/20190805163212.png)
这里的单租户同样也适于小型项目,或者是项目不太多时的实施方案
通过定义不同的环境,不同环境的项目在不同的Namespace下进行管理,不同环境之间通过Namespace进行隔离
当多个项目同时使用该Nacos集群时,还可以通过Group进行Namespace内的细化分组
这里以`Namespace:dev`为例,在Namespace中通过不同Group进行同一环境中不同项目的`再分类`
[![方案1内部Group分组](https://img-blog.csdnimg.cn/img_convert/059f7a35a139f73f943b6afea4db8b34.png)](https://cdn.jsdelivr.net/gh/larscheng/myImg//blogImg/Nacos/20190805163727.png)
有了以上思路,我们通过代码来实践一下
## Namespace下新建配置文件
启动Nacos-Server,进入Nacos控制台,切换到Namespace:dev界面,新建配置文件
- DataId:`nacos-namespace-one-dev.yml`
- Group:`namespace-one`
- 配置格式:`YAML`
- 配置内容:
```
nacos:
config: 项目:nacos-namespace-one,Namespace:dev
```
继续新建配置文件
- DataId:`nacos-namespace-two-dev.yml`
- Group:`namespace-two`
- 配置格式:`YAML`
- 配置内容:
```
nacos:
config: 项目:nacos-namespace-two,Namespace:dev
```
**切换到Namespace:test环境,按照dev中的创建方式,分别创建`nacos-namespace-one-test.yml`和`nacos-namespace-two-test.yml`**
> 注意检查DataId是否正确、group、配置内容与环境是否匹配
## 创建项目
在聚合工程Nacos下创建名为`nacos-namespace-one`的子项目,该工程的依赖文件和启动类的代码与[Nacos(四)](https://www.larscheng.com/config-service/)完全一致。
> 以下NamespaceId均来自创建Namespace时生成的Id,在控制台命名空间页面中可以查看
创建dev环境配置文件`bootstrap-dev.yml`
```
server:
port: 9911
spring:
application:
name: nacos-namespace-one
profiles:
active: dev
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: edbd013b-b178-44f7-8caa-e73071e49c4d
group: namespace-one
config:
server-addr: 127.0.0.1:8848
prefix: ${spring.application.name}
file-extension: yml
namespace: edbd013b-b178-44f7-8caa-e73071e49c4d
group: namespace-one
```
创建test环境配置文件`bootstrap-dev.yml`
```
server:
port: 9912
spring:
application:
name: nacos-namespace-one
profiles:
active: test
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: 0133bd1e-25c3-4985-96ed-a4e34efdea2e
group: namespace-one
config:
server-addr: 127.0.0.1:8848
prefix: ${spring.application.name}
file-extension: yml
namespace: 0133bd1e-25c3-4985-96ed-a4e34efdea2e
group: namespace-one
```
**重复以上操作,再创建一个名为`nacos-namespace-two`的子项目**
> nacos-namespace-two项目的dev和test启动端口分别设置为9921和9922,group为:namespace-two
> 记得修改`spring.application.name`、`namespace`和`group`
## 启动工程
分别启动两个项目的两个环境(四个启动类),如下图
[![两个环境都启动dev和test](https://img-blog.csdnimg.cn/img_convert/3329ce3add424ce8d6873679879b4694.png)](https://cdn.jsdelivr.net/gh/larscheng/myImg//blogImg/Nacos/20190805185416.png)
现在我们有2个项目:`nacos-namespace-one`和`nacos-namespace-two`
2个项目分别有两个不同的环境`dev`和`test`
此时观察Nacos-Server控制台如下:
[![Nacos控制台](https://img-blog.csdnimg.cn/img_convert/b5228e3e205d4b62a875edd320310263.gif)](https://cdn.jsdelivr.net/gh/larscheng/myImg//blogImg/Nacos/namespace1.gif)
尝试访问接口来获取配置信息,验证是否可以读取相应环境配置
```
访问127.0.0.1:9911/getValue,返回:项目:nacos-namespace-one,Namespace:dev
访问127.0.0.1:9912/getValue,返回:项目:nacos-namespace-one,Namespace:test
访问127.0.0.1:9921/getValue,返回:项目:nacos-namespace-two,Namespace:dev
访问127.0.0.1:9922/getValue,返回:项目:nacos-namespace-two,Namespace:test
```
通过以上实验,方案1可以达到多环境多项目下的服务、配置管理的目标
> 方案1通过Namespace来隔离不同的环境(dev\test),在具体的环境Namespace中通过Group来管理不同的项目
## Namespace实施方案2
了解了单租户的方案1,再来看看Nacos推荐的面向多租户的方案2
从多个租户(用户)的角度来看,每个租户(用户)可能会有自己的 namespace,每个租户(用户)的配置数据以及注册的服务数据都会归属到自己的 namespace 下,以此来实现多租户间的数据隔离。
例如超级管理员分配了三个租户,分别为张三、李四和王五。张三负责A项目,李四负责B项目,王五负责C项目
分配好了之后,各租户用自己的账户名和密码登录后,创建自己的命名空间。如下图所示:
[![多租户namespace](https://img-blog.csdnimg.cn/img_convert/d33037006d41fb3d9135953c10723baa.png)](https://cdn.jsdelivr.net/gh/larscheng/myImg//blogImg/Nacos/20190805194232.png)
> 方案2通过Namespace来隔离多租户之间的服务和配置,但不仅于此,他有很好的扩展性
在该方案中,Group同样也有用武之地。
**需求改变下**,公司发展迅速业务调整,张三负责A项目、B项目、C项目,李四负责D项目、E项目、F项目,王五负责G项目、H项目、I项目,
而每个项目又分了dev、test、prod三个环境,继续沿用之前的Namespace隔离租户方案,显得有些管理不便,这时候可以在NameSpace中加入Group进行项目环境分组,如图:
[![Group环境分组](https://img-blog.csdnimg.cn/img_convert/d05cf19ee02c0acc181b46e14e09bf1a.png)](https://cdn.jsdelivr.net/gh/larscheng/myImg//blogImg/Nacos/20190805193836.png)
但是当业务规模更大的时候(不考虑Nacos集群能否支持的因素),张三、李四、王五每人都负责10多个项目时,即`项目数>环境数`时,可以通过Group进行项目分组,如下图:
[![Group项目分组](https://img-blog.csdnimg.cn/img_convert/7427741c4a9298af9de04ee524564f93.png)](https://cdn.jsdelivr.net/gh/larscheng/myImg//blogImg/Nacos/20190805194131.png)
通过上面的理论分析,可以看出方案二有很好的扩展性
依旧如上,我们通过代码来实践一下方案2(Namespace隔离租户 + group环境分组)
## 场景描述
依旧使用上面的两个项目,假设现在有两个租户,张三、李四
张三负责项目:`nacos-namespace-one`, 李四负责项目:`nacos-namespace-two`,项目分别有dev和test环境
## 新建Namespace和配置文件
新建两个Namespace来隔离租户,分别为`zhangsan`、`lisi`
[![zhangsan\lisi](https://img-blog.csdnimg.cn/img_convert/a946243e001f692c83b7631f9cb2dab2.png)](https://cdn.jsdelivr.net/gh/larscheng/myImg//blogImg/Nacos/20190805195206.png)
在Namespace:zhangsan 下创建配置文件
- DataId:`nacos-namespace-one-dev.yml`
- Group:`namespace-one-dev`
- 配置格式:`YAML`
- 配置内容:
```
nacos:
config: 项目:nacos-namespace-one,Namespace:张三,环境:dev
```
继续创建test环境配置文件
- DataId:`nacos-namespace-one-test.yml`
- Group:`namespace-one-test`
- 配置格式:`YAML`
- 配置内容:
```
nacos:
config: 项目:nacos-namespace-one,Namespace:张三,环境:test
```
参照以上操作,在Namespace:lisi命名空间中创建配置文件`nacos-namespace-two-dev.yml`和`nacos-namespace-two-test.yml`
> 注意核对DataId、Group、和配置内容
## 修改项目的配置文件bootstrap.yml
修改项目nacos-namespace-one的dev配置文件`bootstrap-dev.yml`
```
server:
port: 9911
spring:
application:
name: nacos-namespace-one
profiles:
active: dev
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
# 方案2:NamespaceID\Group
namespace: e0d75068-a12c-4314-9296-3f396139d5b3
group: namespace-one-dev
config:
server-addr: 127.0.0.1:8848
prefix: ${spring.application.name}
file-extension: yml
# 方案2:NamespaceID\Group
namespace: e0d75068-a12c-4314-9296-3f396139d5b3
group: namespace-one-dev
```
修改test配置文件`bootstrap-test.yml`
```
server:
port: 9912
spring:
application:
name: nacos-namespace-one
profiles:
active: test
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
# 方案2:NamespaceID\Group
namespace: e0d75068-a12c-4314-9296-3f396139d5b3
group: namespace-one-test
config:
server-addr: 127.0.0.1:8848
prefix: ${spring.application.name}
file-extension: yml
# 方案2:NamespaceID\Group
namespace: e0d75068-a12c-4314-9296-3f396139d5b3
group: namespace-one-test
```
> 重复以上操作相应的修改项目nacos-namespace-two的dev和test配置文件
> 主要修改namespace和group属性,与命名空间lisi的ID和其下配置文件的Group对应
## 启动项目
分别启动两个项目的两个环境(四个启动类),启动成功如下图
[![两个环境都启动dev和test](https://img-blog.csdnimg.cn/img_convert/3329ce3add424ce8d6873679879b4694.png)](https://cdn.jsdelivr.net/gh/larscheng/myImg//blogImg/Nacos/20190805185416.png)
此时两个项目分别启动两个环境后,注册到Nacos上不同的Namespace下,并读取相应环境的配置,具体如下:
nacos-namespace-one
- dev: 注册到Namespace:zhangsan,读取Namespace:zhangsan下Group:namespace-one-dev的配置
- test: 注册到Namespace:zhangsan,读取Namespace:zhangsan下Group:namespace-one-test的配置
nacos-namespace-two
- dev: 注册到Namespace:lisi,读取Namespace:lisi下Group:namespace-two-dev的配置
- test: 注册到Namespace:lisi,读取Namespace:lisi下Group:namespace-two-test的配置
此时Nacos控制台如下图:
[![namespace2console](https://img-blog.csdnimg.cn/img_convert/a79b9e7395bd68c356cc85d0b521c1cb.gif)](https://cdn.jsdelivr.net/gh/larscheng/myImg//blogImg/Nacos/namespace2.gif)
ok我们来测试下各个环境的服务能否访问到对应的配置
```
访问127.0.0.1:9911/getValue,返回:项目:nacos-namespace-one,Namespace:张三,环境:dev
访问127.0.0.1:9912/getValue,返回:项目:nacos-namespace-one,Namespace:张三,环境:test
访问127.0.0.1:9921/getValue,返回:项目:nacos-namespace-two,Namespace:李四,环境:dev
访问127.0.0.1:9922/getValue,返回:项目:nacos-namespace-two,Namespace:李四,环境:test
```
通过访问服务的接口,各个服务都可以准确的读取到各自环境下的配置文件
> 方案二可以看到同样支持服务和配置的隔离分组,同时支持业务的扩展,有较好的扩展性
# 三、问题描述
但是相信大家已经发现了一个问题,当使用的Group来进行分组后,配置文件相互之间可以实现不同环境与不同项目之间的分组隔离
但是服务注册后,虽然可以通过Namespace隔离,但指定的Group分组却并没有生效,依然是`DEFAULT_GROUP`
比如方案1 所有项目启动后Nacos服务列表页如下图
[![question](https://img-blog.csdnimg.cn/img_convert/b630cdebd49cb06568c3f05c23b799ec.png)](https://cdn.jsdelivr.net/gh/larscheng/myImg//blogImg/Nacos/20190806145037.png)
这里本应该是我们自定义的分组`namespace-one`和`namespace-two`却没有生效
由此发现,配置之间是达到了相互分组隔离名但`服务列表暂时并不支持`。
> 但是不要担心,Nacos的社区极度活跃,社区的大佬们也发现了这一情况,并且在Nacos-client的源码中可以看到NameingService在加载配置文件时是有预留`Group`这一属性字段的。
所以既然Nacos提供了这一实践方案,正常使用只不过是时间问题。
# 四、总结
以上分析了Nacos对于Namespace提供的两种实践方案,同时进行了代码实验,均达到了预期的要求。
现对两种方案进行一个总结
- 单租户方案(方案1):适合小型项目,服务数量不多时,方案一完全够用
- 多租户方案(方案2):适合项目量多,有一定的团队规模,且服务数量较多时,可以相对条理清晰的管理和隔离配置及服务。
**本文源码**:https://github.com/larscheng/larscheng-learning-demo/tree/master/Nacos**
[Namespace最佳实践](https://nacos.io/zh-cn/docs/namespace-endpoint-best-practices.html)
>文章作者: LarsCheng
文章链接: https://www.larscheng.com/nacos-namespace/
版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-ND 4.0, 转载请注明来自 LarsCheng!
- 简介
- 更新说明
- 其他作品
- 第一部分 Java框架基础
- 第一章 Java基础
- 多线程实战
- 尝试一下Guava带返回值的多线程处理类ListenableFuture
- LocalDate和Date有什么区别
- JAVA8接口增强实践
- 第二章 Spring框架基础
- MVC究竟是个啥?
- @ApiImplicitParam
- 七种方式,教你在SpringBoot初始化时搞点事情!
- Spring事务状态
- maven
- Mybatis小总结
- mybatis-plus的使用
- 第三章 SpringSecurity实战
- 基于SpringSecurity+jwt的用户认证
- spring-security-oauth2
- 第四章 数据库
- mysql
- mysql授权
- mysql数据库三个关键性能指标--TPS\QPS\IOPS
- 梳理一下那些年Mysql的弱语法可能会踩的坑
- 关于Mysql的“字符串”数值的转换和使用
- 凭这一文咱把事务讲透
- Mysql性能优化
- 查询性能优化
- 不常用的一些语法
- elasticsearch
- elasticsearch文档操作
- 索引的基本操作
- java操作ElaticSearch
- elasticsearch中的各种查询
- DB与ES混合应用可能存在的问题及解决方案探索
- 使用es必须要知道的一些知识点:索引篇
- Es中的日期操作
- MongoDB
- 入门篇(了解非关系型数据库 NoSQL - MongoDB)
- 集群分片 (高级篇)
- 互联网大厂的建表规范
- 第五章 中间件
- nginx
- nginx动静分离配置,这个雷你踩过吗?
- Canal
- Sharding-jdbc
- 水平分库实践
- kafka
- 第六章 版本管理
- git
- Not currently on any branch 情况提交版本
- 第七章 IO编程
- 第八章 JVM实战调优
- jvisualvm
- jstat
- 第二部分 高级项目实战篇
- 第一章 微信开发实战
- 第二章 文件处理
- 使用EasyExcel处理导入导出
- 第三章 踩坑指南
- 邮件发送功能
- 第三部分 架构实战篇
- 第一章 架构实战原则
- 接口防止重复调用的一种方案
- 第二章 高并发缓存一致性管理办法
- 第三章 异地多活场景下的数据同步之道
- 第四章 用户体系
- 集成登录
- auth-sso的管理
- 第五章 分库分表场景
- 第六章 秒杀与高并发
- 秒杀场景
- 第七章 业务中台
- 中台的使用效果是怎样的?
- 通用黑白名单方案
- 第八章 领域驱动设计
- 第十一章 微服务实战
- Nacos多环境管理之道
- logback日志双写问题及Springboot项目正确的启动方式
- 第四部分 优雅的代码
- java中的链式编程
- 面向对象
- 开发原则
- Stream操作案例分享
- 注重性能的代码
- 第五部分 谈谈成长
- 新手入门指北
- 不可不知的调试技巧
- 构建自己的知识体系
- 我是如何做笔记的
- 有效的提问
- 谨防思维定势
- 学会与上级沟通
- 想清楚再去做
- 碎片化学习
- 第六部分 思维导图(付费)
- 技术基础篇
- 技术框架篇
- 数据存储篇
- 项目实战篇
- 第七部分 吾爱开源
- 7-1 麻雀聊天
- 项目启动
- 前端登录无请求问题解决
- websocket测试
- 7-2 ocp微服务框架
- evm框架集成
- 项目构建与集成
- zentao-center
- 二次开发:初始框架的搭建
- 二次开发:增加细分菜单、权限到应用
- 7-3 书栈网
- 项目启动
- 源码分析
- 我的书架
- 文章发布机制
- IM
- 第八章 团队管理篇
- 大厂是怎么运作的
- 第九章 码山有道
- 简历内推
- 联系我内推
- 第十章 学点前端
- Vue