1、Nacos简介
Nacos命名的前四个字母分别取自Naming(服务注册,即服务命名管理)和Configuration(服务配置)的前两个字母,s取自Service,也就是服务的意思。它是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
简单一句话:Nacos 等价于 注册中心 + 配置中心 类似于 Eureka + Config + Bus。

Nacos官网地址:https://nacos.io/zh-cn/,可以在这里下载和查阅官方文档。
| 服务注册与服务发现框架 | CAP模型 | 控制台管理 | 社区活跃度 |
|---|---|---|---|
| Eureka | AP | 支持 | 低(2.x版本闭源) |
| Zookeeper | CP | 不支持 | 中 |
| Consul | CP | 支持 | 高 |
| Nacos | AP | 支持 | 高 |
2、安装并运行Nacos
2-1、Windows安装
通过Nacos下载地址选择合适的版本(最好选稳定版本)下载zip包,需要本地配置好了Java8和Maven环境,解压缩后,运行startup.cmd启动Nacos,浏览器访问http://localhost:8848/nacos查看管理后台,输入用户名密码(都是nacos)进入。
2-2、Linux安装
这里还是采用Docker的安装和启动方式,命令如下:
[root@bogon ~]# docker search nacos # 搜索Nacos镜像,这里只列出了第一个,我们等下也要用这个
INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED
docker.io docker.io/nacos/nacos-server This project contains a Docker image meant... 73 [OK]
[root@bogon ~]# docker pull docker.io/nacos/nacos-server:1.3.0 # 拉取1.3.0版本镜像,稍等片刻,如果不带tag时候,默认下载的最新版本
[root@bogon ~]# docker run --env MODE=standalone -d -p 8848:8848 nacos/nacos-server:1.3.0 # 后台运行Nacos,以单机模式运行
[root@bogon ~]# docker ps # 查看当前运行中的docker容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
563aac734e9e nacos/nacos-server:1.3.0 "bin/docker-startu..." 26 seconds ago Up 24 seconds 0.0.0.0:8848->8848/tcp practical_mcnulty
[root@bogon ~]# docker ps -a # 查看所有容器(不管是运行的还是没运行的)
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
563aac734e9e nacos/nacos-server:1.3.0 "bin/docker-startu..." About a minute ago Up About a minute 0.0.0.0:8848->8848/tcp practical_mcnulty
4d6cb9734993 nacos/nacos-server:1.3.0 "bin/docker-startu..." 3 minutes ago Exited (1) 2 minutes ago amazing_liskov
e4622b9228e7 rabbitmq:management "docker-entrypoint..." 7 days ago Exited (255) 23 hours ago 4369/tcp, 5671/tcp, 0.0.0.0:5672->5672/tcp, 15671/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp dreamy_cray
262532b32087 consul:1.6.1 "docker-entrypoint..." 2 weeks ago Exited (255) 7 days ago 8300-8302/tcp, 8301-8302/udp, 8600/tcp, 8600/udp, 0.0.0.0:8500->8500/tcp condescending_bartik
12121ee7ccdf zookeeper:3.4.9 "/docker-entrypoin..." 3 weeks ago Exited (143) 4 hours ago focused_mclean
3a4738e5d496 elasticsearch:6.8.7 "/usr/local/bin/do..." 7 weeks ago Exited (255) 7 weeks ago 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp xenodochial_banach
5eb892279b83 docker.io/rabbitmq:3.7.26-management "docker-entrypoint..." 7 weeks ago Exited (255) 7 weeks ago 4369/tcp, 5671/tcp, 0.0.0.0:5672->5672/tcp, 15671/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp nifty_visvesvaraya
9478537d54f6 redis "docker-entrypoint..." 7 weeks ago Exited (255) 7 weeks ago 0.0.0.0:6379->6379/tcp frosty_easley
0c492ce51767 mysql "docker-entrypoint..." 2 months ago Up 51 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp jolly_sammet
73f3714f4798 tomcat:8.5.34 "catalina.sh run" 2 months ago Exited (143) 2 months ago myTomcat
[root@bogon ~]# docker start 563aac734e9e # 如果已经有了容器,但是容器是关闭状态的,只需要使用docker start 容器id启动即可
安装完成,启动成功后,访问http://192.168.0.123:8848/nacos,输入用户名密码(都是nacos)查看管理后台。
2-2、macOS安装



在终端进入下载好nacos-server-2.0.3.zip目录:
test-MBP:~ test$
cd /Users/test/Documents/Development-Configuration
然后进行解压:
test-MBP:Development-Configuration test$
unzip nacos-server-2.0.3.zip
解压完之后,进入/nacos/bin目录:
test-MBP:Development-Configuration test$
cd /nacos/bin
启动命令(standalone代表着单机模式运行,非集群模式):
test-MBP:bin test$
sh startup.sh -m standalone
/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java -Djava.ext.dirs=/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/jre/lib/ext:/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/ext -Xms512m -Xmx512m -Xmn256m -Dnacos.standalone=true -Dnacos.member.list= -Xloggc:/Users/test/Documents/Development-Configuration/nacos/logs/nacos_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dloader.path=/Users/test/Documents/Development-Configuration/nacos/plugins/health,/Users/test/Documents/Development-Configuration/nacos/plugins/cmdb -Dnacos.home=/Users/test/Documents/Development-Configuration/nacos -jar /Users/test/Documents/Development-Configuration/nacos/target/nacos-server.jar --spring.config.additional-location=file:/Users/test/Documents/Development-Configuration/nacos/conf/ --logging.config=/Users/test/Documents/Development-Configuration/nacos/conf/nacos-logback.xml --server.max-http-header-size=524288
nacos is starting with standalone
nacos is starting,you can check the /Users/test/Documents/Development-Configuration/nacos/logs/start.out
访问http://127.0.0.1:8848/nacos,输入用户名密码(都是nacos)查看管理后台。
查看当前存活的线程数量:
ps -ef|grep nacos|grep -v grep|wc -l
关闭服务器命令:
test-MBP:bin test$
sh shutdown.sh
The nacosServer(50237) is running…
Send shutdown request to nacosServer(50237) OK
3、Nacos作为服务注册中心演示
这里,我们需要创建一个服务提供者和一个服务消费者,把他们都注册进Nacos里。
3-1、基于Nacos的服务提供者
Spring Cloud Alibaba Reference Documentation
新建cloudalibaba-provider-payment9001模块,在父pom.xml的dependencyManagement坐标的dependencies中加入spring-cloud-alibaba-dependencies依赖。
<!-- spring cloud alibaba 2.2.0.RELEASE 依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
cloudalibaba-provider-payment9001模块的pom.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- 引入父级模块名称 -->
<parent>
<artifactId>cloud2020</artifactId>
<groupId>com.king.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<!-- 子模块名称 -->
<artifactId>cloudalibaba-provider-payment9001</artifactId>
<dependencies>
<!-- 引用spring cloud alibaba nacos注册中心/服务发现依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 引用父级spring boot的依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 引用父级spring boot健康监控的依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 配置热部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- 引用父级的lombok依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
cloudalibaba-provider-payment9001模块的application.yml文件:
# 配置服务端口号
server:
port: 9001
# 配置应用信息
spring:
application:
name: nacos-payment-provider # 配置应用名称
cloud:
# nacos配置
nacos:
discovery:
server-addr: 192.168.1.78:8848 # 指明Nacos的地址
# 暴露所有监控端点
management:
endpoints:
web:
exposure:
include: '*'
cloudalibaba-provider-payment9001模块的主启动类:
package com.king.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* 微服务提供者服务端支付模块主启动类
* @EnableDiscoveryClient:表示开启DiscoveryClient服务发现
*/
@EnableDiscoveryClient
@SpringBootApplication
public class PaymentMain9001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain9001.class, args);
}
}
cloudalibaba-provider-payment9001模块的控制类:
package com.king.springcloud.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class PaymentController {
/**
* 获取本服务的端口号
*/
@Value("${server.port}")
private String serverPort;
/**
* 测试是否成功注册到nacos注册中心
* @param id
* @return
*/
@GetMapping(value = "/payment/nacos/{id}")
public String getPayment(@PathVariable("id") Integer id) {
return "Hello Nacos Discovery: " + serverPort + "\t id: " + id;
}
}
在终端启动Nacos服务,在项目里启动Provider9001模块访问http://192.168.1.78:8848/nacos,点击左侧“服务管理”-“服务列表”即可看到Provider9001服务已经注册进来了。
再访问http://192.168.1.78:9001/payment/nacos/1可见环境测试通过:
Nacos自带负载均衡,为了演示负载均衡,仿照cloudalibaba-provider-payment9001模块创建cloudalibaba-provider-payment9002模块,端口号做相应的修改即可,其他大致相同。
cloudalibaba-provider-payment9002模块的pom.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- 引入父级模块名称 -->
<parent>
<artifactId>cloud2020</artifactId>
<groupId>com.king.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<!-- 子模块名称 -->
<artifactId>cloudalibaba-provider-payment9002</artifactId>
<dependencies>
<!-- 引用spring cloud alibaba nacos注册中心/服务发现依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 引用父级spring boot的依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 引用父级spring boot健康监控的依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 配置热部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- 引用父级的lombok依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
cloudalibaba-provider-payment9002模块的application.yml文件:
# 配置服务端口号
server:
port: 9002
# 配置应用信息
spring:
application:
name: nacos-payment-provider # 配置应用名称
cloud:
# nacos配置
nacos:
discovery:
server-addr: 192.168.1.78:8848 # 指明Nacos的地址
# 暴露所有监控端点
management:
endpoints:
web:
exposure:
include: '*'
cloudalibaba-provider-payment9002模块的主启动类:
package com.king.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* 微服务提供者服务端支付模块主启动类
* @EnableDiscoveryClient:表示开启DiscoveryClient服务发现
*/
@EnableDiscoveryClient
@SpringBootApplication
public class PaymentMain9002 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain9002.class, args);
}
}
cloudalibaba-provider-payment9002模块的控制类:
package com.king.springcloud.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class PaymentController {
/**
* 获取本服务的端口号
*/
@Value("${server.port}")
private String serverPort;
/**
* 测试是否成功注册到nacos注册中心
* @param id
* @return
*/
@GetMapping(value = "/payment/nacos/{id}")
public String getPayment(@PathVariable("id") Integer id) {
return "Hello Nacos Discovery: " + serverPort + "\t id: " + id;
}
}
创建完成后,启动Nacos服务、启动Provider9001、启动Provider9002,查看Nacos管理后台,nacos-payment-provider服务名对应的实例数由1变成了2。

3-2、基于Nacos的服务消费者和负载
Spring Cloud Alibaba Reference Documentation
因为spring-cloud-starter-alibaba-nacos-discovery依赖集成了ribbon,所以能实现负载均衡。
新建cloudalibaba-consumer-nacos-order83模块,pom.xml和cloudalibaba-provider-payment9001一样。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- 引入父级模块名称 -->
<parent>
<artifactId>cloud2020</artifactId>
<groupId>com.king.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<!-- 子模块名称 -->
<artifactId>cloudalibaba-consumer-nacos-order83</artifactId>
<dependencies>
<!-- 引用spring cloud alibaba nacos注册中心/服务发现依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 引用父级spring boot的依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 引用父级spring boot健康监控的依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 配置热部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- 引用父级的lombok依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
cloudalibaba-consumer-nacos-order83模块的application.yml文件:
# 配置服务端口号
server:
port: 83
# 配置应用信息
spring:
application:
name: nacos-order-consumer # 配置应用名称
cloud:
# nacos配置
nacos:
discovery:
server-addr: 192.168.0.123:8848 # 配置Nacos地址
# 消费者将去访问的微服务地址,这里采用服务名称查找服务(成功注册进nacos的微服务提供者)
service-url:
nacos-user-service: http://nacos-payment-provider
cloudalibaba-consumer-nacos-order83模块的主启动类:
package com.king.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* 微服务消费者客户端订单模块主启动类
* @EnableDiscoveryClient:表示开启DiscoveryClient服务发现
*/
@EnableDiscoveryClient
@SpringBootApplication
public class OrderNacosMain83 {
public static void main(String[] args) {
SpringApplication.run(OrderNacosMain83.class, args);
}
}
cloudalibaba-consumer-nacos-order83模块的配置类,注意,这里一定要带上@LoadBalance注解,因为我们是通过服务名访问生产者的,现在同一个服务名称有两个生产者就没有办法具体解析到哪一个生产者中了,要通过负载均衡来分发。即使只有一个生产者,通过服务名访问,也要带上@LoadBalance注解,否则会报java.net.UnknownHostException错:
package com.king.springcloud.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* 配置类
*/
@Configuration
public class ApplicationContextConfig {
/**
* 获取RestTemplate对象
* @LoadBalanced:开启RestTemplate负载均衡,轮询方式
* @return 返回RestTemplate对象
*/
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
cloudalibaba-consumer-nacos-order83模块的控制类:
package com.king.springcloud.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
public class OrderNacosController {
@Resource
private RestTemplate restTemplate;
@Value("${service-url.nacos-user-service}")// 读取application.yml里的值
private String serverURL;
@GetMapping(value = "/consumer/payment/nacos/{id}")
public String paymentInfo(@PathVariable("id") Integer id) {
// getForObject读操作,返回JSON对象
return restTemplate.getForObject(serverURL + "/payment/nacos/" + id, String.class);
}
}
启动Nacos服务,启动两个生产者和一个消费者,通过浏览器访问http://localhost:83/consumer/payment/nacos/1,根据请求返回值,可以看到负载均衡生效了,实际上,Nacos有负载均衡能力,是因为它包含了Ribbon的jar包。

3-3、服务注册中心对比
| Nacos | Eureka | Consul | CoreDNS | Zookeeper | |
|---|---|---|---|---|---|
| 一致性检查 | CP+AP | 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 |
| 监听支持 | 支持 | 支持 | 支持 | 不支持 | 支持 |
| 多数据中心 | 支持 | 支持 | 支持 | 不支持 | 不支持 |
| 跨注册中心 | 支持 | 不支持 | 支持 | 不支持 | 不支持 |
| Spring Cloud集成 | 支持 | 支持 | 支持 | 不支持 | 不支持 |
| Dubbo集成 | 支持 | 不支持 | 不支持 | 不支持 | 支持 |
| Kubernetes(K8s)集成 | 支持 | 不支持 | 支持 | 支持 | 不支持 |
Nacos支持AP和CP的切换,命令如下:
curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'

CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。
如果不需要存储服务界别的信息且服务实例是通nacos-client注册的,并且能够保持心跳上报,那么就可以选择AP模式,当前主流服务如Spring Cloud和Dubbo服务,都适用于AP模式,AP模式为了服务的可用性(Availability)减弱了一致性(Consistency),因此AP模式下只支持注册临时实例。
如果需要在服务级别编辑或存储配置信息,必须使用CP,Kubernetes服务和DNS服务都适用于CP模式,CP模式下支持注册持久化实例,此时以Raft协议为集群运行,该模式下注册实例前必须先注册服务,如果服务不存在,会报错。
4、Nacos作为服务配置中心演示
之前使用 Spring Cloud Config 配置都是通过GitHub/Gitee进行操作,现在可以直接配置在Nacos 的 配置列表中。
4-1、基础配置
新建cloudalibaba-config-nacos-client3377模块,修改pom.xml,加入spring-cloud-starter-alibaba-nacos-config和spring-cloud-starter-alibaba-nacos-discovery依赖。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- 引入父级模块名称 -->
<parent>
<artifactId>cloud2020</artifactId>
<groupId>com.king.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<!-- 子模块名称 -->
<artifactId>cloudalibaba-config-nacos-client3377</artifactId>
<dependencies>
<!-- 引用spring cloud alibaba nacos配置中心依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 引用spring cloud alibaba nacos注册中心/服务发现依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 引用父级spring boot的依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 引用父级spring boot健康监控的依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 配置热部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- 引用父级的lombok依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
cloudalibaba-config-nacos-client3377模块添加bootstrap.yml和application.yml配置文件。这里的bootstrap.yml和application.yml和之前的Spring Cloud Config里的意思是一样的,在项目初始化的时候,会先读取bootstrap.yml,后读取application.yml,其中bootstrap.yml属于系统层面,application.yml属于应用层面。
bootstrap.yml文件:
# 配置服务端口号
server:
port: 3377
# 配置应用信息
spring:
application:
name: nacos-config-client # 配置应用名称
cloud:
# nacos配置
nacos:
discovery:
server-addr: 192.168.1.78:8848 # Nacos服务注册中心地址
config:
server-addr: 192.168.1.78:8848 # Nacos作为配置中心地址,去这个地址找后缀名是yml的配置文件
file-extension: yml #指定yml格式配置
# ${prefix}-${spring.profile.active}.${file-extension} 等价于 nacos-config-client-dev.yml
application.yml文件:
spring:
profiles:
active: dev # 表示开发环境
cloudalibaba-config-nacos-client3377模块的主启动类:
package com.king.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* nacos配置中心主启动类
* @EnableDiscoveryClient:表示开启DiscoveryClient服务发现
*/
@EnableDiscoveryClient
@SpringBootApplication
public class NacosConfigClientMain3377 {
public static void main(String[] args) {
SpringApplication.run(NacosConfigClientMain3377.class, args);
}
}
cloudalibaba-config-nacos-client3377模块的控制类:
package com.king.springcloud.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RefreshScope // 通过Spring Cloud原生注解@RefreshScope实现配置动态刷新
@RestController
public class ConfigClientController {
// ${config.info}的读取路径是Nacos配置列表文件的配置内容,@Value("${config.info}")这种写法,项目的配置文件一定要是bootstrap.yml因为权限要高于application.yml文件
@Value("${config.info}")
private String configInfo;
@GetMapping("/config/info")
public String getConfigInfo() {
return configInfo;
}
}
我们配置bootstrap.yml的目的,就是让模块启动的时候,读取bootstrap.yml的内容,去Nacos配置中心里配置列表上查找配置文件的,那么查找配置文件的规则是怎样的呢?
在 bootstrap.properties 中配置 Nacos server 的应用名:
# 配置应用信息
spring:
application:
name: nacos-config-client # 配置应用名称
说明:之所以需要配置 spring.application.name,是因为它是构成 Nacos 配置管理 dataId 字段的一部分。
从官方文档可以看到一个公式,在 Nacos Spring Cloud 中,dataId的完整格式如下:${prefix}-${spring.profile.active}.${file-extension}。下面也对这里的参数做了解释:
${prefix}:默认为spring.application.name的值,也可以通过配置项spring.cloud.nacos.config.prefix来配置${spring.profile.active}:为当前环境对应的profile,当spring.profile.active为空时,对应的连接符 - 也将不存在,dataId的拼接格式变成${prefix}.${file-extension}${file-extension}:为配置内容的数据格式,可以通过配置项spring.cloud.nacos.config.file-extension来配置,目前只支持properties和yaml类型
根据bootstrap.yml和application.yml可知,这个公式对应的值是:nacos-config-client-dev.yml,有了这个值,就可以在Nacos管理后台做配置了,这个值对应管理后台的Data Id。
进入Nacos管理后台,点击“配置管理”-“配置列表”,点击右侧的“+”,将刚才的值输入到Data Id里。Group保持DEFAULT_GROUP默认即可,配置格式选择YAML,在配置内容里输入如下内容,也就是要对应测试类Controller中的@Value("${config.info}"),最后点击“发布”即可。
config:
info: "this is nacos-config-client-dev.yml version=1"

启动Nacos服务,启动nacos-client3377模块,访问http://localhost:3377/config/info,可以读取到刚才的配置文件。
接下来,我们在Nacos上修改配置nacos-config-client-dev.yml文件,再次发布:
再次访问http://localhost:3377/config/info,发现读取到的配置信息立刻就变化了:
4-2、分组配置
在前面,我们往Nacos里添加配置文件的时候,可以发现有Data Id,Group,命名空间(NameSpace)这些参数,通过这些参数,我们可以把配置文件做分组,便于查找和归类。
其中NameSpace用于区分部署环境,Group和Data Id在逻辑上区分两个目标对象。
根据官方文档的说明,我们可以知道:
NameSpace:用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的Group或Data ID的配置。Namespace的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。Group:Nacos中的一组配置集,是组织配置的维度之一。通过一个有意义的字符串对配置集进行分组,从而区分Data ID相同的配置集。当您在Nacos上创建一个配置时,如果未填写配置分组的名称,则配置分组的名称默认采用DEFAULT_GROUP。配置分组的常见场景:不同的应用或组件使用了相同的配置类型,如database_url配置和MQ_topic配置。- Data Id:
Nacos中的某个配置集的ID。配置集ID是组织划分配置的维度之一。Data ID通常用于组织划分系统的配置集。一个系统或者应用可以包含多个配置集,每个配置集都可以被一个有意义的名称标识。
Data Id配置方案:使用默认的NameSpace和默认的Group,在Nacos管理后台创建两个不同Data Id的配置文件,通过修改application.yml里的spring.profile.active的值,即可实现读取不同配置文件。
Group配置方案:在Nacos管理后台创建一个Group,创建几个配置文件,在Group里输入刚才创建的Group的名称。要想读取指定Group下的配置文件,需要在spring.cloud.nacos.config下添加一个group属性,指定要访问哪个Group取配置文件。
NameSpace配置方案:在Nacos管理后台创建一个NameSpace,在它下面创建几个配置文件,要想读取自定义NameSpace下的配置文件,需要在spring.cloud.nacos.config下添加一个namespace属性,值为命名空间的ID。
如果把Data Id、Group、NameSpace类比成一个Java项目的话,那么NameSpace可以类比为一个模块,Group可以类比为某个模块里的一个包,Data Id可以类比为一个类。目的就是为了不同粒度的配置隔离。

5、Nacos集群和持久化配置(重要)
5-1、官网说明
在重启Nacos后,我们可以看到,之前的配置还是存在的,这是因为Nacos里内置了Derby数据库,但是,因为我们不方便操作Derby数据库,所以,改用MySQL和Nacos进行整合。
另外,正式环境,不可能只有一台Nacos服务,需要Nacos服务集群模式。如果启动了多个Nacos结点,数据存储存在一致性问题,为了解决这个问题,Nacos采用集中式存储来支持集群化部署,目前只支持MySQL存储。
Nacos支持三种部署模式
- 单机模式 - 用于测试和单机试用。
- 集群模式 - 用于生产环境,确保高可用。
- 多集群模式 - 用于多数据中心场景。
集群部署架构图
因此开源的时候推荐用户把所有服务列表放到一个SLB负载均衡下面,然后挂到一个域名下面
http://ip1:port/openAPI 直连ip模式,机器挂则需要修改ip才可以使用。
http://SLB:port/openAPI 挂载SLB模式(内网SLB,不可暴露到公网,以免带来安全风险),直连SLB即可,下面挂server真实ip,可读性不好。
http://nacos.com:port/openAPI 域名 + SLB模式(内网SLB,不可暴露到公网,以免带来安全风险),可读性好,而且换ip方便,推荐模式
我们先对单机支持MySQL数据库,具体操作步骤:
- 安装
MySQL数据库,版本:5.6.5+ - 使用数据库初始化文件初始化
MySQL数据库,配置文件的内容不要修改 - 修改
Nacos的conf/application.properties配置文件,增加MySQL数据源配置支持
5-2、Nacos持久化配置解释
Nacos默认自带的是嵌入式数据库derby:https://github.com/alibaba/nacos/blob/develop/config/pom.xml
derby到mysql切换配置步骤:
因为配置Nacos集群,数据存储存在一致性问题,要高可用,所以Nacos采用集中式存储来支持集群化部署,目前只支持MySQL存储。
- 在
nacos文件夹目录下找到/Users/test/Documents/Development-Configuration/nacos/conf/nacos-mysql.sql脚本。 - 在
Navicat Premium下新建一个nacos_config数据库,然后再执行nacos-mysql.sql脚本,创建数据库表。
- 再来到
nacos文件夹目录下找到/Users/leiliang/Documents/Development-Configuration/nacos/conf/application.properties文件进行修改数据源配置,修改前先将它复制一份出来作为备份文件.bk。

- 启动Nacos,可以看到是个全新的空记录界面,以前是记录进derby。

5-3、Linux版Nacos+MySQL生产环境配置
5-3-1、Linux版
64 bit OS Linux/Unix/Mac,推荐使用Linux系统。Linux的下载安装启动,和Windows上类似,去官网下载即可,Linux需要下载*.tar.gz文件,下载后解压,在bin文件夹下可以看到startup.sh,启动即可。这里,这里继续使用Docker进行操作。
为了演示集群搭建,我们需要1个Nginx,3个Nacos注册中心,1个MySQL。使用Docker安装Nginx并启动。
[root@bogon ~]# docker pull nginx:stable
Trying to pull repository docker.io/library/nginx ...
stable: Pulling from docker.io/library/nginx
8559a31e96f4: Already exists
9a38be3aab21: Pull complete
522e5edd83fa: Pull complete
2ccf5a90baa6: Pull complete
Digest: sha256:159aedcc6acb8147c524ec2d11f02112bc21f9e8eb33e328fb7c04b05fc44e1c
Status: Downloaded newer image for docker.io/nginx:stable
[root@bogon ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/rabbitmq management 95bc78c8d15d 10 days ago 187 MB
docker.io/nginx stable 9fc56f7e4c11 2 weeks ago 132 MB
docker.io/mysql 5.7 9cfcce23593a 2 weeks ago 448 MB
docker.io/nacos/nacos-server 1.3.0 d1f1facebfbc 3 weeks ago 756 MB
docker.io/rabbitmq 3.7.26-management d2d45254c99b 7 weeks ago 180 MB
docker.io/redis latest f9b990972689 8 weeks ago 104 MB
docker.io/mysql latest 0c27e8e5fcfa 2 months ago 546 MB
docker.io/elasticsearch 6.8.7 9cdc9986c313 4 months ago 880 MB
docker.io/consul 1.6.1 48b314e920d6 9 months ago 116 MB
docker.io/tomcat 8.5.34 ca9e2fccef98 20 months ago 463 MB
docker.io/zookeeper 3.4.9 3b83d9104a4c 3 years ago 129 MB
[root@bogon ~]# docker run -d -p 80:80 nginx:stable
e950da524e2aa17716f435fe5e745978b4ea36e7fd53a6506efcbed2f7946c7a
[root@bogon ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e950da524e2a nginx:stable "nginx -g 'daemon ..." 3 seconds ago Up 2 seconds 0.0.0.0:80->80/tcp festive_booth
fe0f363d0c89 mysql:5.7 "docker-entrypoint..." About an hour ago Up About an hour 0.0.0.0:3306->3306/tcp, 33060/tcp hungry_colden
563aac734e9e nacos/nacos-server:1.3.0 "bin/docker-startu..." 2 hours ago Up 52 minutes 0.0.0.0:8848->8848/tcp practical_mcnulty
[root@bogon ~]#
通过浏览器访问http://192.168.1.78:80,如果能看到Welcome to nginx!说明Nginx启动成功。Nginx先放到一边过会再做配置,先搭建Nacos集群。
这里使用的是nacos/nacos-server:1.3.0的镜像,在一台机器上通过Docker镜像的方式,部署了3台Nacos,通过端口号作为区分,虚拟机分配了4G内存(勉强够用,小了恐怕启动不起来),下面开始吧:
docker pull nacos/nacos-server:1.3.0 # 拉取nacos/nacos-server:1.3.0镜像,静静等待即可
# 输入以下命令,搭建集群
docker run -d \
-e MODE=cluster \
-e NACOS_APPLICATION_PORT=3333 \
-e NACOS_SERVERS=192.168.1.78:3333,1192.168.1.78:4444,192.168.1.78:5555 \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=192.168.1.78 \
-e MYSQL_SERVICE_PORT=3306 \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=root \
-e MYSQL_SERVICE_DB_NAME=nacos_config \
-e NACOS_SERVER_IP=192.168.1.78 \
-p 3333:3333 \
--name nacos3333 \
nacos/nacos-server:1.3.0
docker run -d \
-e MODE=cluster \
-e NACOS_APPLICATION_PORT=4444 \
-e NACOS_SERVERS=192.168.1.78:3333,192.168.1.78:4444,192.168.1.78:5555 \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=192.168.1.78 \
-e MYSQL_SERVICE_PORT=3306 \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=root \
-e MYSQL_SERVICE_DB_NAME=nacos_config \
-e NACOS_SERVER_IP=192.168.1.78 \
-p 4444:4444 \
--name nacos4444 \
nacos/nacos-server:1.3.0
docker run -d \
-e MODE=cluster \
-e NACOS_APPLICATION_PORT=5555 \
-e NACOS_SERVERS=192.168.1.78:3333,192.168.1.78:4444,192.168.1.78:5555 \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=192.168.1.78 \
-e MYSQL_SERVICE_PORT=3306 \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=root \
-e MYSQL_SERVICE_DB_NAME=nacos_config \
-e NACOS_SERVER_IP=192.168.1.78 \
-p 5555:5555 \
--name nacos5555 \
nacos/nacos-server:1.3.0
拿一个出来简单说说配置吧。
docker run -d \ # -d表示是后台运行
-e MODE=cluster \ # 以集群模式运行
-e NACOS_APPLICATION_PORT=3333 \ # 这台Nacos服务的port是3333
-e NACOS_SERVERS=192.168.1.78:3333,192.168.1.78:4444,192.168.1.78:5555 \ # Nacos集群的所有机器的信息
-e SPRING_DATASOURCE_PLATFORM=mysql \ # 使用外置MySQL存储配置信息
-e MYSQL_SERVICE_HOST=192.168.1.78 \ # 外置MySQL的IP
-e MYSQL_SERVICE_PORT=3306 \ # 外置MySQL的port
-e MYSQL_SERVICE_USER=root \ # 外置MySQL的用户名
-e MYSQL_SERVICE_PASSWORD=root \ # 外置MySQL的密码
-e MYSQL_SERVICE_DB_NAME=nacos_config \ # 外置MySQL的数据库,也就是Nacos的配置文件要存储得到哪个数据库,这个在单机版Nacos使用外置数据库时候介绍过
-e NACOS_SERVER_IP=192.168.1.78 \ # 这台Nacos服务的IP
-p 3333:3333 \ # 容器外部端口映射
--name nacos3333 \ # 给容器起个名字吧
nacos/nacos-server:1.3.0 # 运行哪个镜像
先说下我碰到的坑,从官方文档找参数,Nacos的port对应的是NACOS_SERVER_PORT,那就照着写呗,写上之后,3台启动呗,启动后,使用命令docker logs -f容器id查看启动日志,3台Nacos看到的都是Nacos started successfully in cluster mode. use external storage,表示启动成功了,那就访问访问呗,结果,提示“无法访问此网站,拒绝了我们的连接请求”,这就很尴尬,肯定是哪里还有问题。进入其中某一台机器,查看conf/naming-raft.log日志,提示的是no leader is available now!,也就是这个集群没有leader,奇了怪了,3台机器都正常启动,正常情况下,要选出一个leader呀。
突然发现了文档上的一个问题,MYSQL_DATABASE_NUM给的默认值是2,和之前conf/application.properties里的${MYSQL_DATABASE_NUM:1}默认值是1不符呀?哪里错了?翻了翻GitHub,找到了答案:移除数据库主从镜像配置。再看官方文档,里面还有MYSQL_MASTER_SERVICE_HOST、MYSQL_SLAVE_SERVICE_HOST等字眼。突然意识到了一个问题:文档很可能没有更新。
查看bin/docker-startup.sh和conf/application.properties这两个文件,因为我们通过-e指定的参数,大多数都用在这里了,很快我发现了conf/application.properties里的{NACOS_APPLICATION_PORT:8848},似曾相识啊!和NACOS_SERVER_PORT确实有点像,坑点就在这里:对于nacos/nacos-server:1.3.0镜像,自定义Nacos端口号的时候,不要使用NACOS_SERVER_PORT,要使用NACOS_APPLICATION_PORT!因为conf/application.properties里写了。
在看bin/docker-startup.sh的时候,我发现了这么一段,不懂Bash,但是大致能看懂一些,就是遍历${NACOS_SERVERS}的值,把它们输出到$CLUSTER_CONF文件里。
function print_servers(){
if [[ ! -d "${PLUGINS_DIR}" ]]; then
echo "" > "$CLUSTER_CONF"
for server in ${NACOS_SERVERS}; do
echo "$server" >> "$CLUSTER_CONF"
done
else
bash $PLUGINS_DIR/plugin.sh
sleep 30
fi
}
看看这个配置文件里写了什么,这就有意思了,打开配置文件cluster.conf一看,里面竟然有4行ip:port值,除了我定义的3333,4444,5555端口之外,还有一个8848端口,这是怎么冒出来的?又一次验证了我对端口配置的怀疑,自定义端口可能没生效,有的服务可能走了默认端口。
抱着试一试的想法,把-e参数里的NACOS_SERVER_PORT改成了NACOS_APPLICATION_PORT,启动3台机器容器,访问http://192.168.1.78:3333/nacos/、http://192.168.1.78:4444/nacos/、http://192.168.1.78:5555/nacos/都可以正常访问了,和刚才相比,向成功迈进了一步。再点击“集群管理”-“结点列表”查看结点,集群搭建成功了!

上面这种方式搭建Nacos集群有点麻烦,另外介绍一种简单点的方式:使用docker-compose运行Nacos集群,下面开始操作:
使用命令docker-compose -v查看本机是否安装过docker-compose,如果没有安装,可以参考这里进行安装。
[root@localhost ~]# sudo curl -L "https://github.com/docker/compose/releases/download/1.26.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose # 下载docker-compose
……
[root@localhost ~]# sudo chmod +x /usr/local/bin/docker-compose # 给docker-compose加运行权限
[root@localhost ~]# docker-compose -v # 验证docker-compose是否安装成功
docker-compose version 1.26.0, build d4451659
这里还要用到git,如果没有git的还要安装下git才行。
[root@localhost ~]# git --version # 验证是否安装git
git version 1.8.3.1
[root@localhost ~]# yum install -y git # 如果没有安装git,使用这个命令安装git
……
[root@localhost ~]# git clone https://github.com/nacos-group/nacos-docker.git # 下载nacos-docker
很快,nacos-docker下载完成了,主要关注env和example文件夹。env里是一些环境变量,example是运行实例的例子,先把相关的命令列出来,在运行(在nacos-docker文件夹下执行命令)之前,需要查看下*.yaml里到底写的什么,是否需要根据自己的情况做修改呢?
[root@localhost ~]# docker-compose -f example/standalone-derby.yaml up # 使用Derby作为数据源,单机模式启动
[root@localhost ~]# docker-compose -f example/standalone-mysql-5.7.yaml up # 使用mysql-5.7作为数据源,单机模式启动
[root@localhost ~]# docker-compose -f example/standalone-mysql-8.yaml up # 使用mysql-8作为数据源,单机模式启动
[root@localhost ~]# docker-compose -f example/cluster-hostname.yaml up # 使用mysql5.7作为数据源,集群模式启动
这里只说集群模式了(cluster-hostname.yaml),集群模式看懂了,单机就不在话下了。
version: "3"
services:
nacos1:
hostname: nacos1
container_name: nacos1 # 容器名称
image: nacos/nacos-server:latest # 容器使用的镜像
volumes:
- ./cluster-logs/nacos1:/home/nacos/logs
- ./init.d/custom.properties:/home/nacos/init.d/custom.properties
ports: # 端口映射
- "8848:8848"
- "9555:9555"
env_file: # nacos环境变量
- ../env/nacos-hostname.env
restart: always # 开机自启
depends_on: # 数据源使用的是mysql
- mysql
nacos2:
hostname: nacos2
image: nacos/nacos-server:latest
container_name: nacos2
volumes:
- ./cluster-logs/nacos2:/home/nacos/logs
- ./init.d/custom.properties:/home/nacos/init.d/custom.properties
ports:
- "8849:8848"
env_file:
- ../env/nacos-hostname.env
restart: always
depends_on:
- mysql
nacos3:
hostname: nacos3
image: nacos/nacos-server:latest
container_name: nacos3
volumes:
- ./cluster-logs/nacos3:/home/nacos/logs
- ./init.d/custom.properties:/home/nacos/init.d/custom.properties
ports:
- "8850:8848"
env_file:
- ../env/nacos-hostname.env
restart: always
depends_on:
- mysql
mysql:
container_name: mysql
image: nacos/nacos-mysql:5.7 # 使用的mysql版本号
env_file:
- ../env/mysql.env # mysql环境变量
volumes:
- ./mysql:/var/lib/mysql
ports: # 端口映射
- "3306:3306"
如果虚拟机内存足够大(大于等于4G),那么可以直接运行上面的命令,否则,需要在nacos-hostname.env里添加jvm参数后,再使用上面的命令启动(配置完参数后实测,3台Nacos+1台mysql刚刚跑起来已经2.25G内存了,如果不配参数,4G内存接近吃满)。
#jvm
JVM_XMS=256m
JVM_XMX=256m
JVM_XMN=256m
启动的时候,报了一个错:chown: cannot read directory '/var/lib/mysql/': Permission denied,这是因为CentOS7默认开启了selinux安全模块,使用命令:su -c "setenforce 0"临时关闭selinux模块再启动,等待拉取镜像以及初始化之后,通过浏览器就可以访问了,放一个效果图。
既然Nacos集群搭建好了,下面看一下Nginx的配置。
[root@bogon ~]# docker exec -it festive_booth bash # 进入Nginx容器,festive_booth是docker ps命令中nginx的NAMES字段值
root@e950da524e2a:/# cd /etc/nginx/ # 进入/etc/nginx目录
root@e950da524e2a:/etc/nginx# ls -l # 查看目录下的文件
total 36
drwxr-xr-x. 1 root root 26 Jun 9 16:58 conf.d
-rw-r--r--. 1 root root 1007 Apr 21 12:43 fastcgi_params
-rw-r--r--. 1 root root 2837 Apr 21 12:43 koi-utf
-rw-r--r--. 1 root root 2223 Apr 21 12:43 koi-win
-rw-r--r--. 1 root root 5231 Apr 21 12:43 mime.types
lrwxrwxrwx. 1 root root 22 Apr 21 12:43 modules -> /usr/lib/nginx/modules
-rw-r--r--. 1 root root 643 Apr 21 12:43 nginx.conf
-rw-r--r--. 1 root root 636 Apr 21 12:43 scgi_params
-rw-r--r--. 1 root root 664 Apr 21 12:43 uwsgi_params
-rw-r--r--. 1 root root 3610 Apr 21 12:43 win-utf
root@e950da524e2a:/etc/nginx# cat nginx.conf # 查看nginx.conf的内容
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
nginx.conf就是nginx的主配置文件,注意最后一行有一个include /etc/nginx/conf.d/*.conf;的语句,它的意思是:加载配置文件的时候,把/etc/nginx/conf.d下的*.conf文件包括进来,我们看看/etc/nginx/conf.d下有什么文件,发现另一个default.conf。
root@e950da524e2a:/etc/nginx# cd /etc/nginx/conf.d/
root@e950da524e2a:/etc/nginx/conf.d# ls -l
total 4
-rw-r--r--. 1 root root 1114 Jun 9 16:58 default.conf
root@e950da524e2a:/etc/nginx/conf.d# cat default.conf
server {
listen 80;
listen [::]:80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
当我尝试修改这个配置文件的时候,发现vi和vim命令无法使用,只能采用别的方法:挂载外部配置文件以替代docker容器内的配置文件。
在/usr/下创建一个docker-nginx的文件夹,在里面添加一个nginx.conf配置文件,主要关注点在upstream结点上,内容如下:
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
upstream cluster {
server 192.168.1.78:3333;
server 192.168.1.78:4444;
server 192.168.1.78:5555;
}
server {
listen 80;
listen [::]:80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
#root /usr/share/nginx/html;
#index index.html index.htm;
proxy_pass http://cluster;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}
使用docker stop 容器id命令,把之前的容器停掉,docker rm 容器id把之前的容器删除,以挂载外置配置文件方式重新运行一个容器,启动命令:docker run -d -p 80:80 -v /usr/docker-nginx/nginx.conf:/etc/nginx/nginx.conf nginx:stable。
浏览器访问:http://192.168.1.78/nacos,根据Nginx的负载均衡规则, 可以正常访问到某台Nacos,登陆进去即可,一切顺利!
最后一步,我们将cloud-alibaba-provider-payment9002服务注册进Nacos集群。修改application.yml配置文件的server-addr的值,让其指向Nginx。
server:
port: 9002
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: 192.168.1.78:80 # 指向Nginx,由Nginx进行转发(nginx下部署了3台Nacos集群)
# server-addr: 192.168.1.78:8848 # 指明Nacos的地址
management:
endpoints:
web:
exposure:
include: '*'
Nginx下有3台Nacos部署的集群环境,由Nginx进行转发,启动Payment9002,访问http://192.168.1.78/nacos,查看“服务管理”-“服务列表”,可以看到服务成功注册进来了。
5-3-2、macOS版
配置Nacos集群,数据存储存在一致性问题,要高可用,所以Nacos采用集中式存储来支持集群化部署,目前只支持MySQL存储。
5-3-2-1、修改Nacos对mysql数据库配置以及application.properties配置
5-3-2-2、nacos的集群配置cluster.conf
在
nacos文件夹目录下找到/Users/test/Documents/Development-Configuration/nacos/conf/cluster.conf.example文件,先将它复制一份出来去掉后缀.example,变成cluster.conf有效的配置文件。
修改
cluster.conf文件,添加3个nacos集群ip地址。
5-3-2-3、编辑Nacos的启动脚本
- 在
/Users/test/Documents/Development-Configuration/nacos/bin/startup.sh,使它能够接受不同的启动端口,编辑修改前,先备份一下startup.sh文件,备份文件名改成startup.sh.bk。





- 启动3个Nacos集群,分别在多个终端执行
sh startup.sh -p 3333、sh startup.sh -p 4444、sh startup.sh -p 5555,成功启动后能看到输出nacos is starting with cluster。查看多少个Nacos在运行:ps -ef|grep nacos|grep -v grep|wc -l。

5-3-2-4、Nginx的配置,由它作为负载均衡器
- 在终端执行
open /usr/local/etc/nginx/打开文件夹找到nginx.conf文件并修改它。

- 修改好
nginx.conf文件后,进行启动nginx,关闭nginx -s stop。
5-3-2-3、截止到此处,1个Nginx+3个Nacos+1个Mysql
访问http://localhost:1111/nacos/进来点击“集群管理-节点列表”可见成功启动了:
注意:Nacos 2.x版本配置集群需要3份nacos文件,因为查看start.out日志,踢皮球让我去nacos.log日志查看详细,nacos.log日志中最后显示Fail to init node, please see the logs to find the reason.
异常是由com.alipay.sofa.jraft.***类抛出的,再踢皮球让我去查看alipay-jraft.log日志。
那就猜测是这个文件只能被一个服务使用,那就把nacos文件夹在前面已经配置好的前提下复制3份,每份启动一个端口,问题解决。
分别进入指定的nacos 的bin目录执行:sh startup.sh -p 3333、nacos4444 的bin目录执行:sh startup.sh -p 4444以及nacos5555 的bin目录执行:sh startup.sh -p 5555
最后一步,将cloud-alibaba-provider-payment9002服务注册进Nacos集群。修改application.yml配置文件的server-addr的值,让其指向Nginx。
# 配置服务端口号
server:
port: 9002
# 配置应用信息
spring:
application:
name: nacos-payment-provider # 配置应用名称
cloud:
# nacos配置
nacos:
discovery:
# server-addr: 192.168.1.78:8848 # 指明Nacos的地址
server-addr: 192.168.1.78:1111 # 指向Nginx,由Nginx进行转发(nginx下部署了3台Nacos集群)
# 暴露所有监控端点
management:
endpoints:
web:
exposure:
include: '*'
Nginx下有3台Nacos部署的集群环境,由Nginx进行转发,有可能转发到3333节点上或者4444节点上也有可能到5555节点,启动Payment9002,访问http://192.168.0.123/nacos,查看“服务管理”-“服务列表”,可以看到服务成功注册进来了。