企业集成架构设计

995 阅读11分钟

遇到的问题

  1. 今年我们团队【企业内部信息化CRM】在人力资源有限的情况下,整体技术方向会发生一些侧重,具体是CRM除商业化系统外,由自研和集成为主转向集成为主,自研为辅。目前诸如外呼、大客纷享销客、小程序、客满机器人等场景,都属于集成的范围,其中大多数场景还未涉及到CRM核心领域能力的集成。未来,随着纷享销客、EC等crm端产品的使用,势必会涉及到更多核心领域模型和周边设施的集成。
  2. 随着集成应用和场景越来越多,对我们研发侧的挑战也会越来越不一样。同等条件下,自研更容易控制研发质量,可维护性更高,更有序,但能力的建设会滞后于业务发展;集成更容易获得市场成熟的业务能力,满足业务发展要求,但大量的无序的集成会导致系统熵增加速,系统快速向无序发展。

\

在以上的前提下,统一的集成方案是为系统减熵或维持熵值得必然路径~

解决策略

关于集成,本质上属于企业应用集成(EAI)范畴,对于企业集成有比较常见的解决方案。

关于EAI

借助于百度百科,看下EAI的定义:

EAI(Enterprise Application Integration,企业应用集成)是将基于各种不同平台、用不同方案建立的异构应用集成的一种方法和技术。EAI 通过建立底层结构,来联系横贯整个企业的异构系统、应用、数据源等,实现企业内部的 ERP、CRM、SCM、数据库、数据仓库,以及其他重要的内部系统之间无缝地共享和交换数据。有了 EAI,企业就可以将企业核心应用和新的 Internet解决方案结合在一起。

一句话概括:EAI做的就是企业内外应用之间的连接和信息交换。

我们的现状

  1. 当前我们的系统中是已经存在集成问题的,具体应用场景有:
    1. 销售云呼
    2. 清洗机器人
    3. 客服的坐席电话
    4. 客服机器人
    5. crm小程序
    6. 大客纷享销客的接入
    7. etc...

如此多的场景,相当于我们外部对接这很多个“渠道”,只是针对每个“渠道”场景,我们都是基于个性化的开发,代码逻辑分散我们各个业务系统中。随之带来的问题有:系统腐化越来越快,后续集成新场景成本越来越高,业务诉求的响应越来越慢。

  1. 今年的目标中,我们将会继续集成更多的三方工具,集成也会进入核心领域,涉及到我们核心的领域模型,包括客户、商机、联系人等等。但目前我们还缺少统一的集成方案来降低集成成本、后续维护成本,提升系统架构稳定性等等

我们的目标

对于我们业务系统来说,领域模型和通用的业务流程才是我们的精髓,我们应该致力于让自己的领域模型更完善、支持更多元化的业务上面,而不是浪费大多数时间再进行功能对接。所以后续目标主要有两个:

  1. 快速整合三方各场景业务能力: 可被集成内容包括如图各类三方能力,其中包括CRM核心领域能力,如客户管理,商机跟进,也包括周边工具如机器人,外呼,飞书表格等
  2. 提供统一、低成本、好维护的集成方案:无论三方、内部何种形式能力,都可被统一方式集成,将各类集成统一到集成中心系统,为系统减熵。

整体方案

在整体的集成方案中,无论内外部的服务集成,整体上都是在做服务的连接和信息的交换。

当前方案

如图1示,为当前和三方集成时的现状示意:

服务的连接

  1. 我方提供定制化http(https)协议服务,三方回调
  2. 三方提供http(https)协议,我方定制化调用
  3. 多个业务模块多个系统相互独立的在进行服务定制化开发

信息的交换

  • 本质是内外部信息的相互映射,目前我们还属于根据外部不同的要求定制化映射
  • 无论是在当前还是在后续的集成中,内外部的领域模型都不可能完全一致,相互映射是必然

图1:

当前的研发模式

对于研发来说,每个工具的集成的整体研发过程都是如图所示:

开发工作失焦,大部分工作在各个流程、拉分支、协议对接、映射转换、测试联调等等上面

后续方案

在未来整体的集成方案中,依然主要是服务的连接和信息的交换,但形式上会有较大区别。

后续整体方案如图2示意:

服务的连接

  • CRM提供统一的EAI集成入口,包括被三方回调,以及调用三方,以及无论何种集成协议
  • EAI集成入口统一进行路由、数据转换、映射到CRM业务领域

信息的交换

  • CRM研发着重于内部核心领域能力的抽象,提供核心领域的服务能力,如客户,资源,联系人、拜访
  • 内外部的领域模型相互映射交给EAI集成,减少定制化逻辑

图2:

后续集成的研发模式

CRM聚焦于领域模型开发,对接三方的事情统一在集成中心进行解决,包括调用和被调用。

技术方案选型

EAI无论是产品还是框架都是有成熟的方案的,这里简单介绍几个常见的,以及优劣势。

行业方案

【产品】mulesoft

详细介绍可参考:blog.csdn.net/huyinabccc/…

mulesoft只有一款产品,叫做Anypoint平台,被salesforce 18年收购,号称为集成平台即服务。是目前国内外最成熟的集成方案提供商,可以解决大多数的集成问题。

问题主要有以下几个:

  1. 整体服务在国外,可能会有一些风险
  2. 整体比较完备,但接入成本和后续复杂度会比较大,需要专业人士去对接和后续维护。
  3. 算是比较重量级的方案,比较适合制造业、医疗、政府、金融..

【框架】spring integration

spring integration是spring提供的一套企业集成框架,实现了EIP的核心能力。

优势:

  1. 基于spring无缝集成,在sring框架下比较容易学习和上手

弱势:

  1. 仅提供了非常基本的支持例如文件,FTP,JMS,TCP,HTTP或Web服务,其他都还比较基础
  2. 集成是通过编写大量的XML代码(没有一个真正的DSL)实现的。使用它,寓意着大量的XML编写工作

【框架】Mule ESB

Mule ESB是由MuleSoft所提供的基于Java的轻量级ESB(Enterprise Service Bus)集成框架。

他不是仅仅一个集成框架,而是一个包括一些额外功能的完整ESB,比Spring集成它更像是一个DSL。 因为是一个完整的ESB,所以集成逻辑会比较繁琐且复杂

【框架】Apache Camel

Apache Camel 核心理念和实现的功能上,几乎和mule esb差不多,实现了你能想到的几乎每一个技术,提供很多组件,同时你可以很容易的自定义组件。

优势:

  1. Camel和Spring的集成很完善。Camel可以实现用到才依赖,不用不依赖。
  2. 提供了应该超过100+的集成组件,几乎能想到的集成组件都有了
  3. 同时支持xml,java,groovy等多种dsl语法
  4. 社区比较活跃,从流程设计到监控都比较完善

最终对比,我们可以选择apache camel来实现我们的集成方案。

接下来会详细介绍可以做到的效果以及大致思路~~

详细方案

方案选型Apache Camel 介绍

camel整体概念也比较简单,它有几个比较重要的概念就是:

  1. endpoint,所谓的endpoint,就是一种可以接收或发送数据的组件。可以支持多种协议,如jms,http,file等。
  2. processor,它是用来处理具体业务逻辑的组件。
  3. route,用来路由,指示数据从哪里来到哪里去,中间用哪个processor处理。

而processor之间用exchange对象来传送数据,有点像jms,通俗一点就像上学时传的小纸条。

具体路径比如应用A --> 路由-->内容转换-->路由-->应用B,其中在每一步,camel都提供了完备和可扩展的机制。

适用场景举例

企业集成不仅仅限于内外部集成,内外、内部、微服务间都属于集成范畴,以下为常见场景举例:

  1. 【内外】大客纷享销客端客户信息录入后,集成到CRM的客户
  2. 【内外】EC查重时回调CRM的客户查重服务
  3. 【内外】三方云呼、机器人的服务接入
  4. 【内外】CRM需要调用三方接口进行数据同步的场景
  5. 【内内】CRM需要集成公司内部的ES,DB,redis等等场景
  6. 【内内】CRM需要集成公司内部的资产、店铺等等场景
  7. etc.....

方案详细设计

系统大图 TODO

集成系统功能列表

暂时无法在文档外展示此内容

集成系统模块关系

暂时无法在文档外展示此内容

应用组件调用关系

CRM调用三方的关系和流程

暂时无法在文档外展示此内容

三方调CRM的关系和流程

暂时无法在文档外展示此内容

方案Demo草图

以下demo借助于camel开源可视化工具,真实情况下可以使用,需要前端接入下。

后续的无论是CRM集成三方服务,还是CRM内部常见的集成,都可以被配置化出来。集成系统作为一个协调总线,被各方直接调用。

  1. 集成器列表页,可以看到配置好的所有的集成器

  1. 能力管理:在配置流程设计器需要用到的CRM的业务能力API和事件API

image.png

  1. 应用管理

  1. 流程设计器,完整的流程设计器,可以转换为yaml格式被直接使用。下图为一个带分支的定时集成器

  1. 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>