5.Nacos注册中心
官网是这么介绍的:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。功能和上面提到的Eureka类似,Nacos支持几乎所有主流类型的服务发现、配置和管理:
- Kubernetes Service
- gRPC & Dubbo RPC Service
- Spring Cloud RESTful Service
先看如何使用再讲原理:
5.1 安装
需要先从官网下载Nacos并启动Nacos Server:github
有两个需要注意的点
1.JAVA_HOME配置
这里在环境变量里配置JAVA_HOME没用,得去startup.cmd文件中
2.鉴权
在2.2.1版本的Nacos需要手动配置secret.key
,否则启动会报错,secret.key
随便生成一串≥32位的字符串即可。(我这次下载2.2.2版本已经不需要配置鉴权也可以正常使用了,但是不需要登录,访问Nacos还是会提示开启鉴权)
Windows
启动命令(standalone代表着单机模式运行,非集群模式):
startup.cmd -m standalone
启动成功后从给出的url访问,账号密码都是Nacos
:

5.2 服务注册
Eureka注册中心配置时,需要在server和client分别引入pom坐标并配置yml文件,Nacos除了这些还多了一个步骤,因为Nacos是spring-cloud-alibaba的依赖,所以需要先在父工程引入阿里巴巴依赖。
注意引入的版本要和spring-cloud兼容,参考版本说明
1.父工程pom文件引入坐标
<properties>
<!--指定版本-->
<spring-cloud-alibaba.version>2022.0.0.0-RC1</spring-cloud-alibaba.version>
</properties>
<!--为了使用Nacos-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
我使用的spring-boot版本是3.0.5,spring-cloud版本是2022.0.2,所以要注意spring-cloud-alibaba的版本和这些兼容。Idea的Maven提示版本是你之前安装过的repository里的版本不一定对应,可以去maven官网查一下。
2.子工程client端pom文件引入Nacos依赖
<!--Nacos客户端依赖包-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-Nacos-discovery</artifactId>
</dependency>
3.子工程yml文件配置Nacos
spring:
cloud:
Nacos:
server-addr: localhost:8848 # Nacos服务地址
4.配置文件
spring.cloud.nacos.server-addr=127.0.0.1:8848
注意:⭐
因为ribbon已经逐渐被spring-cloud弃用,改用loadBalancer,所以RestTemplate方法使用@LoadBalanced
注解时无法使用ribbon负载均衡,需要手动引入loadBalancer的依赖才能正常解析user-service.在服务消费者的pom中添加其坐标即可.
<!--2022版spring-cloud-alibaba必须添加这个依赖,否则域名解析不正确,找不到服务地址
参考:https://blog.csdn.net/weixin_43887184/article/details/124036205-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
5.3 服务发现

步骤:
1.pom中添加nacos-discovery依赖
2.application.yml中添加nacos服务地址
3.Spring Cloud原生注解@EnableDiscoveryClient
开启服务注册发现功能
@MapperScan("cn.itcast.user.mapper")
@SpringBootApplication
@EnableDiscoveryClient
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
4.服务消费者的RestTemplate
添加@LoadBalanced
注解
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
依然可以直接调用RestTemplate
进行访问,但要注意返回值类型处理:
//OrderService.java
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
if (null!=order && null!= order.getUserId()){
String url = URL_PREFIX+order.getUserId();
//⭐注意:这里拿到的不是User类型而是Result类型,所以需要提取一下
Result result = restTemplate.getForObject(url, Result.class);
assert result != null;
//将hashmap转成json再转成实体类对象
ObjectMapper mapper = new ObjectMapper();
User user = mapper.convertValue(result.getData(),User.class);
order.setUser(user);
}
return order;
}
5.3.1 Nacos服务分级存储模型

设置集群属性:
spring.cloud.Nacos.discovery.cluster-name: BJ
Nacos注册结果如下:

微服务调用优先访问本地集群
eg.BJ的order-service优先调用BJ的user-service
默认是轮询调用,所以需要配置负载均衡规则
旧版SpringCloud仍然使用ribbon,所以可以通过如下方式配置:
# 设置负载均衡,优先访问本地集群
user-service:
ribbon:
NFLoadBalancerRuleClassName: com.alibaba.cloud.Nacos.ribbon.NacosRule
但我使用的项目是2022版的SpringCloud,以及启用了ribbon,所以使用新的方法配置负载均衡
spring:
application:
name: order-service
cloud:
loadbalancer:
# 使用Nacos做负载均衡,默认优先访问本地集群,默认使用随机方式访问服务
Nacos:
enabled: true
Nacos:
server-addr: localhost:8848
discovery:
cluster-name: BJ
根据权重负载均衡
直接在Nacos注册中心(localhost:8848)修改微服务权重,权重范围在0-1之间.

这样Nacos就会控制优先访问权重更大的微服务. 如果权重为0则不会被访问,方便版本升级修改等,不需要重启。
5.3.2 环境隔离-namespace
一般实际开发中,可能会用到生产环境、开发环境切换等情况,可以使用环境隔离方便切换。

- 进入浏览器Nacos控制台,新建命名空间,复制id并在java项目中配置

配置文件中添加命名空间
spring:
cloud:
Nacos:
discovery:
cluster-name: BJ
namespace: 2823f44e-dfec-4276-990c-8062646b9b13 # dev环境
成功
⭐注意:namespace用来做环境隔离,不同namespace下的服务不可见
group:group是一个次于namespace的隔离概念,属于弱隔离,主要用于逻辑区分一些服务使用场景或不同应用的同名服务,eg同一个服务的测试分组和生产分组.
5.3.3 Nacos注册中心原理

Nacos和Eureka对比
- 相同
- 都支持服务注册和拉取
- 都支持服务提供者心跳方式做健康检测
- 区别
- Nacos支持服务端主动检测提供者状态:临时实例和Eureka类似,采用心跳模式(Nacos更快),若无心跳则删掉实例;非临时实例,由注册中心定时询问,若无响应则等待实例恢复而非直接从注册中心删掉.
- Nacos和Eureka都有一个服务缓存列表,服务消费者调用服务时就不需要每次都请求注册中心了. 服务缓存列表根据定时Pull更新.
- 若服务提供者实例出现故障,则Nacos会立即通过push方式推送给服务消费者,避免服务缓存列表更新不及时消费者访问到故障微服务.Eureka没有这个即时通知机制.
- Nacos集群默认采用AP方式(强调数据可用性),当集群中存在非临时实例时采用CP模式(强调数据可靠性和一致性);Eureka采用AP方式
- Eureka主要关注服务注册和服务发现,Nacos除了这两者之外还提供了配置管理功能,支持集中式配置和动态推送,无需重启服务.
- Nacos提供服务命名空间和分组概念,使得服务可以按照业务、环境等进行划分和隔离.
设置Nacos实例为临时实例的方式:修改yml文件
spring:
cloud:
Nacos:
discovery:
# false则为非临时实例,默认值为true
ephemeral: true
5.4 Nacos配置管理
作用:统一配置;配置更改热更新
5.4.1 统一配置
1.Nacos中添加配置信息,为了防止命名冲突,DataID命名一般采用形式:[服务名称]-[profile].[后缀名],后缀支持yaml和properties.

2.因为部分配置信息写在了Nacos中,所以需要先读取Nacos的yaml配置,与本地yml合并后创建spring容器进行后续内容.因此需要先拿到Nacos的地址才能获取Nacos配置文件,就需要在比application.yml优先级更高的bootstrap.yml文件中给出Nacos地址.

3.Nacos服务器刚刚新建配置的service(user-service)的pom引入Nacos配置管理客户端依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-Nacos-config</artifactId>
</dependency>
4.在resource目录下添加bootstrap.yml
引导文件,其优先级高于application.yml
spring:
application:
name: user-service
profiles:
active: dev # 环境
cloud:
Nacos:
server-addr: localhost:8848 #Nacos地址
config:
file-extension: yaml # 文件后缀名

5.删掉application.yml
中与bootstrap.yml
重复的配置
6.注意springcloud2020已经弃用bootstrap方式(,所以要想继续使用,需要在对应service的pom文件中引入bootstrap依赖
注意
bootstrap是系统级的资源配置文件,是用在程序引导执行时更加早期配置信息读取;application是用户级的资源配置文件,是用来后续的一些配置所需要的公共参数.bootstrap.yml比application.yml优先级更高. 可能会覆盖掉application的配置,不够优雅?
<!--使用bootstrap
但是官方已经弃用了,所以不建议使用|-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
7.⭐采用springcloud最新的配置中心文件的引入方式根据官方文档,可以直接在application.yml中添加配置,不需要重建bootstrap文件.
但是官网给出的配置方案报错
java.lang.IllegalStateException: Unable to load config data from 'optional:configserver:http://localhost:8848'
通过搜索发现,可以使用另一种配置方法:
spring:
config:
import:
# 注意格式(-后面要有空格,optional可以不写,其实-也可以不写,这是列表形式,只有一个参数时可以省略),冒号后面直接写配置文件名称即可
- optional:Nacos:user-service-dev.yaml
# 除此之外,把bootstrap.yml的配置信息写在application.yml中即可.
5.4.2 热更新
实现热更新还需要进一步配置,有两种方法
1.在@Value
注入的变量所在类上添加注解@RefreshScope
2.使用@ConfigurationProperties
注解
@Component
@Data
@ConfigurationProperties(prefix="pattern")
public class PatternProperties{
private String dateformat;
}然后在需要使用的地方直接调用即可: @Slf4j
@RestController
//@RefreshScope
@RequestMapping("/user")
public class UserController {
@Autowired
private PatternProperties patternProperties;
// @Value("${pattern.dateformat}")
// private String dateformat;
@GetMapping("/now")
public String now(){
return LocalDateTime.now().format(DateTimeFormatter.ofPattern(patternProperties.getDateformat()));
}
}
5.4.3 多环境配置共享

所以Nacos服务器新建一个user-service.yaml放置多环境共享的配置,使用方式同上.
优先级:[spring.application.name]-[spring.profiels.active].yaml
>[spring.application.name].yaml
>本地application.yml
5.4.4 Nacos集群搭建
如图:Nacos生产环境下一定要部署为集群方式

模拟Nacos集群:
官方参考文档进入Nacos的conf目录,修改配置文件cluster.conf.example,重命名为cluster.conf:
然后添加内容:
127.0.0.1:8845
127.0.0.1.8846
127.0.0.1.8847
配置Nacos数据库
Nacos使用时是需要配置数据库以便记录Nacos运行信息的,而数据库创建由Nacos官方文档给出创建方式,我直接复制了黑马的建表语句结果添加Nacos配置时报了发布失败的错误,因为黑马用的是低版本的Nacos所以不可用,我们需要用匹配版本,有两种获取资源方式:
- 官网集群部署说明,注意要在分支中选择对应版本的sql源文件
- 直接使用Nacos/conf/mysql-schema.sql,这个文件的内容和通过官网获取到的sql语句源文件一致,新建一个名为Nacos的数据库,将其加载到数据库中,创建出Nacos所需的表.此后使用Nacos会自动向表中填入数据.

然后修改application.properties文件,添加数据库配置,db.url.0
的数据库名称即为上面导入Nacos数据库的库名.
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/Nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=root72760
此后对Nacos的操作都会记录在Nacos数据库的对应表内,例如添加Nacos服务器的配置文件后数据库记录如下:


之后分别启动三份Nacos(集群启动cluster)
startup.cmd
注意:启动Nacos集群时会发现,接口之间会相互占用导致启动失败,原因如下,官方文档:

原始端口 | 8845 | 8846 | 8847 |
---|---|---|---|
+1000 | 9845 | 9846 | 9847 |
+1001 | 9846 | 9847 | 9848 |
所以无论这三个Nacos节点以什么顺序启动,都会有端口被占用而无法启动,做法就是端口间隔至少为2,改成8845 8847 8849.
nginx配置集群:
进入nginx的conf/nginx.conf文件在http中添加如下配置:
http {
# config for Nacos cluster
upstream Nacos-cluster{
server 127.0.0.1:8845;
server 127.0.0.1:8847;
server 127.0.0.1:8849;
}
server{
listen 80;
server_name localhost;
location /Nacos{
proxy_pass http://Nacos-cluster
}
}
⭐注意:因为Nacos多了个rGpc的通信方式,所以还需要配置rgpc的端口,即端口转发,所以还需要在nginx.conf文件中添加如下配置,需要注意的是顺序一定不能错!stream在http下方!!!

http {
...
}
# Nacos集群的nginx配置
stream {
upstream Nacos-cluster-tcp {
# 都加上1000的偏移量
server 10.28.221.178:9845;
server 10.28.221.178:9847;
server 10.28.221.178:9849;
}
server {
# Nacos 80+1000
listen 1080;
proxy_pass Nacos-cluster-tcp;
}
}
监听80端口时记得把配置文件中nginx的默认监听注释掉,否则会出现以下警告:

打开nginx
start nginx.exe
启动后访问Nacos可以看到集群后的节点列表:

注册服务:需要在idea的项目中把Nacos服务器端口改为nginx中配置的端口号80

注意:这个时候还没有建立Nacos服务端的配置文件,所以idea中引用Nacos的配置会造成appication启动失败,先把引用的部分注释掉就好了:
