作者简介:罗意,广发证券 IT 中后台系统架构师。2013 年初加入腾讯,主要负责腾讯微博的转发评论的逻辑层和存储层,后期负责微博后台的基础组件研发。2016 年加入广发证券信息技术部,主要负责行情、交易等中后台业务的系统架构设计和研发工作。在高性能、高可用后台系统架构设计方面经验丰富。目前专注于金融 IT 系统、FinTech 等相关技术的应用,关注互联网技术和金融系统的深度融合。


目录

  1. 证券行情和交易系统服务架构

  2. 如何做到高并发、高性能?

  3. 如何做到高质量推送?

  4. 如何做到高可用、可扩展?

  5. 遇到的挑战点

广发证券是最早在自研系统中使用Go语言的券商之一,我们大概有接近3年的使用经验。现在广发自研的分布式系统以及一些高性能的系统或者对性能优要求的系统,基本上都是用Go实现的。

我们团队使用Go语言自研的系统有:

1、行情云系统,要求高性能。

2、分布式交易中台系统,要求安全、稳定。

今天主要和大家交流这两个基于Go改造的系统。

证券行情和交易系统的特点

• 行情用户连接并发峰值高

• 行情数据时效性要求高

• 行情数据推送流量大

• 行情指标计算量大

• 安全、稳定、快速

行情和交易系统有各自的特点:

1、行情用户连接并发数高。9点到11点半开盘期间,用户在线时间比较长,而且是长链接。

2、行情数据时效性要求高。用户要求我们的行情数据更新速度要尽量快,来自于交易所(深交所、上交所)的行情数据,大概是3秒一个更新数据快照,要求券商系统尽快将交易所的最新行情数据送达用户终端。我们要采用的是行情数据由后台主动推送的方式。

3、行情数据推送流量大。广发证券作为第一梯队券商有约1800万用户,牛市时最高同时在线约50-80万。一个用户平均订阅自选股约10个,这样同时对外的行情推送量就很大,约200万左右QPS,实际是100万QPS左右。高峰时刻在9点30开盘和13点开盘的那会儿,流量非常大。

4、行情数据指标的计算量大。从交易所快照行情数据到行情指标数据,需要经过大量计算工作。以十种K线计算为例,证券数约2W,每天开市4小时,每3秒刷新一次行情,共需计算7.2亿次。再加上实时,分时,市盈率,涨跌幅,委比,委差等十几项指标计算,每日计算量在10亿级别以上。

5、主管部门对于券商管控比较严。交易系统的安全、稳定就显得非常重要的。虽然我们用互联网思维解决这些问题,但还是需要有适应性来适应券商的环境,不能做得像互联网那么灵活,比如说用户无感升级,比如说扩容,服务器和网络成本。其实针对灵活性、成本、安全、稳定等指标会有一些平衡性的取舍。一旦有一个用户下单没有成功或者下错单了,下单没成功我们系统需要尽快让用户知道是否成功与否,而不应去做重试了,以避免系统下错单。再者就是交易速度要快,在牛市的时候,很多券商下不了单,也就是处理速度和稳定性存在问题的。我们需要在交易速度快的同时也进行过载保护等措施。

1.证券行情和交易系统服务架构



广发行情云系统从外包转向自研,我们做的事情改变后台设计架构,以适当高并发、高推送流量的稳定可靠的系统要求首先,我们对整个行情和交易业务进行梳理拆分:

       一是横向拆分,借鉴于微服务或分布式相关理念来进行业务拆分。依据功能完整、数据同构、职责单一的原则进行横向拆分为实时行情、K线行情、分时行情、分笔行情、板块行情、资金流向、代码链、鉴权服务、交易服务、期权期货、基金债券和Lv2行情。

       二是纵向拆分依据合理分层,剥离逻辑和存储的原则将行情云系统进行纵向拆分为接入网关、读逻辑层、数据存储层、写逻辑层、行情转码层。将交易系统拆分为接入层、逻辑层、柜台接入层、柜台交易层。

证券行情和交易系统服务架构图

交易系统架构



我们首先用户侧来看,再从行情源侧(深交所行情、上交所行情)来用户侧需要一个高并发、高性能的接入层,用于屏蔽大规模用户连接,将用户请求通过长连接转到对应的业务逻辑模块。接入层同时可以针对逻辑层的具体业务逻辑模块做负载均衡、路由容灾、服务发现。接入层设计指标是一个进程四核心、1G内存的情况下支持5万连接数10万QPS行情小包,一个请求包大概是200字节左右。我们需要考虑以下问题:

1、接入层如何提供50万左右的同时在线连接数?绝大多数的TCP连接数来自于APP,Web用户使用WS协议连接的

2、接入层如何支持不同的接入协议(tcp/ws/http)

读逻辑层有分时、K线、资金流向、实时等行情模块,只需要与接入层进行通信,而无须接触每个用户连接,这样读逻辑层就可以专注于处理自己的业务逻辑。

要实现推送大规模的行情数据需要一个推送系统管理用户自选股的订阅,从而实现给某个用户推送他关心的行情数据,同时管理用户连接与接入层进程、接入机器的映射关系推送系统从写逻辑层订阅全量标准行情数据,然后再用户的订阅关系推送出去。

数据层,主要用于存储行情数据。最开始的方案使用Redis存储,写很高频,3秒一个快照,主Redis是不停写,高并发量,备redis不停的同步,容易造成redis读取性能差的问题同时因为自建机房和合规的原因,我们不能架设大规模的redis集群,所以我们最后采用了性能好、但开发难度大一些的文件存储行情的方式。

逻辑层,负责解码深交所、上交所的行情源数据。交易所过来的数据是源数据,而我们给用户展示的是标准化的行情数据,如分时、K线、分笔和资金流向等数据。

周边支撑系统,包括HttpDNS、服务发现、负载均衡、监控告警、日志服务等。

此外本架构方案在行情服务稳定运行后,也应用于交易系统。交易系统有加密和安全的要求,一是对通信数据进行加密交易数据需要进行严格加密,二是对用户权限登录态进行安全校验,此外还需要提供验证码制等措施。

横向拆分交易系统逻辑层,可分为股票的查持仓、委托买卖,基金查询和申购,OTC(场内交易),融资融券等等。逻辑模块采用读写分离方案比如:些用户不断刷持仓查询,但不一定会下单,读写分离方案可以做到委托下单与查询接口相互独立。柜台接入层,承接恒生柜台金证柜台、顶点柜台的统一接入功能将不同柜台的接入与业务逻辑进行解耦。

2.如何做到高并发、高性能?

接入层是解决高并发和高性能问题的关键,我们采用TCP接入来承接广发证券体系内最大流量的行情服务。

首先要解决的问题是管理高并发的TCP连接,一个进程如何做到同时5万TCP连接,总体QPS 10万?其实用常规的Go来写,那就是写一个Socket监听,每来一个连接甩出一个读协程,再甩出一个写的协程,中间可能还需要一个协调控制的协程,再去处理这个事情。这样是否可行?我们最开始就是这样做,但是测试结果是可以达到 1万个TCP连接,2~3万QPS,再往上增加压力就跑不动了。所以这种方式很难达到我们的设计要求,我们需要进行改进。

第一、对于10万级别的协程数,Go是很难调度的,基本上是超过了它的调度能力,一旦GC使用程序进入短暂停顿,就会堆积大量的任务,GC过后就是大爆发的时候,这时候很容易出问题。用户连接管理和业务协程池是平等关系,所以5万连接产生的10万协程和N个业务协程(常数级别)是平等关系,所以10万协程应该作为一个整体参与到N个业务协程来分配CPU的调度,我们要设法让这10万协程变为一个整体。

第二,各个模块的职能要单一和专注,有converger进程专门进行accept用户连接,有netcgo模块专门进行用户管理,有业务逻辑模块专门进行请求转发,同时有推送逻辑进行推送数据的转发,tcpClient专门负责与业务系统进行连接和转发数据,这样将业务模块的请求收敛为一个长连接上来了,这样可以更高效的处理数据。



我们做自定义协议设计需要考虑如下问题:



我们为了更高效的传输行情小包的数据,增加了一个handshake的过程,这样可以极大压缩业务请求所需携带的包头信息,提高传输效率。同时,我们将接入协议和内部协议分离,这样内部模块协议升级和发布不会影响前端用户请求。



这是我们上线之前针对接入层做的性能测试Client ->接入层->server,server进行echo回射。

当时的监控图如下,大概跑了一个多小时。

3.如何做到高质量推送?

推送系统主要职责是管理用户订阅行情,推送行情数据。PushManager负责和接入层通信,管理用户的订阅请求,同时将用户和接入层进程ID进行映射,将映射关关系发送到push Proxy,由Push proxy进行UDP推送行情数据对于同一个接入进程上的用户推送数据,PushProxy会进行合并,这样能更高效的进行推送。

4.如何做到高可用、可扩展?

4.1 服务发现



业务模块要做到无限可扩展,需要实现服务发现和负载均衡机制。我们的服务发现方案是采用的开源组件Consul来实现的,基于docker容器化部署。比如对于K线业务模块取名为kline.gf.com,该服务部署在2台机器的集群里,每台机器部署2个进程,每台机器都有一个registrator来实现自动注册服务这样在consul里kline.gf.com会对应四个IP:PORT对标识的进程客户端需要调用时会从consul拿到4个IP:PORT,然后和他们建立4条连接,接下来就可以把请求包发到对应的进程上去。那么这四个进程怎么路由?这就是负载均衡要解决的事情

4.2 动态负载均衡组件



这个组件和服务发现结合,从服务发现那里拿来4条IP:PORT记录,业务请求过来时如何分配请求业务模块需要传入kline.gf.com调用GET API,负载均衡组件会依据权重返回一个质量比较好的连接,然后业务模块就可以发送请求包了业务逻辑收到回包后需要调用report接口上报调用情况负载均衡组件会依据调用成功次数、业务耗时、连接情况等信息对某一个连接进行计分,然后依据计分结果选择最优连接。连接情况是实时进行反馈,所以该负载均衡方案能在几十毫秒内就能将down的进程移除调度,能在秒级将新增的进程加入到调度。

4.3 解码与转发系统



从交易所层面来看,解码怎么做到高可用?因为VDE是上交所或者深交所的代理服务,你可以理解为把行情快照转发到这里,部署到我们的机房。我们其实部署了三套解码,一个是做容灾,挂了一套,还有其他的交易所来的时候已经打上时间戳,repeater可以针对两路行情数据进行冗余去重。

4.4 数据监控与告警

如果要说高可用,不仅仅考虑负载均衡、异地部署、集群服务数据冗余,监控和告警也是非常重要的。业务进程调用监控上报API上报指标,Api的协程每10秒汇总一次通过UDP上报到本机房的monitor,monitor通过Tcp方式将监控数据转发给influxDB,用户可以通过Grafana在Web上查看监控报表。

5.遇到的挑战点

1、Goroutine调度没有优先级之分

在一些高并发场景下,大量请求Goroutine和其他工作Goroutine数量级差别较大,他们之前调度是没有优先级之分,所以有时会导致调度不合理。

2、10万级别Goroutine调度不均衡

如果一个进程Goroutine数量是10^3 级别,Go的问题不大。如果是10^4级别,Go的调度不一定高效。10^4级别的Goroutine数量调度不均衡。

3、大量Goroutine对象创建和销毁,GC影响系统响应速度

大量Goroutine时,GC影响特别明显,因为一旦停顿一下,就会阻塞很多任务,一旦放开就会像洪水一样过来。

4、cgo通信机制的低效



接入进程Converger专门用来accept连接,然后通过UnixDomain发送到Epooll管理器Epoll管理连接通过一个Goroutine拉起常驻在进程内,所以收敛了Goroutine的数量。

用户频繁上下线,需要频繁的分配内存,我们设计5万个连接,一次创建5万个Hash桶放在那里,用户上来时获取一个内存对象,用户下线后将回收内存对象,打上free标记。

我们通过开辟一个无锁队列,C语言和GO语共享这个队列地址,通过内存通信来代替CGO通信。



接入层要负责很多业务,下面又不同的分布式模块。业务模块之间不能互相影响业务逻辑模块之间比较好隔离,那就是不同的系统、不同模块,使用不同的集群部署。接入层是一个要对多种业务,我们在内部通过不同的命令、不同的业务模块使用不同的Chan,这样的好处是不同的业务转发不会相互影响。比如代码链是比较重的业务,实时业务是比较轻的,这样他们就可以有不同的优先级和处理方式。Chan还有一个好处是削峰填谷,有可能某一时间请求量比较多大,像浪一样打上来。对于你系统来说,这种浪是不友好的,对于一个程序来说这种浪会触发边界值。你有Chan以后,一旦这种浪打过来,会先存储在chan里然后空闲时慢慢处理,所以会有平滑的作用,业务系统看起来是相对平滑的曲线,不会有浪那样的感觉。

编程SDK集成负载均衡、服务发现和异步session,及一致性的协议封包和心跳机制同时管理动态业务连接开发者只需注业务逻辑,每一个程序都能高并发和高可用,同时解决了分布式系统模块间的通信协作问题


2018年的 Gopher Meetup 将在杭州开启巡回第二站,点击阅读原文报名参加

Go在广发证券分布式行情和交易系统的应用和实践相关推荐

  1. 分布式高频量化交易系统架构讲解(企业版,期货ctp,股票xtp,数字货币,附全部源码)(值得收藏)

    目录 1.量化交易系统简介 1.1行情数据 1.2交易策略 1.3交易 2.    分布式高频量化交易系统 2.1.    架构图 2.1.1量化交易系统教程地址 2.1.2量化交易系统教程中讲解的期 ...

  2. 【FIW2022精彩回顾】国泰君安新一代核心交易系统网络底座建设实践

    9 月 21-23 日,第一届"金融现代化IT基础架构转型论坛(FinTech Infrastructure Wave 2022)"成功举办.该论坛由中国信息通信研究院云计算与大数 ...

  3. 分布式实时处理系统架构设计与机器学习实践

    编者按:在2017年的1月11日,CSDN高级架构师金牌授课群为群友们带来了第一次的分享,讲师和主题参见这里,本文为课程后续的文字整理,第一时间发出来分享给读者,课件下载点击这里. 大家好,我们今天主 ...

  4. DockOne微信分享( 八十九):恒生金融交易系统的Docker化实践

    本文讲的是DockOne微信分享( 八十九):恒生金融交易系统的Docker化实践[编者的话]Docker可以显著改善企业软件研发流程.提升企业DevOps效率.借助Docker,企业可以对现有IT系 ...

  5. 阿里专家讲中台:技术中台-分布式架构在蚂蚁金服的实践

    来源| 阿里云峰会 文| 技术领导力社区 本文整理自,阿里高级技术专家-许文奇在2019阿里云峰会上的分享<技术中台-分布式架构在蚂蚁金服的实践>,结合技术领导力社区架构专家的点评和解读, ...

  6. 数据库分布式架构的落地策略与典型实践

    本文根据杨建荣老师在[deeplus直播:数据库分布式架构的落地策略与典型实践]线上分享演讲内容整理而成. 杨建荣 竞技世界 数据库专家 dbaplus社群联合发起人,腾讯云TVP,Oracle AC ...

  7. 打造云原生大型分布式监控系统(三): Thanos 部署与实践

    视频 附上本系列完整视频 打造云原生大型分布式监控系统(一): 大规模场景下 Prometheus 的优化手段 打造云原生大型分布式监控系统(一): 大规模场景下 Prometheus 的优化手段_哔 ...

  8. 再获认可|九州云获评2022分布式云与云边协同创新实践案例

    ​6月14日,由中国信通院.中国通信标准化协会联合主办的"2022云边协同大会"顺利召开,会上正式发布2022分布式云与云边协同创新实践案例评选结果.九州云"5G专网+边 ...

  9. 一文理解分布式服务架构下的混沌工程实践(含PPT)

    导读:近日,在 GIAC(全球互联网架构大会)上,来自阿里巴巴高可用架构团队的高级开发工程师肖长军(花名穹谷)做了<分布式服务架构下的混沌工程实践>主题分享.本次分享包含三部分,第一部分从 ...

最新文章

  1. python基础单词-学Python必背的初级单词,快来看看学吧
  2. ORACLE----触发器,存储过程及JOB
  3. mysql不被其他ip访问_mysql数据库无法被其他ip访问的解决方法
  4. 【SQL语句】MySql、SqlServer查询近期记录
  5. 微信公众号配置后台接入
  6. JavaScript之array
  7. 该如何弥补 GitHub 功能缺陷?
  8. 中科院人工智能应用 福玛特550G解析
  9. 【SQLServer】将Job运行结果发送电子邮件通知用户
  10. 为什么Audition CC2017扫描不了电音插件,你需要这个工具
  11. re学习笔记(0) CG-CTF-re-3 py交易
  12. 虚拟机3-11-14:53,工作记录
  13. 微型计算机键盘上的tab键汉语译为,微型计算机键盘上的Tab键汉语译为()。
  14. Jenkins系列之——第四章 Jenkins编译一个Web项目并远程发布到Tomcat
  15. 开源一个电子胸牌项目,很棒!
  16. 苹果与华为领衔 全球科技巨头进军AI手机领域
  17. PS室内植物素材合成教程分享骞
  18. 使用python解密pdf
  19. 祖母绿canutillos宝石
  20. 等待事件之enq: HW - contention

热门文章

  1. 原油稳步前行因俄罗斯反制措施
  2. UE5项目设置必须开启光晕时,某一场景关闭光晕的方法
  3. Qt phonon多媒体框架
  4. 或许你从未通过这些安卓开发工具
  5. 奇怪的问题 mspaint
  6. 【全国运营商】一证通查‖服务
  7. 360安全卫士怎么开启自动阻止高风险远程登录
  8. 程序员涨薪留小公司还是该跳槽去大厂?
  9. AutoJs学习-自动筛选探探对象
  10. 极大极小算法及​​剪枝