代码随记 SpringBoot Sentinel 服务保护
系列 - 代码随记
目录
雪崩问题:当多个为微服务需要调用某个微服务时,某个微服务崩溃会导致血崩 ,所有微服务不可用。 解决方案:请求限流,线程隔离(限制每个服务可使用的线程数量)。
1 Sentinel
java -Dserver.port=8090 -Dcsp.sentinel.dashboard.server=localhost:8090 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jarhttp://localhost:8090/#/login
<!--sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>spring:
cloud:
sentinel:
transport:
dashboard: localhost:8090
http-method-specify: true # 开启请求方式前缀请求限流:限制请求的QPS,但是这并不能解决问题。 线程隔离:按需分配线程资源,例如其他业务分配10线程,查询购物车分配20线程,假如查询购物车崩溃了,也不会影响其他业务。
服务熔断:通过上面设置限流后,正常查询20ms的,在多线程并发查询下需要500ms,我们希望 当被限流后直接返回null, 而不是继续等待, 从而保持 20ms 的返回。
在API中定义
package com.hmall.api.client.fallback;
import com.hmall.api.client.ItemClient;
import com.hmall.api.dto.ItemDTO;
import com.hmall.api.dto.OrderDetailDTO;
import com.hmall.common.exception.BizIllegalException;
import com.hmall.common.utils.CollUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import java.util.Collection;
import java.util.List;
@Slf4j
public class ItemClientFallback implements FallbackFactory<ItemClient> {
@Override
public ItemClient create(Throwable cause) {
return new ItemClient() {
@Override
public List<ItemDTO> queryItemByIds(Collection<Long> ids) {
log.error("远程调用ItemClient#queryItemByIds方法出现异常,参数:{}", ids, cause);
// 查询购物车允许失败,查询失败,返回空集合
return CollUtils.emptyList();
}
@Override
public void deductStock(List<OrderDetailDTO> items) {
// 库存扣减业务需要触发事务回滚,查询失败,抛出异常
throw new BizIllegalException(cause);
}
};
}
}再去CONFIG中注册 Bean
public class DefaultFeignConfig {
...
@Bean
public ItemClientFallback itemClientFallback() {
return new ItemClientFallback();
}
}在接口中调用
@FeignClient(value = "item-service", fallbackFactory = ItemClientFallback.class)
public interface ItemClient {
@GetMapping("/items")
List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);
@PutMapping("/items/stock/deduct")
void deductStock(@RequestBody List<OrderDetailDTO> items);
}2 分布式事务
Seata
- 三个重要角色
- TC 事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚
- TM 事务管理:定义全局事务的范围、开始全局事务、提交或回滚全局事务
- 定位回滚的范围,在什么时候
- RM 资源管理器:管理分支事务,与TC交谈以注册分支事务和报告分支事务的状态
<!--统一配置管理-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--读取bootstrap文件-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!--seata-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>seata:
registry: # TC服务注册中心的配置,微服务根据这些信息去注册中心获取tc服务地址
type: nacos # 注册中心类型 nacos
nacos:
server-addr: 127.0.0.1:8848 # nacos地址
namespace: "" # namespace,默认为空
group: DEFAULT_GROUP # 分组,默认是DEFAULT_GROUP
application: seata-server # seata服务名称
username: nacos
password: nacos
tx-service-group: hmall # 事务组名称
service:
vgroup-mapping: # 事务组与tc集群的映射关系
hmall: "default"有个坑,SEATA_IP 一定要填IP地址,不然他就报错
seata:
image: seataio/seata-server:1.5.2
container_name: seata
environment:
- SEATA_IP=192.168.3.4 # 这里写宿主机局域网IP
- SEATA_PORT=8099
volumes:
- ./seata:/seata-server/resources
ports:
- 8099:8099
- 7099:7099
restart: unless-stopped2.1 XA模式
全局事务锁的一种
seata:
data-source-proxy-mode: XA然后添加 @GlobalTransactional 就可以了
- 流程
- 每个TM下的微服务
- 1、执行所有SQL
- 2、报告事务状态状态
- 然后 TC 等待所有微服务的状态
- 最后微信服务分别自行提交
缺点是需要事务等待所有服务缺点通过后,才会提交,导致表会一直锁。
XA模式的优点是什么?
- 事务的强一致性,满足ACID原则
- 常用数据库都支持,实现简单,并且没有代码侵入
XA模式的缺点是什么?
- 因为一阶段需要锁定数据库资源,等待二阶段结束才释放,性能较差
- 依赖关系型数据库实现事务
2.2 AT模式
和XA模式不同点在于,先记录undo-log记录数据快找,然后再执行SQL并且直接提交。
简述AT模式与XA模式最大的区别是什么?
XA模式一阶段不提交事务,锁定资源;AT模式一阶段直接提交,不锁定资源。XA模式依赖数据库机制实现回滚;AT模式利用数据快照实现数据回滚。XA模式强一致;AT模式最终一致
可见,AT模式使用起来更加简单,无业务侵入,性能更好。因此企业90%的分布式事务都可以用AT模式来解决。