转载

浙江电信10000号重构札记

省10000现行系统的架构已支撑了近10年,期间由于各类因素的制约没有做过大的架构升级,近而导致了以下几个问题:

  1. 技术框架过于老旧,很多年轻的开发人员都没有听说过,部分框架甚至已经停止维护了,比如使用DWR做为前后端通信架构,服务端使用WebLogic容器;
  2. 前端框架使用Ext JS的早期版本,严重限制了用户体验的优化;
  3. 架构上无法很好地扩展,无法及时地响应新的需求;
  4. 非标准化工程,没有使用Maven/Gradle等主流工程管理工具,导致维护困难;
  5. 代码编写极不规范,10年来新需求不断地开发,但很少做优化,最直接的表现是index页面的单一核心JS文件有2W多行代码;
  6. 业务逻辑过于教条化,不够智能,客服需要经过大量培训才能上手。

目标

基于以上这些问题,对省10000的重构已经迫在眉睫。彼时我正好接手此项目,结合省企信中心领导的要求,确定重构的业务目标如下:

  1. 流程智能化,了解客户的意图进而能更好地帮助客服决策;
  2. 操作简单化,优化交互体验让客服的操作更为流畅快速;
  3. 技术轻量化,使用主流技术去替换之前老旧的过重的技术框架;
  4. 架构通用化,即可以满足省10000的业务需求及部署要求又可以快速实现产品化。

与之对应的技术目标为:

  1. 微服务架构:
    提升系统的可扩展性及可维护性;
    可拔插设计,可与不同地市已有组件整合;
  2. 数据驱动:通过通话过程中不断产生的数据实现修正客户的意图并反馈给客服;
  3. 服务市场设计:
    引入Widget封装原子级的业务,快速构建业务场景,及时响应需求变更;
    降低开发维护人员的技能要求,由原来的针对新需求开发改为新Widget开发。

技术架构

架构设计核心诉求

  • 可依赖 :用户认可运行的 稳定性 及数据的 准确性 进而相信、依赖系统,在架构之初就必须视系统的鲁棒性设计为第一要素,如:分布式多机多机房部署、多数据源策略设计等;
  • 可扩展 :在软件生命周期内需求往往是永无止尽的,如何快速影响需求的变化是架构成功的关键之一,微服务设计在此方面有天然的优势;
  • 高性能 :性能指标是架构永恒的追求,异步化编程、基于事件循环的服务处理、合理的使用缓存、良好的数据库设计都有助于提升性能;
  • 安全 :这是最基本的要求,现代开发框架几乎不会存在SQL注入风险,但在存储架构、备份设计及认证鉴权等方面必须重视;
  • 使用简单 :尽可能地降低对开发人员的技能要求是架构必须考虑的关键因素,如使用主流的语言/框架、对复杂且通用的功能做最大化地封装等;
  • 可测试 :微服务最大的劣势之一可能就是测试的复杂性,如何将之降到最低,如何在单一组件中就可以完成核心测试是对架构的一大挑战;
  • 持续交付 :这是开发流程架构必须考虑的因素,各类CI及DevOps工具的兴起及成熟让持续交付变成可能,同时这也是微服务的优势之一。

开发架构

浙江电信10000号重构札记

整个平台使用微服务架构,其中绿底组件为基于Spring Cloud封装的组件。

  • Gateway:基于Zuul封装的服务网关,扩展了权限控制及日志监控等功能,其中还包含了针对Websocket协议支持的高性能WSGateway子网关;
  • Auth:基于多租户RBAC模型的权限管理组件;
  • Config:Spring Config统一配置管理组件;
  • Register:Netflix Eureka服务注册管理组件;
  • Monitor:基于Turbine及Hystrix Dashboard的服务状态/性能监控组件。

浙江电信10000号重构札记

平台分四层:View、APP、Service、Support。

  • View:视图层,即大前端,用户交互层,可分为Web、H5、APP、SDK等多个形式;
  • APP:应用层,处理核心功能,与视图通过基于JSON的HTTP(S)协议或Webscoket交互;
  • Service:服务层,是对常用功能的抽象与封装,多用于与第三方系统直接或间接(ESB)通讯;
  • Support:支持层,提供了常用的基础环境,如数据库、消息队列、大数据等。

所有数据交互都会经由Gateway处理,主要用于鉴权及路由分发,不同架构下View可能会通过F5或Nginx做负载后与Gateway交互。

部署架构

浙江电信10000号重构札记

整个平台部署示例如上图,可以是公网或DCN网络,只要IT做好网络控制就可以,核心的要求是需要如下几类服务器:

  1. 前端服务器:部署Nginx服务,存放静态的前端页面,当用户访问UI资源时调用此服务;
  2. 网关服务器:部署微服务网关组件,这是核心组件,建议多机部署;
  3. 权限及其它微服务管控服务器: 部署认证、服务注册发现、统一配置、监控等常用支撑服务;
  4. 应用层服务器:部署各应用组件;
  5. 服务层服务器:部署各服务组件;
  6. 支持层服务器:部署诸如MySQL、Rabbit、Redis等基础环境。

日志体系

浙江电信10000号重构札记

一般的日志类型可分为:

  • 行为日志:记录用户的操作行为,多用于交互优化之用;
  • 调试日志:记录各类debug/trace等级别的日志用于程序错误调试;
  • 业务日志:记录一些关键业务,如登录、改密等;
  • 第三方工具日志,如Nginx的访问日志。

日志既可以是服务侧发起的,也可以是视图侧(Web页面、APP等),如果是视图侧发起则需要高性能采集器来接收。

在日志量大、并发量高时可以用Kafka来削峰,将日志生产与消费解耦。

日志存储主要有三类:

  • DB:用于存储非常核心的日志,(关系型)数据库永远是大中型系统的瓶颈,所以不应该存储数据量大或并发量高的日志,不应该在主业务库;
  • 日志文件:常规的存储方式,用于存储相对而言不是很重要的,不需要集中的且不需要实时分析的日志;
  • ES:通过Logstash将日志写到搜索系统中,对于需要简单分析的、数据量大且并发量高的日志是非常好的存储方式。

日志分析用Kibana做简单的实时查询分析、使用Spark做实时或离线分析也可以使用自定义的工具。

技术选型

技术选型考察的几个原则:

  • 开源优先原则 :优先考察开源解决方案,存在多个开源方案时主要关注社区成熟度、活跃度、代码质量及行业案例,在开源方案无法满足需求时才考察厂商方案;
  • 轻量化原则 :所有技术方案必须是轻量化、去耦合的,禁止引入高侵入性的方案;
  • 需求适配原则 :世上没有脱离业务而言的“好”技术,合适的业务下选用适合技术;
  • 人员适配原则 :所选方案必须匹配团队整体的技术能力,不一味追求技术的前瞻性。

大前端

所谓“大”前端指的是包含桌面、APP、微信在内所有与用户有直接交互的视图层。

桌面平台

MVVM模型:一种架构模式,其核心是提供对View和ViewModel的双向数据绑定,ViewModel的状态改变可以自动传递给View ,即所谓的数据双向绑定。

为什么一定要支持MVVM模型呢?本产品的一个重要特性是 数据驱动 ,这一架构需要在前端保持一份 关键数据集合 ,前端 关键数据集合 的变更会触发一定的视图变化,传统框架需要自己实现这一功能,而MVVM模型天然地解决这一数据订阅与操作行为。

桌面平台主要考察JS及CSS框架,主要指标是MVVM模型、兼容性、性能、组件化、是否包含常用控件。现有两个方案:

  • 兼容省10000现有平台

    省10000的基本环境是Win XP sp3 + IE8 + 2G内存

    其中IE8最为制约技术选型,基本把主流前端框架隔离在外,可选的JS框架有JQ(需要自己做组件化封装)、Knockout.js、Avalon.js等,CSS框架暂无好的选择。
  • 支持主流标准
    此方案技术可选的空间很大,但基本只考察基于MVVM的AngularJS、VueJS、React.js等三个主流JS框架,CSS框架可使用Bootstrap。

省10000是我们首要落地工程,调研结果是:

  • 不可能为所有电脑升级系统进而支持高版本IE;
  • 现版客服支撑系统只支持IE8及IE高版本的兼容模式,Chrome等第三方浏览器无法使用;
  • 现版客服支撑系统改造以支持IE11的成本比较大;
  • 需求方负责人确认可以不考虑兼容性,新系统先在部分新配电脑上运行,但需要考虑新老系统并行环境;
  • 中兴IVR及坐席控件会做升级,支持32位IE11(非兼容模式),新版将不再支持IE8,现版本只支持IE8。

经与需求方协商我们的选型确定为第二个方案(支持主流标准)

APP

APP有两种形式,一种是完整功能的APP,另一种是APP插件形式,前者开箱即用,后者服务于第三方APP。使用主流技术实现即可。

微信、易信等第三方工具

基于H5界面交互,使用特定SDK开发。

后端服务/应用

后端服务/应用使用Spring Cloud这一成熟的微服务框架,功能与省10000的ESB在服务注册发现有一定重合,但Spring Cloud集成了诸如统一配置中心、服务网关、断路保护等非常实用的功能,而开发上又基于Spring Boot这一简单的框架,所以很适合快速开发大型微服务系统。

由于Java8提供了FP支持,给开发带来了很大便利,所以本产品后端语言必须基于Java8及以上。

算法平台

算法处理主要关注数据量、算法复杂度及实效要求,分单机与分布式版本,如考虑SaaS化,建议使用分布式算法,推荐基于Spark的MLlib算法库,数据存储可选用HBase。

第三方工具

数据库

本产品使用关系型数据库作为主要存储库,但只对MySQL及Oracle提供官方支持。

缓存

本产品使用Redis做为缓存工具,以提升服务性能。

数据网格及MQ

为支撑 数据驱动 特性,本产品使用 Hazelcast(或Ignite) 做数据网格,数据网格提供了分布式数据操作及数据变更订阅等能力,同时 Hazelcast(或Ignite) 也实现了轻量级MQ功能,本产品对MQ的依赖度不高,从简化依赖的角度出发直接选用它们提供的MQ能力。

10000号系统由多个子系统组成,由于保密限制,这里只简单地介绍一下最核心的 客服支撑系统(CSS)子系统的设计。

客服支撑系统(Customer Support System)

组件说明

浙江电信10000号重构札记

如上图,客服支撑系统遵循 核心架构 中的四层模型,视图层提供了桌面Web版本、主流语言的SDK、H5嵌入版本以及微信小程序等终端,应用层由两个模块及三个组件组成:

  • 模块(module)
    1. app-common:所有应用组件都依赖此模块,此模块包含了应用公共功能,如浙江版本的Dubbo连接封装;
    2. css-common:客户支撑系统的公共依赖模块,包含了核心共享模型、数据驱动单元、客服操作跟踪单元等;
      Data Drive Unit:数据驱动单元,实现了数据驱动的核心能力;
      Opt Trace Unit:客服操作跟踪单元,用于记录客服在话务流程中的各项操作,用于IVR及场景等历史回溯;
  • 组件
    1. Kernel:核心组件,主要包含四个业务单元、管理配置及其它周边功能:
      RBAC Unit:用户认证及鉴权处理单元,浙江版本对接的是门户应用;
      Index Unit:首页功能处理单元,包含了首页操作的核心功能;
      Call Unit:话务处理单元,管理话务的生命周期,提供了Session化的客户认证、IVR各项操作、小结等功能;
      Scene Unit:场景处理单元,包含了场景类别及场景的显示等功能;
      Rating:满意度调查功能;
      Scene Build:场景构建管理;
      Widget Mgr:Widget管理;
      Key Data:关键数据处理;
    2. Widget:Widget处理组件,用于Widget数据交互处理,Widget组件在收到数据后会经过一系列拦截器组成的拦截器栈处理并与服务层交互取数;
      Interceptors: 拦截器栈,内置的拦截器有:
      WidgetDefInterceptor: 用于判断Widget请求的合法性,是否是已启用的Widget,关键数据是否满足要求等;
      WidgetAuthInterceptor:对同一通话务中没有认证的信息做脱敏处理;
      WidgetOptLogInterceptor:记录Widget数据访问日志;
      WidgetCacheInterceptor: 对允许缓存的Widget做数据缓存,缓存针对同一通话务;
      WidgetKeyDataInterceptor: 关键数据获取,数据驱动的触发器之一;
      Dispatch:Widget分发,根据传入的Widget Code及Widget Method将请求将由指定的Widget方法处理;
      Widget Load:Widget加载器,加载并初始化Widget配置;
    3. Recommend:推荐组件,基于数据驱动的推荐处理,多用于场景推荐;
      Core Process:核心处理器,用于处理接收到的要处理推荐的数据;
      Adapter:适配器,适配不同的运算触发机制及结果反馈机制,目前适配于 数据驱动 触发及WS数据Push;
      SPI:推荐组件支持多种推荐实现,目前只支持基于规则(Rule)的推荐机制,后续会增加基于智能算法相关的推荐。

浙江电信10000号重构札记

Kernel、Widget通过HTTP与Gateway交互,有关键数据变更时通过数据订阅向Recommend推送消息,Recommend收到消息并处理后通过HTTP与WSGateway交互,WSGateway会对外暴露Websocket服务。

为什么需要WSGateway

推荐组件需要Websocket支持,有两种方式实现:

  • 在推荐组件开启WS支持,此时不需要WSGateway,但推荐组件是业务型的组件,业务型组件聚焦业务功能,编程模型上使用的是同步模型,基于Tomcat对外提供服务,在连接过多时会有性能问题;
  • 使用独立的WS服务,即这里所谓的WSGateway,这是一个特殊的组件,使用基于Netty的事件模型,可轻松应对海量连接,同时此组件又可以使用基于Token的WS连接路由,所以可以支持HTTP协议调起WS Push请求。

综上,推荐增加WSGateway这一组件以处理WS通信。

数据驱动与KeyData(关键数据)

有这样几种需求:

一个Widget中某些数据的变更会触发其它一个或多个Widget联动。

锚点功能:在场景操作中满足一定条件会触发场景推荐的变更(如账单语音通信费两个账单对比月份差值大于X%且大于Y元向客服推荐语音分析场景)。

首页预判功能,在开始话务显示推荐场景(如单月累计国际长途费用超过X元向客服推荐账单分析场景)。

对于第一个需求由于Widget是独立的,不同Widget可被自由组合,所以无法直接为多个Widget设置关联,第二、三个需求都是数据变更推荐场景,所以可以使用同一套推荐机制实现。

综合这三个需求的特点都是 数据变更触发外部动作 ,故可用 数据驱动 机制实现。

数据驱动最基本的要解决数据统一的问题,如WidgetB订阅了 业务号码 变更触发X动作,而WidgetA正好会产生 业务号码 变更,那么对于 业务号码 这个数据的名称定义及口径解释必须是一致的,再如账单对比月份差值大于X%且大于Y元向客服推荐语音分析场景,那么必须定义诸如 bill_compare_diff_ratebill_month_current_amount_total 这两个数据,规则引擎订阅这两个数据用于规则处理。

为解决上述问题,设计上引入了 关键数据 这一概念,关键数据就是对需要用于上述几个需求的数据做的统一及规范。

CallSession(话务级Session)

系统实现了话务级Session,即对同一通话务有效的数据共享机制,共享的数据包含但不限于:话务SessionCode、业务号码、客户认证信息等。此设计可用于解决诸如:

  • 同一通务话同一业务号码多次重复认证问题(配合 关键数据 实现)
  • 操作轨迹范围记录
  • 场景推荐刷新周期(配合 关键数据规则引擎 实现)

由于同一客服同一时间内只能操作同一通话务,所以话务级Session以登录用户编号为key保存于Redis中,请求只要带上登录用户token就可以获取到对应的话务级Session。

推荐处理

浙江电信10000号重构札记

推荐组件的触发基于 关键数据 的变更,在客服登录时需要向推荐组件注册,推荐组件会建立此客服对应的关键数据网络,并订阅数据变更,由于数据域以话务为单位,所以在电话呼入、业务号码变更、呼叫结束时都要清空此客服的关键数据。

在客服操作过程中会不断产生新的数据,系统用全局关键数据变更监控来保证一旦有关键数据变更就向关键数据网络中Put变更数据,这样推荐组件就可以收到数据变更进而开始计算,计算完成后向客户端推送变更。

目前推荐基于规则实现,使用轻量化的嵌入或规则引擎,引擎提供了基于JS语法的规则执行器。

服务市场(Service Market)

由于业务需求会不断增加且需要及时响应,而后端的数据又多来源自第三方系统,构建一个业务可扩展的体系显得尤为急迫,本设计将这一体系称为服务市场。

浙江电信10000号重构札记

上图是服务市场的整体架构,整体上为两块:Widget和Plugin,分别属于应用域和服务域。

  • Widget为“小控件”之意,又细分为基于HTML/JS/CSS的UI控件和对应的应用端,两者共享一些通用方法及统一Key Data(关键数据),通过HTTP交互。Widget是对业务抽象,每个Widget都是最小业务单元,不同的Widget组成场景对象,一般而言一个场景是指一个包含特定业务的页面。
  • Plugin是对服务的抽象,一个Plugin可以用于数据交互,与一组特定第三方接口通信,也可以是对一组复杂业务的封装。

最终效果示例

浙江电信10000号重构札记

浙江电信10000号重构札记

后记

10000号改造涉及很多子系统,上文只介绍了核心系统及客服支撑子系统的架构,其它的诸如IVR、报表、绩效、质检、知识库等本文都未涉及。

总结改造的几个难点如下:

  1. 业务庞大复杂,我做过电信系统及互联网公司的架构师,相比而言,互联网这点逻辑在电信系统中根本不足一提,一个例子是目前支撑客服系统的服务接口就是2000多个,并且还是封装后的,裸接口估计有上万个之多;
  2. 双系统并行,新系统替换从省到市各个呼叫中心需要一层层推广,需要半年左右的时间新系统才能全面部署,但新老系统无论是从表结构到前后端架构都做了颠覆性的修改,如何确保新老系统并存是一个很重要且麻烦的课题,有机会另起一文叙述;
  3. 人员的因素,相对而言电信系统的开发工程师对新技术敏感性差一些,需要花比较的精力在宣讲及培训上;
  4. 不能停机,电信SLO中可用性要求5个9以上,这需要在架构设计需要综合考虑各种场景可能性及制定对应的应急预案,最大化地确保将服务可用。

原文链接: https://zhuanlan.zhihu.com/p/29791472 ,作者:蒋震宇

原文  http://dockone.io/article/2796
正文到此结束
Loading...