文章目录
- 前言
- Spring Cloud
-
- Spring框架
- Spring Boot
- Spring Cloud
- Spring Cloud Alibaba
-
- 组件
- 如何使用如何引入依赖
- 如何掌握Spring Cloud Alibaba
-
- 特色
- 内容简介
- 以RocketMQ为例
-
- 下载并启动 RocketMQ
- 引入依赖
- 简单示例
-
- 创建Topic
- 示例代码
- 应用启动
- 消息处理
- 消息发送
- 消息接收
前言
本文从spring和springboot 引出Spring Cloud,紧接着介绍Spring Cloud Alibaba。以及如何快速上手Spring Cloud Alibaba:Spring Cloud Alibaba核心技术与实战案例
Spring Cloud
等等。在我们深入研究Spring Cloud之前,让我们先了解一下Spring和Spring Boot。
Spring框架
我们都知道Spring框架已经存在很长时间了,它提供了以下功能:
- Spring JDBC
- Spring MVC
- Spring Security
- Spring AOP
- Spring ORM(与Hibernate进行映射)
- Spring Test
通过这些功能,Java开发人员过去通常使用Spring MVC开发Web应用程序,然后将Spring应用程序与任何ORM框架(如Hibernate)进行连接。
在那个时代,我们使用JSP页面调用Spring Controller来调用与数据库交互的Service层。然后我们需要运行一个独立的Web服务器(如tomcat),并将war/ear文件放入tomcat中来运行我们的Web应用程序。
很多年前,有一个著名的面试问题:
“如何将Spring与Hibernate集成?” – 我们都知道我们需要执行以下步骤:
- 创建applicatoncontext.xml文件
- 声明数据源并提供配置
- 声明Hibernate Session Factory并与数据源关联
- 最后,将Session Factory映射到Spring框架的HibernateTemplate
在进行了这些配置之后,Spring和Hibernate可以无缝地工作。
Spring Boot
Spring框架有很多功能,它是一个强大的框架,被Java开发人员广泛使用。但正如我们上面讨论的,它仍然存在一些缺点。世界正在朝着松耦合的架构发展,以使用任何可插拔的前端框架,如Angular、React等,但Spring框架与Spring MVC紧密耦合,使用JSP页面。
然后,Spring Boot框架出现了,它用于快速构建与任何UI框架插件相关的REST API。它还通过提供以下功能解决了Spring框架的所有缺点:
- 内嵌的Tomcat服务器
- Spring Data JPA(无需任何配置即可自动连接Hibernate)
- 默认日志记录器的自动记录
- 全局异常处理器(使用AOP来处理异常)
- 自动配置
- 内存数据库(非常适用于执行单元测试用例)
- Starter依赖项
在Spring Boot和微服务进化之后,传统的Spring框架的使用量已经减少,几乎每个组织都已经迁移到了Spring Boot,这是开发生产级Java Web应用程序的现代方式。
Spring Cloud
现在让我们来看看Spring Cloud领域。正如前面讨论的,Spring Boot用于编写独立的Java Web应用程序。那么如何配置它与外部系统或组件一起使用呢?答案是Spring Cloud。是的,你没听错。
Spring Cloud提供了以下对于现代分布式系统非常关键的功能:
-
分布式/版本化配置
一个集中的配置服务器用于维护应用程序配置
这可以与代码仓库分开维护,并且易于管理 -
服务注册和发现
所有服务都将其标识注册到注册服务器,其中最著名的是Eureka。
连接到中央服务器的客户端可以更新和检索地址。 -
服务间调用
服务可以通过以下步骤相互发现以进行通信:- 注册服务
- 获取注册表
- 查找下游服务
- 解析底层IP地址
- 使用RestTemplate调用REST端点
-
负载均衡
负载均衡的目标是最大化吞吐量,最小化响应时间,提高效率和优化资源使用。
使用带有负载均衡的多个组件可以通过冗余提高可靠性和可用性。
Eureka依赖项具有名为Ribbon的内置负载均衡器,它在单个服务的实例之间平衡负载。 -
断路器
当调用另一个微服务/另一个系统的API失败时,断路器用作回退机制。
它们使得打开和关闭电路以及在失败情况下该做什么成为可能。断路器能够优雅地处理这些故障。
Spring Boot中广泛使用的断路器是resilience4j。 -
API网关
Spring Cloud Gateway是为Spring Boot应用程序设计的API网关。它具有以下功能:- 基于Spring框架5、项目反应器和Spring Boot 2.0构建
- 能够根据任何请求属性匹配路由
- 谓词和过滤器特定于路由
- 断路器集成
- Spring Cloud Discovery Client集成
- 易于编写谓词和过滤器
- 请求速率限制
- 路径重写
-
Spring Cloud安全
Spring Security集成,提供身份验证和授权
支持JWT令牌验证
Spring Cloud Security通过使用Spring Boot和Spring Security OAuth2提供了一组用于构建安全应用程序的基本功能
我们可以快速创建实现单点登录、令牌中继和令牌交换等常见模式的系统。 -
分布式跟踪
跟踪在微服务中非常有用,因为来自客户端的请求可能在多个微服务之间传递。对于开发人员来说,查看请求在服务之间的状态是至关重要的,而Spring Cloud通过提供以下依赖项来解决这个问题
我们可以向项目中添加Spring Cloud Sleuth库以启用跟踪。Sleuth负责记录时间,并生成用于延迟分析的请求ID。有了这个请求ID,我们可以跟踪请求在服务之间的传递情况。
Zipkin是一种专为分析微服务架构内的延迟问题而设计的分布式跟踪工具。它公开了用于收集输入数据的HTTP端点。如果我们需要向项目中添加跟踪功能,我们应该添加spring-cloud-starter-Zipkin依赖项。 -
分布式消息传递
Spring Cloud Bus通过轻量级消息代理将分布式系统的节点连接起来。然后可以使用AMQP和其他消息传递协议来广播应用程序中的状态更改。
这是微服务中非常常见的一种用例,通过将消息推送到RabbitMQ、Kafka、AWS SQS等实现异步通信。
Spring Cloud Stream是Spring Cloud中的另一个框架,用于构建与共享消息系统连接的高度可扩展的事件驱动微服务。它用于流处理。
正如我们上面所看到的,Spring Cloud具有许多用于分布式系统通信的功能,我们可以包含所需的依赖项并非常容易地使用它。
简而言之,Spring Boot是用于开发独立的微服务应用程序的应用程序,而Spring Cloud用于配置这些服务之间的通信。因此,为了实现生产级微服务系统,两者都是必需的。
Spring Cloud Alibaba
Spring Cloud作为微服务的大管家,可以管理众多微服务,因此需要很多小助手来提供帮助。
pring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。
组件
-
Sentinel:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
-
Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
-
RocketMQ:一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。
-
Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。
-
Alibaba Cloud OSS: 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
-
Alibaba Cloud SchedulerX: 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。
-
Alibaba Cloud SMS: 覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。
如何使用如何引入依赖
如果需要使用已发布的版本,在 dependencyManagement 中添加如下配置。
com.alibaba.cloud
spring-cloud-alibaba-dependencies
2022.0.0.0-RC2
pom
import
然后在 dependencies 中添加自己所需使用的依赖即可使用。
如何掌握Spring Cloud Alibaba
为了让大家快速上手掌握Spring Cloud Alibaba,给大家推荐一本书《Spring Cloud Alibaba核心技术与实战案例》
京东链接:https://item.jd.com/14010448.html
特色
不留遗漏:全面覆盖Dubbo核心知识点
直击要害:实战化案例精准定位技术细节
学以致用:精要式演示确保开发、学习不脱节
潜移默化:研磨式知识讲解渗透技术要点
提升效率:垂直式技术精讲不饶弯路
循序提升:渐进式知识点编排确保连贯
配套资源:赠送全书案例源文件助力学习
内容简介
本书从分布式系统的基础概念讲起,逐步深入分布式系统中间件Spring Cloud Alibaba进阶实战,重点介绍了使用Spring Cloud Alibaba框架整合各种分布式组件的完整过程,让读者不但可以系统地学习分布式中间件的相关知识,
而且还能对业务逻辑的分析思路、实际应用开发有更为深入的理解。
全书共分5大章节,第1章开篇部分,讲解分布式系统的演进过程和Spring Cloud Alibaba概述及版本的选择,以及单体架构/微服务架构的优缺点;
第2章讲解如何使用Spring Cloud Alibaba实现RPC通讯;
第3章在介绍主流Nacos组件时,介绍了三元的概念以及使用Nacos实现注册中心和配置中心,包含环境的动态切换、配置的动态刷新、通用型配置、版本回滚等核心技术,为微服务环境提供基础的架构;
第4章介绍了负责限流和熔断降级的Sentinel组件,包含收集系统运行状态、流量控制、熔断降级、热点、授权、系统规则、流控的异常处理、熔断的异常处理、规则持久化等;
第5章介绍了网关常用案例,以及在软件项目中常用的高频使用技术点,力求为开发微服务项目的程序员提供一个快速学习的捷径。
本书内容由浅入深、结构清晰、实例丰富、通俗易懂、实用性强,适合需要全方位学习Spring Cloud Alibaba相关技术的人员,也适合培训学校作为培训教材,还可作为大、中专院校相关专业的教学参考书。
以RocketMQ为例
RocketMQ 是一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。
下载并启动 RocketMQ
在接入 RocketMQ Binder 之前,首先需要启动 RocketMQ 的 Name Server 和 Broker。
-
下载RocketMQ最新的二进制文件,并解压
-
启动 Name Server
sh bin/mqnamesrv
- 启动 Broker
sh bin/mqbroker -n localhost:9876
引入依赖
修改 pom.xml
文件,引入 RocketMQ Stream Starter。
dependency>
groupId>com.alibaba.cloudgroupId>
artifactId>spring-cloud-starter-stream-rocketmqartifactId>
dependency>
简单示例
创建Topic
sh bin/mqadmin updateTopic -n localhost:9876 -c DefaultCluster -t test-topic
示例代码
配置 Input 和 Output 的 Binding 信息并配合 @EnableBinding
注解使其生效
@SpringBootApplication
@EnableBinding({ Source.class, Sink.class })
public class RocketMQApplication {
public static void main(String[] args) {
SpringApplication.run(RocketMQApplication.class, args);
}
}
配置 Binding 信息:
# 配置rocketmq的nameserver地址
spring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876
# 定义name为output的binding
spring.cloud.stream.bindings.output.destination=test-topic
spring.cloud.stream.bindings.output.content-type=application/json
# 定义name为input的binding
spring.cloud.stream.bindings.input.destination=test-topic
spring.cloud.stream.bindings.input.content-type=application/json
spring.cloud.stream.bindings.input.group=test-group
应用启动
- 增加配置,在应用的 /src/main/resources/application.properties 中添加基本配置信息
spring.application.name=rocketmq-example
server.port=28081
-
启动应用,支持 IDE 直接启动和编译打包后启动。
- IDE 直接启动:找到主类
RocketMQApplication
,执行 main 方法启动应用。 - 打包编译后启动:首先执行
mvn clean package
将工程编译打包,然后执行java -jar rocketmq-example.jar
启动应用。
- IDE 直接启动:找到主类
消息处理
使用 name 为 output 对应的 binding 发送消息到 test-topic 这个 topic。
使用2个 input binding 订阅数据。
-
input1: 订阅 topic 为 test-topic 的消息,顺序消费所有消息(顺序消费的前提是所有消息都在一个 MessageQueue 中)
-
input2: 订阅 topic 为 test-topic 的消息,异步消费 tags 为 tagStr 的消息,Consumer 端线程池个数为20
配置信息如下:
spring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876
spring.cloud.stream.bindings.output.destination=test-topic
spring.cloud.stream.bindings.output.content-type=application/json
spring.cloud.stream.bindings.input1.destination=test-topic
spring.cloud.stream.bindings.input1.content-type=text/plain
spring.cloud.stream.bindings.input1.group=test-group1
spring.cloud.stream.rocketmq.bindings.input1.consumer.orderly=true
spring.cloud.stream.bindings.input2.destination=test-topic
spring.cloud.stream.bindings.input2.content-type=text/plain
spring.cloud.stream.bindings.input2.group=test-group2
spring.cloud.stream.rocketmq.bindings.input2.consumer.orderly=false
spring.cloud.stream.rocketmq.bindings.input2.consumer.tags=tagStr
spring.cloud.stream.bindings.input2.consumer.concurrency=20
消息发送
使用 MessageChannel 进行消息发送:
public class ProducerRunner implements CommandLineRunner {
@Autowired
private MessageChannel output; // 获取name为output的binding
@Override
public void run(String... args) throws Exception {
MapString, Object> headers = new HashMap>();
headers.put(MessageConst.PROPERTY_TAGS, "tagStr");
Message message = MessageBuilder.createMessage(msg, new MessageHeaders(headers));
output.send(message);
}
}
或者使用 RocketMQ 原生的 API 进行消息发送:
public class RocketMQProducer {
DefaultMQProducer producer = new DefaultMQProducer("producer_group");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();
Message msg = new Message("test-topic", "tagStr", "message from rocketmq producer".getBytes());
producer.send(msg);
}
消息接收
使用 @StreamListener
注解接收消息:
@Service
public class ReceiveService {
@StreamListener("input1")
public void receiveInput1(String receiveMsg) {
System.out.println("input1 receive: " + receiveMsg);
}
@StreamListener("input2")
public void receiveInput2(String receiveMsg) {
System.out.println("input2 receive: " + receiveMsg);
}
}