一、Spring Cloud Alibaba 之 Nacos
日积月累,水滴石穿 😄
前言
过去了两年,我又重新开始学习 Spring Cloud 微服务技术,不过是学习 Spring Cloud alibaba 系的微服务组件。之前学的白学了,忘的干干净净的。因为在工作当中,一直使用的是 Spring Boot。
为什么选择 Spring Cloud Alibaba
一、Spring Cloud Netflix 进入维护模式
由于 Spring Cloud Netflix
项目进入维护模式,文章地址:spring.io/blog/2018/1…
什么是维护模式?
将模块置于维护模式,意味着 Spring Cloud 团队将不会再向模块添加新功能。他们将修复block级别的 bug 以及安全问题。
二、Spring Cloud Alibaba 加入 Spring 官方官方孵化器
2018.10.31,Spring Cloud Alibaba 正式入驻了 Spring Cloud 官方孵化器,并在 Maven 中央库发布了第一个版本。
如图所示:
Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。
依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。
Spring alibaba的主要组件:
- Sentinel:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
- Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
- RocketMQ:一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。
- Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。
- Alibaba Cloud OSS: 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
- Alibaba Cloud SchedulerX: 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。
- Alibaba Cloud SMS: 覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。 如上信息都能在官网找到。
什么是 Nacos
Nacos 是 Spring Cloud Alibaba 众多组件中之一。官网是这么形容的:Nacos 是 Dynamic Naming and Configuration Service 的首字母简称;它是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。说直白点,替代 Eureka 做服务注册中心,替代 Config 做服务配置中心。
在老一代微服务中,也就是使用 Eureka 时,还要搭建 Eureka 的本地服务,而 Nacos 直接提供一个后台管理页面,可以在其后台进行管理服务的上线、服务的配置、多项目环境隔离等等。。。
各种注册中心的比较
框架 | CAP模型 | 控制台管理 | 社区活跃度 |
---|---|---|---|
Eureka | AP | 支持 | 低(2.x版本闭源) |
Zookeeper | CP | 不支持 | 中 |
consul | CP | 支持 | 高 |
Nacos | AP(默认) | 支持 | 高 |
安装
下载官方推荐版本
Nacos安装
tar.gz 是 Linux 版本。.zip 是 window 版本。本文是入门基础使用篇,先使用 window 版本安装。
- 在安装之前需要保证电脑上已经有了 JDK 1.8+ 、Maven 3.2.x+ 的环境。
- 将下载下来的安装包,进行解压
- 进入 bin 目录下,可以看到有文件名为 startup.cmd 的文件,这是 window 的启动文件,.sh 是 Linux 的启动文件。
- 打开 cmd 命令窗口,执行命令
startup.cmd -m standalone
(standalone 代表着单机模式运行)
Nacos started successfully in stand alone mode. use embedded storage(Nacos在独立模式下成功启动。使用嵌入式存储)
- 运行成功后,在浏览器直接访问
http://localhost:8848/nacos
,使用默认账号密码登录,可以看到如下页面,默认的账号密码都是 nacos。
Nacos 服务注册
创建顶级父项目
在其 pom.xml 文件加入以下依赖:
<dependencyManagement>
<dependencies>
<!-- SpringCloud 微服务 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring-cloud-alibaba 依赖管理器-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.0.1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring-boot 依赖管理器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.6.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!--由于2020版本后,不再默认加载 bootstrap.yml/properties、所以需要手动加依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
</dependencies>
加入 Spring Cloud 依赖,只是为了管理 spring-cloud-starter-bootstrap 依赖的版本。
创建子模块 nacos-9001
在其 pom.xml 加入如下依赖
<dependencies>
<!--spring-cloud-alibaba 注册中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
创建启动类,并在类上加上注解@EnableDiscoveryClient
开启服务注册发现功能
@SpringBootApplication
@EnableDiscoveryClient
public class NacosApplication9001 {
public static void main(String[] args) {
SpringApplication.run(NacosApplication9001.class, args);
}
}
创建一个业务接口。
@Value("${server.port}")
private String serverPort;
@GetMapping("/nacos/{id}")
public String payment(@PathVariable("id") String id) {
return "Hello Nacos Discovery, serverPort:" + serverPort + ", id:" + id;
}
创建 bootstrap.yml
文件,配置 Nacos server 的地址和服务应用名。
server:
port: 9001
spring:
application:
name: nacos-start
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
启动 nacos-9001 项目
负载均衡
比如现在有 A 服务需要远程调用 B 服务,但 B 服务有两个实例,那 A 服务应该调用哪个实例呢。
创建 nacos-9002 项目
演示 Nacos 的负载均衡,那就需要有多个服务。
- copy nacos-9001 项目,修改项目名、artifactId为 nacos-9002,端口为 9002。
- 利用 IDEA 工具修改服务启动端口。
指定启动参数 -Dserver.port=9002
搭建 Nacos 服务消费者
创建项目 nacos-consumer-9003。在 pom.xml 添加依赖:
<dependencies>
<!--spring-cloud-alibaba 注册中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--Spring Cloud 2020 版本以后,默认移除了对Netflix的依赖,loadbalancer 取缔了 Netflix 的 Ribbon
loadbalancer 成为了Spring Cloud负载均衡器的唯一实现
-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
</dependencies>
在 bootstrap.yml 中配置 Nacos server 的地址
server:
port: 9003
spring:
application:
name: nacos-consumer
cloud:
nacos:
server-addr: 127.0.0.1:8848
启动类
package cn.cxyxj;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
public class NacosConsumerApplication9003 {
public static void main(String[] args) {
SpringApplication.run(NacosConsumerApplication9003.class, args);
}
// 给 RestTemplate 实例添加 @LoadBalanced 注解,
// 开启 @LoadBalanced 与 Ribbon 的集成:
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@RestController
public class TestController {
private final RestTemplate restTemplate;
@Autowired
public TestController(RestTemplate restTemplate) {this.restTemplate = restTemplate;}
@RequestMapping(value = "/get", method = RequestMethod.GET)
public String get(@PathVariable Integer id) {
// 将要访问的微服务名称
String serviceName = "http://nacos-start";
return restTemplate.getForObject(serviceName + "/nacos/" + id, String.class);
}
}
}
测试
启动 nacos-9001、nacos-9002、nacos-consumer-9003。
调用 nacos-consumer-9003 服务的接口:localhost:9003/get/9
默认的负载均衡策略是轮询。
Nacos配置中心
创建新模块 nacos-config-9004
在其 pom.xml 文件中加入如下依赖:
<dependencies>
<!--spring-cloud-alibaba 注册中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--spring-cloud-alibaba 配置中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
创建启动类,并在类上加上注解@EnableDiscoveryClient
开启服务注册发现功能
@SpringBootApplication
@EnableDiscoveryClient
public class NacosConfigApplication9004 {
public static void main(String[] args) {
SpringApplication.run(NacosConfigApplication9004.class, args);
}
}
创建业务接口,读取配置内容
@RestController
public class HelloNacosConfigController {
@Value("${config.info}")
private String configInfo;
@RequestMapping("/get-config-info")
public String getConfigInfo() {
return configInfo;
}
}
创建 bootstrap.yml
文件,配置 Nacos server 的地址和服务应用名。
server:
port: 9004
spring:
application:
name: nacos-config-start
profiles:
active: dev
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # Nacos 服务地址
config:
erver-addr: 127.0.0.1:8848 # Nacos 服务地址
file-extension: yaml # 指定yaml格式的配置
说明:之所以需要配置 spring.application.name
,是因为它是构成 Nacos 配置管理 dataId
字段的一部分。
在 Nacos 中,dataId
的完整格式如下:
${prefix}-${spring.profiles.active}.${file-extension}
prefix
默认为spring.application.name
的值,也可以通过配置项spring.cloud.nacos.config.prefix
来配置。spring.profiles.active
即为当前环境对应的 profile, 注意:当spring.profiles.active
为空时,对应的连接符-
也将不存在,dataId 的拼接格式变成${prefix}.${file-extension}
file-exetension
为配置内容的数据格式,可以通过配置项spring.cloud.nacos.config.file-extension
来配置。目前只支持properties
和yaml
类型。
项目结构如图所示。
Nacos客户端添加配置信息
- 第一步
- 第二步
再次强调 Data ID 的配置规则为:
${prefix}-${spring-profile.active}.${file-extension}
。
- 第三步,点击发布按钮
测试
- 运行 nacos-config-9004 服务的主启动类
- 调用接口查看配置信息 - http://localhost:9004/get-config-info
动态刷新
如果需要对 Bean 进行动态刷新,推荐给类添加 @RefreshScope
或 @ConfigurationProperties
注解。
分类配置
Namespaces
命名空间用于隔离不同租户的配置。不同命名空间中的 Group 和 Data ID 可以相同。命名空间的典型场景是隔离不同环境的配置,例如,开发/测试环境和生产环境(配置和服务等)之间的隔离。
如果${spring.cloud.Nacos.config.namespace}
中没有指定命名空间,则使用 Nacos的Public
命名空间。此配置必须位于bootstrap.properties/yml
文件中。spring.cloud.nacos.config.namespace
的值是命名空间的id。
spring.cloud.nacos.config.namespace=fde7e3e9-6e44-45c3-b04e-34e4baa99339
Groups
Group 可以把不同的微服务划分到同一个分组里面去。默认情况下,当未定义${spring.cloud.nacos.config.GROUP}
配置时,将使用 DEFAULT_GROUP。如果需要定义自己的组,可以在以下属性中定义它:
spring.cloud.nacos.config.group=DEV_GROUP
此配置必须位于bootstrap.properties/yml
文件中,Group 的值必须与spring.cloud.nacos.config.Group
的值相同。
演示
新建 dev Namespaces
- 第一步
- 第二步
- 第三步,copy 命名空间ID
新建配置文件
- 第一步:选择对应的 Namespaces
- 第二步,创建配置文件,注意:Group 的值为 cxyxj。
修改 bootstrap.properties/yml
server:
port: 9004
spring:
application:
name: nacos-config-start
profiles:
active: dev
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # Nacos 服务地址
namespace: fde7e3e9-6e44-45c3-b04e-34e4baa99339 # 命名空间ID
config:
erver-addr: 127.0.0.1:8848 # Nacos 服务地址
file-extension: yaml # 指定yaml格式的配置
namespace: fde7e3e9-6e44-45c3-b04e-34e4baa99339 # 命名空间ID
group: cxyxj
调用接口测试
请求接口:http://localhost:9004/get-config-info
Nacos 多配置文件配置
在实际开发应用中,一般很少将所有的配置内容放在单个配置文件中,我们会将公用的配置进行抽取。多配置文件配置需要使用到了 extension-configs
进行配置,老版本中使用config.ext-config
。
新建配置文件 mybatis-dev.yaml
新建配置文件 datasource-dev.yaml
所有配置文件
修改 bootstrap.yml
server:
port: 9004
spring:
application:
name: nacos-config-start
profiles:
active: dev
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # Nacos 服务地址
namespace: fde7e3e9-6e44-45c3-b04e-34e4baa99339 # 命名空间ID
config:
erver-addr: 127.0.0.1:8848 # Nacos 服务地址
file-extension: yaml # 指定yaml格式的配置
namespace: fde7e3e9-6e44-45c3-b04e-34e4baa99339 # 命名空间ID
group: cxyxj
extension-configs[0]:
dataId: datasource-${spring.profiles.active}.yaml
group: cxyxj
refresh: true
extension-configs[1]:
dataId: mybatis-${spring.profiles.active}.yaml
group: cxyxj
refresh: true
修改业务接口
@Value("${config.info}")
private String configInfo;
@Value("${mybatis-dev}")
private String mybatisDev;
@Value("${datasource-dev}")
private String datasourceDev;
@RequestMapping("/get-config-info")
public String getConfigInfo() {
return configInfo + ",datasourceDev = " + datasourceDev + ",mybatisDev" + mybatisDev;
}
请求接口:localhost:9004/get-config-info
下一篇介绍 Nacos 集群架构以及持久化
。
转载自:https://juejin.cn/post/7352661916387622950