三方系统集成(低代码)平台实践

维权提醒:如果你或身边的朋友近五年内因投顾公司虚假宣传、诱导交费导致亏损,别放弃!立即联系小羊维权(158 2783 9931,微信同号),专业团队帮你讨回公道!


                                                                                                                                                <blockquote> 

作者:vivo IT 平台团队- Wang Qin

本文从作者实际痛点出发,到产生愿景,最后再到落地的全过程,并结合实例案例,介绍了一些核心设计思路,希望读者阅读后对vivo分销业务,能有一些了解,也希望能对读者在应用的认证鉴权、流程编排、低代码等方面有所启发。

一、背景和痛点

本文首先对vivo分销业务系统(简称V-Work,V-Work是分销系统的Portal,非1个系统)做个简单的介绍,V-Work作为vivo手机/智能终端等全系产品的分销系统,覆盖了全球范围线上/线下的供应和销售网。

**线下业务:**主要支撑各省市代理,以及下属零售商,零售商下的门店,门店到消费者的货物流和财务流,这些业务的操作入口一般直接在V-Work页面发起。

**线上业务:**核心是通过对接各类B2C平台、O2O平台、政企平台、运营商系统等,将订单同步到V-Work进行履约,通过调度自有WMS、三方WMS、三方TMS进行仓库作业和物流发货,同时返回发货的信息给到各类下单系统。

**全球部署:**V-Work共部署了4套集群(分别是国内机房、海外1机房、海外2机房、海外3机房),服务于全球用户。

类似很多互联网公司系统的迭代,V-Work系统经历过的架构演进:

单体架构: 2022年前V-Work是有多个包括订单、履约、库存、策略模块的独立单体系统。

微服务架构: 2022年开始进行了系统架构升级,将通用模块进行了抽取,形成了独立的服务,避免了重复造轮子的问题,目前整个架构升级工作还在持续进行中。

图片

随着V-Work的业务场景越来越多(订单业务从线下分销拓展到线上电商平台+运营商平台等,仓储物流从vivo内部的代理wms拓展为支撑各个区域的承运仓),导致对接的三方系统也呈现陡增之势,在系统迭代过程期间,主要遇到了以下几个问题:

  1. V-Work履约流程相对是固定的,但每对接一个三方平台时,都要开发一套适配代码, 这种硬编码的方式效率不高。

  2. 从代码提交到可用时间慢,特别在联调和测试环节,因需转换的内容繁琐,转换的字段较多,很容易出现错误,这个时候要经过代码调整、提交,DEVOPS流水线,应用启动,才最终可用,而不能即时生效。

  3. 三方集成的代码,对开发能力本身的要求不高,但因为是硬编码,所以还是需要开发人员,投入产出比不高。

  4. 不同三方系统,因会抽象出一些公共代码,这个时候就有可能出现比如改了抖音对接的公共代码,影响了其它平台。

  5. 每次对接一个平台,都要开发一套针对该平台的授权代码,定制开发导致效率低。

  6. 日志运维功能定制化,因每个平台的接口字段不同,导致日志的记录和展示等运维功能都是定制开发,成本较高。

透过问题的表面看本质,在有了多个三方平台集成的前车之鉴后,我开始反思能否针对当前的各种能力可以进行总结和抽象,最终形成一套配置化平台,即产生了一开始的三方系统集成平台,当初只是想解决vivo内部系统和vivo外部系统的集成,让内部业务系统开发人员仅需专注自身业务的开发,而不care外部的接口定义,能提升研发效率,来快速支撑业务的交付。

当三方集成平台成功上线,并经过2个月的推广后,很快发现他的应用场景不止能支持内外部系统的集成,内部系统之间的集成也很适合,比如结算中心和ERP的对接,2个系统都具有各自的业务模型,结算需要把过账数据推给ERP系统进行财务结算,就涉及到数据的转换和适配,本平台也是较好的应用场景。

所以最终将本平台命名为通用集成平台(Common Integration Platform),简称CIP,给他的定位是:适合多个核心业务系统直接进行对接,业务系统只需关注自身业务,通过本平台进行适配和桥接,可作为当前的适配系统、前置系统、业务网关系统,甚至渠道系统的配置化替代解决方案。

二、整体架构

2.1 架构目标

1.100%配置化(低代码)

要完成一次有实际意义的系统间的集成,肯定不止会有源系统和目标系统参与,期间还会涉及其它系统的参与,即会存在多个系统的多个接口协同完成一次业务流程,那就需要有编排和串联系统和接口的能力,这种能力采用配置化的解决方案进行落地,力争达到低代码化。

配置数据的存储上,常见的有XML和JSON两种格式,考虑到使用习惯和灵活性,最终选择了JSON作为配置元数据的存储格式。

站在平台建设角度,要做到这一点,最考验的是过往经验,以及对经验的归纳总结,然后抽象的能力,同时要有对可能变化点的识别能力,即对不确定的方面,要留好扩展性,这样才能建设一个健康稳定发展的平台。

2. 自助式接入

这里自助式有2个层面的含义:

**第一层:**指的是可以由业务团队自行配置和调试,而不限于必须是CIP平台的人员,比如V-Work也会对接多个三方仓储系统,去提高我们的履约时效,就会涉及V-Work和顺丰WMS、京东宙斯、EMS CTL的对接,那完全可以由V-Work中履约模块的人员在本平台完成配置和调试。

**第二层:**配置化+可视化可以降低使用者的门槛,类似一名HR在OA系统给员工办理入职那样简单,只要简单培训,即可上手,目标是运维、产品、测试、甚至业务都可以轻松在本平台上进行操作,完成业务实施。

3. 开发效率提升

通过对相似的事物进行抽象,抽象成各个具有独自特性的积木,同时将变化的东西看作是数据,而非代码本身,可灵活支撑各业务的个性化需求,提高开发效率,降低人力成本。

4. 隔离性

**物理隔离:**通过部署多套集群,可以让项目之间做到物理隔离,比如”抖音对接项目”不会影响”顺丰WMS对接项目”(可以见后文的部署架构)。

**逻辑隔离:**不像传统的硬编码方式,因系统对接之间会复用某些代码,导致相互影响,本平台配置管理上天然就具有隔离性,通过项目和项目之间,项目下的流程之间,都是可独立配置,不会影响到其它项目和任务流,实现了逻辑上的隔离,即真正做到了不同的需求的应用之间集成,不会相互影响。

5. 配置即时生效

配置完能立即生效,而不需要经过代码提交,分支合并,持续交付流水线,应用启动的等待时间,也不会因为发布应用导致的服务不可用(现在V-Work做不到完全无损部署)。

2.2 系统架构

图片

核心概念解释:应用、触发器、执行器、连接器、项目、任务流:

(1)”应用、触发器、执行器、连接器”:属于静态配置,只需配置一次,就可以在多个”任务流”中被引用。

  • **应用:**和我们的微服务是一一对应的,一个微服务维护成一个应用。

  • **触发器:**流程中的首节点,流程中的触发节点,一个任务流只能含有一个触发器。

  • **执行器:**流程中的非首个节点,即首节点后面的所有节点都属于执行器,一个任务流可以包括多个执行器。

  • **连接器:**是一种特殊的触发器或执行器,正常触发器和执行器通过配置完成,而连接器是需要预先进行定制开发。

(2)”项目、任务流”:属于动态配置,每一次项目的实施都是不同的配置。

  • **项目:**用于组织完成一次需求的实施,可包括多个任务流。

  • **任务流:**用于串联触发器、连接器和执行器且带有方向的一条流程任务。

图片

三方系统集成场景,包括三层架构:

  • 上层是外部三方系统,目前V-Work对接的三方系统主要包括:国内和海外的主流电商平台、O2O平台、三大运营商系统,以及V-Work线下代理公司系统的集成。

  • 中层由开放平台和CIP平台组成:开放平台主要对外提供了网关功能,包括统一的鉴权和限流方案。

  • 底层是V-Work内的多个系统组成。

图片

部署架构重点支持了不同项目的物理隔离,当前CIP部署架构:

  • **CIP-CORE:**主集群(包括电商、政企、代理赋能等业务)。

  • **CIP-CPC:**工厂业务集群(包括vivo的制造和供应域的各类系统)。

  • **CIP-WMS:**仓储和物流业务集群(包括各类WMS和TMS系统)。

  • **CIP-Finance:**财务业务集群(ERP和三方财务系统)。

  • **CIP-ADMIN:**服务于以上CIP-CORE、CIP-CPC等的控制台,处理非核心功能,与核心功能分离。

三、关键设计

3.1 内置常见接口授权方法

图片

以下用最常见的2种授权方式(hmac和oAuth2)举例说明

(1)hmac授权

加签方式定义:

语法定义:

sign(key-values, start="", end='', connector="", signType="md5/rsa", target="=", exclude="",extra=json)

  • **key-values:**要加签的业务字段的字段名和字段值

  • **start:**待加签串的起始额外内容

  • **end:**待加签串的结尾额外内容

  • **connector:**多个业务字段的连接符

  • **signType:**加签的加密类型

  • **target:**业务字段名和字段值的连接符

  • **exclude:**要过滤的业务字段

  • **extra:**扩展配置

    ① “innerFormat”=false //嵌套对象是否格式化,默认true

    ② “innerSort”=false //嵌套对象是否参与排序,默认true

    ③ “salt”=”qbc12” //hmac加盐

    ④”innerExcludeKey”=true ,”outerExcludeKey”=true //是否过滤字段key,默认false

    ⑤resultType=base64/hex //返回的数据格式

(2)oAuth2授权

仅需2步就可配置一个oAuth2授权类型系统的集成。

第一步:接口授权配置,以下以tiktok举例:

  "create": {  
    "url": "https://auth.tiktok-shops.com/api/v2/token/get",  
    "param": {  
      "app_key": "{# ad.ak #}",  
      "auth_code": "{# ad.code #}",  
      "app_secret": "{# ad.sk #}",  
      "grant_type": "authorized_code"
    },  
    "method": "GET",  
    "resultMap": {  
      "token": "{# ob.data.access_token #}",  
      "refresh_token": "{# ob.data.refresh_token #}",  
      "token_invalid_date": "{$ dfconvert({# ob.data.access_token_expire_in #}*1000,'yyyy-MM-dd HH:mm:ss') $}",  
      "refresh_token_invalid_date": "{$ dfconvert({# ob.data.refresh_token_expire_in#}*1000,'yyyy-MM-dd HH:mm:ss') $}"
    }  
  },  
"getCode": {  
    "url": "https://services.tiktokshop.com/open/authorize",  
    "param": {  
      "service_id": "{#ad.extra.serviceId#}",  
      "redirectUri": "{$ 'https://xxx.vivo.xyz/app/authCode/factory-tiktok/tiktok/' + {#ad.shopId#} $}"
    }  
  },  
"refresh": {  
    "url": "https://auth.tiktok-shops.com/api/v2/token/refresh",  
    "param": {  
      "app_key": "{# ad.ak #}",  
      "app_secret": "{# ad.sk #}",  
      "grant_type": "refresh_token",  
      "refresh_token": "{# ad.refreshToken #}"
    },  
    "method": "GET",  
    "resultMap": {  
      "token": "{# ob.data.access_token #}",  
      "refresh_token": "{# ob.data.refresh_token #}",  
      "token_invalid_date": "{$ dfconvert({# ob.data.access_token_expire_in #}*1000,'yyyy-MM-dd HH:mm:ss') $}",  
      "refresh_token_invalid_date": "{$ dfconvert({# ob.data.refresh_token_expire_in#}*1000,'yyyy-MM-dd HH:mm:ss') $}"
    }  
  }  
}

第二步:点击CIP分配的URL:https://xxx.vivo.xyz/app/auth?project=ina-vk&app=douyin&shopId=sfdsa3t8fds,会跳转到tiktok登录页面,输入用户名和密码,即完成整个oAuth2授权流程,并且在token失效之前,CIP会定时进行检查,在后台进行token刷新。

CIP数据库会有这样一条数据,为后续业务接口调用提供授权相关的信息:

| id | project_code | app_code | shop_id | api_key | api_secret | token | token_invalid_date | refresh_token | refresh_token_invalid_date |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 1 | factory-tiktok | tiktok |06944 | 67715 |7e68f17b8 | ROW |2025-01-22| ROW_6-gD |2122-12-0413:45:16|

3.2. 支持流程编排

一次数据传输定义为”任务流”,我们需要控制节点的执行顺序,支持逻辑转换和数据补全,逻辑转换比如时间的转换,外部电商的时间格式有很多种,我们需要转换成一种标准的格式,推到内部系统,数据补齐一般只是的是拉到外部数据后,会通过查询主数据去补充信息,转换成标准的数据格式,推到内部系统。

以下用V-Work中tiktok退款状态查询功能举例:

[  
  {  
    "code": "con-webhook",  
    "name": "1"
  },  
  {  
    "code": "tiktok.cancedDetail",  
    "name": "2",  
    "fieldMap": {  
      "params": {  
        "order_ids": [  
          "{#ib1.orderNo#}"
        ]  
      }  
    }  
  },  
  {  
    "code": "con-branch",  
    "name": "3",  
    "action": "{${#ob2[0].cancel_status#}=='CANCELLATION_REQUEST_PENDING'||{#ob2[0].cancel_status#}=='CANCELLATION_REQUEST_SUCCESS'||{#ob2[0].cancel_status#}=='CANCELLATION_REQUEST_COMPLETE'$}",  
    "resultMap": {  
      "code": "200",  
      "data": {  
        "status": 1
      },  
      "message": "SUCCESS",  
      "subCode": "10000"
    }  
  }  
]

3.3 内置数据池存取方法,支持流程中节点对数据池共享访问

任务流中每个节点的执行,即系统接口的方法调用,都会有输入输出参数,CIP会把每个节点的执行数据存储到流程数据池中,这样后续的节点,就可以对数据池数据进行访问,从而获取前面节点的执行数据,保证本节点能正常执行。当前定义了4种变量引用的方法:

  • 接口输入字段:{# ih.xxx #}、{# ib.xxx #} 、{# ip.xxx #} 、ih = input-header,ib = input-body,ip = input-param ,当前请求执行关联的输入字段。

  • 接口输出字段:{# oh.xxx #}、{# ob.xxx #} 、oh = output-header,ob = output-body,当前请求执行关联的输出字段。

  • 项目授权账号:{# ad.xxx #},ad = auth-data,当前请求执行关联的授权账号和token信息。

  • 项目常量:{# pc.xxx #} ,pc = project-constant。

以ib举例:ib表示从当前节点获取数据、ib3表示从别名为3的节点获取数据;ib.order.orderId表示获取ib的order对象的orderId字段值、ib.order表示获取ib的order对象、ib表示获取ib的所有字段值、ib[0]表示获取ib列表中的第1条数据。

3.4 支持远程dubbo方法、本地方法、MQ、HTTP配置调用

具体看下每种调用类型的配置方法。

(1)Dubbo方法

{  
  "application": "trade-center",  
  "interfaceName":"com.vivo.tradecenter.EcomOrderApi",   
  "method": "createOrder",   
  "param": [  
    {# orderId #}  
  ]  
}

本地方法和RPC类似,主要用在对电商平台SDK的调用场景。

(2)HTTP

{  
"url": "/wms/factory/outbound",  
"body": {  
    "language": "{# language #}",  
    "serialNo": "{# serialNo #}",  
    "timeZone": "{# timeZone #}",  
    "sourceFrom": "{# sourceFrom #}",  
    "invokerSystem": "{# invokerSystem #}",  
    "requestBodyDTO": "{# requestBodyDTO #}"
  },  
"param": {},  
"header": {  
    "accept": "application/json"
  }  
}

(3)MQ

{  
    "topic": "delivery_handle_result_topic",  
    "tag": "outbound",  
    "delayLevel": "1"  
    "body": {  
        "logistics_code": {# logisticsCode #}  
    }  
}

3.5 支持分支、循环、合并、webhook、数据存储和文件存储

这些内置的能力,我们定义为”连接器”,可作为任务流配置的节点,同触发器、执行器配合,共同完成多个系统之间的集成,当前定义了以下几种类型的连接器:

图片

3.6 内置EL表达式语言

表达式引擎并没有选择自研,主要是因为市面上有成熟好用的规则引擎,没必要重复造轮子,调研了几个规则引擎框架,最终选择了QLExpress作为基础引擎,在它基础之上,根据实际业务,进行扩展开发,CIP扩展的表达式,主要包括以下几大类:

图片

3.7 异步流程执行

同步任务指的就是遇到比较多的场景,系统集成实时返回结果。还有一种我们称之为异步任务,比如仓库出库结果,同步外部系统场景,履约系统抛出的是MQ出库结果消息,这个时候我们就要先接收下来,不能阻塞MQ,然后异步的将MQ消息转换适配后,推给外部对接系统。

异步任务可能出现在任何节点,都有可能:

  1. 针对MQ类型的触发流程,那任务流的第一个接口执行完成后,就需要commit,然后异步从第2个节点开始执行。

  2. 外部推送的一些同步数据,先进行初步校验,校验通过后,就需要返回成功给外围,这时候可能已经执行了比如3个节点,那后续异步执行就要从第4个节点开始。

即可以指定任何节点开始重试,但目前我们只有可能在第1个节点后和最后1个节点异步执行,所以限制node=first/last。

异步任务必须要具备重试的能力,所以需要能够指定重试次数和重试间隔:”count”: 3,”interval”: “1/2/3″。

TaskFlowInvokeStrategyEnum strategyType = null;  
//第一个节点执行后  
if (task.getExecutionStrategy().isFirstAfter()) {  
    strategyType = TaskFlowInvokeStrategyEnum.FIRST;  
}  
//最后一个节点执行前  
if (task.getExecutionStrategy().isLastBefore()) {  
    strategyType = TaskFlowInvokeStrategyEnum.LAST;  
}  
TaskFlowExecuteStrategyBO strategy = new TaskFlowExecuteStrategyBO(task, taskFlow, strategyType);  
taskFlowExecuteStrategyDomain.insert(strategy);  
mqPublisherFactory.doPublish(strategy, taskFlowTopic, task.getExecutionStrategy().getInterval(delayLevel));

3.8 错误机制

关于任务流(即某个系统间的集成任务)执行失败的控制机制,站在简化任务流配置方面考虑,即任务流中每个节点执行成功失败的判断,并没有放在任务流中通过分支条件去控制,我认为任务流的核心关注点是指定参与节点,节点主要指的是操作了某系统的某个方法,而不是有很多的判断配置,降低了任务流的可读性。当前错误码可以在2个层级进行定义:

  • **应用层级:**它的适用范围比较广,可影响本应用下的所有触发器和执行器。

  • **节点层级:**仅影响某个触发器或者执行器。

目前遇到了2种返回情况,第一种是直接通过http的状态码,第二种是HTTP状态码为200,通过JSON数据返回,这种情况更常见。节点成功判断规则:

  • 配了执行器的httpSuccess和success,只看执行器配置,否则看应用的httpSuccess和success。

  • httpSuccess和success判断规则:

    ① httpSuccess和success都没配:如果http的status code为2XX,就认为成功,否则失败。

    ② 只配httpSuccess:以httpSuccess为准。

    ③ 只配success:如果http的status code为2XX,再与success进行比较,否则失败。

    ④ httpSuccess和success同时配:必须同时满足。

四、应用

从2024年2月份提出创意开始,并经过三四个月的规划,设计和开发后,最终现在已经推广半年多的时间里,当前已经能覆盖vivo分销的主要应用场景,使用数据情况:覆盖vivo分销核心业务场景(仓储管理系统对接执行订单出入库作业、财务系统对接完成结算过账、电商平台对接实现销售订单履约、分销商系统对接实现交易数据的共享等)、50+系统、25个项目、300+的集成场景、日调用量10万级,较正常开发预计节省人力50%以上。

五、总结和展望

本文从作者实际痛点出发,到产生愿景,最后再到落地的全过程,并结合实例案例,介绍了一些核心设计思路,希望读者阅读后对vivo分销业务,能有一些了解,也希望能对读者在应用的认证鉴权、流程编排、低代码等方面有所启发。

站在本平台规划起初的目标上,已经算基本完成了目标,但如果想进一步在部门或者公司层面进行推广,我们还需要进一步提高平台可视化和易操作性,因为当前可视化功能,还没有把配置语义转换成业务语义,而是直接把里面存储的语法暴露给开发人员去配置,最终目标是系统集成的开发,能够转化为系统集成的数据管理,暴露给不懂开发的人员去配置,这是未来要重点提升的方面。

                                                                                </div>



Source link

未经允许不得转载:紫竹林-程序员中文网 » 三方系统集成(低代码)平台实践

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
关于我们 免责申明 意见反馈 隐私政策
程序员中文网:公益在线网站,帮助学习者快速成长!
关注微信 技术交流
推荐文章
每天精选资源文章推送
推荐文章
随时随地碎片化学习
推荐文章
发现有趣的