微服务架构 | 服务注册发现中心/配置中心/消息总线 - [nacos]
@
§1 简介
Nacos = Naming Configration Service
在 SpringCloud alibaba 中,nacos 同时扮演了 服务注册发现中心、配置中心、消息总线等角色。
nacos 与其他注册中心特性对比
nacos | Eureka | Consul | CoreDNS | zookeeper | |
---|---|---|---|---|---|
一致性协议 | AP/CP | AP | CP | / | CP |
健康检查 | TCP/Http/Mysql/Client Beat | Client Beat | TCP/Http/gRPC/Cmd | / | Client Beat |
负载均衡 | 权重/DSL/metadata/CMDB | ribbon | fabio | RR | / |
雪崩保护 | √ | √ | × | × | × |
自动注销实例 | √ | √ | × | × | √ |
访问协议 | Http/DNS/UDP | Http | Http/DNS | DNS | TCP |
监听支持 | √ | √ | √ | × | √ |
多数据中心 | √ | √ | √ | × | × |
跨注册中心 | √ | × | √ | × | × |
springcloud 集成 | √ | √ | √ | × | × |
Dubbo 集成 | √ | × | × | × | √ |
k8s 集成 | √ | × | √ | √ | × |
§2 简单使用
§2.1 搭建 nacos-server
在官网下载
移动到指定位置并解压安装
tar -zxvf nacos-server-2.1.0.tar.gz
启动 nacos 服务
sh startup.sh -m standalone
使用 localhost:8848/nacos 本机访问
非本机访问
在非本机上,使用 ip:8848/nacos 可能连接超时,按下面步骤尝试
- 关闭防火墙
service iptables stop
- 重试访问
- 若访问成功,添加防火墙规则
vim /etc/sysconfig/iptables
然后在文件中按队形增加一行
-A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT
重启防火墙 (不用 restart是因为不成功,分开操作就可以了,原因不明)
service iptables stop
service iptables start
§2.2 作为服务注册发现中心
注意事项:
- nacos 可以同时成为 springcloud 的配置中心和服务发现中心
- 但两个职能对应的 依赖、配置文件、配置项均不同
provider / comsumer 均按如下配置
默认服务调用方式同 ribbon
依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
配置文件
在 application.yml 中
server:
port: 9001
spring:
application:
name: provider-nacos
cloud:
nacos:
discovery:
server-addr: 192.168.3.10:8848
服务启动后可见
§2.3 作为服务配置中心
依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
配置文件
在 bootstrap.yml 中
server:
port: 3377
spring:
application:
name: nacos-config-client
cloud:
nacos:
config:
server-addr: 192.168.3.10:8848
file-extension: yml
discovery:
server-addr: 192.168.3.10:8848
在 application.yml 中
spring:
profiles:
active: dev
配置文件
注意使用注解 @RefreshScope,以支持热更新
除下面示例中的 @ConfigurationProperties 外,@Value 的方式也支持
@Configuration
@ConfigurationProperties(prefix = "config")
@RefreshScope
public class ConfigTest {
String info;
/* *******************************
* 以下是 setter/getter
******************************* */
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
在 nacos 控制台添加配置
Data ID
即配置文件名,完整格式如下
${prefix}-${spring.profiles.active}.${file-extension}
- ${prefix} 默认是 ${spring.application.name} 的值,即示例中的 nacos-config-client
- ${prefix} 也可以通过 ${spring.cloud.nacos.config.prefix} 配置
- ${spring.profiles.active} 即示例中的 dev
- ${spring.profiles.active} 可以省略,省略时,前面的 - 也会省略,但强烈建议保留
- ${file-extension} 即示例中的 yml
- ${file-extension} 的值必须与 ${spring.cloud.nacos.config.file-extension} 一致,比如混淆 yml 和 yaml 会导致问题(虽然二者其实是一回事)
Group
默认是 DEFAULT_GROUP
配置格式
配置格式要和配置文件名(Data ID)的后缀相匹配
配置内容
配置内容的格式要和配置格式相匹配
§2.4 切换 nacos 的一致性协议
curl -X ==PUT== '**$NACOS_SERVER**:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'
§3 配置的层次和分组
nacos 中,如下图所示,
每个配置文件依次有三级所属层次,由概念的从大到小依次为
- namespace,命名空间,默认 public
- Group,组,默认 DEFAULT_GROUP
- Data Id,数据id(配置文件名),默认 ${prefix}-${spring.profiles.active}.${file-extension}
namespace、group 和 data id 的作用和实践(存疑)
说明
众多视频和帖子在讲解 nacos 时,多数会涉及上述三个配置层次,感谢各位大佬的分享。
但讲解的过程中鲜见对应用场景的套用,尤其在演示切换不同 namespace、group、data_id 的作用时,均以 通过切换上述三个层次已达到切换 DEV/TEST/PROD 环境 为例。
笔者学习时递归懵逼,无法区分三者在真实使用上的区别。
从 nacos 的官网(nacos.io)中,笔者未找到三者比较明确的配置指导,比如 namespace 是用来具体配置什么的(也可能是没找对地方[手动捂脸])。
由此, namespace、group 和 data id 可能不存在比较严格的使用标准,而只是配置中心划分出三个维度,用来区分各个配置文件,以方便研发人员使用。因此,在示例项目的部署场景比较简单的情况下可以十分灵活的使用它们,只要别找不到正确的配置即可(否则无法解释为啥众多教程使用“不恰当”的例子)。
但这仨层级毕竟不是按 namespace.group.data_id 的形式出现在 nacos 中的,命名空间甚至是个单独的标签页,因此肯定存在需要进行明确区分的场景。
一种在应用上可行的使用方案
下面,结合使用 apollo 的经验,尝试分享一种可行的使用方案,谬误之处请各位大佬斧正。
首先三个配置层级的关系如下 图 3-1 所示无疑
然后我们设想一个使用 nacos 的场景,并尽量假设的复杂一点
- 有一个公司,叫 company,为了防止过于灵活假设它很大(废话,小公司小项目都多余上配置中心)
- 因此,company 下有多个业务线,换句话说,好多产品,每个产品都是一个项目,P1/P2/P3
- 每个项目都有很多子项目,或者服务,P1s1/P1s2/P2s1/P2s2……
- 每个服务下有多个实例(instance)
- 每个项目在部署时,为了异地容灾都会部署在多个机房,company 本部/武汉/成都……
- 机房考虑进一步灾备,防止一套环境挂了后,所有使用此服务的业务都挂了,于是又划分了多个集群,单个个集群负责业务中的一部分
- 现在,company 搭建了一个 nacos 平台作为配置中心
上述内容如下 图 3-2 所示:
对比 图 3-1 和 图 3-2,我们可以如下使用三者:
data id
作用于 instance,它的作用是使一些实例按当前配置进行启动
一个标准的 data id 主要包含两个维度,
- ${prefix} 用来标注属于哪个服务(service),默认值是 ${spring.application.name}
- ${spring.profiles.active} 用来标注属于哪个环境,默认值是 ${spring.profiles.active}
- data id 可能存在更多维度,此时可以通过 ${spring.cloud.nacos.config.prefix} 配置
- 比如 P1s1 需要两个配置文件,可以参考 Nacos加载多个配置集 中的场景
- 一个用来配置相关环境比如 kafka 地址
- 另一个配置业务比如这个服务太小了所以不需要记录日志
namespace
作用于项目或者租户,以区分不同项目中的同名服务("那个瓜是孙红雷的,与我闰土何干!")
项目和租户在某些平台(比如 OpenStack)上是同一个概念,
每个项目加入配置中心,占用一块资源。对于配置中心来说,这个项目就是一个租户
group(主要是这里存疑)
作用于 data id 往上,namespace 往下的中间维度
组是对服务实例的分组,
- 这里的服务实例不局限于同一个服务
比如只要是部署在武汉机房的服务实例,无论属于的哪个服务只要用了 kafka 的,都配置成某个地址 - 同时一个服务的所有实例也不一定都在同一个组里
比如都是 P1s1 的实例,划分两个集群,一个处理客户1(这里的客户可能是指一个公司)的业务,另一个处理客户2
总结(顺便皮一下)
若有如下配置文件
namespace = coding dog ICU each-help platform
group = wuhan_oldest
data id = roast-publish-flow-prod.yml
这个配置文件用来配置 代码狗 ICU 互助平台(coding dog ICU each-help platform) 这个项目里,我也来喷一段(roast-publish-flow) 这个服务的 生产环境(prod)
服务部署在多个机房,现在这个配置文件是部署在 武汉(wuhan)机房 的实例用的
并且武汉的机房有多套环境,有的旧有的新,这个业务线的一部分还是跑在 最老性能最差的那套环境(_oldest) 里的,因为没办法,都 ICU 了,都上最新的环境太贵
§4 集群 & 持久化实战
在 §2 简单使用 中,完成了 单点 nacos 的搭建和使用。
但是,实际开发、生产环境中不可能按上面的姿势使用 nacos
- standalone 的结构摆明了是等着单点故障
- standalone 的 nacos 使用的内嵌的 derby 数据库,这意味着如果只是简单的部署多节点,会导致节点间的数据隔离
因此,实践上需要向下 图4-1 所示架构进行调整,官方文档 见此 和 此
nacos 的官方文档,有的前面的文章说过的事,后面的文章就不提了,所以只能一起看
下面的示例中(出 nacos 外的集群使用单点代替)
- 使用 nginx 反向代理 nacos 集群,并对外暴露虚拟 ip
- 持久化层使用 mysql
§4.1 变更 nacos 的持久化
准备 mysql 实例
略
创建 nacos 库
在 nacos 的安装目录的 config 路径下,有一个 nacos 出厂自带的建库 sql 文件,如下 图 4-1-1
使用它建立自己的 nacos 库(手动建库,sql 文件内容粘出来,运行即可) ,效果如下图
修改配置文件
配置文件即 图4-1-1 中 application.properties
按官网教程配置
效果如下,注意红框处于实际建库使用的数据库名一致
重启 nacos 验证
先单点重启 nacos,查看持久化层切换效果
sh startup.sh -m standalone
看到一个空白的 nacos
创建一个配置,在数据库中查看数据
§4.2 准备 nacos 实例
PS: 现在停止上一节启动的 nacos,如果没有,后面实践时会出现莫名其妙的问题
cluster.conf
cluster.conf 用于配置集群内各节点的 ip:port,因为是纵向集群模拟,所以示例中使用端口号区分
同时参考 §2.1 搭建 nacos-server#非本机访问 的方式配置防火墙(注意重启)
startup.sh(在这个示例中很重要)
nacos 是基于 JVM 运行的,默认的 nacos 集群模式配置 JVM 的参数为
-Xms2g -Xmx2g -Xmn1g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m
若机器性能有限,需要调整启动脚本以降低硬件需求(实际开发生产环境 务必不要这样搞)
startup.sh 的摘要和修改点如下:
#!/bin/bash
#
# 这里有一大坨代码
#
# 指令参数对应的变量
export SERVER="nacos-server"
export MODE="cluster"
export FUNCTION_MODE="all"
export MEMBER_LIST=""
export EMBEDDED_STORAGE=""
# 接受指令参数
while getopts ":m:f:s:c:p:" opt
do
case $opt in
m)
MODE=$OPTARG;;
# 依次用接受的参数给上面变量复制
?)
echo "Unknown parameter"
exit 1;;
esac
done
#===========================================================================================
# JVM Configuration,
# nacos 是基于 java 的,这里是针对 -m 参数给 jvm 配置启动参数
#===========================================================================================
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
# 抄到这里,原始的值是 -Xms2g -Xmx2g -Xmn1g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m
JAVA_OPT="${JAVA_OPT} -server -Xms512m -Xmx512m -Xmn256m -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m"
JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${BASE_DIR}/logs/java_heapdump.hprof"
JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages"
fi
#
# 这里是一大坨代码,处理其他参数和日志目录
#
# start
# 下面是实际启动 nacos 的命令,启动时用了上面的 JVM Configuration
if [[ "$JAVA_OPT_EXT_FIX" == "" ]]; then
nohup "$JAVA" ${JAVA_OPT} nacos.nacos >> ${BASE_DIR}/logs/start.out 2>&1 &
else
nohup "$JAVA" "$JAVA_OPT_EXT_FIX" ${JAVA_OPT} nacos.nacos >> ${BASE_DIR}/logs/start.out 2>&1 &
fi
准备多个nacos
将上面改好的 nacos 准备三份
application.properties
application.properties 里需要配置两个地方
- 如上节演示的变更持久化层
- 本示例需要修改默认端口,按 cluster.conf 的值变更,本示例中上面准备的三份 nacos 依次改为 8838/8848/8858
启动和验证
使用启动指令依次启动三个 nacos 实例
./shartup.sh
而后,可以再管理端看到效果
§4.3 加入 nginx 支持
上面已经实现了 nacos 的集群部署,引入 nginx 的目的是对 nacos 集群进行代理和负载均衡,实现统一的集群访问
准备 nginx
下载解压 nginx,因环境限制略,有需要的可参考 Linux安装nginx
配置 nginx.conf
vim opt/nginx-1.22.0/conf/nginx.conf
#gzip on;
# 配置上游服务器,用 nginx 进行代理和负载均衡
upstream cluster{
server 192.168.3.10:8838;
server 192.168.3.10:8848;
server 192.168.3.10:8858;
}
# 配置 nginx 的访问地址
server {
listen 8888;
server_name localhost;
...... 略
启动并验证
因环境限制,直接用 windows 版的
§4.4 项目应用
修改项目配置
调整对应项目的 application.yml
server:
port: 9001
logging:
config: classpath:logback.cfg.dev.xml
spring:
application:
name: provider-nacos
cloud:
nacos:
discovery:
server-addr: 192.168.3.7:8888 #换成 nginx 的访问地址,这里现在已经是个 nacos 集群了
management:
endpoints:
web:
exposure:
include: '*'
启动验证
本文部分内容参考自
Nacos加载多个配置集
Linux安装nginx
传送门:
微服务架构 | 组件目录