华泰证券:如何自研高效可靠的交易系统通信框架?

阅读数:6199 2019 年 1 月 24 日

一、引言

华泰证券自研交易系统经过近两年的建设,取得了阶段性的成果,并在线上为华泰自营部门和部分机构客户提供了优质的服务。本文对自研交易系统的通信框架进行总体的介绍。

首先,我们以委托(交易下单)这个最普通的场景为例,大致观察下数据是如何在系统内部流动的。如图 1,客户端从下单到接收成交回报,数据大致流经了网关、OMS(订单管理系统,以下简称 OMS)、DownStream(报盘)、订阅中心。

image

图 1- 委托(交易下单)

看似简单的数据流,在项目设计和开发的过程中,我们自己、业务后台,提了很多的问题,比如:
1)客户端与网关间通信的安全如何保障?如何避免用户感知链路的通断?
2)成交回报如何快速回到客户端?
3)业务系统只想关注于业务逻辑,不关注权限的控制,可行吗?
4)OMS 是内存交易系统,为了解决用户规模问题,需要基于分片水平扩展,高可用方案需要支持分片内的主备机切换,通信框架可以支持这些需求吗?
5)DownStream 有多个节点,这些节点面向不同的报盘对象,如柜台、交易所等,可以对上游的使用者(OMS)屏蔽这些差异吗?
6)部分应用没有状态,可以平行扩展,消费者可以负载均衡地访问我们的应用,可以吗?
7)是否可以支持灰度升级?
带着对这些问题的探索和解决,我们来介绍自研系统的通信框架。

二、通信框架

我们先给出系统整体的示意图(如图 2 所示),然后介绍我们通信框架的核心组成部分。
外部系统访问交易相关的任何后台服务,需要通过 NGINX 代理,访问相应的网关服务组,通过网关路由到相应的后台系统。内部访问交易相关后台服务时,通过 XSTEP 的服务发现机制,直接对目标服务发起访问。

image

图 2- 自研交易系统示意图

2.1 XSTEP 协议

2.1.1 协议分层

XSTEP 协议是自研交易系统内部采用的协议,为了与 Dubbo 更好的兼容,我们将 XSTEP 协议进行了分层设计,由会话层和应用层协议两部分组成。业务系统可以在会话层与应用层皆使用 XSTEP 协议,也可以会话层使用 Dubbo,应用层使用 XSTEP。

2.1.1.1 会话层协议

会话层协议采用了轻量级的设计理念:信任 TCP 的可靠传输能力,正常情况下可以保证消息的完整与顺序,当出现异常情况时(如协议类型异常、校验异常),代表网络环境异常,会话层中断重连,不尝试进行消息的重传。

会话层规定 T 为标准空闲间隙,3 个间隙未有任何报文传输,需要中断链路。XSTEP 会话层在实现时,提供了链路空闲自动心跳的能力。为了防止恶意攻击或数据异常跳变引起的通讯异常,XSTEP 会话层规定了最大报文长度,超过此大小的报文会被丢弃。

会话层在实现时,支持自动重连,支持自动重连策略的设置。同时为兼顾安全与效率,会话层支持非加密方式传输和 TLS 加密方式传输,应用可以根据应用场景自由选择。

会话层还提供了服务发现与路由的能力,将在 2.1.2 节中介绍。

2.1.1.2 应用层协议

XSTEP 应用层协议定义了数据在内存中的组织形式,并通过统一的数据结构,提供数据的访问接口。
Event 数据结构的定义如图 -3 所示。数据结构通过 MAP<K,V> 键值对的方式作为基本的数据存储结构,接口上,支持所有的基础数据类型。

image

图 -3 Event 结构示意

同时为了支持数组及嵌套结构,还提供了 Group 数据结构(如图 -4),该结构支持嵌套定义,形成无限扩展的树形结构。上述数据形式的定义,在实践中可以满足目前所有业务的数据形式。

image

图 -4 Group 结构示意

2.1.2 服务发现与路由

协议设计过程中,我们定义了几个原则:1)服务的消费者不应感知具体服务提供者的变化 2)要支持服务的负载均衡访问 3)要支持服务的主备访问 4)要支持服务分组,以隔离不同的用户或业务或版本,并支持服务的灰度升级 。

基于上述目标,我们设计了服务的自动发布与发现机制,并设计了两级路由。通过 XSTEP 开发包开发的应用,启动后将会自动发布到注册中心。

2.1.2.1 服务发布

注册中心包含多级目录,顶级目录 XSTEP 表示这个一个 XSTEP 应用;第二级目录为系统名;第三级目录区分了服务的提供者和消费者,同时该级提供了一个名称为 router 的固定文件,用于系统自定义分片路由规则;第四级目录用于区分不同的分片;第五级目录是真正的服务实体,该信息是动态创建和消失的,同时第五级还提供了一个名称为 master 的固定文件,用于主备模式下主机地址的注册。

服务提供者在发布服务时,需指定自身的系统名称、所属分片(不指定默认分片)、服务地址和端口(不指定则默认)。

如果该服务需要由服务提供者自行决定分片路由的规则,则服务提供者应该在 router 中写入路由的规则。如果该服务工作在主备模式下,则服务提供者应根据自身策略,在 master 中写入相应的 IP、PORT 等信息。

应用可以根据报文中存在的任意一个字段来定义路由的规则,非常灵活,路由的目的地是系统内的不同分片号。分片号可以根据不同的用户来划分,也可以根据不同的业务来划分(如 A 股 OMS、期权 OMS),还可以根据不同的版本来划分,这样系统升级时可以做到部分升级,用户逐步切换,达到灰度发布的目的。

2.1.2.2 服务发现

XSTEP 开发包提供统一的服务消费类,使用时需要指定目标系统的名称,分片的路由方式,具体服务的路由方式(主备或负载均衡)。

开发包会根据应用提供的上述信息,自动将数据投送到具体的服务提供者,并自动管理服务注册信息的变更、链路的变化等。 在主备模式下,当主节点发生变化时,开发包会自动建立与新主节点的连接关系。

2.2 网关与订阅服务

完整的通信框架中,仅有协议开发包是不够的,因此基于 XSTEP 协议开发包,又实现了统一的网关和订阅中心服务,搭建完整的通信框架。

为了统一开发模型,我们定义了开发框架和运行时容器 XGATEWAY-PLATFORM,网关和订阅中心作为不同的插件在该框架中开发,并运行在统一的容器中。

2.2.1 网关

网关面对的是一个复杂的环境。首先是协议的复杂性:1)接入协议目前使用 XSTEP,后期也有支持 FIX 接入的需求。2)面对的后台应用有 XSTEP 协议,也有 Dubbo 协议,也有使用 Restful 协议。

其次是部署的复杂性:1)为了交易的稳定可靠,需要区分资讯接入和交易接入。2)需要区分 API 接入和客户端接入 3)出于安全或合规的考虑,某些接入网关上需要屏蔽特定的后台应用。

网关的解决思路是:1)每种协议的接入作为独立插件开发 2)用户登录状态的管理、流量控制、权限控制等作为公共基础服务提供。3)部署时,根据不同的需求,配置不同的插件和路由规则,形成不同定位的网关服务组。4)网关在设计上是无状态的,每个网关组内的网关可以平行无限扩展。5)网关内部通过事件驱动的方式投递事件,通过本地路由规则决定事件最终归属的插件。
下一步网关还将对接入的后台服务进行质量管理,可以做到服务降维,防止部分服务异常导致的系统性风险。

image

图 -5 网关框架

2.2.1.1 登录状态管理

外部系统访问网关时,必须通过认证的链路。一个链路通过认证,有两种方式:1)发送登录报文,并携带合法的用户标识与口令。2)携带此前登录成功时,获取到的未过期 TOKEN 标识。

登录报文处理逻辑:网关通过统一认证校验标识和口令的合法性,对于验证合法的登录,网关缓存统一认证办法的 TOKEN,将链路标识为合法,并将 TOKEN 返回客户端。由于 TCP 长连接的安全特性,在该链路未中断的情况下,对于链路上发起的请求,网关不再校验合法性。但是网关会定期通过统一认证校验此前颁发的 TOKEN 是否失效,如果失效则通知相应链路的接入者。

在实际应用中有一种常见的场景,链路发生了中断重连,此时并不希望用户重新输入用户名和口令。网关在未经认证的链路上,此时则会通过缓存 TOKEN 进行校验,自动对链路进行合法性认证。
另一种场景是某一台网关服务中断,或接入者链路中断,重连时接入了一台新的网关。新的网关上并没有缓存的 TOKEN 信息,此时网关会向统一认证发起一个 TOKEN 校验,并获取该 TOKEN 对应的用户基本信息,自动进行链路的合法性校验。

2.2.1.2 流量控制

网关支持链路级的用户流量控制。通过 IBOS 运行平台可以设置每个用户每秒允许的最大流量及特定功能每秒允许的最大流量。

为了提升流量控制的效率,网关并不会统计每条报文的时间,而是基于目标数进行控制。假设用户的流量限制为 N,则网关会在该用户接入消息达到 N 时,认为一个统计周期结束,并检查(结束时间 - 周期开始时间)是否超过一秒。超过限制则触发流控,该链路报文将禁入时间 T。未超过限制,则清空统计报文,开始一个新的统计周期。

2.2.1.3 权限控制

网关为 OMS 等关键系统提供了统一的权限控制服务,使得业务可以专注于业务本身。用户权限相关数据存储于 IBOS 平台,网关会在链路鉴权时获取该数据。

权限模型定义了交易、订阅、查询等权限,网关将每种权限作为独立的鉴权实例开发,同时支持通过消息类型配置消息所适用的权限模型,未配置的消息则不进行权限控制。

2.2.2 订阅中心

订阅中心与网关采用相同的框架开发,运行在相同的容器中,只是加载了订阅中心插件。订阅中心支持多种订阅维度,并支持较为复杂的订阅条件过滤。

订阅中心将订阅关系存储在 REDIS 中,并通过 KAFAK 接收应用推送的消息。因此订阅中心本身是无状态的,可以水平扩展,并且通过 KAFKA 的 PARTITION 机制,可以负载均衡地处理推送消息。

image

图 -6 订阅中心

三、结语

现在让我们回到初始的几个问题,并进行回答。
1)客户端与网关间通信的安全如何保障?如何避免用户感知链路的通断?

答:XSTEP 支持 TLS 链路加密,并提供加密算法,可对特定字段加密。通过网关的登录状态管理和 XSTEP 开发包的自动重连机制,可以不感知链路的通断。

2)成交回报如何快速回到客户端?

答:OMS 接收到成交回报后,推送至订阅中心,订阅中心根据用户的订阅信息,主动将成交回报通过网关推送至客户端。无需客户端主动查询。

3)我们的业务系统只想关注于业务逻辑,不关注权限的控制,可以吗?

答:我们在接入网关层实现了通用的权限控制模型,可以做到消息级的权限控制。

4)OMS 是内存交易系统,为了解决用户规模问题,需要基于分片水平扩展,高可用方案需要支持分片内的主备机切换,通信框架可以支持这些需求吗?

答:XSTEP 的服务发布机制,支持分片,并且服务提供者可自主控制分片的路由规则。XSTEP 服务发布支持分片内的主备,并对消费者屏蔽具体的切换逻辑。

5)DownStream 有多个节点,这些节点面向不同的报盘对象,如柜台、交易所等,可以对上游的使用者(OMS)屏蔽这些差异吗?

答:使用分片机制,可以解决上述问题。

6)我们的应用没有状态,可以平行扩展,所以我们希望消费者可以负载均衡地访问我们的应用,可以吗?

答:XSTEP 服务支持分片内的负载均衡的访问方式,并且对使用者屏蔽细节。

7)可以支持灰度升级吗?

答:通过分片支持,新的版本部署在新的分片中,并通过用户属性配置,逐步将用户切换到新的服务分片中。

作者介绍:李想,华泰证券信息技术部系统架构师。关注内存交易系统、高性能网络、容器等领域。

收藏

评论

微博

发表评论

注册/登录 InfoQ 发表评论

最新评论

Elan 2019 年 01 月 29 日 12:44 0 回复
如果多一些场景描述会更好理解。
李有幸 2019 年 01 月 25 日 12:27 0 回复
高端实用,有价值!赞!
没有更多了