一、SpringCloud Alibaba 入门简介
1、为什么会出现 SpringCloud Alibaba
SpringCloud Netflix 项目进入了维护模式。Spring Cloud Greenwich.RC1 available now
将模块处于维护模块意味着 Spring Cloud Netflix 团队将不会再向模块添加新功能。
2、SpringCloud Alibaba 带来了什么
官网:https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md
2018.10.31,SpringCloud Alibaba 正式入驻了 SpringCloud 官方孵化器,并在 Maven 中央库发布了第一个版本。
SpringCloud Alibaba可以干什么?
- 服务限流降级:默认支持 Servlet、Feign、RestTemplate、Dubbo 和 RocketMQ 限流降级功能的借入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。
- 服务注册与发现:适配 SpringCloud 服务注册与发现,默认集成了 Ribbon 的支持。
- 分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新。
- 消息驱动能力:基于 SpringCloud Stream 为微服务应用构建消息驱动能力。
- 阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。
- 分布式任务调度:提供秒级、精准、高可靠的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有 Worker(Schedule-client)上执行。
- 阿里云短信服务:覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。
SpringCloud Alibaba 包含的组件:
- Sentinel:阿里巴巴开源产品,把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
- Nacos:阿里巴巴开源产品,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
- RocketMQ:Apache RocketMQ™基于 Java 的高性能、高吞吐量的分布式消息和流计算平台。
- Dubbo:Apache Dubbo™ 是一款高性能 Java RPC 框架。
- Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。
- Alibaba Cloud OSS:阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
- Alibaba Cloud SchedulerX:阿里中间件团队开发的一款分布式任务调度产品,支持周期性的任务与固定时间点触发任务。
- Alibaba Cloud SMS:覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。
3、SpringCloud Alibaba 学习资料获取
中文:
- spring-cloud-alibaba/Roadmap-zh.md at master · alibaba/spring-cloud-alibaba · GitHub
- https://nacos.io/zh-cn/
二、SpringCloud Alibaba Nacos 服务注册中心和配置中心
1、Nacos 简介
1.1 Nacos 是什么?
Nacos 是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
Nacos:Dynamic Naming And Configuration Service
Nacos:就是注册中心+配置中心的组合
Nacos = Eureka + Config + Bus
1.2 Nacos 能干嘛
替代 Eureka 做服务注册中心
替代 Config 做服务配置中心
1.3 去哪里下载
Nacos官网: ,点击版本说明
点击 Tags
自行选择一个合适的版本下载
本人下载的是 2.0.2,拉到页面的最下方,点击下载(.zip 是window 版本,.tar.gz 是linux 版本)。
1.4 各注册中心比较
据说 Nacos 在阿里巴巴内部有超过 10万 的实例运行,已经过了双十一等各种大型流量的考验。
2、Nacos 安装
本地 Java8+Maven环境已经OK。
前期准备(本人运行环境 Win10):
- 如果是只有单台机器,则需要修改 nacos/bin/startup.cmd 启动文件,将 MODE 修改为单例 standalone
- 修改 nacos/conf/application.properties ,配置数据库,注意数据库名称和用户名密码
- 在本地 数据库执行 nacos/conf/nacos-mysql.sql 的语句
双击 nacos/bin/startup.cmd 启动,如下则表示启动成功
命令运行成功后直接访问 http://localhost:8848/nacos , 默认账号密码都是 nacos
3、Nacos 作为服务注册中心演示
3.1 基于 Nacos 的服务提供者
新建 Module :cloudalibaba-provider-payment9001
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">
<parent>
<artifactId>cloud-study</artifactId>
<groupId>com.cloud.study</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudalibaba-provider-payment9001</artifactId>
<dependencies>
<!-- alibaba-nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 引入自己的 cloud-api-commons 模块-->
<dependency>
<groupId>com.cloud.study</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<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>
<!--开启热部署-->
<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>
<!-- test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
在 父 POM 引入了 spring-cloud-alibaba-dependencies 的依赖,如下图:
<!-- SpringCloud Alibaba 2.2.6.RELEASE --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.2.6.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency>
YAML
server:
port: 9001
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848
#暴露监控端点
management:
endpoints:
web:
exposure:
include: "*"
主启动
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain9001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain9001.class, args);
}
}
业务类
@RestController
public class PaymentController {
@Value("${server.port}")
private String serverPort;
@GetMapping("/payment/nacos/{id}")
public String getPayment(@PathVariable("id") Integer id){
return "nacos registry, serverPort: " + serverPort + "\t id:"+id;
}
}
测试,启动 9001
为了下一章节演示 nacos的负载均衡效果,参照 9001
新建 cloudalibaba-provider-payment9002
3.2 基于 Nacos 的服务消费者
新建 Module: cloudalibaba-consumer-order83
POM
<dependencies>
<!-- alibaba-nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 引入自己的 cloud-api-commons 模块-->
<dependency>
<groupId>com.cloud.study</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<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>
<!--开启热部署-->
<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>
<!-- test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
yaml
server:
port: 83
spring:
application:
name: nacos-order-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848
#消费者将要去访问的微服务名称(注册成功的微服务提供者)
service-url:
nacos-user-service: http://nacos-payment-provider
主启动
@SpringBootApplication
@EnableDiscoveryClient
public class OrderMain83 {
public static void main(String[] args) {
SpringApplication.run(OrderMain83.class, args);
}
}
业务类
@RestController
@Slf4j
public class OrderNacosController {
@Resource
private RestTemplate restTemplate;
@Value("${service-url.nacos-user-service}")
private String serverURL;
@GetMapping("/consumer/payment/nacos/{id}")
public String getPayment(@PathVariable("id") Integer id){
return restTemplate.getForObject(serverURL+"/payment/nacos/"+id, String.class);
}
}
配置类
@Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
测试
- 启动83,在 Nacos 控制台可以看到微服务注册上来了
- 多刷新几次 http://localhost:83/consumer/payment/nacos/1 ,发现输出的端口不同,实现了负载均衡。
3.3 服务注册中心对比
Nacos 支持 AP 和 CP 模式的切换:
C 是所有节点在同一时间看到的数据是一致的;而 A 的定义是所有的请求都会受到响应。
合适选择用何种模式?
一般来说,如果不需要存储服务级别的信息,且服务实例是通过 nacos-client 注册,并能够保持心跳上报,那么就可以选择 AP 模式。当前主流的服务如 Spring Cloud 和 Dubbo 服务,都使用 AP 模式, AP 模式为了服务的可能性而减弱了一致性,因此 AP 模式下只支持注册临时实例。
如果需要在服务级别编辑或存储配置信息,那么 CP 是必须的,K8S 服务 和 DNS 服务使用 CP 模式。CP模式下则支持注册持久化实例,此时则是以 Raft 协议为集群运行模式,该模式下注册实例之前必须先注册服务,如果服务不存在,则会返回错误。
切换并启动 nacos 服务的模式:
curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'
4、Nacos 作为服务配置中心演示
4.1 Nacos 作为配置中心-基础配置
新 Module : cloudalibaba-config-nacos-client3377
POM
<dependencies>
<!-- alibaba-config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- alibaba-nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 引入自己的 cloud-api-commons 模块-->
<dependency>
<groupId>com.cloud.study</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</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>
<!--开启热部署-->
<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>
<!-- test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
yaml:Nacos 与 SpringCloud-config 一样,在项目初始化时,要保证先从配置中心进行配置拉取,拉取配置后,才能保证项目的正常启动。bootstrap 优先级高于 application。
- bootstrap.yaml
server:
port: 3377
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos 服务注册中心
config:
server-addr: localhost:8848 #Nacos 配置中心
file-extension: yaml #指定 yaml 格式的配置
- application.yaml
spring:
profiles:
active: dev # 表示开发环境
主启动
@SpringBootApplication
@EnableDiscoveryClient
public class NacosConfigClientMain3377 {
public static void main(String[] args) {
SpringApplication.run(NacosConfigClientMain3377.class, args);
}
}
业务类
@RestController
@RefreshScope //支持Nacos的动态刷新功能
public class ConfigClientController {
@Value("${config.ingo}")
private String configInfo;
@GetMapping("/config/info")
public String getConfigInfo(){
return configInfo;
}
}
在Nacos中添加配置信息
最后的公式为:
${spring.application.name}-${spring.profiles.active}.${file-extension}
根据上述 yaml 得出 dataid = 【nacos-config-client-dev.yaml】
- 点击【配置列表】中的“添加”按钮
- 在 输入页面 输入【Data Id】,配置格式,配置内容,然后发布。
注意:【Data Id】的“${file-extension}”必须为 yaml,不能是 yml,否则会有问题 。
测试
- 访问 http://localhost:3377/config/info ,可以得到 配置的信息。
- 自带动态刷新:我们在修改【nacos-config-client-dev.yaml】的配置,刷新 http://localhost:3377/config/info 发现输出的配置是最新的。
4.2 Nacos 作为配置中心-分类配置
问题
问题1
实际开发中,通常一个系统会准备:
- dev 开发环境
- test 测试环境
- prod 生成环境
如何保证指定环境启动时能正确读取到 Nacos 上相应环境的配置文件呢?
问题2
一个大型分布式微服务系统会有很多微服务子项目,每个微服务项目又会有相应的开发环境、测试环境、预发环境、正式环境....
那怎么对这些微服务配置进行管理呢?
Nacos管理后台图形化界面
Nacos 配置管理界面
Nacos 命名空间,public 是保留的
Namespace + Group + Data ID 三者关系?为什么这么设计?
1、是什么
类似Java里面的 package 名和类名,最外层的 Namespace 是可以用于区分部署环境的,Group 和 Data ID 逻辑上区分两个目标对象。
2 三者情况
3.默认情况
- Namespace = public
- Group = DEFAULT_GROUP
- Cluster = DEFAULT
Nacos 默认的命名空间是 public,Namespace 主要用来实现隔离。比方说我们现在有三个环境:开发、测试、生成环境,我们就可以创建三个 Namespace,不同的 Namespace 之间是隔离的。
Group 默认是 DEFAULT_GROUP,Group 可以把不同的微服务划分到同一分组里面去。
Service 就是微服务,一个 Service 可以包含多个 Cluster(集群),Nacos 默认 Cluster 是 DEFAULT,Cluster 是对指定微服务的一个虚拟划分。比方说为了容灾,将 Service 微服务分别部署在了杭州机房和广州机房,这时就可以给杭州机房的 Service 微服务起一个集群名称(HZ),给广州机房的 Service 微服务起一个集群名称(GZ),还可以尽量让同一个机房的微服务互相调用,以提升性能。
最后 Instance,就是微服务的实例。
案例 - DataID 方案
指定 spring.profile.active 和 配置文件的 DataId来使不同环境下读取不同的配置。
默认空间 + 默认分组 + 新建 dev 和 test 两个 DataID
通过 spring.profile.active 属性就能进行多环境下配置文件的读取
测试
- 当 spring.profile.active 是 dev 时,读取的内容为 nacos-config-client-dev.yaml 的 config.info
- 当 spring.profile.active 是 test 时,读取的内容为 nacos-config-client-test.yaml 的 config.info
案例 - Group 方案
通过 Group 实现环境区分,新建 Group(注意,组名为 DEV_GROUP)
配置完成后,如下图:
在 bootstrap.yaml 文件下增加一条 group 的配置(DEV_GROUP或TEST_GROUP),同时将application.yaml 的 spring.profile.active 配置为 info。
根据 spring.cloud.nacos.config.group 的值,来读取不同配置文件的配置。
案例 - Namespace 方案
新建 dev/tes 的 Namespace
回到服务管理-配置列表查看
按照域名配置新建配置
YAML:新增 namespace 配置(namespace 的 内容为 namespaceID)
5、Nacos 集群和持久化配置(重要)
5.1 官网说明
https://nacos.io/zh-cn/docs/cluster-mode-quick-start.html
我们理解官网架构图,自行翻译后的架构图如下:
默认 Nacos 使用嵌入式数据库实现数据的存储。所以,如果启动多个默认配置下的 Nacos 节点,数据存储是存在一致性问题的。为了解决这个问题,Nacos 采用了 集中式存储的方式来支持集群化部署,目前只支持 Mysql 的存储。
Nacos 支持三种部署模式:
- 单机模式-用于测试和单机测试。
- 集群模式-用于生产环境,确保高可用。
- 多集群模式-用于多数据中心场景。
5.2 准备环境-服务器ip说明
nacos(192.168.65.128、192.168.65.129)
mysql(192.168.65.128)
nginx(192.168.65.130)
5.3.linux下 mysql初始化(192.168.65.128)
在 0.7 版本之前,在单机模式时,Nacos 使用嵌入式数据库实现数据的存储,不方便观察数据存储的基本情况。0.7版本之火增加了支持 mysql 数据源能力,具体的操作步骤:
- 安装数据库,版本要求:5.6.5+
- 初始化 数据库初始化文件: nacos-mysql.sql
5.4 Linux版 Nacos
安装 nacos 需要 JAVA_HOME 环境变量,请参考 linux 下安装jdk源码_chenjian723122704的专栏-CSDN博客
Nacos 下载Linux 版 :https://github.com/alibaba/nacos/releases/tag/2.0.2
在两台服务器上上传 nacos-server-2.0.2.tar.gz,并解压(我解压到 /usr/soft)。
修改 application.properties 配置文件中 数据库部分:
修改集群配置 conf/cluster.conf
192.168.65.128:8848
192.168.65.129:8848
启动nginx:切换到 nacos/bin 目录下,执行 startup.sh
./startup.sh
输入网址 http://192.168.65.129:8848/nacos 、http://192.168.65.129:8848/nacos 分表能访问成功说明安装成功。
5.5 Nginx 的配置,由它作为负载均衡器
在 192.168.65.130 安装好nginx。
在 Nginx 配置文件中配置两台 Nacos 服务器的负载均衡,如下图。
启动 nacos
在浏览器输入 http://192.168.65.130/nacos/ ,可以访问到我们的 nacos 页面。
当停止 192.168.65.128、192.168.65.129 中的任何一个 nacos 服务时,http://192.168.65.130/nacos/ 都能正常访问;当两台 nacos 服务都停止时,则访问 http://192.168.65.130/nacos/ 出现报错页。
5.5 改造 cloudalibaba-config-nacos-client3377
在 linux 的 Nacos 增加如下配置
cloudalibaba-config-nacos-client3377 的 bootstrap.yaml 如下:
server:
port: 3377
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: 192.168.65.130:80 #Nacos 服务注册中心
config:
server-addr: 192.168.65.130:80 #Nacos 配置中心
file-extension: yaml #指定 yaml 格式的配置
application.yaml 如下
spring:
profiles:
active: info
启动 cloudalibaba-config-nacos-client3377 正常。访问 http://localhost:3377/config/info ,能正常得到我们的配置。