什么是Spring Clould
Spring Cloud是由Spring提供的一套能够快速搭建微服务架构程序的框架集
框架集表示Spring Cloud不是一个框架,而是很多框架的统称
Spring Cloud就是为了搭建微服务架构项目出现的
Spring Cloud侠义上就成为"Spring全家桶"。
Spring Cloud主要功能上的分类
- 微服务的注册中心
- 微服务间的调用
- 微服务的分布式事务
- 微服务的限流
- 微服务的网关
注册中心Nacos
什么是Nacos
Nacos是Spring Cloud Alibaba提供的一个软件
这个软件主要具有注册中心和配置中心的功能在本文,我们先学习它注册中心的功能
微服务中所有项目都必须注册到注册中心才能成为微服务的一部分
当前微服务项目中所有的模块,在启动前,必须添加注册到Nacos的配置所谓注册
就是将自己的信息,提交到Nacos来保存。
Nacos的下载地址
Nacos的启动
默认已完成Java的开发环境配置。
文件下载后,文件显示如下
cmd结尾的文件是windows版本的
sh结尾的文件是linux和mac版本的
startup是启动文件,shutdown是停止文件
Windows下启动Nacos
在dos窗口运行,并进去Nacos文件解压后的bin文件夹,输入如下命令
D:\tools\nacos\bin>startup.cmd -m standalone
(或者)在Idea环境下运行
Nacos运行成功的标记
默认端口8848
在浏览器输入地址http://localhost:8848/nacos 可以进去Nacos页面
如果是首次访问,会出现这个界面
登录系统
用户名:nacos
密码:nacos
登录之后可以进入后台列表
不能关闭启动nacos的dos窗口
我们要让我们编写的项目注册到Nacos,才能真正是微服务项目
把项目添加入Nacos
创建项目
以此项目为载体展示 https://gitee.com/wingxu8859_admin/csmallhttps://gitee.com/wingxu8859_admin/csmall
此项目主要实现的需求为,把每一个项目(主要分为订单,购物车,库存三个大类),进行统一管理端口从而实现:新增一个订单=>同时需要减少购物车和减少库存 。
整体实现的逻辑如下图:
上图各个色块的代码设置可以参考下面各图。
csmall项目:
csmall-business项目:
csmall-commons项目:
csmall-order项目及其2个子项目csmall-order-service和csmall-order-webapi:
csmall-cart项目及其2个子项目csmall-cart-service和csmall-cart-webapi:
csmall-order项目及其2个子项目csmall-order-service和csmall-order-webapi:
gateway项目:
Nacos心跳机制
项目配置完成启动后,输入http://localhost:8848/nacos可以进入Nacos页面。
在服务管理=>服务列表里面,可以看到在Nacos注册了的项目。
项目名称写在yml文件里面。
spring:
application:
# 为当前项目起名,这个名字会被Nacos记录并使用
name: nacos-business
cloud:
nacos:
discovery:
# 配置Nacos所在的位置,用于注册时提交信息
server-addr: localhost:8848
sentinel:
transport:
dashboard: localhost:8080
port: 8722
Dubbo概述
什么是RPC
RPC是Remote Procedure Call的缩写 翻译为:远程过程调用
目标是为了实现两台(多台)计算机\服务器,相互调用方法\通信的解决方案
RPC只是实现远程调用的一套标准
该标准主要规定了两部分内容
1.通信协议
2.序列化协议
这个流程可以理解为项目内的功能的调用,类似面向对象编程实例化对象,调用方法的过程
但是这个调用关系如果是远程的
为了方便大家理解RPC,下面的图片帮助理解:
通讯协议
通信协议指的就是远程调用的通信方式
实际上这个通知的方式可以有多种
例如:写信,飞鸽传书,闪送等等
在程序中,通信方式也有多种
序列化协议
序列化协议指通信内容的格式,双方都要理解这个格式
上面的图片中,老婆给老公发信息,一定是双方都能理解的信息
发送信息是序列化过程,接收信息需要反序列化
程序中,序列化的方式也是多种的
什么是Dubbo
上面对RPC有基本认识之后,再学习Dubbo就简单了
Dubbo是一套RPC框架。既然是框架,我们可以在框架结构高度,定义Dubbo中使用的通信协议,使用的序列化框架技术,而数据格式由Dubbo定义,我们负责配置之后直接通过客户端调用服务端代码。
可以说Dubbo就是RPC概念的实现
Dubbo是SpringCloudAlibaba提供的框架
能够实现微服务相互调用的功能!
Dubbo对协议的支持
RPC框架分通信协议和序列化协议
Dubbo框架支持多种通信协议和序列化协议,可以通过配置文件进行修改
Dubbo支持的通信协议
- dubbo协议(默认)
- rmi协议
- hessian协议
- http协议
- webservice
- .....
支持的序列化协议
- hessian2(默认)
- java序列化
- compactedjava
- nativejava
- fastjson
- dubbo
- fst
- kryo
Dubbo默认情况下,支持的协议有如下特征
- 采用NIO单一长链接
- 优秀的并发性能,但是处理大型文件的能力差
Dubbo方便支持高并发和高性能
Dubbo服务的注册与发现
在Dubbo的调用过程中,必须包含注册中心的支持
注册中心推荐阿里自己的Nacos,兼容性好,能够发挥最大性能
但是Dubbo也支持其它软件作为注册中心(例如Redis,zookeeper等)
服务发现,即消费端自动发现服务地址列表的能力,是微服务框架需要具备的关键能力,借助于自动化的服务发现,微服务之间可以在无需感知对端部署位置与 IP 地址的情况下实现通信。
上面RPC的示例中,老婆就是服务的消费端,她能发现老公具备的服务
如果老婆调用了老公的服务,就是完成了Dubbo调用
consumer服务的消费者,指服务的调用者(使用者)也就是老婆的位置
provider服务的提供者,指服务的拥有者(生产者)也就是老公的位置
在Dubbo中,远程调用依据是服务的提供者在Nacos中注册的服务名称
一个服务名称,可能有多个运行的实例,任何一个空闲的实例都可以提供服务
我们当前csmall项目的远程调用关系如下:
Dubbo实现微服务调用
- order模块调用stock模块的减少库存的功能
- order模块调用cart模块的删除购物车的功能
- business模块调用order新增订单的功能
要想实现Dubbo调用
必须按照Dubbo规定的配置和行业标准的结构来实现
Dubbo调用的好处是直接将要消费的目标(例如order模块中消费stock的方法)编写在当前消费者的业务逻辑层中,无需编写新的代码结构,开发流程不会因为Dubbo而变化
@DubboService //为business提供服务
@Service
@Slf4j
public class OrderServiceImpl implements IOrderService {
@Autowired
private OrderMapper orderMapper;
// 添加@DubboReference注解,表示当前业务逻辑层代码,要消费其它模块的服务
// 可以编写当前Nacos中注册的其它模块的业务逻辑层接口
// 因为在Nacos中注册的是接口的实现类,可以实现自动装配实现类的效果
// 先添加stock模块的业务对象,有些公司要求dubbo引用的对象使用dubbo开头
@DubboReference
private IStockService dubboStockService;
@DubboReference
private ICartService dubboCartService;
@Override
public void orderAdd(OrderAddDTO orderAddDTO) {
// 1.减少订单中商品的库存数(要调用stock模块的方法)
// 实例化减少订单业务的DTO对象
StockReduceCountDTO countDTO=new StockReduceCountDTO();
countDTO.setCommodityCode(orderAddDTO.getCommodityCode());
countDTO.setReduceCount(orderAddDTO.getCount());
// dubbo调用stock模块减少库存数的方法
dubboStockService.reduceCommodityCount(countDTO);
// 2.删除订单中选中的购物车的商品(要调用cart模块的方法)
dubboCartService.deleteUserCart(orderAddDTO.getUserId(),
orderAddDTO.getCommodityCode());
// 3.执行将orderAddDTO中的信息新增到订单表中的功能
// 实例化一个Order对象
Order order=new Order();
BeanUtils.copyProperties(orderAddDTO,order);
orderMapper.insertOrder(order);
log.info("新增的订单信息为{}",order);
}
}
负载均衡
什么是负载均衡
在实际项目中,一个服务基本都是集群模式的,也就是多个功能相同的项目在运行,这样才能承受更高的并发
这时一个请求到这个服务,就需要确定访问哪一个服务器
Dubbo框架内部支持负载均衡算法,能够尽可能的让请求在相对空闲的服务器上运行
在不同的项目中,可能选用不同的负载均衡策略,以达到最好效果
Loadbalance:就是负载均衡的意思
Dubbo内置负载均衡策略的算法
Dubbo内置4种负载均衡算法
- random loadbalance:随机分配策略(默认)
- round Robin Loadbalance:权重平均分配
- leastactive Loadbalance:活跃度自动感知分配
- consistanthash Loadbalance:一致性hash算法分配
实际运行过程中,每个服务器性能不同
在负载均衡时,都会有性能权重,这些策略算法都考虑权重问题
随机分配策略
假设我们当前3台服务器,经过测试它们的性能权重比值为5:3:1
下面可以生成一个权重模型
随机生成随机数
在哪个范围内让哪个服务器运行
优点:
算法简单,效率高,长时间运行下,任务分配比例准确
缺点:
偶然性高,如果连续的几个随机请求发送到性能弱的服务器,会导致异常甚至宕机
权重平滑分配
如果几个服务器权重一致,那么就是依次运行
但是服务器的性能权重一致的可能性很小
所以我们需要权重平滑分配
一个优秀的权重分配算法,应该是让每个服务器都有机会运行的
如果一个集群服务器性能比为5:3:1
1>A 2>A 3>A 4>A 5>A 6>B 7>B 8>B 9>C
10>A
上面的安排中,连续请求一个服务器肯定是不好的,我们希望所有的服务器都能够穿插在一起运行
Dubbo2.7之后更新了这个算法使用"平滑加权算法"优化权重平均分配策略
优点:
能够尽可能的在权重要求的情况下,实现请求的穿插运行(交替运行),不会发生随机策略中的偶发情况
缺点
服务器较多时,可能需要减权和复权的计算,需要消耗系统资源
活跃度自动感知
记录每个服务器处理一次请求的时间
按照时间比例来分配任务数,运行一次需要时间多的分配的请求数较少
一致性Hash算法
根据请求的参数进行hash运算
以后每次相同参数的请求都会访问固定服务器
因为根据参数选择服务器,不能平均分配到每台服务器上
使用的也不多
Seata概述
为什么需要Seata
我们之前学习了单体项目中的事务
使用的技术叫Spring声明式事务
能够保证一个业务中所有对数据库的操作要么都成功,要么都失败,来保证数据库的数据完整性
但是在微服务的项目中,业务逻辑层涉及远程调用,当前模块发生异常,无法操作远程服务器回滚
这时要想让远程调用也支持事务功能,就需要使用分布式事务组件Seata
事务的4个特性:ACID特性
- 原子性
- 一致性
- 隔离性
- 永久性
Seata保证微服务远程调用业务的原子性
Seata将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
Seata的运行原理(AT模式)
上面结构是比较典型的远程调用结构
如果account操作数据库失败需要让order模块和storage模块撤销(回滚)操作
声明式事务不能完成这个操作
需要使用Seata来解决
Seata构成部分包含
- 事务协调器TC
- 事务管理器TM
- 资源管理器RM
我们项目使用AT(自动)模式完成分布式事务的解决
AT模式运行过程
1.事务的发起方(TM)会向事务协调器(TC)申请一个全局事务id,并保存
2.Seata会管理事务中所有相关的参与方的数据源,将数据操作之前和之后的镜像都保存在undo_log表中,这个表是seata组件规定的表,没有它就不能实现效果,依靠它来实现提交(commit)或回滚(roll back)的操作
3.事务的发起方(TM)会连同全局id一起通过远程调用运行资源管理器(RM)中的方法
4.RM接收到全局id,去运行指定方法,并将运行结果的状态发送给TC
5.如果所有分支运行都正常,事务管理器(TM)会通过事务协调器通知所有模块执行数据库操作,真正影响数据库内容,反之如果有任何一个分支模块运行异常,都会通知TC,再由TC通知所有分支将数据库操作回滚,恢复成运行之前的样子
Seata的启动
seata也是java开发的,启动方式和nacos很像
只是启动命令不同
它要求配置环境变量中Path属性值有java的bin目录路径
解压后路径不要用中文,不要用空格
也是解压之后的bin目录下
在路径上输入cmd进入dos窗口
D:\tools\seata\seata-server-1.4.2\bin>seata-server.bat -h 127.0.0.1 -m file
输入后,最后出现8091端口的提示即可!
其它模式简介
上次课我们讲解了Seata软件AT模式的运行流程
AT模式的运行有一个非常明显的前提条件,这个条件不满足,就无法使用AT模式
这个条件就是事务分支都必须是操作关系型数据库(mysql\MariaDB\Oracle)
因为关系型数据库才支持提交和回滚,其它非关系型数据库都是直接影响数据(例如Redis)
所以如果我们在业务过程中有一个节点操作的是Redis或其它非关系型数据库时,就无法使用AT模式
除了AT模式之外还有TCC、SAGA 和 XA 事务模式
TCC模式
简单来说,TCC模式就是自己编写代码完成事务的提交和回滚
在TCC模式下,我们需要为参与事务的业务逻辑编写一组共3个方法
(prepare\commit\rollback)
prepare:准备
commit:提交
rollback:回滚
- prepare方法是每个模块都会运行的方法
- 当所有模块的prepare方法运行都正常时,运行commit
- 当任意模块运行的prepare方法有异常时,运行rollback
这样的话所有提交或回滚代码都由自己编写
优点:虽然代码是自己写的,但是事务整体提交或回滚的机制仍然可用(仍然由TC来调度)
缺点:每个业务都要编写3个方法来对应,代码冗余,而且业务入侵量大
SAGA模式
SAGA模式的思想是对应每个业务逻辑层编写一个新的类,可以设置指定的业务逻辑层方法发生异常时,运行当新编写的类中的代码
这样编写代码不影响已经编写好的业务逻辑代码
一般用于修改已经编写完成的老代码
缺点是每个事务分支都要编写一个类来回滚业务,
会造成类的数量较多,开发量比较大
XA模式
支持XA协议的数据库分布式事务,使用比较少
SpringGateway网关
奈非框架简介
早期(2020年前)奈非提供的微服务组件和框架受到了很多开发者的欢迎
这些框架和SpringCloud Alibaba的对应关系我们要了解
现在还有很多旧项目维护是使用奈非框架完成的微服务架构
Nacos对应Eureka都是注册中心
Dubbo对应Ribbon+feign都是实现微服务远程RPC调用的组件
Sentinel对应Hystrix都是做项目限流熔断降级的组件
Gateway对应Zuul都是网关组件
Gateway框架不是阿里写的,是Spring提供的
什么是网关
"网"指网络,"关"指关口或关卡
网关:就是指网络中的关口\关卡
网关就是当前微服务项目的"统一入口"
程序中的网关就是当前微服务项目对外界开放的统一入口
所有外界的请求都需要先经过网关才能访问到我们的程序
提供了统一入口之后,方便对所有请求进行统一的检查和管理
网关的主要功能有
- 将所有请求统一经过网关
- 网关可以对这些请求进行检查
- 网关方便记录所有请求的日志
- 网关可以统一将所有请求路由到正确的模块\服务上
路由的近义词就是"分配"
Spring Gateway简介
我们使用Spring Gateway作为当前项目的网关框架
Spring Gateway是Spring自己编写的,也是SpringCloud中的组件
SpringGateway官网
网关项目git地址:引用自达内课堂的demo项目
jtzhanghl/gateway-demohttps://gitee.com/jtzhanghl/gateway-demo.git
总结
整个csmall demo项目实现了简单的微服务搭建
项目的架构为,csmall为全部项目的父类项目,旗下有business项目=>操作order项目=>分别操作cart和stock项目,而cart和stock项目通过commons获取了pojo、ex、restful类,而不用在每个项目中都配置这些公共类。这几个项目统一通过gateway的网管类来统一配置路由,实现客户只需要通过网关路由即可访问到全部项目的内容,把子项目的端口隐藏起来。
各个项目之间需要通过Nacos进行注册,注册后再通过Dubbo来远程调用。
由于各个项目都对应了一个数据库的表,在business调用order从而调用各个项目的过程当中,需要对多个数据表进行操作,如果其中有部分数据表更新了但有部分数据表又无法进行更新,需要对数据表进行回滚,以免产生脏数据,此时就需要用到Seata进行全局事务管理,这种做法有点类似Spring框架的@Transactional注解。
最后,由于可能会存在高并发的问题,到时同一时间内可能有多个客户端访问数据,就需要用到Sentinel对项目进行限流操作。
此微服务知识来源于达内教育,老师专业授课,把各架构通俗易懂地阐述。