前言
参考资料:
《Spring Microservices in Action》
《Spring Cloud Alibaba 微服务原理与实战》
《B站 尚硅谷 SpringCloud 框架开发教程 周阳》
《Nacos 官网》
Nacos 致力于解决微服务中的统一配置、服务注册与发现等问题。它提供了一组简单易用的特性集,帮助开发者快速实现动态服务发现、服务配置、服务元数据及流量管理;
1. Nacos 基础知识
1.1 Nacos 命名方式
- 前四个字母分别为 Naming 和 Configuration 的前两个字母,最后的 s 为 Service;
1.2 Nasoc 是什么
- 一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台;
- Nacos: Dynamic Naming and Configuration Service;
- Nacos 是注册中心 + 配置中心的组合,相当于:Nacos = Eureka+Config +Bus;
1.3 Nacos 的 4 个关键特性
-
服务发现和服务健康监测:
- Nacos 支持基于 DNS 和基于 RPC(HTTP&API)的服务发现;
- Nacos 提供对服务的实时的健康检查,阻止向不健康的主机或服务实例发送请求;
- 对于复杂的云环境和网络拓扑环境中(如VPC、边缘网络等)服务的健康检查,Nacos 提供了 agent 上报和服务端主动检测两种健康检查模式;
- Nacos 还提供了统一的健康检查仪表盘,帮助用户根据健康状态管理服务的可用性及流量;
-
动态配置服务:
- Nacos 提供了一个简洁易用的 UI(控制台样例 Demo)帮助用户管理所有服务和应用的配置;
- Nacos 还提供了包括配置版本跟踪、金丝雀发布、一键回滚配置及客户端配置更新状态跟踪在内的一系列开箱即用的配置管理特性;
-
动态 DNS 服务:
- 动态 DNS 服务支持权重路由,让开发者更容易地实现中间层负载均衡、更灵活的路由策略、流量控制,以及数据中心内网的简单 DNS 解析服务;
-
服务及其元数据管理:
- Nacos 可以使开发者从微服务平台建设的视角管理数据中心的所有服务及元数据;
- 包括;管理服务的描述、生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略、服务的 SLA 及最重要的 metrics 统计数据;
1.4 Nacos 生态图
1.5 Nacos 架构图
- 服务提供者通过 VIP(Virtual IP)访问 Nacos Server 高可用集群,基于 Open API 完成服务的注册和服务查询;
- Nacos Server 本身可以支持主备模式,所以底层会采用数据一致性算法来完成从节点的数据同步;
- 服务消费者也是如此,基于 Open API 从 Nacos Server 中查询服务列表;
1.6 Nacos 支持 AP 和 CP 模式的切换
-
简单来说:
- C 是所有节点在同一时间看到的数据是一致的;而 A 的定义是所有的请求都会收到响应;
-
模式选择:
- 如果不需要存储服务级别的信息且服务实例是通过 nacos-client 注册,并能够保持心跳上报,那么就可以选择 AP 模式;
- 当前主流的服务如 Spring cloud 和 Dubbo 服务,都适用于 AP 模式,AP 模式为了服务的可能性而减弱了一致性,因此 AP 模式下只支持注册临时实例;
- 如果需要在服务级别编辑或者存储配置信息,那么 CP 是必须, K8S 服务和 DNS 服务则适用于 CP 模式;
- CP 模式下则支持注册持久化实例,此时则是以 Raft 协议为集群运行模式,该模式下注册实例之前必须先注册服务,如果服务不存在,则会返回错误;
-
切换模式:
-
curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'
;
-
1.7 Nacos 文件结构说明
- bin 目录:服务启动/停止脚本;
- conf 目录:配置文件;
- application.properties 文件:Spring Boot 项目默认的配置文件;
- cluster.conf.example:集群配置样例文件;
- nacos-mysql.sql:MySQL 数据库脚本;
- nacos-logback.xml:Nacos 日志配置文件;
- data 目录:Derby 数据库存储;
- logs 目录:日志;
- target 目录:编译打包后的文件;
1.8 Nacos 服务注册与发现的源码分析
- 由于篇幅有限,该内容放在:《微服务架构 | *3.5 Nacos 服务注册与发现的源码分析》;
2. 安装并运行 Nacos 服务器
Nacos 依赖 Java 1.8 以上环境,有两种安装方式:使用已经编译好的安装包和源码部署;由于《*3.5 Nacos 服务注册与发现的源码分析》要对 Nacos 源码进行分析,这里推荐源码部署;
这里选择的版本是 2.0.3;
2.1 安装包安装 Nacos 服务器
2.1.1 下载 Nacos
- 从官网下载 Nacos:https://github.com/alibaba/nacos/releases;
2.1.2 直接运行报错
-
下载解压后如图:
直接双击运行
startup.cmd
会报错:
org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:156)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:544)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
- 原因是 Nacos 默认以集群模式启动,我们需要单机模式,修改启动方式即可;
2.1.3 修改启动方式后启动
- 修改
startup.cmd
里第26行为standalone
:
- 保存后启动,访问
http://localhost:8848/nacos
即可;
- 默认起始密码和账号都是
nacos
;
2.2 源码部署 Nacos 服务器
由于 2.0.3 版本笔者一直部署失败,因此这里以 1.4.2 版本为例;
2.2.1 下载源码
- 访问链接:https://github.com/alibaba/nacos
- 将代码派生到自己的仓库,在 Tags 标签里选择 1.4.2 版本的,拉取 Nacos-1.4.2 源码;
-
创建 Nacos 1.4.2 分支(名字可以自己取);
由于 GitHub Http 默认拉取 default 标签下的代码,因此这里选择修改 default 为 1.4.2 标签,再拉取代码;
点击 Update;
然后在 idea 上拉取代码即可;
2.2.2 本地编译
- 源码下载后,会自动导入依赖 jar 包,有导入不成功的可以尝试手动导入,亲测有效;
- 需要使用 Maven 对源码进行编译。进入到 Nacos 源码目录,使用如下mvn命令,开始本地编译:
mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U
- 编译完成后截图如下:
2.2.3 修改配置
- 跟安装包部署一样,我们需要以单机方式启动 Nacos;
- 因此需要在启动参数中进行设置,在 JVM 的启动参数中,添加:
-Dnacos.standalone=true
2.2.4 启动 Nacos
- 找到 nacos-console 模块下的启动类 com.alibaba.nacos.Nacos 启动即可;
- 浏览器访问:http://localhost:8848/nacos
- 默认账号和密码都是 nacos;
2.2.5 启动报错
-
如果启动失败报错 找不到 entity 包,这需要编译 nacos-consistency 模块,刷新下 Maven,然后重新启动即可;
3. 使用 Nacos 管理服务提供者
使用 Nacos 构建服务提供者大致与 Zookeeper 和 Consul 相同; Zookeeper 与 Consul 的构建方式详情请见《3.3 Apache Zookeeper 注册中心》与《3.4 HashiCorp Consul 注册中心》;
3.1 引入 pom.xml 依赖文件
- 父工程的依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
- 本模块的依赖:
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
3.2 修改 application.yml 配置文件
server:
port: 9001
spring:
application:
name: nacos-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848 #配置Nacos地址
management:
endpoints:
web:
exposure:
include: '*'
3.3 在主程序类上添加注解
- @EnableDiscoveryClient:使用其他组件(Nacos、zookeeper、Consul)作为注册中心;
3.4 编写业务类
这里编写一个简单接口仅作为示例;
@RestController
public class providerController{
@Value("${server.port}")
private String serverPort;
@RequestMapping(value = "/provider/nacos")
public String providerNacos(){
return "springcloud with nacos: "+serverPort+"\t"+ UUID.randomUUID().toString();
}
}
4. 使用 Nacos 管理服务消费者
使用 Nacos 构建服务提供者大致与 Zookeeper 和 Consul 相同; Zookeeper 与 Consul 的构建方式详情请见《3.3 Apache Zookeeper 注册中心》与《3.4 HashiCorp Consul 注册中心》;
4.1 引入 pom.xml 依赖文件
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
4.2 修改 application.yml 配置文件
server:
port: 80
spring:
application:
name: nacos-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848
#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)
service-url:
nacos-user-service: http://nacos-provider
4.3 在主程序类上添加注解
- 同提供者;
- @EnableDiscoveryClient:使用其他组件(Nacos、zookeeper、Consul)作为注册中心;
4.4 编写业务类
- 由于我们使用 Ribbon + RestTemplate 的负载均衡策略,因此需要在 IoC 容器中添加一个 RestTemplate JavaBean;
- 详情请见《4.1 基于 Ribbon 的负载均衡详解》;
- 该 Bean 可以在主启动类中添加;也可以在主启动类所在包或子包的 config 包中添加,如下:
@Configuration
public class ApplicationContextBean{
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
- 我们在 controller 层开放接口给客户端,并在该接口里调用提供者的 API;
@RestController
public class ComsumerNacosController{
public static final String INVOKE_URL = "http:// nacos-provider";
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/consumer/nacos")
public String paymentInfo(){
String result = restTemplate.getForObject(INVOKE_URL+"/provider/nacos", String.class);
System.out.println("消费者调用提供者获取服务--->result:" + result);
return result;
}
}
5. Nacos 持久化配置
- 在 0.7 版本之前,在单机模式时 Nacos 使用嵌入式数据库 Derby 实现数据的存储,不方便观察数据存储的基本情况。0.7 版本增加了支持 MySQL 数据源能力;
- Derby 数据库是一种文件类型的数据库,在使用时会存在一定的局限性。比如它无法支持多用户同时操作,在数据量大、连接数多的情况下会产生大量连接的积压。所以在生产环境中,可以用 MySQL 替换;
- 在 pom.xml 里可以找到 Derby 依赖;
5.1 切换成 MySQL
- 首先在
nacos-server-2.0.3\nacos\conf
目录下找到 sql 脚本nacos-mysql.sql
;
#需要自己先创建数据库,再执行 sql 脚本;
CREATE DATABASE nacos_config;
USE nacos_config;
- 在 MySQL 里执行该脚本新建数据库;
5.2 修改配置文件
- 接着在
nacos-server-2.0.3\nacos\conf
目录下找到application.properties
配置文件,修改成 MySQL 相关; - 源码部署需要在
..\nacos\console\src\main\resources\application.properties
文件里配置;
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=123456
- 再以单机模式启动 Nacos,Nacos 所有写嵌入式数据库的数据都写到了 MySQL;
6. Nacos 的高可用部署
- 集群模式:用于生产环境,确保高可用;
- 集群部署官方文档:https://nacos.io/zh-cn/docs/cluster-mode-quick-start.html;
-
Nacos 的数据一致性算法采用的是 Raft,同样采用了该算法的中间件有 Redis Sentinel 的 Leader 选举、Etcd 等;
6.1 环境要求
- 64 bit OS Linux/UNIX/Mac,推荐 Linux 系统;
- 64bit JDK1.8 及以上;
- Maven3.2.x 及以上;
- 3 个或 3 个以上 Nacos 节点才能构成集群;
- MySQL 数据库,版本 5.6.5+;
6.2 安装包及环境准备
- 准备 3 台服务器;
- 到官方 GitHub 下载 Linux 版:https://github.com/alibaba/nacos/releases/tag/2.0.3;
- 解压文件:
unzip nacos-server-2.0.3.zip
6.3 修改集群配置
- 在 Nacos 的解压目录
nacos/conf
下,有配置文件集群的cluster.conf
文件,里面配置 ip:port,需要配置3个或3个以上节点;
cd ${NACOS_HOME}/config
cp cluster.conf.example cluster.conf
- 使用 vi 编辑器打开
cluster.config
,按 a/i/o 键可进入插入模式,输入以下内容(3 台机器都需要修改);
#ip:port
10.51.10.128:8848
10.51.10.129:8848
10.51.10.130:8848
- 然后按ESC键返回到命令模式,再按shif+:进入末行模式,输入wq敲回车(保存并退出);
- 由于 3 台机器需要彼此通信,在部署时需要防火墙对外开放 8848 端口;
6.4 初始化 MySQL
- 参考:《5. Nacos 持久化配置》,将每个 Nacos 的数据源换成 MySQL;
- 同样,3 台机器都需要配置 MySQL 数据库;
6.5 启动 Nacos 服务
- 分别进入 3 台机器的 bin 目录,执行
sh startup.sh
或者startup.cmd-m cluster
命令启动服务; - 服务启动成功之后,在
${NACOS_HOME}\logs\start.out
下可以获得如下日志,表示服务启动成功:
2020-01-2814:26:25,654INFO Nacos Log files:/data/program/nacos/1ogs/
2020-01-2014:26:25,654 INFO Nacos Conf files:/data/program/nacos/conf/
2020-01-20 14:26:25,654 INFO Nacos Data files:/data/program/nacos/data/
2020-01-20 14:26:25,654 INFO Nacos started successfully in cluster mode.
- 通过
http://$NACOS_CLUSTER_IP:8848/nacos
即可访问 Nacos 控制台;
7. 包含 Nginx 的 Nacos 高可用示例
- 即要完成上图的集群配置;
- 在《6. Nacos 的高可用部署》的基础上,还需要配置 Nginx 服务器;
7.1 [可选] 修改 startup.sh 启动配置
- 这里指在一台服务器上启动 3 个 Nacos 实例模拟集群时才需要配置;
- 比如
cluster.config
的配置如下(指一台服务器上开放三个端口模拟集群):
#ip:port
192.168.111.144:3333
192.168.111.144:4444
192.168.111.144:5555
- 目的:使 Nacos 能够接受不同的启动端口,即传递不同的端口号启动不同的 Nacos 实例;
- 在
${NACOS_HOME}\bin\startup.sh
文件里:
-
修改完后,我们可以指定不同的端口启动不同的 Nacos 实例;
7.2 配置 Nginx 负载均衡器
- 如果需要通过 Nignx 对 Nacos 实例进行负载均衡,需要以下配置;
- 修改 Nginx 的配置文件
nginx/conf/nginx.conf
;
- 按照指定启动:
7.3 测试通过 Nginx 访问 Nacos
- 需要修改服务提供者的 application.yml 文件指向 Nginx 服务器:
server:
port: 9002
spring:
application:
name: nacos-provider
cloud:
nacos:
discovery:
#配置Nacos地址
#server-addr: localhost:8848
# 换成nginx的1111端口,做集群
server-addr: 192.168.111.144:1111
management:
endpoints:
web:
exposure:
include: '*'
- 访问连接:
http://192.168.111.144:1111/nacos/#/login
; - 结果如下:
8. Dubbo 使用 Nacos 作为注册中心
- 详情请见:本系列另外一篇文章《12.1 使用 Apache Dubbo 实现远程通信》里的《6. Dubbo 使用 Nacos 作为注册中心》;