作者 | 文库主站研发
导读:百度文库是百度公布的供网友在线分享文档的平台,文档下载服务是文库的一个根底服务。通过多年倒退,以后文库的下载服务在业务方面和技术方面都面临着泛滥困扰。因而咱们把传统的面向接口开发的下载服务革新成一个独立的微服务零碎,重点做了两件事件:第一件是定义微服务调用的协定和规定,并且将下载零碎独立部署独立上线,让微服务垂直划分,这是微服务化的根底。第二件事是基于咱们的下载业务,开发一个满足业务要求,适宜业务倒退的下载技术框架。从而化繁为简,解决了简单的业务问题。
全文 6212 字,预计浏览工夫 16 分钟。
01 引子
百度文库是百度公布的供网友在线分享文档的平台,用户能够在百度文库下载各类文档。百度文库平台自 2009 年 11 月上线以来,通过十余年倒退,文档数量和每日下载次数都是一个十分微小的数字。内容是文库的外围资产,文档下载服务是文库的一个根底服务,用户来到文库的次要目标之一就是获取内容,所以下载服务的体验是重中之重,同时下载性能也是各种黑产们薅羊毛的重要指标。
以后文库是一个大的分布式单体架构,文库所有的代码都作为零碎整体一起部署,只管文库领有多个利用多个实例以实现分布式扩大,从根本上讲,所有的代码都打包在一个程序中。文档下载性能是这个微小单体架构的一部分,在文库十余年的倒退历史中,这个微小的单体架构,和下载服务都在各自继续地成长扩大。
02 面临的问题景象
在业务方面和技术方面,以后文库的下载服务都面临着泛滥困扰:
- 体验差客诉多:
每天很多用户反馈文档下载失败,或者提醒胜利然而找不到文档,或者下载了然而内容不全等等。为此文库值班客服和研发人员不得不每天破费大量精力解决下载的客诉问题,疲于奔命。
<p align=center> 场景 </p>
文库用户甲:我刚买了个文档,下载提醒胜利,然而文档没有下载下来。
文库客服乙:十分道歉给你带来不好的体验……
文库研发:因为这个文档作者设置了『不可下载』,这个是历史遗留问题,我修一下。
文库用户甲:这个文档我下载下来只有个摘要,内容不全。快给我退款!
文库客服乙:好的收到,我马上分割研发解决……
文库研发:因为这个是第三方文档,文库调用第三方服务失败,只能用咱们这边保留的摘要兜底。
- 下载方式泛滥,开发保护老本高:
文库通过多年倒退,下载方式也变得多种多样。PC、WAP、小程序、APP 端各自有各自的下载接口,还有一些跟第三方单干相干的下载服务。如用户能够在一些高校的内网下载百度文库的文档,也能够在文库下载来自第三方平台的文档内容。还有其它变种模式的下载服务,比方文档转存网盘,文档发送邮件附件等。这些下载服务大同小异,根本逻辑差不多,也有各自的非凡逻辑。
<p align=center> 场景 </p>
文库产品:咱们明天谈了一家新的内容合作方,把咱们文档在他们 app 展现,要提供下载性能。
文库研发:好的,我开发一个下载接口。
文库产品:咱们跟 XX 高校单干,局部文档能够收费给他们应用。
文库研发:那我独自给他们提供个下载服务吧。
- 反黑产反作弊老本高:
因为下载方式多种多样,文库历史上开发的各种反作弊逻辑也是多种多样,没有做到策略对立。想减少一个新的反作弊策略十分艰难。网上呈现过一些转卖或者下载文档的工具,咱们很难定位他们是通过什么形式获取到文库的内容。
<p align=center> 场景 </p>
文库产品:最近又发现一个文库下载工具,能下载咱们的文档。咱们的下载服务须要接入 XX 反作弊平台
文库研发:好的,我可能须要改十几个接口……
针对这些下载 case,只管文库研发人员每天都有整顿跟进,并归类,但实际效果并不显著,问题没有失去彻底解决。因为各种下载 case 纷繁复杂,难以尽述。随着新我的项目上线,也一直会有新问题呈现,难以收敛。
起因
通过剖析,问题有以下几方面起因:
- 【业务层面】
文库的下载服务属于根底服务,业务场景比拟固定。所有的下载服务和下载方式,其逻辑和步骤都大同小异。下载服务都有安全检查,业务逻辑查看,获取下载地址,后置解决 (扣特权,计数) 等流程,能够求出最大公约数,形象通用步骤。而以后是面向接口开发,应答新需要时,很多状况下优先保障短平快上线,没有抉择长期计划。
- 【架构层面】
以后下载服务和文库整体耦合在一起,相互影响。且下载的代码比拟扩散,根本都是面向接口编程,没有对立的根底模块和通用标准,也不足对立的异样解决机制和错误码信息。
- 【监控 & 经营层面】
因为文库的下载接口多且扩散,没有整体的日志收集机制,并且不足对立的监控、数据报表、经营工具等。导致不能及时发现问题进行预警,出问题往往要等到用户反馈才发现。即便用户反馈了问题,因为不足无效的经营工具,客服人员无奈自行定位问题,必须依赖研发的帮助。
- 【用户体验方面】
下载行为的提醒文案不精确,有些下载谬误不足敌对的提醒文案,下载流程体验不佳。
归根结底是因为以后的技术设计,难以满足业务的疾速倒退变动的须要。最开始文档下载只是一个简略的接口或者性能,随着业务变迁变得越来越简单。实际上曾经成了一套简单的零碎,而且是在一直扩大一直降级的零碎。然而技术架构上多年未改良,曾经落后于业务倒退。
所以要彻底解决它们,不能着眼于以后的问题,须要从新思考咱们的业务场景,建设适宜以后业务倒退的技术体系,用技术来系统性的解决以后问题,咱们文库研发开出的药方是 ” 微服务化 ”。
03 解决问题之道
微服务是围绕业务领域建模的、可独立部署的服务。微服务利用网络互相通信,把耦合在一起的整体架构拆离开,微服务是一种面向服务的架构,基于多个微服务间的合作,为解决简单零碎问题供了一个不错的抉择。
在定义下载服务的边界时,如何保障耦合和内聚之间的均衡十分重要。耦合和内聚这两个概念互相关联,如果一个架构具备高内聚、低耦合的个性,则该架构是稳固的。单体构造的问题在于,单体对内聚和耦合而言是相同的(低内聚,高耦合)。单体架构不是偏向于内聚,而是趋向于把变动的代码组织在一起,衍生出各种不相干的代码逻辑并将其拼贴在一起。
回到咱们具体的下载业务上来,如果下载服务外部各子模块性能越繁多,内聚性就越高,其独立性就越强。同样的一个服务应该做好本人业务范围内的性能就能够了,不须要八面玲珑,不然难以保护。同时,下载服务跟其它服务之间分割越少,耦合性就越低,各服务之间的绝对独立性就越强。这就是咱们进行下载微服务革新的根本指导思想。基于这个思维,咱们从新思考了文库业务,让这个新的微服务架构能实现咱们下载业务须要的性能和个性。咱们设计实现了一个下载的微服务零碎,这个零碎独立部署独立上线,跟其它业务隔离开来。同时把文库的下载接口全副纳入到这个框架里来,这个框架重点做了以下几方面的事件:
- 形象下载过程,定义通用的下载步骤。使研发人员当前开发下载服务时都依照此框架的标准来开发。
- 形象下载行为,对每一次下载过程,都记录具体的数据,包含下载现场数据,下载过程和下载后果。为监控和经营工具提供根底数据。
- 开发组件化的功能模块,不便复用和对立批改降级。
- 制订对立的异样解决机制,标准错误码,主动收集下载日志,优化提醒文案。
- 产出配套的经营剖析工具,不便客服人员定位问题,同时减少下载数据实时监控。
综上,文库研发,PM,QA 联结启动了一个下载服务优化我的项目,来解决困扰咱们已久的下载问题。
04 计划实现
要把传统的面向接口开发的零碎革新成一个独立的微服务零碎,咱们重点做了两件事件。第一件是定义微服务调用的协定和规定,并且将下载零碎独立部署独立上线,让微服务垂直划分,这是微服务化的根底。第二件事是基于咱们的下载业务,开发一个满足业务要求,适宜业务倒退的下载技术框架。
4.1 微服务根底
在单体式利用中,各个模块之间的调用是通过本机的编程语言的办法或者函数来实现的。然而一个基于微服务的分布式应用是运行在多台机器上的,分布式的部署,服务之间通过网络通信来相互调用。文库下载服务借助百度公司外部通用的 BNS 来实现流量调度和负载平衡。BNS 服务全称:Baidu Naming Service,即百度名字服务,用于满足服务间交互中常见的的资源定位、模块间 ip 白名单 受权验证、负载平衡以及其余任何依赖于这些信息的开发和运维需要。咱们给下载服务的所有线上机器退出到咱们创立的 BNS。客户端或者其它外部业务要拜访下载服务,都通过这个 BNS 来拜访,并且反对就近拜访对应的机房,防止近程网络通信带来的额定开销。
近程拜访和重试机制依赖百度外部的 RAL 客户端。RAL 反对多种交互协定和数据打包格局,具备高性能和低成本的特点,并且能够与 BNS 完满配合。调用方应用 RAL 与下载服务进行交互,而不须要关注数据格式解决与协定交互的过程,是一种简略可依赖的形式。
部署采纳百度云平台,也是十分成熟牢靠的解决方案。实现跟文库主业务隔离,开发和上线互不影响。
4.2 业务框架
基于对文库业务的思考,在新的文库下载微服务零碎中,咱们开发了一个适宜文库业务场景,满足长期倒退变动的下载服务框架。这个框架做了以下五局部的工作:
- 形象下载过程,下载流程规范化
首先咱们对下载过程做了形象。做形象是为了简化业务,对下载行为进⾏总结和过滤,去除掉咱们不须要的步骤或者多余的信息,剖析其本质。通过剖析,文库的下载业务逻辑通常比拟固定,能够把下载过程分为下载行为初始化,安全检查,权限查看,主业务操作,后置操作几局部。
其中,下载行为初始化操作会事后收集本次下载行为的根底数据,即不蕴含隐衷数据的用户信息,以及以后下载场景信息,以及被下载的对象信息等,前面各个环节,以及写下载日志都会用到这些信息。第二步为安全检查,本步骤会做频率限度,避免某些 IP 或者账号短时间内进行大量下载,以及会有一些封禁查看,反作弊查看等。第三步为权限查看。个别下载服务都不是收费的,须要用户有肯定的积分,或者曾经购买过内容,或者用户身份具备下载权限等。第四步为下载主业务逻辑,本步骤依据被下载的内容 id,获取到内容保留的地址,把内容返回给用户的设施。最初一步为后置操作,个别用于扣减用户积分或者金钱耗费,以及记录用户数据等。
最终咱们的框架里定义了以上几个下载步骤,各个下载的具体业务实现里,依照事后定义好的步骤进行开发,保障了下载流程规范化,也为整个下载零碎的日志收集,监控等打下了根底。
示意代码:
- 形容下载行为
一次下载行为实际上是一个网络申请,咱们须要收集这类网络申请的一些附加信息,联合以后的利用场景,再加上这个行为的后果,就能很好的形容出这一次下载过程。下载行为通常是由终端用户发动,在一个特定的场景下,下载特定的内容对象。用户通常具备账号 id,终端 IP 地址,所用浏览器或者设施信息,以及 cookie 信息等特色(不蕴含用户隐衷信息)。而场景包含用户在哪个产品线发动下载行为,这个下载行为的起源,下载工夫,下载过程后果等。内容对象包含用户所下载的内容的类型,以及这个内容的 id,内容题目等一些能形容此内容的信息。
收集这些数据能大大晋升咱们疾速定位问题的能力,以及用于监控下载服务的稳定性和业务数据变动。
- 提供组件化的根底模块
软件架构设计自身就是一个简单的事件,但其实业界曾经演化出了卓有成效的应答方法,那就是“通过组件化实现关注点的拆散从而升高部分复杂度”。其实当初咱们用的无论是容器、中间件、音讯、数据库等,在某种意义上都是组件化的产物,这样的益处是在不同的零碎里能够复用,正是这样的复用才成就了明天的互联网级架构。
对应到咱们具体的下载服务,反作弊,频率限度,权限校验,身份查看等都能够开发成通用的、组件化的功能模块,以晋升开发效率,升高屡次迭代引入的危险。
以后代码中下载和转存别离笼罩 pc, wap, 小程序三端以及其它单干接口, 各接口代码中局部逻辑是各自为战, 代码冗余度高, 逻辑不统一。为解决这种问题, 将局部根底服务形象剥离, 业务解耦,开发成独立的,可复用的根底模块,就能做到一改全改。对于一些有特殊要求的逻辑,例如 PC 限度一天最多下载 M 次,WAP 限度一天最多下载 N 次,通常用传参或者配置文件来管制,保留灵活性。
举个例子,咱们对不同类型的文档,查看权利也不一样。单篇付费类文档,下载过程中须要检查用户是否已购买这篇文档,而 VIP 收费文档只需检查用户是否 VIP 身份就行,对于 VIP 专享文档,除了要查看 VIP 身份,还要检查用户是否有足够的下载特权。这些权利规定也不是固定不变的,随着业务倒退会有新的权利规定。将权利管制封装成一个独立的模块后,当前新增和批改权利都会变得很容易。
- 标准异样解决机制,主动收集日志
任何服务都须要思考到异样解决机制,这里说的异样,既包含程序逻辑上的异样,也包含业务逻辑上的异样。程序异样诸如指针谬误,变量类型谬误之类,个别程序员都会思考到这些。理论业务执行过程中也会有异样,比方非 VIP 身份却去下载 VIP 专属文档,一天下载超限了还在持续下载文档。很多开发者通常会不太在意这种业务异样,然而对于咱们下载服务来说十分重要,咱们须要记录这种异样来帮忙咱们剖析异样 case。
以前下载过程抛异样很凌乱,没有标准的谬误提醒。框架从新定义错误码,标准异样解决。减少异样收集机制。如果框架检测到任一步骤返回错误码,则自动记录下载日志,如果下载过程最终胜利,同样会记录下载日志。最初格式化返回错误信息以及数据。
在这个下载微服务框架下,业务开发只须要实现各自下载服务的 Downloader 就行,其它的步骤,比方流程定义,行为收集,日志落库工作都是框架主动实现。主框架会监测执行过程,执行完结时,获取下载行为数据,并且主动写入日志。
日志的存储上,因为下载量微小,不不便用单表存储,采取按月分表的形式,因为这个数据只是用于经营定位问题,以及一些数据分析,不作为在线业务应用,所以这种分表形式齐全满足咱们的应用场景。
- 产出配套的经营剖析工具和监控
新的下载服务框架收集数据的同时,也产出了相应的经营工具,报表,监控等。如果有客诉,客服人员能够自行查问下载记录,看是否用户下载是否胜利,以及相应的日志。并且减少实时监控,如果是十分钟内下载胜利数 / 失败数有激烈稳定,就会向研发人员发送报警信息。
=
04 成果和总结
通过如上革新后,再遇到相似的问题,应答形式曾经齐全不一样了:
<p align=center> 场景 </p>
文库用户甲:我刚买了个文档,下载提醒失败请重试,是什么起因?
文库客服乙:您好,经查问你下载的文档属于第三方问题,下载过后对方服务稳定性有问题,咱们曾经分割合作伙伴解决,当初好了。
文库产品:咱们发现 XX 黑产工具再用非法手段下载咱们的内容,须要在所有下载入口针对此工具紧急上线一个封禁策略
文库研发:好的,一改全改。
咱们通过微服务化革新,从微小单体式利用拆散出独立的下载业务架构,从而化繁为简,解决了复杂性问题。新的微服务架构也不局限于原来的技术栈,开发者能够自由选择新的开发技术, 提供 API 服务。新的下载服务只关注于本人的业务性能,并且独立开发部署,解决了耦合问题。实际上,进行微服务化革新之后,下载业务的迭代无需依赖其它服务,迭代速度也快了很多,最终业务问题也失去了收敛。
——————END——————
举荐浏览:
百度 APP Android 包体积优化实际(二)Dex 行号优化
百度 APP Android 包体积优化实际(一)总览
百度 APP iOS 端内存优化实际 - 大块内存监控计划
百家号基于 AE 的视频渲染技术摸索
百度工程师教你玩转设计模式(观察者模式)
Linux 通明大页机制在云上大规模集群实际介绍