重构国内游戏账号登录系统的思考和实践

news/2024/5/17 18:22:22

本期作者

背景

账号登录系统,作为游戏发行平台最重要的应用之一,在当前的发行平台的应用架构中,主要承载的是用户的账号注册、登录、实名、防沉迷、隐私合规、风控等职责。合规作为企业经营的生命线,同时,账号登录作为在线链路转化的第一站,因此账号登录系统的稳定性,一直面临极高的要求。

出于稳定性需要,游戏发行平台在很早期就实践了两地三中心的多活架构。目前以公司公司机房为中心,同时在华东公有云和华南公有云,实现了两地三中心部署方案。依托公有云的主要考量因素在于,早期公有云提供的快速弹性和按量付费的能力,能够高效的承接游戏业务方的发展诉求;其次,对于华南地区的选择,也是优先考虑重要合作方所处的地理位置。

基于稳定性、效率、成本的多方考量,最终实现了公司机房、华东公有云A、华南公有云B的混合云架构。混合云架构带来便利的同时,也存在普遍的挑战,其中最显著在于两个方面:

其一、数据架构,数据在云端存储的存在的泄露风险。在具体实施层面,数据架构的差异化,将会导致底层的领域服务所能交付的API必定存在差异,主要差异体现在API的能力范围。比如,bilibili授权登录等能力,云上机房是无法做到实际支持的,服务端只能将相关请求转发至公司机房处理。

其二、PaaS平台的差异。公司基础架构在数据库管理平台、KV数据管理平台、消息队列等产品支撑已相当成熟,但早期在公有云的应用部署只能依托云原生的能力。这导致在底层的依赖上,原本需要建立一个标准防腐层,屏蔽具体的实现差异,但因为业务进度的需要,导致有所折中欠缺。

由于存在以上两个显著的挑战,项目进展等因素的考虑,最终演变的应用架构如下,也因此账号登录系统,在公司机房和公有云机房演变出了两套代码仓库(login-idc-api / login-cloud-api)。

图片

游戏账号登录应用的两套代码,迭代至今已近7年。当前应用,虽然在主观上理解已经迭代趋于稳定,但是基于最近一年完成的迭代版本统计,全年迭代版本超过10次,版本平均耗时接近4周,包括设计、开发、测试、上线。双代码仓库导致的设计、开发、测试,部署平均耗时增加了30%~40%。其次,在双代码仓库,且依赖Spring等核心组件版本较低的情况下,对齐公司基础架构的各项产品,可预见工作量的前提之下,该系统的重构工作,已经到了不得不行的地步。

挑战

为稳定性诉求极高、迭代长久的系统发起重构,需要巨大勇气,得失于转瞬之间。

  1. 重要性:承载千万MAU,L0不可降级链路;支撑113个SDK版本(采样周期:2024/02/15 - 2024/03/15)

  2. 稳定性:重构过程中SLO 4个9的约定,必须在执行之前规划完成执行细节和过程,全面又不失细致;

  3. 复杂度:业务本身内在的复杂度,7年来的高速发展,积累的大量技术债。

价值

1.效率:开发效率提升50%,迭代效率提升30%-40%

2.成本:节省人力(预期当前系统的生命周期至少5年)

3.质量:

  • 代码圈复杂度:降低40%;

  • 内网调用去SLB依赖,核心链路接口RT 99.9Line 提升31.5%

4.文化:践行“极致执行”的价值观。

实践:如何实现重构?

战略方向

方案一、放弃现有的两地三中心,账号登录全部统一到公司标准,不依赖云厂商。该方案作为未来的长期方向,完全回公司部署符合公司长期战略规划,难点在于发行平台的应用架构,目前绝大多数服务还是重点依赖公有云,短期内不具备独立完成的可行性。

方案二、推动主站账号团队,打通公司和公有云的数据架构,实现领域能力的对等,但存在数据安全风险,考虑到项目收益和跨团队的工作成本,并非当前最高ROI的选择。

方案三、将双代码仓库中,有关于数据架构和PaaS的差异,以重构的办法实现兼容,达到最终的代码仓库统一。

思考过程

重构的前提

回顾Martin Flower有关重构的著作《重构 改善既有代码的设计》一文中,将”重构“以名词、动词两种方式定义如下:

重构(名词):对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。

重构(动词):使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。

这本关于重构的经典,在两种定义方式中,提到了3个关键概念,”调整“、”结构“、”不改变软件可观察行为“。这3个关键词组合起来,约等于行动指南。”不改变软件的可观察行为“作为前提,如何理解可观察行为,Martin并未在技术和业务上做过明确的定义,因此在这个概念的理解上,不免要多一些执行者的个人理解和思考。

如果把应用架构视为当前的结构,对于“可观察行为”的理解,从以下几个角度尝试去思考:

1.系统职责,前后端分离的应用架构之下,交付这些职责的API是一类可观察的行为;

2.系统依赖项,是一类可观察的行为,包括两个大部分:

  • bilibili账号的领域服务、游戏发行的领域服务、第三方服务(比如:极验服务提供商)

  • PaaS基础架构(公司的数据库、KV数据系统、消息队列等等;公有云的云MySQL、Redis、Kafka等等)

3.系统的横向服务。从分层架构的层次上来说,当前定位是应用服务层BFF,本不应该出现较大的横向影响,但是过往高速演进的过程中,承载了部分领域服务的职责(比如:查询游戏信息、查询活跃游戏、查询用户信息等),因此姑且对于这一类概括为横向的影响。

形形色色的差异

当前应用架构下,双仓库在逻辑模块、应用内分层(J2EE的3层模型)的特点,展示如图:

图片

在不可变的前提之下,试图通过对齐双仓库代码差异,以求得统一的思路,单从Service这一层来说(其依赖的bilibili账号服务API超过80个),理解起来已足够让人头大,其变更风险也是极其巨大,更何况还有JDBC ORM、Redis在技术选型和使用约束上的差异。如此风险再加上即将投入较大的工作量,势必提案困难重重。基于静态的模块和应用内代码分层来看,这巨大的差异看似是无法“暴力”抹平。

消失的复杂度

柳暗花明时刻,来源于应用运行时的一个事实:“生产环境多次高可用切流”。这个事实不仅实现了对SDK上游异地多活的承诺,而且经过了生产环境的多次验证。简而言之,双仓库在Controller、Service这两个最业务逻辑最复杂,技术债积累最多的分层,虽各有千秋,但殊途同归。

由此推理,重构过程中的最大的认知注意力负担,可以直接从这两层忽视。这两层注意力的移除,同时也利好DB和Redis的兼容工作量,作为基础架构中最重要的两个组件,完全无需再关注各类RedisTemplate/Jedis,Key命名、JdbcTemplate/Mybatis 、SQL的之间的逻辑差异,因为他们只是Controller和Service最终呈现出来的一部分。

在混沌中聚焦

SDK API链路:由于Controller、Service复杂度的消失,那么剩余的不可变的可观察行为,就只集中在DAO。DAO差异的本质来源于混合云部署架构的挑战(数据架构、PaaS差异),那么实现策略也就清晰了,在DAO层基于运行时ZONE来标识依赖的bilibili账号API调用即可。参考六边形架构,对于外部依赖和业务逻辑的隔离方式,实现核心业务逻辑对于外部API和PaaS解耦,以此降低变更侵入的影响面。

图片

PaaS的差异在业务逻辑层Service(或者少量的Controller)已经被消化,因此无需再考虑逻辑上的差异,只需关注框架和数据库的版本兼容性。

领域类和通知类API链路:这条链路虽然不是核心,但这是混合云数据架构差异的体现。生产环境的调用集中在公司机房,能力”较小“的公有云应用,向公司应用融合靠拢,也正因如此,统一之后的代码仓库是以公司机房代码仓为基准。

转发类API链路:这条链路差异化的本质也是来源于混合云部署的数据架构差异,在当前的融合方案中无法解决,因此只能沿用现有的转发策略,但转发后续可向上移交至API GW实现,这个已在计划当中。

具体实现

图片

公司机房原仓库为基准,在公有云A/B可用区部署,可用区选择与当前两地三中心保持一致。依赖的DB Schema在三机房原本就相同,因此可直接复用已有的DB实例。Redis,因其均有读写操作,避免灰度过程对于线上应用的数据污染,因此部署单独的Redis集群用于数据隔离,待完成灰度之后,一并下线原应用和原Redis集群。

数据验证

产品视角

  1. 基于用户维度,验证比对新老集群的数据写入和查询;

  2. 基于游戏维度,验证比对新老集群的数据写入和查询;

  3. 生产环境SDK,基于测试域名,实现核心SDK产品回归验证,覆盖全量用例;

  4. 其他非SDK API,实现全量的单测覆盖,基于接口实现验收。

数据视角

  1. 数据库:基于Job任务,实现源与目标数据源内容比对;

  2. 缓存:纯缓存场景,灰度期间隔离部署,回滚后不影响业务逻辑。缓存未命中直接远程调用;

  3. 埋点/报表:基于灰度过程观察游戏维度的报表趋势,并与过往数据进行比对。

发布方案

发布计划设计,严格遵守公司安全生产要求:可灰度、可观测、可恢复。

可灰度

灰度过程一共分为两个大步:

Step1

在公司机房执行灰度部署,分批部署导入生产流量,发现异常立即回滚。

Step2

在公有云A执行全量发布,但未接流;通过SLB规则配置,基于域名、规则的重要性、API的量级(调用量/周)制定规则级的SLB发布计划。公有云B部署同样重复此步骤。

可观测

观测的主要维度:业务和SLO、日志、性能

观测1:原公有云A应用流量切流后分布和成功率

图片

观测2:新公有云A应用流量切流后分布和成功率

图片

观测3:新公有云A应用错误码分布

图片

观测4:新公有云A应用API性能

图片

观测5:新公有云A应用JVM性能

图片

可恢复

1.公司机房应用执行灰度部署,如遇异常立即回滚,且不产生脏数据

2.新的公有云A/B应用,通过SLB基于规则分批发布,如遇异常立即回滚,回滚后流量指向原有对应机房服务集群,Redis写产生的脏数据不影响回滚后业务逻辑

3.新的公有云可用区,申请单独的Redis实例,用于隔离不同代码仓库,不同Key命名风格的数据,避免回滚过程中脏数据,对于原可用区服务的影响。

参考资料

  • 《B站安全生产专项建设实践》 https://mp.weixin.qq.com/s/tj1PEUWAyRZ1QzeW_oCWfg

  • 《重构 改善既有代码的设计》Martin Flower

  • 《Complexity Has to Live Somewhere》https://ferd.ca/complexity-has-to-live-somewhere.html


http://www.mrgr.cn/p/51043883

相关文章

在线编辑器 CodeMirror

如何优雅的在网页显示代码 如果开发在线编辑器 引入资源&#xff1a; <link rel"stylesheet" href"https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.60.0/codemirror.min.css"><script src"https://cdnjs.cloudflare.com/ajax/libs/c…

AI极速批量换脸!Roop-unleashed下载介绍,可直播

要说AI换脸领域,最开始火的项目就是Roop了,Roop-unleashed作为Roop的嫡系分支,不仅继承了前者的强大基因,更是在功能上实现了重大突破与升级 核心特性 1、可以进行高精度的图片、视频换脸,还能实时直播换脸,换脸效果真实、自然 2、不仅支持N卡处理程序(cuda),还额外提…

AI大模型日报#0416:李飞飞《2024年人工智能指数报告》、Sora加入Adobe、李彦宏聊百度大模型之路

​导读&#xff1a; 欢迎阅读《AI大模型日报》&#xff0c;内容基于Python爬虫和LLM自动生成。目前采用“文心一言”生成了每条资讯的摘要。标题: 刚刚&#xff0c;李飞飞团队发布《2024年人工智能指数报告》&#xff1a;10大趋势&#xff0c;揭示AI大模型的“喜”与“忧” 摘…

uni-app如何生成骨架屏

为什么需要骨架屏&#xff1a;为了缓解用户打开程序时等待接口的焦虑情绪 1.打开微信开发者工具&#xff0c;找到模拟器中的页面信息&#xff0c;选择生成骨架屏 2.将生成的wxml代码复制到vscode&#xff0c;在index的components中新建一个vue文件&#xff0c;只需保留请求接口…

使用Lagent AgentLego 搭建智能体

对于这个作业,这里只给出截图,不给详细过程,因为确实没有什么好写的。具体的步骤可以查看官方教程。 作业要求 基础作业完成 Lagent Web Demo 使用,并在作业中上传截图。文档可见 Lagent Web Demo 完成 AgentLego 直接使用部分,并在作业中上传截图。文档可见 直接使用 Age…

CentOS7 boa服务器的搭建和配置

环境是CentOS7&#xff0c;但方法不局限于此版系统&#xff0c;应该是通用的。 具体步骤如下&#xff1a; 1. 下载boa源码 下载地址: Boa Webserver 下载后&#xff0c;进入压缩包所在目录&#xff0c;进行解压&#xff1a; tar xzf boa-0.94.13.tar.gz 2. 安装需要的工具b…

RILIR 复现 一些 idea

伪代码:在 if done 的时候,在环境中已经跑了一个 trajectory 了,利用当前的 trajectory 和专家的 demo 求一下 reward(文章中用的是 optimal transport 的几种方法) 否则,就继续在 observation 的基础上利用 actor 学到的策略 sample 出 action,并用 list 记录下当前的 …

PolarDB MySQL 版 Serverless评测|一文带你体验什么是极致弹性|后续

PolarDB MySQL 版 Serverless评测|一文带你体验什么是极致弹性|后续 弹性压测三后续自动缩容全局一致性测试测评体验 在上一篇PolarDB MySQL 版 Serverless测评博文中&#xff1a;https://developer.aliyun.com/article/1385834 关于弹性压测三通过增加只读节点压测来观测到Ser…

【C语言】多字节字符、宽字符(涉及字符集和编码)

字符集、编码&#xff1a; 字符集&#xff1a;一个系统支持的所有抽象字符的集合。字符是各种文字和符号的总称&#xff0c;包括各国家文字、标点符号、图形符号、数字等。例如&#xff1a;ASCII、Unicode、GB2312、GBK、GB18030、BIG5(繁体中文) ... 编码方式&#xff1a;符号…

【React】Ant Design自定义主题风格及主题切换

Ant Design 的自定义主题&#xff0c;对于刚入手的时候感觉真是一脸蒙圈&#xff0c;那今天给它梳理倒腾下&#xff1b; 1、自定义主题要点 整体样式变化&#xff0c;主要两个部分&#xff1a; 1.1、Design Token https://ant.design/docs/react/customize-theme-cn#theme 官…

MySQL基础-----约束详解

目录 一. 概述: 二.约束演示&#xff1a; 三.外键约束&#xff1a; 3.1介绍&#xff1a; 3.2外键约束语法&#xff1a; 3.3删除&#xff0c;更新行为&#xff1a; 一. 概述: &#x1f9d0;&#x1f9d0;概念&#xff1a;约束是作用于表中字段上的规则&#xff0c;用于限制…

LCD显示器 --- 8080接口 和 RGB接口 的区别

主要介绍LCD显示的基本原理,涉及像素、分辨率、颜色模型、RGB888等格式、Framebuffer、8080接口、RGB接口。 1.LCD显示出图片的基本原理 LCD作为显示器,它的显示原理和图片是一样的。 图片可以看作由一个一个点(即像素pixel)组成。每行有xres个像素,有yres行,则这个图片的分…

Vue 3 项目构建与效率提升:vite-plugin-vue-setup-extend 插件应用指南

一、Vue3项目创建 前提是已安装Node.js&#xff08;点击跳转Node官网&#xff09; npm create vuelatest这一指令将会安装并执行 create-vue&#xff0c;它是 Vue 官方的项目脚手架工具。你将会看到一些诸如 TypeScript 和测试支持之类的可选功能提示&#xff1a; ✔ Projec…

Ubuntu 22.04 解决和 Windows 共享蓝牙设备的问题

我有一个 Airpods,连接到 WIndows 可以正常工作,但连接到 ubuntu 后会无法连接,只能删除设备选择重联,但是这又会导致 Windows 不能连接到耳机,只能也删除重新连接,费神费力。 要解决此问题,仍有两办法,让 Windows 将就 Linux,或者 Linux 将就 Windows,由于折腾注册表…

【STM32+HAL库】---- 驱动MAX30102心率血氧传感器

硬件开发板:STM32F407VET6 软件平台:cubemax+keil+VScode1 MAX30102心率血氧传感器工作原理 MAX30102传感器是一种集成了红外光源、光电检测器和信号处理电路的高度集成传感器,主要用于心率和血氧饱和度的测量。以下是MAX30102传感器的主要特点和工作原理:红外光源:MAX301…

OO第一次博客作业

OO第一次博客作业 目录1.前言 2.设计与分析 3.采坑心得 4.改进建议 5.总结 1.前言 正则表达式是java语言中一种非常重要的语言,他的重要性主要体现在以下方面: 1.高效的文本处理:正则表达式提供了一种高效的方式来处理文本数据。它可以快速地进行字符串的搜索、匹配、替换和…

【机器学习】数据变换---小波变换特征提取及应用案列介绍

引言 在机器学习领域&#xff0c;数据变换是一种常见且重要的预处理步骤。通过对原始数据进行变换&#xff0c;我们可以提取出更有意义的特征&#xff0c;提高模型的性能。在众多数据变换方法中&#xff0c;小波变换是一种非常有效的方法&#xff0c;尤其适用于处理非平稳信号和…

JVM——面试

https://juejin.cn/post/6998527815964426271 https://juejin.cn/post/7101120209540349959垃圾回收器 Serial(新生代)+ Serial Old(老年代) 特点:单线程垃圾回收器,垃圾回收过程中需要 STW,适用于运行在 Client 模式下的虚拟机; 新生代标记复制算法,老年代标记整理算法…

内存分配器

内存分配器 文章目录 内存分配器项目介绍内存池介绍池化技术内存池内存池主要解决的问题malloc 实现定长内存分配器怎么控制定长通过系统调用申请空间定长内存分配器中应该包含哪些成员变量内存池如何管理释放的对象内存分配器如何为我们申请对象定长内存池整体代码性能对比 高…

2024.4.19

2024.4.19 【你知道的都是真相。只可惜那些并不是真相的全部。】 Friday 三月十一 谷雨<BGM = "谷雨--音阙诗听"> AC :Answer Coarse,粗劣的答案 ​ CE :Compile Easily,轻松通过 ​ PC :Perfect Compile 完美的编译 ​ WA :Wonderful Answer,好答案 ​ RE :Ru…