遇到的问题
- 今年我们团队【企业内部信息化CRM】在人力资源有限的情况下,整体技术方向会发生一些侧重,具体是CRM除商业化系统外,由自研和集成为主转向集成为主,自研为辅。目前诸如外呼、大客纷享销客、小程序、客满机器人等场景,都属于集成的范围,其中大多数场景还未涉及到CRM核心领域能力的集成。未来,随着纷享销客、EC等crm端产品的使用,势必会涉及到更多核心领域模型和周边设施的集成。
- 随着集成应用和场景越来越多,对我们研发侧的挑战也会越来越不一样。同等条件下,自研更容易控制研发质量,可维护性更高,更有序,但能力的建设会滞后于业务发展;集成更容易获得市场成熟的业务能力,满足业务发展要求,但大量的无序的集成会导致系统熵增加速,系统快速向无序发展。
\
在以上的前提下,统一的集成方案是为系统减熵或维持熵值得必然路径~
解决策略
关于集成,本质上属于企业应用集成(EAI)范畴,对于企业集成有比较常见的解决方案。
关于EAI
借助于百度百科,看下EAI的定义:
EAI(Enterprise Application Integration,企业应用集成)是将基于各种不同平台、用不同方案建立的异构应用集成的一种方法和技术。EAI 通过建立底层结构,来联系横贯整个企业的异构系统、应用、数据源等,实现企业内部的 ERP、CRM、SCM、数据库、数据仓库,以及其他重要的内部系统之间无缝地共享和交换数据。有了 EAI,企业就可以将企业核心应用和新的 Internet解决方案结合在一起。
一句话概括:EAI做的就是企业内外应用之间的连接和信息交换。
我们的现状
- 当前我们的系统中是已经存在集成问题的,具体应用场景有:
-
- 销售云呼
- 清洗机器人
- 客服的坐席电话
- 客服机器人
- crm小程序
- 大客纷享销客的接入
- etc...
如此多的场景,相当于我们外部对接这很多个“渠道”,只是针对每个“渠道”场景,我们都是基于个性化的开发,代码逻辑分散我们各个业务系统中。随之带来的问题有:系统腐化越来越快,后续集成新场景成本越来越高,业务诉求的响应越来越慢。
- 今年的目标中,我们将会继续集成更多的三方工具,集成也会进入核心领域,涉及到我们核心的领域模型,包括客户、商机、联系人等等。但目前我们还缺少统一的集成方案来降低集成成本、后续维护成本,提升系统架构稳定性等等
我们的目标
对于我们业务系统来说,领域模型和通用的业务流程才是我们的精髓,我们应该致力于让自己的领域模型更完善、支持更多元化的业务上面,而不是浪费大多数时间再进行功能对接。所以后续目标主要有两个:
- 快速整合三方各场景业务能力: 可被集成内容包括如图各类三方能力,其中包括CRM核心领域能力,如客户管理,商机跟进,也包括周边工具如机器人,外呼,飞书表格等
- 提供统一、低成本、好维护的集成方案:无论三方、内部何种形式能力,都可被统一方式集成,将各类集成统一到集成中心系统,为系统减熵。
整体方案
在整体的集成方案中,无论内外部的服务集成,整体上都是在做服务的连接和信息的交换。
当前方案
如图1示,为当前和三方集成时的现状示意:
服务的连接
- 我方提供定制化http(https)协议服务,三方回调
- 三方提供http(https)协议,我方定制化调用
- 多个业务模块多个系统相互独立的在进行服务定制化开发
信息的交换
- 本质是内外部信息的相互映射,目前我们还属于根据外部不同的要求定制化映射
- 无论是在当前还是在后续的集成中,内外部的领域模型都不可能完全一致,相互映射是必然
图1:
当前的研发模式
对于研发来说,每个工具的集成的整体研发过程都是如图所示:
开发工作失焦,大部分工作在各个流程、拉分支、协议对接、映射转换、测试联调等等上面
后续方案
在未来整体的集成方案中,依然主要是服务的连接和信息的交换,但形式上会有较大区别。
后续整体方案如图2示意:
服务的连接
- CRM提供统一的EAI集成入口,包括被三方回调,以及调用三方,以及无论何种集成协议
- EAI集成入口统一进行路由、数据转换、映射到CRM业务领域
信息的交换
- CRM研发着重于内部核心领域能力的抽象,提供核心领域的服务能力,如客户,资源,联系人、拜访
- 内外部的领域模型相互映射交给EAI集成,减少定制化逻辑
图2:
后续集成的研发模式
CRM聚焦于领域模型开发,对接三方的事情统一在集成中心进行解决,包括调用和被调用。
技术方案选型
EAI无论是产品还是框架都是有成熟的方案的,这里简单介绍几个常见的,以及优劣势。
行业方案
【产品】mulesoft
详细介绍可参考:blog.csdn.net/huyinabccc/…
mulesoft只有一款产品,叫做Anypoint平台,被salesforce 18年收购,号称为集成平台即服务。是目前国内外最成熟的集成方案提供商,可以解决大多数的集成问题。
问题主要有以下几个:
- 整体服务在国外,可能会有一些风险
- 整体比较完备,但接入成本和后续复杂度会比较大,需要专业人士去对接和后续维护。
- 算是比较重量级的方案,比较适合制造业、医疗、政府、金融..
【框架】spring integration
spring integration是spring提供的一套企业集成框架,实现了EIP的核心能力。
优势:
- 基于spring无缝集成,在sring框架下比较容易学习和上手
弱势:
- 仅提供了非常基本的支持例如文件,FTP,JMS,TCP,HTTP或Web服务,其他都还比较基础
- 集成是通过编写大量的XML代码(没有一个真正的DSL)实现的。使用它,寓意着大量的XML编写工作。
【框架】Mule ESB
Mule ESB是由MuleSoft所提供的基于Java的轻量级ESB(Enterprise Service Bus)集成框架。
他不是仅仅一个集成框架,而是一个包括一些额外功能的完整ESB,比Spring集成它更像是一个DSL。 因为是一个完整的ESB,所以集成逻辑会比较繁琐且复杂。
【框架】Apache Camel
Apache Camel 核心理念和实现的功能上,几乎和mule esb差不多,实现了你能想到的几乎每一个技术,提供很多组件,同时你可以很容易的自定义组件。
优势:
- Camel和Spring的集成很完善。Camel可以实现用到才依赖,不用不依赖。
- 提供了应该超过100+的集成组件,几乎能想到的集成组件都有了
- 同时支持xml,java,groovy等多种dsl语法
- 社区比较活跃,从流程设计到监控都比较完善
最终对比,我们可以选择apache camel来实现我们的集成方案。
接下来会详细介绍可以做到的效果以及大致思路~~
详细方案
方案选型Apache Camel 介绍
camel整体概念也比较简单,它有几个比较重要的概念就是:
- endpoint,所谓的endpoint,就是一种可以接收或发送数据的组件。可以支持多种协议,如jms,http,file等。
- processor,它是用来处理具体业务逻辑的组件。
- route,用来路由,指示数据从哪里来到哪里去,中间用哪个processor处理。
而processor之间用exchange对象来传送数据,有点像jms,通俗一点就像上学时传的小纸条。
具体路径比如应用A --> 路由-->内容转换-->路由-->应用B,其中在每一步,camel都提供了完备和可扩展的机制。
适用场景举例
企业集成不仅仅限于内外部集成,内外、内部、微服务间都属于集成范畴,以下为常见场景举例:
- 【内外】大客纷享销客端客户信息录入后,集成到CRM的客户
- 【内外】EC查重时回调CRM的客户查重服务
- 【内外】三方云呼、机器人的服务接入
- 【内外】CRM需要调用三方接口进行数据同步的场景
- 【内内】CRM需要集成公司内部的ES,DB,redis等等场景
- 【内内】CRM需要集成公司内部的资产、店铺等等场景
- etc.....
方案详细设计
系统大图 TODO
集成系统功能列表
暂时无法在文档外展示此内容
集成系统模块关系
暂时无法在文档外展示此内容
应用组件调用关系
CRM调用三方的关系和流程
暂时无法在文档外展示此内容
三方调CRM的关系和流程
暂时无法在文档外展示此内容
方案Demo草图
以下demo借助于camel开源可视化工具,真实情况下可以使用,需要前端接入下。
后续的无论是CRM集成三方服务,还是CRM内部常见的集成,都可以被配置化出来。集成系统作为一个协调总线,被各方直接调用。
- 集成器列表页,可以看到配置好的所有的集成器
- 能力管理:在配置流程设计器需要用到的CRM的业务能力API和事件API
- 应用管理
- 流程设计器,完整的流程设计器,可以转换为yaml格式被直接使用。下图为一个带分支的定时集成器
- Rest服务设计器,如可以直接为纷享销客设计一个rest服务端点,rest调用本地的服务。
实施路径
Apache camel属于轻量级集成框架,以上demo无需全部实现也可以直接集成使用。
在当前的多个集成场景中(如外呼,大客,机器人等等),可以先采用最容易入门的java dsl方式进行定制集成,先统一入口,再逐步配置化。研发方式和一般开发无多大区别。
实践Demo
以下demo通过java dsl、xml dsl都可以很容易的完成,工具层面可以借助上面demo中的流程设计器完成。
1. 定时调用本地bean的方法,并输出内容到控制台
demo的DSL使用xml语法,配置出一个定时器,3s中调用本地方法的say方法
<routes xmlns="http://camel.apache.org/schema/spring">
<route id="simple-route">
<from id="route-timer" uri="timer:foo?period=3000"/>
<bean ref="myBean" method="say"/>
<to id="out" uri="stream:out"/>
</route>
</routes>
\
2. 将一个文件转储到另一个文件
public class FileCopyRoute extends RouteBuilder {
@Override
public void configure() throws Exception {
from("file:/Users/myname/working/crm-graphql/in/?delay=30000")
.log("look logs...")
.process(new CustomProcess())
.to("file:/Users/myname/working/crm-graphql/out/")
.log("end....");
}
}
3. 动态声明一个健康检查rest服务
如下声明出一个/camel/h/ping的rest服务,并返回静态值
<rests xmlns="http://camel.apache.org/schema/spring" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<rest id="restsvc" path="/hl" bindingMode="auto" produces="application/json">
<get id="getPing" uri="/ping">
<route id="getPingRoute">
<setBody>
<constant>{"msg" : "ok"}</constant>
</setBody>
</route>
</get>
</rest>
</rests>
4. 动态生命出一个rest服务
动态声明一个rest服务端点,并将服务路由到具体的服务上
见如下配置,同时进行了路由和rest服务的声明,实际可以单独声明路由和rest服务
<rests xmlns="http://camel.apache.org/schema/spring" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<rest path="/say">
<get uri="/hello">
<to uri="direct:hello"/>
</get>
<get uri="/bye" consumes="application/json">
<to uri="direct:bye"/>
</get>
<post uri="/bye">
<to uri="mock:update"/>
</post>
</rest>
<route>
<from uri="direct:hello"/>
<transform>
<constant>Hello World</constant>
</transform>
</route>
<route>
<from uri="direct:bye"/>
<transform>
<constant>Bye World</constant>
</transform>
</route>
</rests>
配置定时钟请求外部网站,内容转储
每分钟请求一次网页,并转储到文件
<route id="quz">
<from uri="quartz://mygroup/myTiggerName?cron=0+0/1+*+*+*+?"/>
<to uri="http://gitee.com/apache/camel-quarkus/blob/main/README.adoc"/>
<to uri="file:/Users/myname/working/crm-graphql/out?fileName=quarz.txt"/>
</route>