Save Load
GitHub 切换暗/亮/自动模式 切换暗/亮/自动模式 切换暗/亮/自动模式 返回首页

拉单模块业务说明

简介

我其实一直想给大家做些分享,但是觉得自己技术太菜了,一直不好意思,最近觉得还是做一个经验分享,不算技术分享。

今天分享的整体氛围是轻松,不要严肃,

我从18年来公司,就一直是在搞API拉单,也有一些经验之谈,这个项目我大大小小零星算是不完善的重构三四次,主要目的是在业务的扩展中保持代码的可维护性和可扩展性,拒绝堆屎山了,拒绝“能跑就行”,但是维护成本越来越高。

我了解项目的主要几个阶段: 1.0 是了解 API拉单 是个什么东西,没问题的跑起来。 1.2 是将项目改成了 redis 为核心,丢掉分布式任务管理、分布式节点管理 跑起来。 1.3 是将项目成为大益源子的一个服务,升级技术栈(比如原先是Java 1.7 和各种古老的 jar),以MQ为核心。 1.4 对API部分抽象 结果是新对接API变的简单,已对接平台升级和新对接API变的简单 1.5 对业务进行抽象 将类似的业务聚合,抽象,干掉冗余代码,

前3次是为了项目能用,后2次是为了项目能好用

为什么要做后两次,1、个人追求;2、作为一个工程师,要满足工程师的要求,(工程师:权衡需求和资源,给出专业可行方案)之前的,有太多不专业的地方。

分享的目标:

1、讲解 API拉单模块的基本概念、基础信息、基本流程的逻辑关系和实现
	
2、讲解 API拉单模块的功能、实现、演化和问题(这个 拉单模块 是怎么一步一步成为现在这样的。)
	功能:
		正向订单拉单、售前退款单拉单、售后退货退款单拉单、售后仅退款单拉单、售后换货单拉单、发货、已发货订单修改物流、AG-取消发货、AG-退货入仓、正向订单修改地址、解密、锁单、SKU查询、其它订单查询(修改地址的订单列表、服务单列表)、部分其它模块对平台的 API 对接承接。

基本概念: API 拉单模块: 假如大益源子是个城市,API 拉单模块,就是这个城市修建的高速路,是石油管道,是比较基础的需求,通过对电商平台开放API的对接,沟通电商平台和大益源子,实现各种功能,比如从平台拉取订单信息,向平台同步订单的发货物流信息。

平台、
	各大电商平台和自建商城
	
店铺、
	开在各大电商平台和自建商城上的店铺
	
基本业务功能说明、		
	3.1、拉单
		从平台拉取订单信息
	3.2、发货
		向平台同步订单的发货物流信息
	3.3、售后单
		从平台拉取售后单信息
		包含:售前退款单拉单、售后退货退款单拉单、售后退款单拉单、售后换货单拉单
	3.4、AG(取消发货、退货入仓)
		自助售后服务
	3.5、正向订单自助修改地址、
		未发货的订单买家自助修改地址
	3.6、订单改配
		已发货订单向平台修改发货的物流信息
	3.7、RDS、API 反向代理
		入云必须
	3.8、加解密
		订单的敏感信息加密、解密、加密字段搜索
	3.9、验签基本过程
		防止中途篡改
	3.10、异常、重试、监控、报警
		因为整个 API 拉单模块几乎都是自动化的定时任务,而且很多都是异步任务,需要监控 

定时任务:
	通过定时任务,自动的从平台的订单列表中拉取订单
	为了分布式的高效的拉取订单,将任务分成了4个阶段,由不同的节点去消费执行:
		1、Create
			根据 店铺配置,创建一个:从某个时间查询区间的 不同业务的 任务
		2、Count
			根据 Create 创建的 某个店铺的 某个业务的 某个时间区间的 任务,去平台查询此时间区间的订单数量,并根据订单数量去分页去创建 Down 任务
		3、Down
			获得订单列表
		4、Info
			根据订单列表获得每个订单详情,并处理加工订单
	
基本概念:串联起来就是:API拉单基本的功能就是:通过定时任务,去各大平台,查询某个时间区间的某个订单列表。(相同业务不同平台分别实现)。

一、首先列出需求,需求约束这个项目要怎么写: 1、抓单业务: 1、基于店铺定时抓不同类型单(正向、售前、售后) 2、不同店铺不同抓单频率 3、异常任务归档、重试 4、区间补单 4.1、不指定店铺时,批量店铺时间区间补单 4.2、不指定类型时,所有类型补单 4.3、区间补单不影响定时抓单时间更新 5、指定单号补单 6、定时任务记录 7、异常需关联任务、统计和处理 7.1、异常处理: 7.1.1、自动重试 7.1.2、手动重试 7.1.3、手动关闭异常,不再重试

	8、抓单时间防止反向更新(抓单任务创建时更新店铺时间时只可扩大,不可缩小,不可反向。重新抓单需修改店铺)
	9、已经生成的执行中的任务不受后续店铺变更影响,比如已经生成店铺抓单任务,生成任务后更改了店铺配置,关闭了店铺,不中途立刻中断任务。
	10、对任务数量、店铺抓取中订单数量数量统计:
	11、每页事务隔离(Count 任务获得订单数量后,每页创建一个 Down)
	12、按单解析事务隔离、按单发送事务隔离
	13、支持 has_next 分页设置
		由于获取三个月内的订单接口是用创建时间过滤的,而创建时间是不可变的,所以从前往后翻页也不会导致漏单,因而可以省掉第一步的count(*),而直接采用入参use_has_next=true的方式分页获取,直到返回结果中has_next=false时终止翻页。
		由于获取增量订单接口是用修改时间过滤的,而修改时间是可变的,所以需要从后往前翻页才能避免漏单。从后往前翻页必须要知道最后一页,所以必须在首次API请求时采用use_has_next=false方式统计订单总数,计算出总页数,然后再设置use_has_next=true终止订单统计,从后往前翻页。
	14、支持延迟时间抓单设置和重复时间抓单设置
	15、全量增量自动切换
	16、指定批量抓单时全量增量
	17、发货同步级别控制
	18、发货屏蔽
		无需发货的屏蔽
			1、不同步到平台的物流编码
			2、不同步到平台的商品
				1、原始单中不包含的商品:组合商品的拆分子商品、赠品
		相同请求的屏蔽
		不满足发货条件的屏蔽
	19、发货处理 赠品、组合商品、其它订单中无的商品
	20、支持配置即发即通知、某单全发后通知、合单全发后通知
	21、对可预期的固定值做枚举(平台订单状态、API订单状态、快递类型)
	
2、API 需求:
	API 管理、配置、验签过程:
	快速的API对接:
	快速的API返回对象扭转
	API监控:
	API测试:
	API重试:
	令牌管理:
	流量监控:借债机制、滑动窗口算法
	API 授权:是否自动延长授权

二、服务 基础服务: redis服务: 1、发货防并发平台订单号记录 2、发货结果记录 订单级 商品级 商品数量级 3、相同请求屏蔽 MQ服务: 承载、分发任务 API服务: 店铺配置服务: 任务服务: 异常服务: 查询订单数量服务: 查询订单列表服务: 查询订单详情服务: 订单字段解密服务: 店铺平台权限服务: 查询商品SKU服务: 查询卖家地址库服务: 同步发货服务: 同步AG服务:

	订单数量API服务:
		店铺累计抓取订单数量:
		店铺抓取中数量统计:
			Count 任务添加
			Down 任务减少
			形成一个 任务ID 和数量变化的表
源子三方服务:
	店铺服务:
	三方售后服务:
	发货配置服务:
	灰名单配置服务:
	AG配置服务:
	订单中心服务:
		订单发货状态:
	日志服务:
	通知服务:
		邮件、
		短信、
		禅道、
		站内信、

三、工具 JsonPath、 JsonConverter、 获取指定节点内容 Json 异构映射: 不同 Json 通过配置的 字段关系 映射为指定对象 HttpClientUtils、 代理、 URL加工、 请求参数检验、 请求参数封装、 网络异常自动重试、 异常指数退避、

四、实体 ↓↓↓↓↓↓↓↓↓↓见下面【实体】↓↓↓↓↓↓↓↓↓↓

三种: API、基于服务、店铺配置

首先先做一个分类: 整个拉单项目分为三类实体: 1、店铺及业务实现配置实体 2、批量任务 流程、配置、处理实体 3、平台 API 接口的相关对象的 本地实体、及相关枚举、及相关验证处理对象

重构抓单流程所需配置: 全量 增量 历史最大时间跨度 单次时间最大跨度 单页数量 是否需抓详情 是否解密 是否需补售后单/交易单 是否需推平台收货信息

发货配置: 同步级别控制 1、订单级 2、商品级 3、商品数量级

基于店铺创建 获得数量 获得列表 获得详情

基础需求: 业务逻辑: 1、定时抓交易单、 2、定时抓 换货、退货退款单、 2.1、不指定售后单类型补单、 3、发货、 3.1、发货补偿抓取交易单 4、售后订单信息推送、 5、买家收货信息推送、

总共分几个部分: core: 全局(全局性的配置) 平台全局变量: XMLConfig: 业务类型: 拉取 Pull、 批量: 全量、 交易单、 增量、 交易单、 退货退款单、 换货单、 单条: 详情、 MQ、 订单、 推送 Push、 平台: 取消订单、 取消发货、 发货信息、 同意退货、 OMS: 交易单中心、 业务阶段: Create、 Count、 Down、 Detail、 routingKey: [平台][拉取][批量][增量][订单]_[业务阶段] 异常体系Exception: 目的:对基础异常进行封装,进行相应处理

	组件(组件提供功能支持)
		MQ、
		Redis、
		MySQL、
		MongoDB、
		HttpClientUtils、
		JsonConverter、
		RequestEntityAssemble、
		URLProcessFun、
		ResponseErrors、
business:
	业务(由业务逻辑代码和多个不同组件配合完成业务):
		说明及注意:
			拉取任务:由定时任务开启,消息触发完成整个业务。
			同步任务:全程由消息触发。
			拉取单条:虽然不是业务,但也抽象出接口
			注意:对于业务来说接口的抽象及实现应该先一步基于业务。
		接口及抽象分层:
			[拉取]_[Create]
				[拉取]_[全量]_[Create]
					[拉取]_[全量]_[订单]_[Create] 
				[拉取]_[增量]_[Create]
					[拉取]_[增量]_[订单]_[Create] 
					[拉取]_[增量]_[退货退款单]_[Create]
					[拉取]_[增量]_[换货单]_[Create]

实体: 1、字典项: 1、拉单平台 2、参数类型 1、基础参数 2、业务参数 3、业务 正向订单拉单、售前退款单拉单、售后退货退款单拉单、售后退款单拉单、售后换货单拉单、发货、已发货订单修改物流、AG-取消发货、AG-退货入仓、正向订单修改地址、解密、锁单、SKU查询、其它订单查询(修改地址的订单列表、服务单列表)、验签、

2、参数key表:
	参数名称
	参数类型
	是否启用
	是否必传
	默认值
	是否删除
	
	1、现阶段常用 基础参数
		外部名称、
		外部店铺ID、
		key1、
		key2、
		key3、
		key4、
		key5、
		key6、
		API配置平台、
		店铺是否开启 on:允许,off:不允许、
		是否删除:1 表示删除,0 表示未删除、
		附加信息、
		版本、
		时间戳、
		
	2、现阶段常用 业务参数
		业务是否开启 on:允许,off:不允许、

	
3、店铺-业务-参数 value 表:
	店铺id
	业务id
	参数id
	参数名称
	参数value
	是否启用
	是否删除




店铺API配置:
	ID、
	店铺ID、
	店铺名称、
	外部名称、
	外部店铺ID、
	key1、
	key2、
	key3、
	key4、
	key5、
	key6、
	API配置平台、
	店铺是否开启 on:允许,off:不允许、
	是否删除:1 表示删除,0 表示未删除、
	附加信息、
	版本、
	时间戳、
	
	详情:
		店铺API配置ID:
		业务ID:1=交易单,2=退货退款单、3=换货单、4=自动补单
		业务类型:1=交易单,2=退货退款单、3=换货单、4=自动补单
		业务类型Name:交易单、退货退款单、换货单、自动补单
		是否开启业务:0关闭,1开启、
		业务参数:
			延迟抓单时间、
			重复抓单时间、
			抓单的结束时间、
			抓单频率、(越大频率越低,默认为0)
			店铺允许抓单的模式 0=RDS,1=API,2=MQ,可多选用英文逗号分隔:0,1,2、
			抓单状态、
		附加信息、
		版本、
		时间戳、
		是否删除:1 表示删除,0 表示未删除、
	备注:
		1、抓单频率 计算是否抓单:
			1、店铺很久没启动,启动后,定时任务 调度,立即通过
			2、定时任务短时间多次调用,需屏蔽,(区间补单需走 区间补单方法)
		2、自动补单 业务按开启的 其它业务类型创建多个任务。
	设计目标:
		1、灵活,可以很容易地启用或停用
		2、性能,不对正常的拉单业务操作造成影响
		3、开放,容易和第三方系统模块扩展整合

	
发货信息实体:
	公司ID、
	公司名称
	店铺 ID、
	店铺 Name、
	发货创建ID、
	发货仓库Name、
	
	外部订单号、
	OMS订单号、
	OMS订单ID、
	
	发货时间、
	是否拆单、(是指发货时此 platOrderNo 有多个OMS 订单)
	是否合单、(是指发货时此 OMS订单 有多个 platOrderNo)
	是否发货完成、(是指发货时此 platOrderNo 有多个OMS 订单,最后一个发货的 OMS订单)
	
	快递ID、
	快递类别、
	快递名称、
		外部订单号、
		外部子订单号、
		平台商品ID、
		商品SKU、
		父级商品SKU、(通过此属性获得商品是否是组合商品)
		商品数量、
		包裹ID、
		快递运单号、
		
	备注:
		1、发货消息以 外部订单号 + OMS订单号 联合唯一,所以,一个外部订单可能有多个消息体,且因多包裹,会导致一消息体有多个 快递运单号。(一个 OMS订单号 使用一种快递,所以虽然多包裹产生多运单号,单不会多快递类型)
		2、OMS发货模块是按 OMS订单 以 外部订单号 group by 后分解为多个 消息体 调 发货 模块。
	
发货_Return extends API_Return:
	开始时间、
	结束时间、
	请求URL、
	重试次数、
	成功信息、
	异常信息、(集合)
	发货结果、
	
	注意:一个订单因多包裹可产生多个发货尝试、每个发货尝试有1个发货结果。


订单:

商品:


任务体:
	任务ID:
	上级任务ID:
	任务类型:
		交易单创建
		退款单创建
		换货单创建
		
		交易单Count
		退款单Count
		换货单Count
		
		交易单Down
		退款单Down
		换货单Down
		
		交易单Detail
		退款单Detail
		换货单Detail
		
	任务创建时间:
	任务接收/开始执行时间:
	API请求开始时间:
	API请求结束时间:
	任务结束时间:
	任务最大执行次数:
	任务执行次数:
	任务执行结果:
	请求参数:
		店铺ID、
		任务类型、
		状态、
		时间区间、
		页码、
		每页条数、
	返回参数集合:
		①、平台返回JSON、订单条数
		②、JSON部分字段、订单ID列表
		③、订单详情
	任务异常对象集合:
	
订单处理:
	1、添加信息、
	2、扭转、
	3、翻译、
	4、解密、
log日志规范:
	店铺、
	业务_阶段、
	关键参数、
	

Exception 异常类型及处理:
	API请求异常:
		异常标识生成异常类
		异常值生成异常类
		异常值且异常标识生成异常类
	
枚举:(去除魔法值)
	平台类型、
	平台订单状态、退款单状态、
	平台支付方式、
	





JSON格式化:

XML格式化:

存任务:

取任务:

API实体:

API 异常的分类: RuntimeException 自动重试 包含: 各种服务异常、网络异常、运行产生的其它异常 可重试异常 重试次数后 收录 不可重试异常 直接收录

基础工具util:

JSON格式化:

XML格式化:

XML 及 json 格式化的工具类

关于异常处理原则: 第一,能处理则进行处理和关心的异常,不能处理或不关心的异常则继续抛出。决不允许出现捕获异常但又不做任何处理或抛出操作,这样会丢失异常信息。 第二,异常抛出源需要在抛出异常之前将异常写入日志中。以备进行检查。 第三,业务逻辑层判断是否 RollBack 业务,,catch 异常后,如果需要回滚事务或业务 第四,finally 块必须对资源对象、流对象进行关闭,不要在 finally 块中使用 return。

对 xxl-job 的代码分析及相应业务代码开发设计

日志:

1设计目标:
	1、灵活,可以很容易地启用或停用
		1、在灵活性方面,可以在配置文件config.properties或config.local.properties中指定选项来启用(true)或停用(false),
					#是否启用系统监控模块中的功能  
					monitor.memory=true  
					monitor.performance=true  
					monitor.runing=true  
					monitor.login=true  
					monitor.index=true  
					monitor.backup=true  
					#是否启用业务日志记录功能  
					log.create=true  
					log.delete=true  
					log.update=true  
	2、性能,不对正常的业务操作造成影响
		在性能方面,使用内存缓冲区来临时存储日志对象,可以节省磁盘和网络开销,缓冲区的大小可以配置,当缓冲区满了或是人工强制执行的时候才会对日志进行持久化或其他处理,这样不但提高了吞吐量(批量提交、批量处理),而且对用户业务处理的影响非常小,因为产生日志对象之后只需要将日志对象加入缓冲区即可(无阻塞、内存操作)。除此之外,当对缓冲区中的日志对象进行持久化或其他处理的时候,会有独立的线程池中的线程来完成,不会阻塞用户业务处理线程(线程复用、异步非阻塞),
		
	3、开放,容易和第三方系统整合
2、日志种类“
	1、业务日志:
		业务日志的要求:
			数据的增删改日志(方便任务重建)、
			失败任务记录(包含:任务参数、失败原因)、
	2、监控日志:
		监控日志的要求:
			用户请求响应时间、内存使用情况

监控: 系统负载监控:Spring Boot Admin 用于监控基于 Spring Boot 的应用 任务监控: 执行任务数量、异常任务数量 节点监控:节点健康、节点任务饱和率、待执行任务-任务类型分布、待执行任务-任务状态分布、 异常任务监控:任务类型监控、任务原因分布

返回的数据结果是以订单的 修改时间 倒序 排列的,通过从后往前翻页的方式可以避免漏单问题 asc 按升序排列 (不用写,默认使用这个) desc 按降序(倒序) 排列

***************************************** 项目中的角色 *********************************** 1、业务 2、服务 3、平台 3.1、平台的信息 3.2、平台的处理 4、店铺 4.1、店铺的信息 4.2、店铺的处理 5、API 6、工具

***************************************** 待确认信息 *********************************** 发货 需要支持配置即发即通知、全发后通知、合单全发后通知。

例如淘宝平台是支持商品级发货信息同步, 如果配置了一个淘宝平台的店铺 全发后通知,那么发货时是按订单级发货信息同步处理,还是去OMS查询之前屏蔽的部分,继续以商品级发货信息分别同步 例如: 当 此店铺订单拆单发货时分 A、B两单,B单发货时此订单全发。 那么当A订单发货时屏蔽,B订单发货时是按整单发货,还是去OMS查询发货信息,然后分别发货。

如果分别发货会有一个逻辑异常。A订单的运单号如果物流公司已经有了物流信息,同步会失败。

基于 发货细粒度 设计发货结果缓存 key-value 发货细粒度:订单级、商品级、商品数量级

订单级:每个订单只可同步一条物流单号 key:shopId + “:” + platOrderNo value:logisticNo + “:” + true/false

商品级:每个订单下的每个商品只可同步一条物流单号 key:shopId + “:” + platOrderNo + “:” + sku value:logisticNo + “:” + true/false

商品数量级:每个订单下的每个商品只可同步多条物流单号 key:shopId + “:” + platOrderNo + “:” + sku + “:” + logisticNo value:logisticNo + “:” goodsCount + “:” + true/false

*************************************** ETL ********************************** ETL的设计分三部分:数据抽取、数据的清洗转换、数据的加载。抽取(extract)、转换(transform)、加载(load)至目的端的过程: 开源 1、Apache Camel

不同的抽取方法: 1、MQ、 2、DB、 3、URL、

一、数据的抽取(Extract) 注意:增量抽取更新数据

二、数据的清洗转换(Cleaning、Transform) 1、映射转换、 2、SQL转换、················ ··· ··· ·····

日志: 一类是执行过程(业务)日志: 一类是错误日志:

消息转换: from(“amqp:queue:order”).process(new XmlToJsonProcessor()).to(“bean:orderHandler”);

过滤: from(“amqp:queue:order”).filter(header(“foo”).isEqualTo(“bar”)).choice() .when(xpath("/person/city = 'London'")) .to(“file:target/messages/uk”) .otherwise() .to(“file:target/messages/others”);

*************************************** Shepherd API网关项目 **********************************

API网关是运行于外部请求与内部服务之间的一个流量入口,实现对外部请求的协议转换、鉴权、流控、参数校验、监控、告警、故障自愈、等通用功能。

*************************************** WMS 项目 **********************************

1、首先要有仓库库位管理系统: 比如要有:仓库、库区、货位,这些事对摆放商品的空间做的抽象 1.1仓库一般属性有:1、仓库类型(例:残损仓、三方仓、零售仓、虚拟仓)2、仓库的联系人、联系电话、仓库地址等仓库位置信息

1.2库区属性与仓库类似:1库区类型(例:存货区、拣货区)2、库区编码、库区的联系人、联系电话、库区在仓库地址等库区位置信息 1.3货位同上,

不同类型用于自动化处理,比如残损商品,入库会限制死路由到残损仓

2、仓库作业 库内作业:补货、移位、入库、出库、借出、归还、盘点、 库间作业:调拨出库、调拨入库 其它:各种单据统计、各种维度数量统计、手持设备接入、一维码系统、库存报警

订单服务需要提供: 1、包含此外部单号的OMS订单的所有已发货信息。 1、发货时间 2、是否拆单 3、是否合单 4、是否发货完成 2、此外部订单发货时是否位于不同OMS订单(判断拆单) 3、此外部订单发货时所在OMS订单是否有其它外部订单(判断合单) 4、此外部订单是否发货完成