SpringCloudAlibaba-Nacos
(来源于尚硅谷)
1.SpringCloudAlibaba由哪些部分组成。
1.1图解
2.Nacoss可以干什么?
2.1 Nacos是什么?
一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
Nacos就是注册中心+配置中心的组合
2.2 Nacos能干什么?
替代Eureka/Consul做服务注册中心.
替代(Config+Bus)/Consul 做服务配置中心和满足动态刷新广播通知.
2.2 Nacos下载地址
https://nacos.io/zh-cn/
2.3 各种注册中心比较
据说 Nacos 在阿里巴巴内部有超过 10 万的实例运行,已经过了类似双十一等各种大型流量的考验,Nacos默认是AP模式,
但也可以调整切换为CP,我们一般用默认AP即可。
3. Nacos的下载、安装和配置
3.1 下载和版本的选择
3.1.1 下载
官网 https://nacos.io/zh-cn/index.htm
直接下载网页(官网):https://nacos.io/download/nacos-server/
3.1.2 版本的选择
最新版本2.4.0-BETA 已经支持取消管理员用户nacos的默认密码,支持初始化指定密码。
我使用的是2.2.3版本
3.2 运行Nacos,访问Nacos界面
3.2.1 运行Nacos
到文件的bin目录下运行cmd,输入启动命令 startup.cmd -m standalone
3.2.2 访问Nacos界面
网址: http://localhost:8848/nacos/
(如果需要登录,账号密码都为Nacos)
访问到这个页面,证明Nacos安装、配置成功。
3.2.3 关闭Nacos
命令:shutdown.cmd
4. Nacos的服务注册中心功能
4.1 功能
通过 Nacos Server 和 spring-cloud-starter-alibaba-nacos-config 实现配置的动态变更
通过 Nacos Server 和 spring-cloud-starter-alibaba-nacos-discovery 实现服务的注册与发现。
4.2 服务提供者Demo实现功能
4.2.1 pom解析:
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atguigu.cloud</groupId>
<artifactId>cloud2024</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>cloudalibaba-provider-payment9001</artifactId>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--openfeign 用来使用Openfeign接口-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--alibaba-sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--nacos-discovery Nacos的依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 引入自己定义的api通用包 -->
<dependency>
<groupId>com.atguigu.cloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--SpringBoot通用依赖模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
<scope>provided</scope>
</dependency>
<!--test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
4.2.2 application.yml解析:
server:
port: 9001 #端口号9001
spring:
application:
name: nacos-payment-provider #服务注入进Nacos的名字
cloud:
nacos:
discovery:
server-addr: localhost:8848 #配置Nacos地址
4.2.3 主启动
package com.atguigu.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient//只要做服务发现的,都需要加一个这个注解
//@EnableDiscoveryClient 是一个 Spring Cloud 注解,用于服务发现。
// 当一个 Spring Boot 应用加上 @EnableDiscoveryClient 注解后,该应用就具备了服务注册与发现的能力,
// 可以将自己注册到服务注册中心,并能从服务注册中心获取注册的服务信息。
public class Main9001 {
public static void main(String[] args) {
SpringApplication.run(Main9001.class, args);
}
}
4.2.4 业务类
package com.atguigu.cloud.controller;
import cn.hutool.core.util.IdUtil;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.atguigu.cloud.entities.PayDTO;
import com.atguigu.cloud.resp.ResultData;
import com.atguigu.cloud.resp.ReturnCodeEnum;
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 java.math.BigDecimal;
@RestController
/**
* @RestController 注解相当于 @Controller 和 @ResponseBody 的结合。其中,@ResponseBody是一个针对方法返回值进行处理的注解,处理后的RestController注解会将所有处理请求的方法默认解析为将方法返回值直接作为响应体内容返回,主要用于构建RESTful API,返回的数据通常是JSON或XML格式。
*
* 而@Controller注解的返回值通常会经过视图解析器解析,返回数据通常是渲染后的HTML页面。
*用法不同。@RestController 注解可以创建RESTful风格的数据,主要有get、post、put、delete等,可以方便地处理输出和输入的JSON或XML数据,适用于前后端分离的架构。
*
* @Controller则更多地与视图渲染和页面跳转相关,适用于传统的MVC架构,通过页面模板引擎将数据渲染成 HTML 页面返回给用户。
*/
public class PayAlibabaController
{
@Value("${server.port}")
private String serverPort;
@GetMapping(value = "/pay/nacos/{id}")
public String getPayInfo(@PathVariable("id") Integer id)
{
return "nacos registry, serverPort: "+ serverPort+"\t id"+id;
}
//openfeign+sentinel 进行服务降级和流量监控的整合处理case
@GetMapping("/pay/nacos/get/{orderNo}")
@SentinelResource(value = "getPayByOrderNo",blockHandler = "handlerBlockHandler")
public ResultData getPayByOrderNo(@PathVariable("orderNo") String orderNo)
{
//模拟从数据库查询出数据并赋值给DTO
PayDTO payDTO = new PayDTO();
payDTO.setId(1024);
payDTO.setOrderNo(orderNo);
payDTO.setAmount(BigDecimal.valueOf(9.9));
payDTO.setPayNo("pay:"+ IdUtil.fastUUID());
payDTO.setUserId(1);
return ResultData.success("查询返回值:"+payDTO);
}
public ResultData handlerBlockHandler(@PathVariable("orderNo") String orderNo, BlockException exception)
{
return ResultData.fail(ReturnCodeEnum.RC500.getCode(),"getPayByOrderNo服务不可用," +
"触发sentinel流控配置规则"+"\t"+"o(╥﹏╥)o");
}
/*
fallback服务降级方法纳入到Feign接口统一处理,全局一个
public ResultData myFallBack(@PathVariable("orderNo") String orderNo,Throwable throwable)
{
return ResultData.fail(ReturnCodeEnum.RC500.getCode(),"异常情况:"+throwable.getMessage());
}
*/
}
4.2.5 测试
4.3 服务消费者Demo实现功能
4.3.1 pom解析:
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atguigu.cloud</groupId>
<artifactId>cloud2024</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>cloudalibaba-consumer-nacos-order83</artifactId>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- 引入自己定义的api通用包 -->
<dependency>
<groupId>com.atguigu.cloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--alibaba-sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--nacos-discovery 表明这个服务也要入住进我们nacos8848-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--loadbalancer 我去调用别人,很有可能有多个服务,所以我们要加入负载均衡-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!--web + actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
4.3.2 yml:
server:
port: 83
spring:
application:
name: nacos-order-consumer //这个微服务进去Nacos的名字
cloud:
nacos:
discovery:
server-addr: localhost:8848
#消费者将要去访问的微服务名称(nacos微服务提供者叫什么你写什么)
service-url:
nacos-user-service: http://nacos-payment-provider
4.3.3 主启动类:
package com.atguigu.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @auther zzyy
* @create 2023-11-23 17:15
*/
@EnableDiscoveryClient//服务注册发现
@SpringBootApplication
public class Main83
{
public static void main(String[] args)
{
SpringApplication.run(Main83.class,args);
}
}
4.3.4 配置类RestTemplateConfig:
RestTemplate 是 Spring 提供的用于访问 RESTful Web 服务的模板类。它简化了在 Java 中使用 HTTP 请求的过程,使得与 RESTful 服务的交互变得更加方便。
具体来说,通过 RestTemplate 可以:
发送 HTTP 请求(如 GET、POST、PUT、DELETE 等)到远程服务器。
接收来自远程服务器的 HTTP 响应。
处理请求和响应的数据,如将 JSON 数据转换为 Java 对象,或将 Java 对象转换为 JSON 数据。
在微服务架构中,RestTemplate 经常用于微服务之间的通信,例如一个服务需要调用另一个服务的 API 接口时,可以使用 RestTemplate 发送 HTTP 请求,获取并处理返回的数据。
总之,RestTemplate 是 Spring 框架中用于简化 RESTful 服务调用的工具类,它封装了底层的 HTTP 请求过程,提供了一套更高级、更易用的 API。
package com.atguigu.cloud.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 RestTemplateConfig
{
@Bean
@LoadBalanced //赋予RestTemplate负载均衡的能力
public RestTemplate restTemplate()
{
return new RestTemplate();
}
}
4.3.5 业务类:
package com.atguigu.cloud.controller;
import com.atguigu.cloud.apis.PayFeignSentinelApi;
import com.atguigu.cloud.resp.ResultData;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;
@RestController
public class OrderNacosController
{
@Resource
private RestTemplate restTemplate;
@Value("${service-url.nacos-user-service}")
private String serverURL;
@GetMapping("/consumer/pay/nacos/{id}")
public String paymentInfo(@PathVariable("id") Integer id)
{
String result = restTemplate.getForObject(serverURL + "/pay/nacos/" + id, String.class);
return result+"\t"+" 我是OrderNacosController83调用者。。。。。。";
}
@Resource
private PayFeignSentinelApi payFeignSentinelApi;
@GetMapping(value = "/consumer/pay/nacos/get/{orderNo}")
public ResultData getPayByOrderNo(@PathVariable("orderNo") String orderNo)
{
return payFeignSentinelApi.getPayByOrderNo(orderNo);
}
}
4.3.6 测试,入住
4.4 实现负载均衡
4.4.1 取巧,直接拷贝虚拟端口映射
4.4.2 测试负载均衡
5. Nacos的服务配置中心功能
5.1 Demo
5.1.1 pom解析:
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atguigu.cloud</groupId>
<artifactId>cloud2024</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>cloudalibaba-config-nacos-clien3377</artifactId>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--bootstrap 只要是配置中心的,都有两个配置文件,一个是本地的application.yml,另一个就是bootstrap.yml-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!--nacos-config 配置化功能-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--nacos-discovery 入住进nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--web + actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
5.1.2 yml解析:
Nacos同Consul一样,在项目初始化时,要保证先从配置中心进行配置拉取,
拉取配置之后,才能保证项目的正常启动,为了满足动态刷新和全局广播通知
springboot中配置文件的加载是存在优先级顺序的,bootstrap优先级高于application
5.1.1.1 bootstrap.yml
# nacos配置
spring:
application:
name: nacos-config-client //nacos中的名字
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
config:
server-addr: localhost:8848 #Nacos作为配置中心地址
file-extension: yaml #指定yaml格式的配置
group: PROD_GROUP
namespace: Prod_Namespace
# nacos端配置文件DataId的命名规则是:
# ${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
# 本案例的DataID是:nacos-config-client-dev.yaml
5.1.1.2 application.yml
server:
port: 3377
spring:
profiles:
# active: dev # 表示开发环境
active: prod # 表示生产环境
#active: test # 表示测试环境
# profiles中的三个不同的环境,对于bootstrap.yml中的nacos端配置文件DataId的命名也不同
5.1.3 业务类:(主启动省略)
package com.atguigu.cloud.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;
/**
* @auther zzyy
* @create 2023-11-27 15:51
*/
@RestController
@RefreshScope //在控制器类加入@RefreshScope注解使当前类下的配置支持Nacos的动态刷新功能。
public class NacosConfigClientController
{
@Value("${config.info}")
private String configInfo;
@GetMapping("/config/info")
public String getConfigInfo() {
return configInfo;
}
}
5.2 在Nacos中添加配置信息(重点)
5.2.1 DataId的配置:
5.2.2 创建配置:
5.2.3 测试配置:
5.3 Nacos数据模型之Namespace-Group-Datald
5.3.1 提出问题
问题1:
实际开发中,通常一个系统会准备
dev开发环境
test测试环境
prod生产环境。
如何保证指定环境启动时服务能正确读取到Nacos上相应环境的配置文件呢?
问题2:
一个大型分布式微服务系统会有很多微服务子项目,
每个微服务项目又都会有相应的开发环境、测试环境、预发环境、正式环境…
那怎么对这些微服务配置进行分组和命名空间管理呢?
5.3.2 Namespace+Group+Datald三者关系?
5.3.3 Nacos的图形化管理界面
5.4 三种加载方案
5.4.1 DatalD方案
指定spring.profile.active和配置文件的DatalD来使不同环境下读取不同的配置
5.4.2 Group方案
通过Group实现环境区分
修改一下配置文件就好了:
# nacos配置 第2种:默认空间+新建分组+新建DataID
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
config:
server-addr: localhost:8848 #Nacos作为配置中心地址
file-extension: yaml #指定yaml格式的配置
group: PROD_GROUP //切换group
# nacos端配置文件DataId的命名规则是:
# ${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
# 本案例的DataID是:nacos-config-client-dev.yaml
5.4.2 Namespace方案
通过Namespace实现命名空间环境区分
修改yml:
# nacos配置 第3种:新建空间+新建分组+新建DataID
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
config:
server-addr: localhost:8848 #Nacos作为配置中心地址
file-extension: yaml #指定yaml格式的配置
group: PROD_GROUP
namespace: Prod_Namespace
# nacos端配置文件DataId的命名规则是:
# ${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
# 本案例的DataID是:nacos-config-client-dev.yaml
6.总结
nacos是一个注册中心+配置中心的组合。可以很方便的看到我们的服务有哪些,也可以统一管理配置。