记录一次还算优雅的代码设计
作者:京东零售 常文标
商卡聚合服务是一个小巧的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>转化为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());

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
MASA Stack 1.0 发布会讲稿——产品篇
架构 基于MASA的云原生技术架构 我们基于MASA去做了一个云原生技术架构,左下角的MASA Blazor主要是为我们去集成一个多端的UI能力,具体的使用场景将在实践篇为大家介绍——MASA Blazor如何去做多端的 接着就是集成非业务能力的MASA Framework,它主要是解决整个云原生架构中非业务性的问题 在这两个基础上,我们就可以去编写业务代码,业务代码完成后上传GitHub并发布到微服务的集群里面,而MASA Stack则是提供的平台管理能力 最右边的第三方系统管理是最关键的一部分,我们第三方系统调用是通过Dapr来管理,不难看到MASA Framework和Dapr有部分重叠,MASA Framework对Dapr进行二次封装,既可以让大家体验类似.Net原生操作,又可以作为适配层对Dapr进行替换 MASA Stack 平台架构 研发协作平台:更多的是去帮助大家解决在研发过程当中的一些协作类的问题 现代化应用治理平台:主要是帮助大家解决在应用层面的一些治理问题 可观测性平台:解决的是一些可观测问题,在平台工程里面,帮助大家去采集一些公共的日志、跟踪、指标、数据等等 ...
- 下一篇
给 Databend 添加 Aggregate 函数 | 函数开发系例二
在介绍 Scalar Function(给 Databend 添加 Scalar 函数 | 函数开发系例一) 后,我们来看 Aggregate Function。 Aggregate Function 用于对列的值进行操作并返回单个值。常见的 Agg Function 有 sum, count, avg 等。 函数注册 Agg Function 的 register 函数以小写的函数名和 AggregateFunctionDescription 类型为参数,每个被注册的函数都存入 case_insensitive_desc ( HashMap 结构) 中。 而 case_insensitive_combinator_desc 是为了存储一些组合函数,比如与 _if 组合的 count_if, sum_if 这类函数。 pubstructAggregateFunctionFactory{ case_insensitive_desc:HashMap<String,AggregateFunctionDescription>, case_insensitive_combinator...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- MySQL8.0.19开启GTID主从同步CentOS8
- Mario游戏-低调大师作品
- Linux系统CentOS6、CentOS7手动修改IP地址
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Docker快速安装Oracle11G,搭建oracle11g学习环境