# 《Seckill秒杀系统》第97章:秒杀系统实现服务容错
作者:冰河
星球:http://m6z.cn/6aeFbs (opens new window)
博客:https://binghe.gitcode.host (opens new window)
文章汇总:https://binghe.gitcode.host/md/all/all.html (opens new window)
源码获取地址:https://t.zsxq.com/0dhvFs5oR (opens new window)
沉淀,成长,突破,帮助他人,成就自我。
- 本章难度:★★☆☆☆
- 本章重点:了解服务容错的实现原理,重点掌握服务容错的落地实现方案,并能够灵活将实现方案应用到自身实际项目中。
大家好,我是冰河~~
不管是秒杀系统,还是其他互联网项目,亦或是体量比较大的一些传统IT项目,哪怕是对系统进行了各种优化和高可用措施,在实际生产环境中可能还是会遇到各种各样的问题。尤其是像秒杀系统这种瞬时高并发、大流量的场景,出现问题的概率就更大了。
# 一、前言
服务容错在一定程度上就是尽最大努力来兼容错误情况的发生,因为在分布式和微服务环境中,不可避免的会出现一些异常情况,我们在设计分布式和微服务系统时,就要考虑到这些异常情况的发生,使得系统具备服务容错能力。在我们研发的秒杀系统中,就更加需要具备服务容错的能力。
# 二、本章诉求
在秒杀系统中实现服务容错功能,并对实现的服务容错功能进行测试,了解服务容错实现的原理,重点掌握服务容错的落地实现方案,并能够灵活将实现方案应用到自身实际项目中。
# 三、实现服务容错
这里,我们以秒杀活动微服为例来实现服务容错,其他微服务实现容错的方式基本相同,大家获取到本章对应的源码分支后,可以根据秒杀活动微服务实现服务容错的方式,对其他微服务实现微服容错功能。好了,正式开始实现服务容错功能。
(1)新增SeckillActivityFallbackService类
SeckillActivityFallbackService类的主要作用就是当秒杀活动微服务出现异常时,会调用SeckillActivityFallbackService类中的方法实现容错功能,避免秒杀活动微服务由于异常影响到其他服务,进而引起服务雪崩效应。
源码详见:seckill-activity-application工程下的io.binghe.seckill.activity.application.service.fallback.SeckillActivityFallbackService。
@Component
public class SeckillActivityFallbackService {
private static final Logger LOGGER = LoggerFactory.getLogger(SeckillActivityFallbackService.class);
public static SeckillActivityDTO getSeckillActivityBlockHandler(Long id, Long version, BlockException e){
LOGGER.info("getSeckillActivityBlockHandler|处理lockHandler|{}|{}|{}",id, version, e.getMessage());
Date date = new Date();
return new SeckillActivityDTO(-1001L, "BlockHandler活动", date, date, SeckillActivityStatus.OFFLINE.getCode(), "BlockHandler活动", 0L);
}
public static SeckillActivityDTO getSeckillActivityFallback(Long id, Long version, Throwable t){
LOGGER.info("getSeckillActivityBlockHandler|处理Fallback|{}|{}|{}", id, version, t.getMessage());
Date date = new Date();
return new SeckillActivityDTO(-1001L, "Fallback活动", date, date, SeckillActivityStatus.OFFLINE.getCode(), "Fallback活动", 0L);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
可以看到,在SeckillActivityFallbackService类中,定义了两个静态方法,分别为getSeckillActivityBlockHandler()方法和getSeckillActivityFallback()方法,getSeckillActivityBlockHandler()方法主要是发生BlockException异常时调用,getSeckillActivityFallback()方法主要是发生业务异常时调用。
(2)修改SeckillActivityServiceImpl类
主要是修改SeckillActivityServiceImpl类中根据秒杀活动id和版本号获取秒杀活动详情的方法,在getSeckillActivity()方法上通过@SentinelResource注解指定当发生BlockException异常时调用的方法,以及发生业务异常时调用的方法。并且为了演示实现的效果,我们还会在getSeckillActivity()方法中新增一行异常代码int i = 1 / 0;
。
SeckillActivityServiceImpl类的源码详见:seckill-activity-application工程下的io.binghe.seckill.activity.application.service.impl.SeckillActivityServiceImpl。
@Override
@SentinelResource(value = "QUEUE-DATA-FLOW", blockHandlerClass = SeckillActivityFallbackService.class, blockHandler = "getSeckillActivityBlockHandler", fallbackClass = SeckillActivityFallbackService.class, fallback = "getSeckillActivityFallback")
public SeckillActivityDTO getSeckillActivity(Long id, Long version) {
if (id == null){
throw new SeckillException(ErrorCode.PARAMS_INVALID);
}
SeckillBusinessCache<SeckillActivity> seckillActivityCache = seckillActivityCacheService.getCachedSeckillActivity(id, version);
//稍后再试,前端需要对这个状态做特殊处理,即不去刷新数据,静默稍后再试
if (seckillActivityCache.isRetryLater()){
throw new SeckillException(ErrorCode.RETRY_LATER);
}
//缓存中的活动数据不存在
if (!seckillActivityCache.isExist()){
throw new SeckillException(ErrorCode.ACTIVITY_NOT_EXISTS);
}
SeckillActivityDTO seckillActivityDTO = SeckillActivityBuilder.toSeckillActivityDTO(seckillActivityCache.getData());
seckillActivityDTO.setVersion(seckillActivityCache.getVersion());
int i = 1 / 0;
return seckillActivityDTO;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 查看完整文章
加入冰河技术 (opens new window)知识星球,解锁完整技术文章与完整代码