速来报名!AICon北京站鸿蒙专场~ 了解详情
写点什么

雪球基于 Apache APISIX 的双活架构演进

  • 2022-06-08
  • 本文字数:3368 字

    阅读完需:约 11 分钟

雪球基于Apache APISIX的双活架构演进

本文整理自雪球基础组件团队在 Apache APISIX Summit ASIA 2022 上的分享。更多技术干货,详见内容专题

背景


雪球成立于 2010 年,起步于投资社区,现已成为国内领先的集投资、交流和交易为一体的在线管理平台,为投资者提供优质内容、实时行情、交易工具、财富管理等多种服务。


其中实时行情服务对接了多种上游数据源,通过数据流式计算、存储与分发,为投资者提供稳定的数据服务。所以实时行情一直是雪球业务系统中的资源消耗大户,持续在高水位运行。雪球内部一项重要的工作就是持续进行稳定性建设,其中包括对行情服务进行性能优化。即便如此,在偶然发生极端行情的情况下,部分系统仍会因为数据量激增而发生响应变慢,甚至是不可用的情况,从而影响用户体验。


在此背景下,雪球为了向广大投资者提供稳定优质的服务,启动了服务双活改造计划。Apache APISIX 能极大地简化双活架构的实施复杂度。同时 APISIX 自身的云原生功能特性、丰富的社区生态和插件等,也为雪球未来云原生架构的演进打下了良好基础。本文将介绍雪球公司如何借助 Apache APISIX 实现内部双活架构的演进。



 上图是雪球单机房时期的简单架构描述,用户流量从云端入口(SLB)进来后,经网关进行简单的公共性逻辑处理,向后端服务转发。后端服务会通过 SDK 的方式,由集成在服务中的鉴权模块向雪球用户中心发起用户鉴权,通过后则继续进行后续的业务处理。

双活改造痛点


在实践业务场景中,该架构下一些痛点也开始逐渐显现。


  1. SDK 鉴权模块复杂

在双活改造实施过程中,微服务的提供方和消费方无法完全同步进行部署上线。当行情服务首先在云端上线,而雪球用户中心还不具备云端服务能力时,便会出现跨机房调用的情况。根据用户中心统计,其 RPC 调用量日均约数十亿,峰值可达到 50K QPS,在行情高的 QPS 场景下会带来较高延迟。


同时雪球鉴权业务复杂度较高,除 OAuth2.0 / JWT 协议外,还需要兼顾客户端版本、雪球旗下多个 APP 等多种因素。由于鉴权模块嵌入了服务内,导致升级也变得较为困难。


  1. OpenResty 功能性稍有不足


雪球在之前一直将 OpenResty 作为网关,其自身功能性上略有不足。所以将 OpenResty 集成雪球现有监控体系时,仍需要一定的工作量;同时扩展流程繁琐,还需要运维侧去添加自定义脚本进行实现。


  1. 依赖自研注册中心


目前雪球的 HTTP 服务注册是在后端服务启动时,请求注册中心将自身注册到网关,服务停止时请求注册中心进行服务节点摘除,注册中心会定期轮询服务节点进行健康检查。但自研的服务相比开源项目而言,维护成本较高。

API 网关选型


所以在这些痛点之上,雪球内部希望在不引入过多变量的同时,尽量保证对业务方透明以及最小化改动; 可以将问题在基础设施层面进行统一处理,并且尽量将鉴权服务在本机房完成。综上考虑,雪球决定将鉴权服务移至 API 网关进行完成。



基于在业务实践场景中逐渐显现的痛点,雪球基础设施团队开始了针对网关产品的调研。通过内部诉求和目前市场中网关产品的对比,最终选择了基于 Apache APISIX 进行后续架构的调整与使用。



基于 Apache APISIX 的实践

调整后架构



如上图是目前雪球行情双活架构。左侧展示的是在原机房里对应的架构,并没有进行太多改动;右侧展示的则是上云之后基于多 Region 设计的多活架构。


上述架构主要基于 APISIX 进行了如下调整:

  • 将鉴权模块统一调整到代理层,利用 APISIX 进行统一鉴权方式。其中涉及到 JWT 类型的可以直接利用 APISIX jwt-auth 插件进行本地鉴权;

  • 兼容 OAuth 2.0 形式,利用 APISIX 统一调用雪球用户中心进行处理;

  • 对接雪球后端 RPC 服务注册中心,用于 JWT 鉴权失败时使用雪球后端服务来鉴权。

应用场景展示


在后端服务接入 APISIX 后,主要在网关鉴权和可观测性等层面进行了一些实践。

场景一:网关鉴权


在前文中提到过,雪球之前架构模式中的鉴权方式并不统一。一种需要依赖于内部的应用端,通过 SDK 形式去调用用户中心实现鉴权,另一种则使用 JWT 鉴权。当两种鉴权方式共存时,会带来扩展性和维护性较差的问题。


接入 APISIX 作为网关之后,在鉴权方案的改造上则是通过 APISIX 网关层来统一管理。基于官方插件 jwt-auth 去替代原有的 JWT 鉴权方式;同时结合雪球内部自身的业务要求,使用 APISIX grpc-transcode 插件代理调用鉴权服务,来处理之前 OAuth 2.0 相关的鉴权方式。


jwt-auth 插件的配置使用较为简单,在 Dashboard 中将路由和上下游等相关信息配置齐全即可开启使用。这里主要描述下雪球内部是如何利用 APISIX 调用 gRPC 来实现鉴权。


在实现调用之前,雪球内部考虑了以下三种解决方案:

  • 方案一:Lua 直接调用 gRPC。由于此方案在执行中,需要去考虑负载均衡和动态上游等相关实现,过程会比较麻烦,故舍弃。

  • 方案二:Lua 协程回调 Golang。由于公司内部缺乏相应的实践经验,不可妄自尝试,故舍弃。

  • 方案三:Lua 进行 HTTP 调用,gRPC 接口采用 APISIX 的 grpc-transcode 插件进行实现。得益于 APISIX 社区对插件优化迭代快的前提,最终选择了方案三去实现 gRPC 调用。


在执行过程中,目前仍需要对 protocol buffers 文件进行手动同步。因为如果用户中心修改了该 protocol buffers 文件,但是与 APISIX 保存的 protocol buffers 文件不一致的话,会导致鉴权出现问题。

场景二:可观测性下的多维监控


雪球的日常使用场景中,通常在网站上线后是需要监控很多指标的,重点主要是以下三部分:

  • NGINX 连接状态和进出口流量

  • HTTP 错误状态码速率(用于排查 Service 或上下游问题)

  • APISIX 请求延迟耗时(APISIX 进行转发时逻辑执行带来的耗时)


比如 APISIX 的延迟指标会在某些情况下,出现指标非常高的现象(如下图所示),这种其实是跟该延迟指标的计算逻辑有关。目前 APISIX 延迟指标的计算逻辑是:单条 HTTP 请求在 NGINX 上的耗时时间-这条请求路由到上游的延迟。两个耗时之间的差数值即为 APISIX 延迟指标数据。



使用 APISIX 后,在新增或修改一些插件时会导致一些逻辑的变更,变更之后可能会导致耗时相关的数据出现偏差。为了避免出现混淆数据真实性的现象发生,雪球在监控层面还增加了基于插件级别的耗时监控。在保证各数据监测的准确性下,还方便了后续进行插件级的业务改造时,提前通过耗时定位一些问题,从而方便排查。



同时可以利用 APISIX 的可观测性能力,收集 Access 日志信息,并通过格式化统一投递到流量大盘中进行视图汇总。更方便地从多角度提前了解整体趋势,发现潜在问题并及时进行处理。



场景三:扩展 ZooKeeper 注册中心


目前,雪球 gRPC 服务调用是基于 Zookeeper 注册中心进行注册和发现。在实现鉴权过程中,API 网关在本地 JWT 校验失败时,需要访问雪球用户中心的 gRPC 服务进行鉴权,这就要求 API 网关能够从注册中心获取后端 gRPC 服务地址列表。APISIX 官方插件 apisix-seed 可以去集成 ZooKeeper 进行服务发现,但结合雪球自身使用场景需求,在 APISIX 上则是进行了更针对自家业务的相关拓展。


具体实现主要是在 APISIX 的一个内容节点上,当 Worker 进程启动时去轮询像下图中的 ZK-Rest 集群,然后定时去拉取整个服务的源数据信息以及实际信息,更新到 Worker 进程内的本地缓存,用于服务列表的更新。



通过上图也可以看到,ZK-Rest 集群相当于通过 Rest 的形式进行访问 ZooKeeper 的数据。所以整个过程其实实现的功能比较少(主要是基于自身业务场景需求),只需要增加它的一个实例就可以实现高可用特性,免去一些复杂操作。


但这样操作也会带来一个比较明显的缺点。当需要定时去轮询 ZK-Rest 集群时,可能会导致服务列表在更新上出现延迟。所以这里也是提供给大家一个思路,仅供参考。

总结及展望

目前,Apache APISIX 在雪球内部作为网关层运行良好。具体表现在:

  • 实现了在网关层统一鉴权、熔断与限流等功能;

  • 降低了整体系统的耦合度,提高了双机房场景下的服务质量;

  • 借助于 APISIX 监控体系,完善了从网关到服务的统一监控方案;

  • 对全链路排查起到了很好的支撑;

  • 对 gRPC 协议的转换与服务管理都提供了比较优雅的实现方式。


在后续的使用中,雪球也在规划如下进程:

  • 使用 APISIX Ingress Controller 应用于 K8s 集群;

  • 利用 grpc-transcode 插件进行 HTTP/gRPC 协议转换,达到后端统一接口形式;

  • 利用 traffic-spilt 插件进行流量打标、对接 Nacos 注册中心,实现全链路灰度等服务治理。


并在后续计划中,用 Apache APISIX 去替代现有的 OpenResty,最终实现全域南北流量的管理。

2022-06-08 10:153865

评论

发布
暂无评论
发现更多内容

流量即生意!红海中的茶饮品牌如何做增量?

游读分享

openGauss数据库源码解析系列文章——执行器解析(三)

openGauss

精彩回顾 | DTC模式构建全域消费者增长指南

游读分享

用户订阅付费如何拆解分析?看这篇就够了

HarmonyOS SDK

HMS Core

算法题每日一练:最长递增子序列

知心宝贝

数据结构 算法 前端 后端 三周年连更

openGauss:共建数据库根社区,打造开源数据库核心竞争力

openGauss

Gradio入门到进阶全网最详细教程[一]:快速搭建AI算法可视化部署演示(侧重项目搭建和案例分享)

汀丶人工智能

人工智能 机器学习 深度学习 Gradio streamlit

软件测试/测试开发丨Pytest 自动化测试框架(四)

测试人

软件测试 自动化测试 测试开发 pytest

语雀-使用指南

六月的雨在InfoQ

在线文档 在线协同文档 三周年连更 语雀

再次!openGauss荣获中国软协产业协会多个奖项

openGauss

阿里“宝妈级”之作,这份Spring Security应用到源码手册,全是精华

做梦都在改BUG

Java spring spring security

复旦MOSS大模型开源了!Github和Hugging Face同时上线

Openlab_cosmoplat

人工智能 开源项目 ChatGPT

Nginx常用配置及和基本功能讲解

京东科技开发者

nginx 负载均衡 正向代理与反向代理 企业号 4 月 PK 榜 Nginx入门

连接OpenAI两大智能产品Whisper & DALL·E,实现智能语音转文本/文本转图像

集简云开放平台

AI 智能 openai 数据集成平台 AI绘画

JUnit 5 参数化测试

码语者

Java JUnit

代码优雅之道——如何干掉过多的if else

小小怪下士

Java 程序员 后端 代码

使用AI优化慢SQL,开发秒变DBA

NineData

sql AI 开发者 dba NineData

Qz学算法-数据结构篇(查找算法--线性、二分)

浅辄

数据结构 三周年连更

用友BIP助力中国领先企业数智化国产替代

用友BIP

国产替代

孔再华:openGauss在民生银行的应用实践

openGauss

迪斯克Disrupt DEX众筹挖矿系统开发技术

薇電13242772558

dapp

黄凯耀:深度解读openGauss架构创新与新特性

openGauss

宠物行业如何做留存?答案都在这里了!

游读分享

突破传统监测模式:业务状态监控HM的新思路

京东科技开发者

系统架构 监控系统 数据监控 业务监控 企业号 4 月 PK 榜

执行个 DEL 竟然也会阻塞 Redis?深挖一下果然不简单

架构精进之路

redis 缓存 后端 bigkey 三周年连更

如何建设一个用于编译 iOS App 的 macOS 云服务器集群?

京东科技开发者

ios 编译 CI/CD 企业号 4 月 PK 榜 云服务集群

用友联合7家信创生态伙伴成立“信创领先实践联盟”,助力企业数智化国产替代

用友BIP

沉默的618下,美妆品牌如何踏上破局之路?

游读分享

区块链数字代币燃烧模式开发技术方案丨(成熟技术)

I8O28578624

李士福:openGauss 自驾驶数据库内核在AI领域的探索和创新

openGauss

深扒Sentinel背后的实现原理之后,我终于明白它为什么这么强了

Java你猿哥

Java spring ssm Sentine

雪球基于Apache APISIX的双活架构演进_架构_雪球基础组件团队_InfoQ精选文章