NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

雪球基于 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:153367

评论

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

Java 结合实例学会使用 静态代理、JDK动态代理、CGLIB动态代理

爱好编程进阶

Java 面试 后端开发

Spring(三)

爱好编程进阶

Java 面试 后端开发

kotlin 如何解决 java 开发痛点,让程序员 happier

爱好编程进阶

Java 面试 后端开发

redis的五种数据类型

爱好编程进阶

Java 面试 后端开发

Netty学习之旅------高仿Dubbo服务调用模型、私有协议实现、编码解码器使用实践

爱好编程进阶

Java 面试 后端开发

Spring框架JDBC Template使用教程

爱好编程进阶

Java 面试 后端开发

Java 线程池原理分析

爱好编程进阶

Java 面试 后端开发

Java语言特点

爱好编程进阶

Java 面试 后端开发

Netty 核心源码解读 —— ServerBootstrap 篇

爱好编程进阶

Java 面试 后端开发

OpenFaaS实战之四:模板操作(template)

爱好编程进阶

Java 面试 后端开发

22道Java Spring Boot高频面试题

爱好编程进阶

Java 面试 后端开发

krpano全景之vtour文件夹和tour

爱好编程进阶

Java 面试 后端开发

Java岗大厂面试百日冲刺 - 日积月累,每日三题【Day39

爱好编程进阶

Java 面试 后端开发

MySQL-InnoDB-事务

爱好编程进阶

Java 面试 后端开发

Shiro认证源码图文解析

爱好编程进阶

Java 面试 后端开发

UML项目实例——抖音的UML图描述

爱好编程进阶

Java 面试 后端开发

2021年秋招,薪资排行NO

爱好编程进阶

Java 面试 后端开发

Choreographer全解析

爱好编程进阶

Java 面试 后端开发

Java泛型机制详解;这些你都知道吗?

爱好编程进阶

Java 面试 后端开发

JVM+分布式+算法

爱好编程进阶

Java 面试 后端开发

Java单例模式实现,一次性学完整,面试加分项

爱好编程进阶

Java 面试 后端开发

RabbitMQ的高级特性和消息补偿机制

爱好编程进阶

Java 面试 后端开发

Spring-Data-Jpa动态查询(Specification)

爱好编程进阶

Java 面试 后端开发

《JVM系列》 第七章 -- 字节码执行引擎

爱好编程进阶

Java 面试 后端开发

自动化的艺术

俞凡

架构 大厂实践 PayPal

AtomicIntegerArray源码分析与感悟

爱好编程进阶

Java 面试 后端开发

SpringCloud-分布式配置中心【动态刷新】

爱好编程进阶

Java 面试 后端开发

自己动手写Docker系列 -- 6.3 手动配置容器网络(上)

Go Docker 4月月更

【Java从0到架构师】SQL 多表查询

爱好编程进阶

Java 面试 后端开发

顶级元宇宙游戏Plato Farm,近期动作不断利好频频

小哈区块

Spring Data ElasticSearch基本使用

爱好编程进阶

Java 面试 后端开发

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