目录
- 前言
- 11 SpringCloud Bus 消息总线
-
- 11.1 概述
- 11.2 RabbitMQ环境配置
- 11.3 SpringCloud Bus动态刷新全局广播
- 11.4 SpringCloud Bus动态刷新定点通知
- 12 SpringCloud Stream 消息驱动
- 13 SpringCloud Sleuth分布式请求链路跟踪
- 14 SpringCloud Alibaba入门简介
- 15 SpringCloud Alibaba Nacos服务注册和配置中心
- 16 SpringCloud Alibaba Sentinel实现熔断与限流
- 17 SpringCloud Alibaba Seata处理分布式事务
-
- 17.1 分布式事务问题
- 17.2 Seata简介
- 17.3 Seata-Server安装
- 17.4 订单/库存/账户业务数据库准备
- 17.5 订单/库存/账户业务微服务准备
- 17.6 Test
- 17.7 一部分补充
- 后记
前言
springcloud的续集,上半部分。
11 SpringCloud Bus 消息总线
11.1 概述
上一讲解的加深和扩充,一言以蔽之。
- 分布式自动刷新配置功能
- Spring Cloud Bus 配合 Spring Cloud Config 使用可以实现配置的动态刷新。
11.1.2 是什么
Bus支持两种消息代理:RabbitMQ 和 Kafka
11.1.3 能干嘛
11.1.4 为何被称为总线
11.2 RabbitMQ环境配置
11.2.1 安装Erlang
- 下载地址
- 步骤
11.2.2 安装RabbitMQ
- 下载地址
- 安装步骤
11.2.3 进入RabbitMQ安装目录下的sbin目录
11.2.4 输入以下命令启动管理功能
rabbitmq-plugins enable rabbitmq_management
注意这里有一个问题需要解决。
- 可视化插件
11.2.5 访问地址查看是否安装成功
-
http://localhost:15672/
-
输入账号密码并登录:guest guest
11.3 SpringCloud Bus动态刷新全局广播
11.3.1 必须先具备良好的RabbitMQ环境
11.3.2 演示广播效果,增加复杂度,再以3355为模板再制作一个3366
[1] cloud-config-client-3366
[2] 改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>mscloud03</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-config-client-3366</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</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>
<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>
[3] 写YML
server:
port: 3366
spring:
application:
name: config-client
cloud:
#Config客户端配置
config:
label: master #分支名称
name: config #配置文件名称
profile: dev #读取后缀名称 上述3个综合:master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/master/config-dev.yml
uri: http://localhost:3344 #配置中心地址
#服务注册到eureka地址
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
# 暴露监控端点
management:
endpoints:
web:
exposure:
include: "*"
[4] 主启动
@EnableEurekaClient
@SpringBootApplication
public class ConfigClientMain3366
{
public static void main(String[] args)
{
SpringApplication.run(ConfigClientMain3366.class,args);
}
}
[5] controller
@RestController
@RefreshScope
public class ConfigClientController
{
@Value("${server.port}")
private String serverPort;
@Value("${config.info}")
private String configInfo;
@GetMapping("/configInfo")
public String configInfo()
{
return "serverPort: "+serverPort+"\t\n\n configInfo: "+configInfo;
}
}
11.3.3 设计思想
[1] 第一种设计思想
利用消息总线触发一个客户端/bus/refresh,从而刷新所有客户端的配置。
发送到一个上,然后由这一个继而传递到其他。
[2] 第二种设计思想
利用消息总线触发一个服务端ConfigServer的/bus/refresh端点,从而刷新所有客户端的配置。
[3] 选择第二种设计思想原因
第一种设计思想有下面的几个原因:
- 打破了微服务的职责单一性,因为微服务本身是业务模块,它本不应该承担配置刷新的职责。
- 破坏了微服务各节点的对等性
- 有一定的局限性。例如,微服务在迁移时,它的网络地址常常会发生变化,此时如果想要做到自动刷新,那就会增加更多的修改
11.3.4 给cloud-config-center-3344配置中心服务端添加消息总线支持
POM
YML
11.3.5 给cloud-config-client-3355客户端添加消息总线支持
pom
YML
11.3.6 给cloud-config-client-3366客户端添加消息总线支持
pom
YML
11.3.7 测试
[1] 运维工程师
- 修改Github上配置文件增加版本号
- 发送POST请求
curl -X POST "http://localhost:3344/actuator/bus-refresh"
一次发送,处处生效
[2] 配置中心
http://config-3344.com:3344/config-dev.yml
[3] 客户端
http://localhost:3355/configInfo
http://localhost:3366/configInfo
- 获取配置信息,发现都已经刷新了
一次修改,广播通知,处处生效
11.4 SpringCloud Bus动态刷新定点通知
11.4.1 不想全部通知,只想定点通知
- 只通知3355
- 不通知3366
11.4.2 简单一句话
- 指定具体某一个实例生效而不是全部
- 公式:
http://localhost:配置中心的端口号/actuator/bus-refresh/{destination}
- /bus/refresh请求不再发送到具体的服务实例上,而是发给config server并 通过destination参数类指定需要更新配置的服务或实例
11.4.3 案例
[1] 我们这里以刷新运行在3355端口上的config-client为例
- 只通知3355
- 不通知3366
[2] 发送请求
curl -X POST "http://localhost:3344/actuator/bus-refresh/config-client:3355"
11.4.4 通知总结All
12 SpringCloud Stream 消息驱动
12.1 消息驱动概述
12.1.1 是什么
[1] 一句话
屏蔽底层消息中间件的差异,降低切换成本,统一消息的编程模型.
[2] 官网
Spring Cloud Stream是用于构建与共享消息传递系统连接的高度可伸缩的事件驱动微服务框架,该框架提供了一个灵活的编程模型,它建立在已经建立和熟悉的Spring熟语和最佳实践上,包括支持持久化的发布/订阅、消费组以及消息分区这三个核心概念.
官网
官网文档
Spring Cloud Stream中文指导手册
12.1.2 设计思想
[1] 标准MQ
-
生产者/消费者之间靠消息媒介传递信息内容
- OUTPUT对应于生产者
- 消息必须走特定的通道
- 消息通道MessageChannel - 消息通道里的消息如何被消费呢,谁负责收发处理
- 消息通道MessageChannel的子接口SubscribableChannel,由MessageHandler消息处理器所订阅
[2] 为什么用Cloud Stream
- stream凭什么可以统一底层差异?
2. Binder
INPUT对应于消费者
OUTPUT对应于生产者
[3] Stream中的消息通信方式遵循了发布-订阅模式
Topic主题进行广播
- 在RabbitMQ就是Exchange
- 在Kakfa中就是Topic
12.1.3 Spring Cloud Stream标准流程套路
[1] Binder
很方便的连接中间件,屏蔽差异
[2] Channel
通道,是队列Queue的一种抽象,在消息通讯系统中就是实现存储和转发的媒介,通过Channel对队列进行配置
[3] Source和Sink
简单的可理解为参照对象是Spring Cloud Stream自身,从Stream发布消息就是输出,接受消息就是输入。
12.1.4 编码API和常用注解
12.2 案例说明
12.2.1 RabbitMQ环境已经OK
12.2.2 工程中新建三个子模块
- cloud-stream-rabbitmq-provider8801, 作为生产者进行发消息模块
- cloud-stream-rabbitmq-consumer8802,作为消息接收模块
- cloud-stream-rabbitmq-consumer8803 作为消息接收模块
12.3 消息驱动之生产者
12.3.1 新建Module cloud-stream-rabbitmq-provider8801
12.3.2 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>mscloud</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-stream-rabbitmq-provider8801</artifactId>
<dependencies>
<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.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
<!--基础配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<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>
12.3.3 YML
server:
port: 8801
spring:
application:
name: cloud-stream-provider
cloud:
stream:
binders: # 在此处配置要绑定的rabbitmq的服务信息;
defaultRabbit: # 表示定义的名称,用于于binding整合
type: rabbit # 消息组件类型
environment: # 设置rabbitmq的相关的环境配置
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
bindings: # 服务的整合处理
output: # 这个名字是一个通道的名称
destination: studyExchange # 表示要使用的Exchange名称定义
content-type: application/json # 设置消息类型,本次为json,文本则设置“text/plain”
binder: defaultRabbit # 设置要绑定的消息服务的具体设置
eureka:
client: # 客户端进行Eureka注册的配置
service-url:
defaultZone: http://localhost:7001/eureka
instance:
lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
instance-id: send-8801.com # 在信息列表时显示主机名称
prefer-ip-address: true # 访问的路径变为IP地址
12.3.4 主启动类StreamMQMain8801
@SpringBootApplication
public class StreamMQMain8801
{
public static void main(String[] args)
{
SpringApplication.run(StreamMQMain8801.class,args);
}
}
12.3.5 业务类
[1] 发送消息接口
public interface IMessageProvider
{
public String send() ;
}
[2] 发送消息接口实现类
@EnableBinding(Source.class) // 可以理解为是一个消息的发送管道的定义
public class MessageProviderImpl implements IMessageProvider
{
@Resource
private MessageChannel output; // 消息的发送管道
@Override
public String send()
{
String serial = UUID.randomUUID().toString();
this.output.send(MessageBuilder.withPayload(serial).build()); // 创建并发送消息
System.out.println("***serial: "+serial);
return serial;
}
}
[3] Controller
@RestController
public class SendMessageController
{
@Resource
private IMessageProvider messageProvider;
@GetMapping(value = "/sendMessage")
public String sendMessage()
{
return messageProvider.send();
}
}
12.3.6 测试
- 启动7001eureka
- 启动rabbitmq
- rabbitmq-plugins enable rabbitmq_management
- http://localhost:15672/
- 启动8801
- 访问
http://localhost:8801/sendMessage
12.4 消息驱动之消费者
12.4.1 新建Module cloud-stream-rabbitmq-consumer8802
12.4.2 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>mscloud</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-stream-rabbitmq-provider8801</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</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>
<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>
12.4.3 YML
server:
port: 8802
spring:
application:
name: cloud-stream-consumer
cloud:
stream:
binders: # 在此处配置要绑定的rabbitmq的服务信息;
defaultRabbit: # 表示定义的名称,用于于binding整合
type: rabbit # 消息组件类型
environment: # 设置rabbitmq的相关的环境配置
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
bindings: # 服务的整合处理
input: # 这个名字是一个通道的名称
destination: studyExchange # 表示要使用的Exchange名称定义
content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
binder: defaultRabbit # 设置要绑定的消息服务的具体设置
eureka:
client: # 客户端进行Eureka注册的配置
service-url:
defaultZone: http://localhost:7001/eureka
instance:
lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
instance-id: receive-8802.com # 在信息列表时显示主机名称
prefer-ip-address: true # 访问的路径变为IP地址
12.4.4 主启动类StreamMQMain8802
@SpringBootApplication
public class StreamMQMain8802
{
public static void main(String[] args)
{
SpringApplication.run(StreamMQMain8802.class,args);
}
}
12.4.5 业务类
@Component
@EnableBinding(Sink.class)
public class ReceiveMessageListener
{
@Value("${server.port}")
private String serverPort;
@StreamListener(Sink.INPUT)
public void input(Message<String> message)
{
System.out.println("消费者1号,------->接收到的消息:" + message.getPayload()+"\t port: "+serverPort);
}
}
12.4.6 测试
测试8801发送8802接收消息 http://localhost:8801/sendMessage
12.5 分组消费与持久化
12.5.1 依照8802,clone出来一份运行8803
cloud-stream-rabbitmq-consumer8803
[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">
<parent>
<artifactId>mscloud</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-stream-rabbitmq-provider8803</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</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>
<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>
[2] yml
server:
port: 8803
spring:
application:
name: cloud-stream-consumer
cloud:
stream:
binders: # 在此处配置要绑定的rabbitmq的服务信息;
defaultRabbit: # 表示定义的名称,用于于binding整合
type: rabbit # 消息组件类型
environment: # 设置rabbitmq的相关的环境配置
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
bindings: # 服务的整合处理
input: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
destination: studyExchange # 表示要使用的Exchange名称定义
content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
binder: defaultRabbit # 设置要绑定的消息服务的具体设置
eureka:
client: # 客户端进行Eureka注册的配置
service-url:
defaultZone: http://localhost:7001/eureka
instance:
lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
instance-id: receive-8803.com # 在信息列表时显示主机名称
prefer-ip-address: true # 访问的路径变为IP地址
[3] 主启动类
@SpringBootApplication
public class StreamMQMain8803
{
public static void main(String[] args)
{
SpringApplication.run(StreamMQMain8803.class,args);
}
}
[4] 业务类
@Component
@EnableBinding(Sink.class)
public class ReceiveMessageListener
{
@Value("${server.port}")
private String serverPort;
@StreamListener(Sink.INPUT)
public void input(Message<String> message)
{
System.out.println("消费者2号,------->接收到的消息:" + message.getPayload()+"\t port: "+serverPort);
}
}
12.5.2 启动
12.5.3 运行后存在问题
- 有重复消费问题
- 消息持久化问题
12.5.4 消费
目前是8802/8803同时都收到了,存在重复消费问题
-
http://localhost:8801/sendMessage
-
如何解决
分组和持久化属性group -
生产实际案例
12.5.5 分组
[1] 原理
微服务应用放置于同一个group中,就能够保证消息只会被其中一个应用消费一次。
不同的组是可以重复消费的,同一个组内会发生竞争关系,只有其中一个可以消费。
[2] 8802/8803都变成不同组,group两个不同
- group: atguiguA、atguiguB
- 8802修改YML
- 8803修改YML
- 我们自己配置
- 结论
还是重复消费,因为是不同组,是可以重复消费的。
[3] 8802/8803都变成相同组,group两个相同
- group: atguiguA
- 8802修改YML
3. 8803修改YML
4. 结论
- 同一个组的多个微服务实例,每次只会有一个拿到
- 8802/8803实现了轮询分组,每次只有一个消费者;8801模块的发的消息只能被8802或8803其中一个接收到,这样避免了重复消费。
12.5.6 持久化
通过上述,解决了重复消费问题,再看看持久化.
[1] 停止8802/8803并去除掉8802的分组group: atguiguA
8803的分组group: atguiguA没有去掉
[2] 8801先发送4条消息到rabbitmq
[3] 先启动8802,无分组属性配置,后台没有打出来消息
[4] 再启动8803,有分组属性配置,后台打出来了MQ上的消息
[5] 结论
有分组属性,消息生产者发送消息到rabbitmq,即使消息消费者宕机,那么当消息消费者重新启动时会自动从rabbitmq中获取消息生产者发送的消息,保证了消息的持久性,不丢消息。
13 SpringCloud Sleuth分布式请求链路跟踪
13.1 概述
- 为什么会出现这个技术?需要解决哪些问题?
- 是什么
- 官网
- Spring Cloud Sleuth提供了一套完整的服务跟踪的解决方案
- 在分布式系统中提供追踪解决方案并且兼容支持了zipkin
- 解决
13.2 搭建链路监控步骤
13.2.1 zipkin
[1] 下载
- SpringCloud从F版起已不需要自己构建Zipkin Server了,只需调用jar包即可
https://repo1.maven.org/maven2/io/zipkin/zipkin-server/
下载地址- zipkin-server-2.12.9-exec.jar
[2] 运行jar
cmd中运行java -jar zipkin-server-2.12.9-exec.jar
[3] 运行控制台
http://localhost:9411/zipkin/
- 术语
- 完整的调用链路
-
上图what
-
名词解释
- Trace:类似于树结构的Span集合,表示一条调用链路,存在唯一标识
- span:表示调用链路来源,通俗的理解span就是一次请求信息
13.2.2 服务提供者 — 修改cloud-provider-payment8001
[1] POM
[2] YML
[3] 业务类PaymentController
加入以下的这个代码。
@GetMapping("/payment/zipkin")
public String paymentZipkin()
{
return "hi ,i'am paymentzipkin server fall back,welcome to atguigu,O(∩_∩)O哈哈~";
}
13.2.3 服务消费者(调用方) — 修改cloud-consumer-order80
[1] pom
[2] yml
[3] 业务类OrderController
// ====================> zipkin+sleuth
@GetMapping("/consumer/payment/zipkin")
public String paymentZipkin()
{
String result = restTemplate.getForObject("http://localhost:8001"+"/payment/zipkin/", String.class);
return result;
}
13.2.4 依次启动eureka7001/8001/80
80调用8001几次测试下
13.2.5 打开浏览器访问:http://localhost:9411
- 会出现以下界面
- 查看
- 查看依赖关系
- 原理
14 SpringCloud Alibaba入门简介
14.1 why会出现SpringCloud alibaba
14.1.1 Spring Cloud Netflix项目进入维护模式
网址
说明
14.1.2 Spring Cloud Netflix Projects Entering Maintenance Mode
-
什么是维护模式
-
进入维护模式意味着什么呢?
14.2 SpringCloud alibaba带来了什么
14.2.1 是什么
14.2.2 能干嘛
服务限流降级:默认支持 Servlet、Feign、RestTemplate、Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。
服务注册与发现:适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。
分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新。
消息驱动能力:基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。
阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。
分布式任务调度:提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有 Worker(schedulerx-client)上执行。
14.2.3 去哪下
14.3 SpringCloud alibaba学习资料获取
15 SpringCloud Alibaba Nacos服务注册和配置中心
15.1 Nacos简介
15.1.1 为什么叫Nacos
前四个字母分别为Naming和Configuration的前两个字母,最后的s为Service。
15.1.2 是什么
- 一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
- Nacos: Dynamic Naming and Configuration Service
- Nacos就是注册中心 + 配置中心的组合
- Nacos = Eureka+Config +Bus
15.1.3 能干嘛
- 替代Eureka做服务注册中心
- 替代Config做服务配置中心
15.1.4 去哪下
15.1.5 各种注册中心比较
15.2 安装并运行Nacos
15.2.1 本地Java8+Maven环境已经OK
15.2.2 先从官网下载Nacos
15.2.3 解压安装包,直接运行bin目录下的startup.cmd
15.2.4 命令运行成功后直接访问http://localhost:8848/nacos
默认账号密码都是nacos
15.2.5 结果页面
15.3 Nacos作为服务注册中心演示
15.3.1 官网文档
15.3.2 基于Nacos的服务提供者
[1] 新建Module cloudalibaba-provider-payment9001
[2] POM
- 父POM
- 本模块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>mscloud</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudalibaba-provider-payment9001</artifactId>
<dependencies>
<!--SpringCloud ailibaba nacos -->
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--日常通用jar包配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<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>
[3] YML
server:
port: 9001
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848 #配置Nacos地址
management:
endpoints:
web:
exposure:
include: '*'
[4] 主启动
@EnableDiscoveryClient
@SpringBootApplication
public class PaymentMain9001
{
public static void main(String[] args) {
SpringApplication.run(PaymentMain9001.class, args);
}
}
作用:都是能够让注册中心能够发现,扫描到该服务
@EnableEurekaClient只适用于Eureka作为注册中心,@EnableDiscoveryClient 可以是其他注册中心。
[5] 业务类
@RestController
public class PaymentController
{
@Value("${server.port}")
private String serverPort;
@GetMapping(value = "/payment/nacos/{id}")
public String getPayment(@PathVariable("id") Integer id)
{
return "nacos registry, serverPort: "+ serverPort+"\t id"+id;
}
}
[6] 测试
http://localhost:9001/payment/nacos/1
- nacos控制台
- nacos服务注册中心+服务提供者9001都OK了