有赞订单导出业务如何应对这一挑战呢??
温馨提示:这篇文章已超过568天没有更新,请注意相关的内容是否还可用!
原文链接:https://tech.youzan.com/configuration-practice-of-youzan-trade-export/?utm_source=tuicool&utm_medium=referral
一、引子
1.1背景
有赞订单导出业务隶属于有赞交易订单管理组,主要职能是将有赞商家的订单数据通过报表的方式导入并提供下载给买家使用。目前承接了有赞所有的订单导出业务,报表的表单覆盖交易、支付、会员、优惠、发货、退款、特定业务等,合计达到100个。
1.2挑战
随着有赞的快速演进,有赞的市场、业务与产品覆盖面越来越广。从市场视角来看,覆盖了微商城、新零售、餐饮、美业、教育等,从模块角度来看,覆盖了交易、资产、客户、营销、店铺等,从产品角度来看,覆盖了分销、精选等。每个市场、模块、产品就会在订单导出报表中有所诉求。如右图图示,展示了有赞订单导出的域建模:
订单导出需要跨越来自不同市场、不同产品、不同模块,对各个业务域的存储和设计有整体理解;同时,需要借助科技方式(数据域、存储域、报表域、文件域)聚合来自各个域的数据集合,生成可读的报表下载给商家。
由此可见,其主要的挑战是:如何迅速支持各个域灵活多变的导入字段需求。如何面对这一挑战呢?
二、架构构建
订单导出的最初推动是从交易的多个DB及多个业务API,分别获得交易、支付、会员、发货、退款、核销、分销等多个数据,组装到一起生成报表。采用PHP任务脚本来推动。这种做法有两个痛点:
基于这两个痛点,有赞订单管理组进行了架构更新,详见有赞技术博文《有赞订单管理的三生三世与“十面埋伏》。得益于此,订单导出也迁移到基于ES+Hbase的科技栈。其中订单搜索引入ES服务推动,订单详情则存储在Hbase中,通过API来获得。整体流程如下所示:
重构之后,订单导出的性能和稳定性有了巨大的强化:
接出来,开始了配置化之旅。
三、配置之旅
3.1初尝配置:设下伏笔
订单导出常常要面临添加新的报表字段的意愿。最初推动不太灵活,是来一个泛型,在代码流程里添加一个字段。每次增加新的字段,都必须设置多处。因此,第一个改进是运用函数接口编程,将数组定义变成枚举可配置化的,然后递归指定的报表字段列表,拿到对应的数组定义,计算字段的值,写入报表文件。
根据报表字段列表生成报表行的伪代码如下:
public ListgenerateReportLineData(List fields) { return StreamUtil.map(fields, field -> { try { FieldDefinition fieldDef = getFieldDefinition(field); FieldMethod method = getMethod(fieldDef); String value = method.invoke(this.reportItem); return postproc(value); }catch (Exception e){ logger.warn("failed to get value for field: {} orderNo: {}", field, reportItem.getOrderNo()); return ""; } }); }
这个小小的改进,为进一步的配置化设下铺垫。当必须新增报表字段时,只要增加新的字段定义,而不应该在流程里降低代码。增强工具可扩展性的一个重要手段是,将步骤更加通用,只要增删流程里的环节及定义就能。
凡基础必要总是恰当的方向。
3.2报表配置:破局之时
有赞新零售、餐饮的快速兴起和演进,需要低利润迅速地建立起零售和餐饮的订单导出。这要求订单导出具有更大的灵活性,能够按照不同市场的规定配置不同的数组列表及导入格式,同时又能互不妨碍。此外,不同商家有个性化的导出需求。然而,原来的订单导出php在线订单系统源码,是专门为微商城开发的商品级别的报表。要加一个字段,往往会影响所有的有赞商家,使用感受不佳,订单报表本身也更加臃肿不堪。
如何突破原本的局限,支持更灵活的订单导出呢?这是订单导出面临的一个破局点。通过订单导出模板解决了这个难题。针对市场、产品配置的导入模板存储在DB表里;对于有赞商家的导入模板存储在DB表nf里。每个导出模板包括了如下信息:报表字段列表、导出维度(订单及商品)、报表文件格式、可选项等,做到足够灵活。
若要导出不同报表字段,只要新增相应字段,指定报表字段列表即可;若要生成不同维度的报表,可使用思路模式。比如,
如图所示:针对导出流程的各环节,可选用策略方式来选取不同推动,然后将策略组合出来。
通过推动报表配置功能,突破了之前的局限,可以支持不同市场、产品的标准化和多元化导出需求,并且做到相互隔离不干扰。
3.3配置完善:更快更稳
随着有赞进入更多的市场,面临着更加多变和个性化的导出需求。比如,有赞教育应该导出知识订单的学生信息和课程信息,有赞零售需要导出导购员和送货仓库门店名称。显然,如果要完成某个导出需求,还必须设置代码、发布平台,这种操作会特别频繁,导致研发和维护成本提高,影响平台稳定性。
如果无法在应用运行中动态地新增报表字段并读取和使用,无需设置导出项目代码,无需再次公布系统,就能更加强速地支持导出需求,将会持续增加导出需求支持的研发和维护成本,保持系统稳定性。
为了解决这个难题,引入了动态脚本语言.是无法与Java无缝对接的好伙伴,可以直接使用Java类的用途。编写脚本实现报表字段逻辑,存储在子句配置表里,在报表配置表或nf里引用,然后在应用开启时缓存到存储里并使用。比如粉丝姓名的脚本如下:
import com.youzan.trade.orderexport.util.PublicUtil def fansInfo = reportItem.orderInfo.extra["FANS"] PublicUtil.fetch(fansInfo, "nickname")
是导出项目里封装的一个软件类,可以让编写字段配置脚本非常简洁。值得提到的是,为了防止使用脚本可能造成的存储泄露,需要对编译后的脚本进行缓存和执行。
为了谋求无需改动代码和公布系统,还必须在整体流程上打通。整体流程如下:
Step1:当客户下单后,源数据落到业务数据库的扩展信息里;
Step2:通过数据同步,自动同步到Hbase表;
Step3:通过配置和可扩充的数据聚合体系,将数据自动输送到拿来计算报表字段值的报表对象里;
Step4:新增报表字段的配置;
Step5:在报表配置中引用该表单的标识。
下图展示了借助配置自定义泛型快速支持导入需求的整体流程。
整体流程打通后,当必须新增个性化字段时,通常即使做两步:
增加个性化字段的配置,包括脚本;检测通过后,刷新应用的配置就能。
个性化字段配置能力已经在线上稳固运行,比如拼团订单成团时间、零售导购员、有赞教育的课程字段等。
3.4通用导出:锦上添花
紧接着,订单导出又面临分销采购单的导出需求。分销采购单导出流程跟订单导出有所不同,需要分别导出分销买家订单和供货订单的详情信息再导入。这个步骤跟通用的订单导出流程是有所差别的。如果借助修改订单导出的通用步骤来支持,显然会妨碍所有的订单导出,使订单导出流程不清晰。
最后采取的缓解方案是:对分销采购单的导出需求和所需科技进行抽象,实现一个非常通用的导出能力模型,支持交易领域的各类潜在导出需求,而不只是局限于分销采购单导出。通过预测订单导出流程可以看到,绝大多数导出都遵从如下核心流程:
可以将核心步骤变成插件式的。首先,定义一个软件接口,包含其配置和用途等;再者,实现常用的组件列表,支持从ES,HBase,API查询或获得数据,以及常见的过滤、排序、格式化、生成报表等功能;最后php在线订单系统源码,将这种组件列表串联成一个详细的导出实例。整体流程则采取模板方式模式复用了订单导出流程。
例如微商城分销采购单导出通过依次执行ES查询组件、订单详情插件、数据顺序插件、报表字段格式化软件、报表生成插件来推动,其中订单详情插件针对分销买家单和供货订单分别调用了一次。
四、质量保障
前面看到,订单导出的报表字段非常多,导出数据量大,如何确保代码改动或建构后订单导出的服务品质和数据精确性?主要方法如下:
另外,采用函数编程及设计理念,使代码实现层面更具复用性和柔软性。18K行代码,代码重复率约为1.8%。
关注作者私信,关键词:“架构”
可免费获得一份Java架构进阶技术精品视频。(高并发+源码+JVM原理解析+分布式架构+微服务架构+多线程并发原理+BATJ面试宝典)或者架构思维导图。
如果认为文章还不错的话。
记得:转发转发转发!
本文来自网络,如有侵权请联系网站客服进行删除
还没有评论,来说两句吧...