在销售日常工作过程中,有很多事情需要通知销售去处理,比如某个酒店比竞对价格lose了,销售收到这个通知后,会联系酒店确认价格,再到改价系统中调价;再比如某个酒店合同要到期了,同样,销售收到这个通知后,会联系酒店确认是否继续合作,再到合同系统中续签合同。上面描述的过程中,可以归纳出三个要素:
事件是某个业务系统发生的事情,通知是将该事情通过某种渠道发送给酒店对应的销售或其它角色,操作是销售收到通知后的处理流程。鉴于这样的业务场景很多,通知渠道的不统一及处理流程的不一致,极大降低了销售的工作效率,并且这个过程中很难去监控,比如每类事情的处理量、积压量、时长等等,所以我们统一了通知渠道,让销售在一个统一的入口去查看待办事情,并且统一了处理流程,把整个过程形成了一个线上闭环,我们把这种通知+操作的整合称之为任务,本文主要总结一下任务系统整个演进过程及一些技术细节。
系统化的一个难点是如何统一任务的处理流程,不同种类的任务处理形式是不一样的,有的任务处理需要填内容,有的任务处理需要操作(同意/驳回),有的任务处理需要上传图片等等,我们抽象了一种动态表单来实现这个特点,动态表单的数据格式大概如下:
[
{
"id": 1,
"name": "名称",
"desc": "描述",
"editor": "radio",
"validators": [],
"required": true,
"items": [
{
"id": 11,
"name": "选项一"
},
{
"id": 12,
"name": "选项二"
}
]
}
]
我们封装了常用的表单元素(文本、单选、复选、日历、文件、图片等等),通过不同的editor来表示,并且每一项都可以设置静态校验规则。表单是配置到任务类型上的,该类型下的任务都使用该表单。此时的系统交互如下:
我们通过多种方式拉取业务数据(schedule/mq),经过具体的业务规则处理后,产生任务给指定的人,接收到任务的人通过动态表单处理后,我们再将处理结果做转换,然后调用对应业务接口,这样就完成了整个过程。对于用户来说,他不需要到A系统或B系统或X系统中去处理,极大简化了用户的处理过程,提升处理效率。 但对于任务系统来说,就不那么美好了,这个过程中有很多问题,当我们接入一类任务的时候,因为发送任务的业务规则是写在任务系统中的,所以需求都是业务系统的pm提给我们,但我们并不了解他们的系统,所以沟通成本很高,另外一个,我们没有业务数据,所以需要通过某种方式把数据拉过来计算,造成很大的数据冗余,除此之外,用户处理完任务后,我们要根据处理结果去判定调用某个业务接口,去完成后续操作,一致性也无法保证。综上所述,每接入一类任务,我们就要根据业务系统写一套对应的实现,有很大的开发成本,并且带来了一致性、扩展性等诸多问题。
基于上面的问题,我们重新梳理了系统边界,确定了任务系统和业务系统的分工,任务系统应该聚焦于任务本身,任务的搜索、呈现、流转、处理、统计等等,而业务系统应该关注具体的发送逻辑,这样分工明确,各司其职,做自己最擅长的事情,这时再回首看一下我们之前写的发送规则,大致流程如下:
根据上面描述的系统边界,前两步需要业务系统完成,这里的一个问题是任务内容以什么形式传递,对于任务系统来说比较简单也很通用的方式是直接使用html,但直接使用html很可能破坏我们页面结构,我们失去了页面样式的控制权,另外对于业务方来说,发起一个任务还需要样式控制,成本也是很高的,所以我们抽象了几种展现形式(MAP/TABLE/URL)来满足大部分的展现场景,然后通过一个模板去渲染,做到了数据与样式分离,格式类似如下:
[
{
"type": "MAP",
"key": "说明1",
"value": "信息1"
},
{
"type": "MAP",
"key": "说明2",
"value": "信息2"
},
{
"type": "TABLE",
"key": "详情",
"value": [
[
"标题1",
"标题2",
"标题3",
"标题4"
],
[
"内容1",
"内容2",
"内容3",
"内容4"
]
]
},
{
"type": "URL",
"key": "点此链接改价",
"value": "http://xxx.com"
}
]
我们为业务方提供了一个ContentBuilder,方便构建这种数据格式。接下来第三步是查找任务接收人,这一步其实是依赖我们系统中的数据,由于找人的规则比较多,并且规则间也存在一定的关系,所以我们把规则抽象出来,也配置到任务类型中。此时的系统交互如下:
和之前的交互图对比可以看到,分析数据这一步已经从任务系统中剥离出去了,另外,用户处理完之后,任务系统通过mq将数据广播出去,而不是去调业务方接口,业务系统收到这个消息后,做对应的处理。这时再看任务系统,我们不关心业务逻辑,提供统一的接入及回馈方式,在这种平台的架构下,接入新的任务只需要业务系统单方面开发即可(以前会存在两方都开发),任务系统本身零成本。 平台化之后,我们快速的接入了上百种任务类型,数据存储迅速的膨胀,任务列表响应开始变慢,除此之外,产品要引入基于处理结果的搜索及统计,我们的处理结果是以JSON存储,基于mysql innodb的搜索已经不能满足产品需求,所以我们在搜索层面使用了ES,同时,根据任务的特点(有效期、状态)建立了冷热两套数据源。
在ES的基础上,我们很容易的去做任务的统计,搭建多种维度的报表,反向驱动任务的处理,同时可以去分析某个任务在整个环节中可能存在的问题。
现在有一些系统将审批类的工作流也利用任务系统实现,这个过程中需要定义多种任务类型,然后业务系统去控制何时触发,这个过程其实也可以抽象,用工作流领域的概念来讲,一个任务相当于一个节点,一个流程就是把多个节点连线,并且线上有一些条件,我们完全可以在任务之上,搭建一个工作流引擎。
动态表单这个东西几乎所有系统都可以用到,所以很适合做成基础服务的,要考虑的问题是服务化后如何渲染。另外,我们的动态表单可以继续扩展,现在还不够动态,比如下拉列表的数据是动态获取的,在数据提交时,某一项数据是动态校验的。
业务流程可能是非常复杂的,但我们抓到了一些共性,并形成了一个产品,一开始可能使用了比较挫的方式,但在后面不断开发的过程中,我们又找到了一些共性,将其归纳并抽象,最终找到一个合理的方式。先解决用户的问题,再解决系统的问题。