当前位置: 首页 > 后端技术 > Java

微服务解决图书馆下载业务问题的实践

时间:2023-04-01 14:39:19 Java

作者|文库主站研发指南:百度文库是百度发布的一个供网友在线共享文档的平台。文献下载服务是图书馆的一项基本服务。经过多年的发展,目前的图书馆下载服务在业务和技术上都面临着诸多问题。因此,我们将传统的面向接口的下载服务改造为一个独立的微服务系统,着重做两件事:一是定义微服务调用的协议和规则,独立部署下载系统,独立上线,这样,微服务的垂直划分是微服务的基础。第二件事就是根据我们的业务,开发一个符合业务需求,适合业务发展的技术框架。从而简化复杂性并解决复杂的业务问题。全文6212字,预计阅读时间16分钟。01简介百度文库是百度发布的一个供网友在线分享文档的平台。用户可以从百度文库下载各种文档。百度文库平台自2009年11月上线以来,经过十余年的发展,文献量和日下载量都非常庞大。内容是图书馆的核心资产,文献下载服务是图书馆的一项基础服务。用户来馆的主要目的之一就是获取内容,所以下载服务的体验是重中之重,下载功能也被各种黑产使用。抓绒的重要对象。目前的图书馆是大型分布式单体架构。库中的所有代码作为一个整体系统一起部署。虽然库有多个应用和多个实例来实现分布式扩展,但是从根本上来说,所有的代码都封装在一个程序中。文档下载功能是这个庞大的单体架构的一部分。在图书馆十多年的发展历程中,这个庞大的单体架构和下载服务不断发展壮大。02面临的问题现象在业务和技术方面,目前图书馆下载服务面临很多问题:体验差,客户投诉多:每天都有很多用户反映文档下载失败,或者文档下载成功找不到,或文档已下载但失败。内容不全等。为此,图书馆的值班客服和研发人员每天要花费大量精力处理下载客诉,疲于奔命。场景

图书馆用户A:刚买了一个文档,提示下载成功,但是文档一直没有下载。图书馆客服B:非常抱歉给您带来不好的体验……图书馆研发:因为这个文档的作者设置了“不可下载”,这是历史遗留问题,我会修复的。图书馆用户A:我下载的这个文件只是摘要,内容不完整。快把我的钱还给我!文库客服B:收到,马上联系研发处理……文库研发:因为是第三方文档,图书馆调用第三方服务失败,只能用总结被我们救了解释。下载方式多,开发维护成本高:图书馆经过多年的发展,下载方式已经多样化。PC、WAP、小程序、APP各有自己的下载接口,也有一些与第三方合作相关的下载服务。例如,用户可以在部分高校内网从百度图书馆下载文献,或者在图书馆从第三方平台下载文献。下载服务还有其他变体,例如将文档传输到网盘、将文档作为电子邮件附件发送等。这些下载服务大同小异,基本逻辑相似,又有自己特殊的逻辑。场景

图书馆产品:我们今天谈到了一个新的内容合作伙伴,在他们的应用程序中显示我们的文档并提供下载功能。库开发:好的,我来开发一个下载接口。图书馆产品:我们与XX大学合作,部分文献可以免费使用。图书馆研发:那我单独给他们提供下载服务。反作弊反作弊成本高:由于下载方式多种多样,图书馆历史上开发的各种反作弊逻辑也五花八门,没有统一的策略。添加新的反作弊策略非常困难。网上已经出现了一些倒卖或下载文档的工具,我们很难定位到他们是如何获得图书馆内容的。场景

图书馆产品:最近发现了一个图书馆下载工具,可以下载我们的文档。我们的下载服务需要对接XX反作弊平台的库研发:OK,我可能需要改十几个接口……对于这些下载案例,虽然库开发者每天都会组织跟进天把它们归类,实际效果并不明显,问题还没有完全解决。由于各种下载案例复杂,难以一一列举。随着新项目的启动,新的问题会不断出现,难以收敛。分析原因,问题有以下几个原因:【业务层面】图书馆的下载服务是基础服务,业务场景比较固定。所有下载服务和下载方式的逻辑和步骤都是相似的。下载服务有安全检查、业务逻辑检查、下载地址获取、后处理(扣除权限、计数)等过程,可以找到最大公约数,抽象出一般步骤。但是,目前是面向接口的开发。在应对新需求时,很多时候优先考虑的是保证短期扁平化和快速上线,并没有选择长期的解决方案。[架构层面]目前的下载服务和库耦合在一起,相互影响。而且下载的代码比较分散,基本都是面向接口的编程。没有统一的基础模块和通用规范,也缺乏统一的异常处理机制和错误码信息。【监控&运维层面】由于图书馆下载接口多且分散,没有整体的日志收集机制,缺乏统一的监控、数据报表、运维工具。导致无法及时发现问题进行预警,问题往往要等到用户反馈后才能发现。即使用户反馈问题,由于缺乏有效的运营工具,客服人员也无法自行定位问题,必须依靠研发的协助。【用户体验】下载行为提示文案不准确,部分下载错误缺少友好的提示文案,下载过程体验不佳。归根结底,是因为目前的技术设计难以满足业务快速发展变化的需求。起初,文档下载只是一个简单的界面或功能,但随着业务的变化,它变得越来越复杂。事实上,它已经成为一个复杂的系统,而且是一个不断扩大和升级的系统。但技术架构多年未见完善,滞后于业务发展。因此,要彻底解决它们,不能只关注当前的问题。我们需要重新思考我们的业务场景,建立适合当前业务发展的技术体系,用技术系统地解决当前的问题。我们图书馆开出的药方是“微服务化”。03解决问题微服务是围绕业务领域建模的可独立部署的服务。微服务使用网络相互通信以分离耦合的整体架构。微服务是一种面向服务的架构。它们基于多个微服务之间的协作,为解决复杂的系统问题提供了很好的选择。在定义下载服务的边界时,如何保证耦合和内聚的平衡非常重要。耦合和内聚这两个概念是相互关联的。如果一个架构具有高内聚、低耦合的特性,那么这个架构就是稳定的。单体结构的问题在于单体的内聚力和耦合力是相反的(低内聚力,高耦合力)。单体架构不倾向于内聚,而是倾向于将变化的代码组织在一起,衍生出各种不相关的代码逻辑,拼贴在一起。回到我们具体的下载业务,如果下载服务中各个子模块的功能更加单一,那么内聚性会更高,独立性也会更强。同一个服务要做好自己业务范围内的功能,不需要面面俱到,否则难以维护。同时,下载服务与其他服务之间的联系越少,耦合度越低,服务之间的相对独立性越强。这是我们下载微服务改造的基本指导思想。基于这样的思路,我们对图书馆业务进行了重新思考,让这个新的微服务架构能够实现我们下载业务所需要的功能和特性。我们设计并实现了一个下载的微服务系统,独立部署,独立启动,与其他业务隔离。同时,库的所有下载接口都包含在这个框架中。该框架主要关注以下几个方面:抽象下载过程和定义通用下载步骤。让研发人员在以后开发下载服务时,按照这个框架的规范进行开发。抽象下载行为,对每个下载过程,记录详细的数据,包括下载站点数据、下载过程和下载结果。为监控和运维工具提供底层数据。开发组件化的功能模块,方便复用和统一修改升级。制定统一的异常处理机制,规范错误代码,自动收集下载日志,优化提示文案。制作配套的运营分析工具,方便客服人员定位问题,同时增加对下载数据的实时监控。综上所述,图书馆研发、PM、QA联合推出下载服务优化项目,解决困扰我们已久的下载问题。04解决方案实施将传统的面向接口的开发系统转变为独立的微服务系统,我们主要关注两点。首先是定义好微服务调用的协议和规则,独立部署下载系统,独立上线,这样微服务就可以垂直划分,这是微服务的基础。第二件事就是根据我们的业务,开发一个符合业务需求,适合业务发展的技术框架。4.1微服务基础在单体应用中,模块之间的调用是通过原生编程语言的方法或函数实现的。但是一个基于微服务的分布式应用运行在多台机器上,分布式部署,服务之间通过网络通信相互调用。图书馆下载服务使用百度内部常用的BNS实现流量调度和负载均衡。BNS服务全称:BaiduNamingService,即BaiduNameService,用于满足服务间交互中的公共资源定位、模块间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专属文档,一天内超过下载限制继续下载文档。很多开发者平时不太关心这种业务异常,但是对于我们的下载服务来说非常重要,我们需要记录这个异常,帮助我们分析异常情况。以前在下载过程中抛出异常是很混乱的,没有标准的错误信息。该框架重新定义了错误代码并标准化了异常处理。添加异常收集机制。如果框架检测到任何步骤返回错误代码,它会自动记录下载日志。如果下载过程最终成功,它还会记录下载日志。最后,格式化返回错误信息和数据。在这个下载微服务框架下,业务开发只需要实现各自下载服务的Downloader即可。其他流程定义、行为收集、日志存储等步骤均由框架自动完成。主框架将监控执行过程。当执行结束时,会获取下载行为数据,并自动写入日志。对于日志存储,由于下载量巨大,使用单表存储不方便,采用按月分表的方式。因为这些数据只是用于运营定位和一些数据分析,不作为线上业务使用。表格方式完全符合我们的使用场景。在制作配套的运营分析工具和监控新的下载服务框架收集数据的同时,也制作了相应的运营工具、报表、监控等,如果有客户投诉,客服人员可以自行查看下载记录查看用户下载是否成功,以及相应的日志。此外,还增加了实时监控。如果十分钟内下载成功/失败次数出现剧烈波动,将向研发人员发送告警信息。=04效果及总结经过以上修改,遇到类似问题,处理方式完全不同:场景

图书馆用户A:刚买了一个文档,下载提示失败请重试,为什么?文库客服B:您好,经查您下载的文件属于第三方问题,下载时对方服务稳定性有问题,我们已联系合作方解决,目前已全部解决。图书馆产品:我们发现XX非法工具被用于非法下载我们的内容。我们需要在所有下载门户网站上紧急启动针对此工具的禁止策略。我们通过微服务改造,将独立的下载业务架构从庞大的单体应用中分离出来,从而简化了复杂性,解决了复杂性问题。全新的微服务架构不局限于原有的技术栈,开发者可以自由选择新的开发技术,提供API服务。新的下载服务只专注于自身的业务功能,独立开发部署,解决耦合问题。其实经过微服务改造后,下载业务的迭代不需要依赖其他服务,迭代速度快很多,最终业务问题已经收敛。——————END——————推荐阅读:百度APP安卓包体积优化实践(二)Dex行号优化百度APP安卓包体积优化实践(一)概述百度APPiOS端内存优化实践-大块内存监控解决方案百家号基于AE的视频渲染技术探索百度工程师教你玩转设计模式(观察者模式)Linux透明大页面机制在云端大规模集群实践