交易系统架构演进之路(三):微服务化

简介: 笔记

前言


60.png

我们 2.0 版本的交易系统整体架构就如上图所示,划分为了行情服务、客户端服务、撮合服务、管理端服务。行情服务主要对外提供推送行情数据的 WebSocket API。撮合服务就是一个内存撮合引擎,其输入是一个定序的委托订单队列,而输出包含成交记录和其他各种事件,包括撤单成功、撤单失败、订单进入了 Orderbook 等。撮合服务如果重启,则会从 MySQL 数据库查询出所有未成交订单,重新组成 Orderbook。客户端服务的核心功能就是接收和处理客户端各种 HTTP 接口请求,管理端则是提供给系统管理人员对整个系统的用户、订单、资产、配置等进行统一查看和管理。

虽然拆解为了 4 个服务,但我觉得,这还不是微服务架构,只能说已经变成分布式架构了,但「分布式」和「微服务」是两个不同的概念。微服务是分布式的,但分布式并不一定用微服务。其实,在实际项目中,从单体应用到微服务应用也不是一蹴而就的,而是一个逐渐演变的过程。而 2.0 版本,只是整个演变过程中的第一个阶段。

现在,好多小团队小项目,一上来就微服务,很多只是为了微服务而微服务,这绝对不是合适的做法。从本质上来说,架构的目的是为了「降本增效」——这四字真言是我从玄姐(真名孙玄)那学来的。项目一开始就采用微服务,一般都达不到降本增效的目的,因为微服务架构应用相比单体应用,其实现成本、维护成本都比单体应用高得多,除非一开始就是构建一个大型应用。

当业务规模和开发人员规模都已经不小的时候,比较适合用微服务,这时候用微服务主要解决两个问题:快速迭代高并发。当业务和人员规模比较小的时候,用一个或几个单体应用完成整个系统,一般迭代速度会更快。但到了某个临界点,就会开始出现一个或多个痛点,这之后,反而会拖慢迭代速度。

而遇到高并发时,其实,单体应用只要是无状态化的,通过部署多个应用实例,也可以承载一定的并发量。但如果单体应用变得庞大了,承载了比较多业务功能的时候,再对整个单体应用横向扩容,就会严重浪费资源。因为,并非所有业务都是需要扩容的,比如,下单容易产生高并发,需要扩容,但注册并不需要扩容。全部业务都绑定到同个单体中一起扩容,那消耗的资源就会比较庞大。另外,当某一块业务出现高并发,服务器承载不了的时候,影响的是该单体应用的所有业务。因此,拆分微服务就可以解决这些因为高并发而导致的问题。

那么,接下来,就来聊聊我们的交易系统,微服务化的架构是如何逐步演进的。


迭代业务需求


2.0 版本之后,就会进入集中迭代业务需求的阶段了,有大量业务需求有待完善和增加。大的业务板块包括:

  • 场外交易:也叫法币交易、OTC交易、C2C交易等,在三大所(火币/币安/OK)现在都叫「买币」。交易平台作为第三方,提供安全、可靠的交易环境,为用户与用户之间提供用法币买卖数字资产的功能。用户可以是个人用户,也可以是企业用户。
  • 杠杆交易:主要为用户提供借币交易的功能,用户通过向平台借币的方式,以实现以小博大、收益倍翻的目标。平台一般最高提供 10 倍杠杆。
  • 合约交易:还分为了交割合约、永续合约、期权合约等,其中永续合约杠杆倍数最高可达到 125 倍。
  • 开放 API:对每种交易都需要开放 API,包括行情接口、交易接口、账户接口等,全部都需要提供 HTTP 接口,而行情数据和一些账户信息的更新推送则再加上 WebSocket 接口。

相比这些交易,现有业务的交易板块一般就称为「币币交易」。另外,币币交易和杠杆交易都属于现货交易的范畴,合约交易属于金融衍生品的范畴。这些板块的业务现在基本成为每个交易平台的标配了。另外,如果业务继续扩展下去,还有持币生息、借贷、挖矿、 DEX(去中心化交易),以及各种 DeFi(去中心化金融) 。就说现在的三大所,每一个的业务线都是已经很多了。但我们现在先不去考虑这些业务。

除了这些大板块,还有些中小业务也需要补充的,包括:手机号注册、人机校验、邀请分佣、在线客服、系统公告、运营活动、语言国际化、资产归集、钱包冷热分离等等。另外,还要增加支持 Android 和 iOS 端。

然而,以上这么多大小业务的需求,肯定不是一蹴而就的,需要根据优先级,通过一个又一个迭代版本逐渐去完成。按需求的优先级来规划的话,应是先完成那些中小业务的需求,紧接着可以依次完成:币币交易开放 API、场外交易、杠杆交易、杠杆交易开放 API、交割合约、永续合约、期权合约、合约开放 API

因为每个版本的迭代周期比较短,目标就是快速实现功能并上线,因此就直接在原有的服务里面添加各业务板块的功能了。开放的 HTTP API 也没有独立出来,就直接和内部 API 共用一套了,只从参数上区分是开放 API 还是内部 API。内部 API 会传 Token,走 JWT 鉴权;开放 API 会传 Sign 参数,走 API Key 的签名校验机制。

这些业务板块都上线之后,我们整个交易系统的架构图就大致如下了:

61.png


业务拆分


加班加点把这些业务板块的需求都上线之后,做个复盘总结,就会发现存在几个比较严重的问题:

  • 客户端后台服务变得好臃肿,里面的好多业务逻辑也变得好复杂,提交代码出现冲突的情况越来越频繁,严重影响了迭代速度。
  • 开放 API 和内部 API 的强耦合,导致开放 API 访问量高的时候,就影响到了内部 API 的访问,从而使得客户端用户时不时就反映说应用慢和卡,甚至超时。
  • 当某个业务板块的交易请求并发量很大的时候,服务器承载不了,导致所有业务都不可用。

服务拆分的时机,是由痛点驱动的。以上这些问题,就是已经出现的痛点,那要解决这些痛点,方法就是一个字:「」。那接下来的问题就是:如何拆分?

微服务拆分,本质就是对业务复杂度进行分解,将整套系统分解为多个独立的微服务,就可以让不同小团队负责不同的微服务,实现整个微服务从产品设计、开发测试,到部署上线,都能由一个团队独立完成。从而,多个小团队就能并行研发多条业务线,实现整套系统的快速迭代。

因此,进行服务拆分,考虑的第一个拆分维度就是相互独立的业务域。很明显,对于我们的交易系统来说,可以拆分的业务域就是:现货交易、场外交易、合约交易。现货交易包括了币币交易和杠杆交易,这两者不能拆分,因为两者是在同一套撮合机制里的,即是说币币交易的订单和杠杆交易的订单是在同一个订单池里撮合的,行情数据也是同一套。合约交易还有各种子域,虽然每种子域也基本是独立运行的,但很多业务规则是大同小异的,所以当前没必要再进一步拆分。

再考虑第二个拆分维度,分析业务流程,如果有异步操作,那就可以拆分。对于交易系统,就看看最核心的撮合交易流程是如何的,最通用的简化流程如下:

下单 ——> 定序队列 ——> 撮合 ——> 输出队列 ——> 清算

撮合的前后,分别有定序队列和输出队列,因此,下单与撮合之间是异步的,撮合与清算之间又是异步的。那就可以将下单、撮合、清算分离独立服务。下单(包括撤单等)部分可以独立为交易服务,撮合就是撮合服务了,清算逻辑则抽离成清算服务

行情数据模块也是相对独立的,所以我们之前也抽离成了独立的行情服务

另外,杠杆交易和各种合约交易都有保证金制度,需要实时监控用户的资产并计算风险率,如果达到风险阀值则自动执行对应策略,如强制平仓、自动清算等。实现这些功能的也最好单独服务,我们可以称为风控服务。这块也是需要全内存高速计算的,以后再讲具体如何设计。

除了场外交易不属于撮合交易,现货和合约都可以按上面的拆分维度进一步拆分:

现货 合约
交易服务 现货交易服务 合约交易服务
撮合服务 现货撮合服务 合约撮合服务
清算服务 现货清算服务 合约清算服务
行情服务 现货行情服务 合约行情服务
风控服务 现货风控服务 合约风控服务

其实,还有一些通用业务,如用户的注册、登录,以及公告内容、Banner 图、在线客服等等,这些可以归到一个公共服务,做统一管理。

还有,管理端后台服务只是一些 CRUD,也没出现痛点问题,可以暂不拆分。

最终,在业务层,我们将系统拆分为了这些业务服务:管理端后台服务、公共服务、场外交易服务、现货交易服务、现货撮合服务、现货清算服务、现货行情服务、现货风控服务、合约交易服务、合约撮合服务、合约清算服务、合约行情服务、合约风控服务

62.png


数据库拆分


业务服务都拆分之后,大一统的数据库就很容易成为性能瓶颈,且还有单点故障的风险。另外,只有一个数据库,所有服务都依赖它,数据库一旦进行调整,就会牵一发而动全身。所以,我们要将数据库也进行拆分。

微服务架构下,一套完整的微服务组件,其独立性不仅仅只是代码上对业务层需求上的研发和部署上线独立,还包括该业务组件对自身的数据层的独立自治和解耦。因此,理想的设计是每个微服务业务组件都有自己单独的数据库,其他服务不能直接调用你的数据库,只能通过服务调用的方式访问其他服务的数据。

所以,数据库如何拆分,基本也是跟随业务组件而定。对于我们的交易系统来说,撮合服务和风控服务是全内存计算的,没有自己独立的数据库,其他服务都有自己的独立数据库或缓存。如下图:

63.png

但拆分之后,数据库变成了分布式的,不可避免地就会引入一些新问题,主要有三大块:

  • 分布式事务问题
  • 数据统计分析问题
  • 跨库查询问题

单个数据库的时候,数据库事务的 ACID 是很容易达到的。但到了分布式环境下,ACID 就很难满足了,就需要在某些特性之间进行平衡取舍。我们应该知道,分布式环境下,有个 CAP 理论,即一致性、可用性、分区容忍性,三者在分布式系统中无法同时满足,最多只能满足两项。P 是必选项,所以一般就需要在 C(一致性)和 A(可用性)之间进行抉择。如果是选择了 C,则需要保证强一致性,保证强一致性的事务,也称为刚性事务。解决刚性事务的方案主要有 2PC、3PC,能够保证强一致性,但性能很差。大部分场景下的分布式事务其实对强一致性的要求不会太高,所以只要在一定时间内做到最终一致性就可以了。保证最终一致性的事务,称为柔性事务,其设计思想则是基于 BASE 理论。柔性事务的解决方案主要有 TCC补偿型、异步确保型、最大努力型。而具体选择哪种方案来解决分布式事务问题,就要根据具体的业务场景来分析和选型了。关于分布式事务更详细的内容,以后再单独细说。

数据统计分析问题,更多是管理后台的需求,管理后台需要为运营人员提供统计报表、数据分析等功能,这其实可以归到 OLAP 的范畴了,因此推荐的方法就是将各个库的数据整合到 NewSQL 数据库里进行处理。

跨库查询,其实最多的场景就是 A 业务组件需要查询 B 业务组件甚至更多其他业务组件的数据的时候,那要解决此问题,常用的有几种解决思路。第一种思路就是增加冗余字段,但冗余字段不宜太多,且还需要解决冗余字段数据同步的问题。第二种方案则是增加聚合服务,将不同服务的数据统一封装到一个新的服务里做聚合,对外提供统一的 API 查询接口。还有一种方案就是分次查询每个服务,再组装数据,可以直接在客户端做,也可以在服务端做。


水平分层


微服务化的最后一步拆分则是采用水平方向的分层架构,可用最简单的三层架构,将所有微服务划分为网关层、业务逻辑层、数据访问层

增加网关层是很好理解的,这是所有微服务系统的标配。网关层是整个系统的后端总入口,对内提供给官方的客户端和管理端访问,对外通过开放 API 的形式提供给第三方应用访问,负责对请求鉴权、限流、路由转发等,不会涉及具体的业务逻辑。

增加网关层是毋庸置疑的,这不用考虑,需要考虑的是配置多少个网关才合适?一个统一的网关无法解决我们前面提到的开放 API 和内部 API 强耦合的问题,所以是肯定需要多网关的。开放 API 和内部 API 是应该要分开的,两者的鉴权方式不同,限流的策略也不同,更重要的是考虑隔离性,互不影响。管理端和客户端的 API 也最好分开,两者用户和权限是不同的,管理端的管理员用户有着访问和操作更多数据的权限,如果不小心泄露给到了客户端,那就是严重的安全事故了。所以,网关层至少可以分为三个网关:Open API Gateway(开放API网关)、Client API Gateway(客户端API网关)、Admin API Gateway(管理端API网关)。与各端的访问关系如下图:

64.png

如果再细分,还可以把 WebSocket API 和 HTTP API 再拆分,不过目前阶段可以暂时先不做分离。

网关层就先聊这么多,接着聊聊业务逻辑层和数据访问层。据我了解,很多项目是没有再独立出数据访问层的微服务的,我以前做过的项目也是。我以前看过的文章和书籍,也从没有提到过这样拆分的思路。这思路还是我从玄姐那学到的,从他那里才了解到,那些大厂的项目,很多都是这么拆分的。

在不拆分的情况下,其实每个服务内部也有划分为业务逻辑层和数据访问层的。在这种情况下,A 业务的服务需要查询 B 业务的数据时,就直接访问 B 服务提供的接口。这种方式,最大缺点就是容易造成数据流紊乱,因为这是横向的服务调用,随着服务越来越多,服务间的调用关系越来越复杂,会变成混乱的网状关系,容易出现非预期的结果,还有可能会发生循环调用,且定位问题也会变得困难。

拆分之后,则 A 需要查询 B 的数据时,就是 A 的业务逻辑层服务调用 B 的数据访问层服务,变成了纵向的服务调用,数据流很清晰。

至此,我们整个系统的微服务化拆分就算基本完成了,最终的整体架构图大致如下:

60.png


最后一块


其实,微服务化还剩下最后一块拼图,那就是注册中心,这也是微服务架构中的一个基础组件。

注册中心主要解决以下几个问题:

  • 服务注册后,如何被及时发现
  • 服务宕机后,如何及时下线
  • 服务发现时,如何进行路由
  • 服务异常时,如何进行降级
  • 服务如何有效的水平扩展

简单地说,注册中心主要实现服务的注册与发现。现在,注册中心的选型有好多种,包括 Zookeeper、Eureka、Consul、Etcd、CoreDNS、Nacos 等,还可以自研。这么多选择,应该选哪个比较好呢?其实,可以先从 CAP 理论去考虑,本质上,注册中心应该是 CP 模型还是 AP 模型的?

对于服务发现场景来说,针对同一个服务,即使注册中心的不同节点保存的服务提供者信息不尽相同,也并不会造成灾难性的后果。但是对于服务消费者来说,如果因为注册中心的异常导致消费不能正常进行,对于系统来说则是灾难性的。因此,对于服务发现来讲,注册中心应该是 AP 模型。

再从服务注册的角度分析,如果注册中心发生了网络分区,CP 场景下新的节点无法注册,新部署的服务节点就不能提供服务,站在业务角度这是我们不想看到的,因为我们希望将新的服务节点通知到尽量多的服务消费方,不能因为注册中心要保证数据的一致性而让所有新节点都不生效。所以,服务注册场景,也是 AP 的效果好于 CP 的。

综上所述,注册中心应该优先选择 AP 模型,保证高可用,而非强一致性。那以上所罗列出来的注册中心,可选的就只剩下 Eureka、Nacos,或者自研了。在实际项目中,自研的相对比较少,现在越来越多项目选择了使用 Nacos,因为其功能特性最强大,而且 Nacos 不只是注册中心,还是配置中心。所以,如果不是自研的话,其实可以直接选择 Nacos。


总结


微服务化的落地,远没有很多网上教程说的那么简单,只有自己去经历过,才知道最佳实践的落地方法。另外,微服务化之后,后续还有很多更复杂的问题需要一一去解决,包括服务治理,比如服务降级、熔断、负载均衡等,以及服务网格化,甚至无服务化,都是需要一步步去实施的。


相关文章
|
21天前
|
缓存 监控 API
探索微服务架构中的API网关模式
【10月更文挑战第5天】随着微服务架构的兴起,企业纷纷采用这一模式构建复杂应用。在这种架构下,应用被拆分成若干小型、独立的服务,每个服务围绕特定业务功能构建并通过HTTP协议协作。随着服务数量增加,统一管理这些服务间的交互变得至关重要。API网关作为微服务架构的关键组件,承担起路由请求、聚合数据、处理认证与授权等功能。本文通过一个在线零售平台的具体案例,探讨API网关的优势及其实现细节,展示其在简化客户端集成、提升安全性和性能方面的关键作用。
62 2
|
25天前
|
存储 缓存 监控
探索微服务架构中的API网关模式
【10月更文挑战第1天】探索微服务架构中的API网关模式
76 2
|
2月前
|
安全 应用服务中间件 API
微服务分布式系统架构之zookeeper与dubbo-2
微服务分布式系统架构之zookeeper与dubbo-2
|
2月前
|
负载均衡 Java 应用服务中间件
微服务分布式系统架构之zookeeper与dubbor-1
微服务分布式系统架构之zookeeper与dubbor-1
|
4天前
|
监控 Cloud Native Java
云原生架构下微服务治理策略与实践####
【10月更文挑战第20天】 本文深入探讨了云原生环境下微服务架构的治理策略,通过分析当前技术趋势与挑战,提出了一系列高效、可扩展的微服务治理最佳实践方案。不同于传统摘要概述内容要点,本部分直接聚焦于治理核心——如何在动态多变的分布式系统中实现服务的自动发现、配置管理、流量控制及故障恢复,旨在为开发者提供一套系统性的方法论,助力企业在云端构建更加健壮、灵活的应用程序。 ####
44 10
|
4天前
|
运维 Cloud Native 持续交付
云原生架构下的微服务设计原则与实践####
【10月更文挑战第20天】 本文深入探讨了云原生环境中微服务设计的几大核心原则,包括服务的细粒度划分、无状态性、独立部署、自动化管理及容错机制。通过分析这些原则背后的技术逻辑与业务价值,结合具体案例,展示了如何在现代云平台上实现高效、灵活且可扩展的微服务架构,以应对快速变化的市场需求和技术挑战。 ####
23 7
|
4天前
|
监控 Cloud Native 持续交付
云原生架构下微服务的最佳实践与挑战####
【10月更文挑战第20天】 本文深入探讨了云原生架构在现代软件开发中的应用,特别是针对微服务设计模式的最优实践与面临的主要挑战。通过分析容器化、持续集成/持续部署(CI/CD)、服务网格等关键技术,阐述了如何高效构建、部署及运维微服务系统。同时,文章也指出了在云原生转型过程中常见的难题,如服务间的复杂通信、安全性问题以及监控与可观测性的实现,为开发者和企业提供了宝贵的策略指导和解决方案建议。 ####
26 5
|
4天前
|
Kubernetes Cloud Native 持续交付
云原生架构下的微服务设计原则与最佳实践##
在数字化转型的浪潮中,云原生技术以其高效、灵活和可扩展的特性成为企业IT架构转型的首选。本文深入探讨了云原生架构的核心理念,聚焦于微服务设计的关键原则与实施策略,旨在为开发者提供一套系统性的方法论,以应对复杂多变的业务需求和技术挑战。通过分析真实案例,揭示了如何有效利用容器化、持续集成/持续部署(CI/CD)、服务网格等关键技术,构建高性能、易维护的云原生应用。文章还强调了文化与组织变革在云原生转型过程中的重要性,为企业顺利过渡到云原生时代提供了宝贵的见解。 ##
|
11天前
|
负载均衡 监控 Cloud Native
云原生架构下的微服务治理策略与实践####
在数字化转型加速的今天,云原生技术以其高效、灵活、可扩展的特性成为企业IT架构转型的首选。本文深入探讨了云原生环境下微服务治理的策略与实践路径,旨在为读者提供一个系统性的微服务治理框架,涵盖从服务设计、部署、监控到运维的全生命周期管理,助力企业在云端构建更加稳定、高效的业务系统。 ####
|
11天前
|
运维 监控 Cloud Native
云原生架构下,微服务治理的艺术与实践####
【10月更文挑战第14天】 在数字化转型的大潮中,云原生技术以其高效、灵活与可扩展性成为企业IT架构的首选。本文深入探讨了云原生架构的核心理念,聚焦于微服务治理的策略与实践,揭示了如何通过精细化管理提升系统的响应速度、稳定性和可维护性。不同于传统的摘要概述,本文摘要旨在直接触及读者关注的核心——即如何在复杂多变的云环境中,实现微服务的高效协同与治理,为读者提供一个清晰的行动指南。 ####
27 1

热门文章

最新文章