记录一次还算优雅的代码设计
作者:京东零售 常文标
商卡聚合服务是一个小巧的rpc应用,功能是统一查询商品的促销、自营包邮、价格信息、区域库存、区域可配送等等利益点或其他信息。本文重点分享商卡聚合服务的代码设计,包括合理的Sirector线程调度(cpu使用率低),和可维护性的设计。 简版代码示例如下: git@github.com:changwenbiao/demosoa.git
代码使用sirector-core组件并行调度(使用线程并行执行EventHandler的onEvent方法)请求上游rpc接口获取各利益点或其他商品信息。因为请求上游有些通用处理逻辑比如ump监控、调用开关等,所以抽象出一个通用的EventHandler名为AbstractBenefitHandler。具体调用利益点的实现类只需继承AbstractBenefitHandler并重写其抽象方法。
接下来重点讲代码如何节省cpu使用率和易于维护的设计。
1.如何节省cpu
AbstractBenefitHandler提供isSwitchOn方法,用于决定是否使用sirector组件分配线程执行调度EventHandler。相对于分配线程执行全部的EventHandler,判断是否需要调用才分配线程调用的方式可有效减少线程调度从而减少cpu使用率。isSwitchOn方法中可加入cms控制开关逻辑比如使用ducc开关,也可加入根据用户参数判断开关的逻辑,比如查询区域库存需要四级地址,若用户不传四级地址则关闭调用EventHandler(请求上游rpc)。代码实现如下:其中ducc开关在父类中的isSwitchOn中实现,sirector.begin方法接受可变参数列表参数,可将List转化为AbstractBenefitHandler[]作为入参。
@Override
public boolean isSwitchOn() {
boolean superSwitchOn = super.isSwitchOn();
if (!superSwitchOn) {
return false;
} else {
//正常为四级地址,如果少于四级则关闭调用
String area = seckillBenefitRequest.getSeckillParam().getArea();
return !StringUtils.isBlank(area) && area.contains("_") && area.split("_").length >= 4;
}
}
List<String> handlerNames = Lists.newArrayList("areaStockHandler", "partitionProductsHandler");
List<AbstractBenefitHandler> handlerList = handlerNames.stream()
.map(handlerName -> applicationContext.getBean(handlerName, AbstractBenefitHandler.class).setBenefitRequestAndBizName(request, "demoAppName"))
.filter(AbstractBenefitHandler::isSwitchOn).collect(Collectors.toList());
Sirector<MiaoShaEvent> sirector = new Sirector<MiaoShaEvent>(bigSeckillEventProcessThreadPool);
AbstractBenefitHandler[] eventHandlersArr = new AbstractBenefitHandler[handlerList.size()];
handlerList.toArray(eventHandlersArr);
sirector.begin(eventHandlersArr);
sirector.ready();
sirector.publish(new MiaoShaEvent(), 500); //这里开始使用线程并行执行EventHandler的onEvent方法
2. 如何容易维护
减少一些模版代码(如ump监控):所有Handler的实现类的ump监控都写在父类中的onEvent中,父类的onEvent调用子类实现的onEvent0(处理具体利益点rpc请求处理)方法。
短小代码的实现:AbstractBenefitHandler提供fillResponseInfo方法以向“ResponseVO”中填数据,具体填利益点数据的代码则由相应handler实现类处理。因此各个handler填充利益点“ResponseVO”的代码都是短小的,避免了代码写在一起的长代码。单个handler填充利益点数据和批量统一填充利益点数据代码分别如下:
@Override
public void fillResponseInfo(List<BftInfo> bftInfoList) {
if (MapUtils.isNotEmpty(areaStockMap)) {
for (BftInfo result : bftInfoList) {
String skuId = result.getBaseInfo().getSkuId();
if (areaStockMap.containsKey(skuId)) {
result.getCommonInfo().setAreaStock(areaStockMap.get(skuId));
}
}
}
}
handlerList.forEach(h -> h.fillResponseInfo(bftInfoList));
减少一些硬编码:handler实现类配置为原型模式(scope=“prototype”)的spring bean,通过applicationContext.getBean方法统一获取,避免一些创建(new关键字)具体实现类的代码,若新增利益点调用只需编码AbstractBenefitHandler实现类并配置为spring bean即可。批量获取handler代码如下
List<String> handlerNames = Lists.newArrayList("areaStockHandler", "partitionProductsHandler");
List<AbstractBenefitHandler> handlerList = handlerNames.stream()
.map(handlerName -> applicationContext.getBean(handlerName, AbstractBenefitHandler.class).setBenefitRequestAndBizName(request, "demoAppName"))
.filter(AbstractBenefitHandler::isSwitchOn).collect(Collectors.toList());
相关文章
- 无意中发现了一位清华大佬的代码模版
- 写代码有这16个好习惯,可以减少80%非业务的bug
- Emacs + etags + cscope 阅读代码
- 之前C#代码的重新设计
- 提升代码的运算速度——代码优化的方法总结
- Google Earth Engine(GEE)——计算ECDI展示的代码2013-2020年6-8月份和循环下载以北京市为例
- Java核心技术卷I基础知识3.6.6 码点与代码单元
- 我的Git stash不小心清空了怎么办,提了代码能反悔吗
- 《iOS 9 开发指南》——第6章,第6.8节实战演练——将设计界面连接到代码
- 《JavaScript专家编程》——第9章 代码质量 9.1 定义代码质量
- 《C++代码设计与重用》——1.2 重用的神话
- 《C++代码设计与重用》——1.7 参考文献和相关资料
- 《C++代码设计与重用》——第2章 类的设计
- 《C++代码设计与重用》——2.1 抽象性
- 《C++代码设计与重用》——2.4 存在最小标准接口吗
- 《C++代码设计与重用》——2.7 转型
- 《C++代码设计与重用》——2.9 总结
- 《C++代码设计与重用》导读
- 《JavaScript设计与开发新思维》——2.5 拼凑一些代码
- 重构·改善既有代码的设计.01之入门基础
- 孙玄&辜教授:基于Linux内核的时间轮算法设计实现【附代码】
- 悲剧的上午丢了近几天的代码
- 使用设计工具创建复杂的 SwiftUI 形状,将设计转换为代码的简单方法
- 线性表的代码实现(C语言)
- 『零行代码』解决键盘遮挡问题(iOS)
- vscode 设置代码高亮
- java高级用法之:在JNA中将本地方法映射到JAVA代码中
- "如何用70行Java代码实现深度神经网络算法" 的delphi版本
- 【校招Verilog手撕代码】VL3、循环仲裁器设计(Round Robin Arbiter)
- 基于单片机的智能电饭煲控制系统的设计(附代码)
- 机器学习完整过程案例分布解析,python代码解析
- Visual Studio 基础 之 VS 代码结构自动生成类图,类设计器的简单安装和使用
- 零代码以“王者荣耀”为例解析设计七原则,助你拿下面试
- 编程算法 - 二叉搜索树(binary search tree) 代码(C)
- ESP32S3系列-- Mac无法通过串口烧写代码问题
- 低代码和零代码火了,十大利器推荐
- 前端工程化之代码规范---ESLint + Prettier + husky + lint-staged代码规范全家桶
- PHPStorm+Wamp+Xdebug+Windows7调试代码