云原生架构下的持续交付实践

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"导读:","attrs":{}},{"type":"text","text":"随着虚拟化技术的成熟和分布式框架的普及,在容器技术、可持续交付、编排系统等开源社区的推动下,以及微服务等开发理念的带动下,应用上云已经是不可逆转的趋势。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"云原生带来了标准化、松耦合、易观测、易扩展的特性,为交付基建与业务解耦、更灵活的环境管理和无损发布带来新机遇。同时,微服务架构下服务数量爆炸式增长,对应的交付基建工作量暴增,且服务间拓扑复杂,又导致了升级影响难评估、问题定位困难、单独测试环境成本极高等问题给高效能交付带来了极大挑战。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic","attrs":{}}],"text":"全文6228字,预计阅读时间17分钟。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爱番番产品从20年4月全面云化,在云化时代,通过与业务解耦的DevOps基建,让业务团队专注与业务开发本身,大幅度提升业务效能,通过智能生成契约测试 case保障服务间调用的可靠性,通过全链路灰度能力为线下测试和无损发布赋能,实现产品的高效能交付。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"一、业务背景","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"爱番番是典型的toB型业务,具有以下特点:","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从产品形态上,产品战线长,涵盖(拓、聊、追、洞察)等核心产品能力;","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从市场环境上,市场环境竞争异常激烈,对产研的效率与质量提出更高的要求;","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从研发模式上,产品与研发采用敏捷思维研发,需要不断的创新与试错,快速完成PoC及MVP产品的研发上线;","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从部署形态上,除了提供SaaS服务外,同时具有多样化售卖的诉求;","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"团队以业务领域划分的多个scrumTeam,如下图:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/bc/bc748b901af4208cc6e11ebb93ae1de8.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"二、效能体系面临的挑战","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2.1 服务爆炸导致的基础设施成本剧增","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"活跃模块数200+,月均新增模块8个,流水线、监控等基础设施接入管理维护成本剧增。每个模块需要接入的基础设施如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/bf/bf9597d44a645bdb4a49649c36e8a02e.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2.2 复杂拓扑导致的问题定位困难和回归范围难以评估","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/eb/eb26c4e2f80e0a728451f0f51d01e51d.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"服务间拓扑复杂,如上图,复杂拓扑带来下列问题:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1、升级影响难评估,回归漏测多;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2、线上问题定位困难;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3、环境规模庞大,联调测试成本高;","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2.3 越来越高频的发布需求和随拓扑复杂度提升的发布成本的矛盾","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"模块众多且复杂拓扑,而且模块间上线有依赖关系,每次上线100+模块,人工控制流程,风险高而且效率越发低下。但是业务上发布的需求愈发频繁,在高频次的发布下,如何保障发布过程的高效、安全也是一项极大的挑战。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"三、整体的效能改进思路","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"流程机制层面: ","attrs":{}},{"type":"text","text":"用户价值,流动效率提升为核心的敏捷体系建设,包含以下几个方面","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"敏捷迭代机制:","attrs":{}},{"type":"text","text":"以用户价值流动效率为核心理念,保障团队目标一致,信息透明;","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"需求拆分管理:","attrs":{}},{"type":"text","text":"标准化、可视化、自动化的管理机制,在成本可控的前提下达成小批量需求加速流动,快速验证价值;","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"分支模式和环境管理:","attrs":{}},{"type":"text","text":"基于云原生强大的流量管控能力,实现基于istio的全链路灰度环境能力,实现简洁、灵活、低风险的分支模式;","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"全流程的数据度量体系:","attrs":{}},{"type":"text","text":"通过目标指标度量了解现状,过程指标度量挖掘问题,问题自动创建任务,协同 peer推动问题闭环;","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"技术层面:","attrs":{}},{"type":"text","text":"全流程环节自动化智能化提升,包含以下几个方面:","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"基础设施:","attrs":{}},{"type":"text","text":"建设与业务解耦的基础设施服务;","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"自动化:","attrs":{}},{"type":"text","text":"微服务下合理分层自动化体系,可控投入下保障有效质量召回;","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"发布能力:","attrs":{}},{"type":"text","text":"一键操作高效执行、过程可视、可感知、可控的极致发布体验;","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"工具赋能:","attrs":{}},{"type":"text","text":"丰富的工具能力赋能研发测试各效能痛点环节,为人员赋能(建设中,本文暂不详细介绍);","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面主要从技术层面的4个方向逐一进行方案说明:","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/f2/f2298654ccd9089646af6afc3fa7dedd.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"四、与业务解耦的Devops基础设施服务","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上文已经提到,基础设施面临的最大问题是,由于爆炸的服务个数带来的暴增的DEVOPS基础设施接入和维护成本问题。在这个问题的处理上,我们借鉴了 serverless 的思路,把基础设施服务化,与业务解耦,独立运维。以前,我们的业务团队研发和QA,除了需要进行业务的开发和测试工作之外,有大量的时间都花费在了新应用、日志、配置的接入以及环境、流水线、监控维护等等和核心业务无关的事项上,就像下面这个图的左边,而且,任意基础设施服务要升级,比如日志平台SDK升级、流水线需要统一增加一项安全检测环节等等,都需要各个业务团队配合升级,落地推广困难。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果我们把这些基建内容通过服务化的形式提供给业务团队使用,就能让业务研发和QA聚焦于业务的关键事项,从而大幅度提升团队效能。就像下面的右边这个图。同时基础设施的升级业务无感知,再也不会有基础设施能力落地推广困难的问题。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/d4/d4cea04bebce635841d8e02ca79bea87.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"如何打造与业务解耦,服务化的基础设施?","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"4.1 基础设施标准化","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"与业务解耦的第一步是基础设施的标准化,只有标准化的过程才有可能规模化,从而实现技术设施服务化。我们主要针对以下几部分内容进行了标准化改造:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"1.模块标准化:","attrs":{}},{"type":"text","text":"代码结构、打包流程、标准容器、镜像管理、部署过程","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"2.标准流水线","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"3.标准的基础服务:","attrs":{}},{"type":"text","text":"APM组件、配置中心、发布平台、资源管理","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"4.研发模式:","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/00/0041b38a4f510f3c93709f5c99fd0616.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"4.2 声明式基础设施","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"与业务解耦的第二步,是基于标准化的基础上,建立声明式的基础设施能力。这里的声明式是指给业务团队声明式的基础设施体验。业务团队只需要在标准配置中声明一些基础属性,即可自动完成所有基础设施的接入,且后续维护上业务0成本。主要分为两个环节的建设:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"接入时:分钟级的一键接入","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我们的做法是通过脚手架为抓手来构建基础设施的一键接入能力。如下图所示:脚手架是我们这边新模块创建的入口。所有新代码库都是通过脚手架创建,他会帮助开发自动生成一整套集成了标准组件的代码框架。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在脚手架创建新模块的时候,根据业务声明的模块属性,如是否接入apm、模块代码类型、模块服务类型等等自动完流水线创建、基础组件接入、集群环境申请、配置文件生成等操作。一个新的服务,从创建代码库到服务全套基础设施接入完成,服务可直接部署到测试集群的时间<10分钟。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/40/404ea068f2825e9151a00ff81c9d7035.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"脚手架:自动生成框架代码,包含基础apm组件、api管理平台等的接入;","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"configMap:自动生成应用标准配置并基于配置新增/变更主动触发接入服务;","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接入服务:拉取configMap配置并解析,根据配置内容调度不同的基础设施服务完成接入初始化;","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"运行时:根据服务声明内容动态运行,实现业务升级维护0成本","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基础组件部分,因为都是以sidecar模式提供服务,所以运行时天然与业务解耦,因此重点在于如何实现流水线在运行时与业务解耦。我们针对流水线进行了模板化、参数化改造,并和业务的声明属性结合。就像下面这张图,流水线每次都是动态运行的,运行的内容是依赖左侧5部分声明数据实时生成,包括cicd通用配置、流水线模板、任务脚本、任务策略、业务声明属性。除了业务自己的声明文件,其余部分都是基础设施组独立运维,故对应任务优化、添加、统一配置修改等均对业务透明。就像右图,如果要针对流水线上的某个环节进行优化,或者增加一些环节,仅需基础设施组修改流水线模板或者任务脚本即可。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/1a/1af530c2de22b0722a5ae7c9724100b0.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"4.3 智能化基础设施","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因为服务化之后,基础设施作为独立运维的服务,所有的问题都需要设施团队独立维护排查,所以与业务解耦的第三步就是建立高稳定高效低运维成本的基础设施能力。我们的思路是通过智能化的策略,来保障高效和稳定。在流水线运行的前中后通过策略给流水线增加一个”监工”,模拟人工判断任务是否应该执行,模拟人工分析跟进、修复问题等。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"分析常见的流水线稳定和效率问题比如环境不稳定、底层资源不稳定、网络异常等等,大体可分为 偶发问题重试可恢复、问题相对复杂需人工排查、阻塞问题需人工修复三类。而效率方面大量重复、无效任务比如只加了个log也要跑全套测试流程,导致了资源浪费,也导致了执行效率低下。如下图左侧所示:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/6b/6b2d94bcc102f9df8b5015449b59f673.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"针对这些场景,我们在流水线运行前后都添加了可配置的策略判断过程,判断任务是否需要跳过、排队、重试等等,从而提升稳定性和效率。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"典型场景:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"自动红灯分析:任务失败后可自动根据日志错误码分析问题原因并给出标注,方面后续根据统计数据更有效的优化。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/d3/d34e34d2716860520bbd5341fe7d96a7.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"排队策略:","attrs":{}},{"type":"text","text":"在自动化等任务执行之前,自动检测依赖环境是否正常,从而降低运行失败导致的红灯。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/8b/8b27b4e5a05a60756d185680477b5870.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"五、分层自动化体系","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"要想实现持续的交付,自动化是一个绕不开的话题,在云原生微服务的背景下,自动化层级会发生怎样的变化呢?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"和传统3层金字塔自动化不一样,云原生架构下的自动化,由于服务内部相对简单,而服务拓扑复杂,所以测试的重点是在系统端到端测试,实际的分层测试的比重更像一个倒过来的金字塔。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/58/580996171104dc7b1adf301a132767bf.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"而由于端到端成本过高,考虑到投入产出比,爱番番的分层自动化是按照右下角这个结构来建设的,其中接口DIFF测试、契约测试、纯前端DIFF测试是无人工介入,最核心的三个部分。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/26/260539f702cca3250474d534abe6c1b3.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"5.1 基于全链路灰度环境的接口DIFF自动化","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"5.1.1 全链路灰度方案","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我们接口的DIFF 测试是基于强大的全链路灰度环境能力来建设的,这是云原生架构给我们带来的红利。先介绍下我们的全链路灰度方案。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我们是基于istio的灵活的路由能力,通过同构底层「分组多维路由」的架构设计, 自研CRD Operator 构建爱番番的「全链路灰度发布」平台。该方案支持了我们的线下多路复用环境、线上安全的容量评估以及金丝雀发布等多个场景。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/c8/c8f297182014219c6c935abcdd188f18.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"5.1.2 测试环境多路复用","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"测试环境多路复用是指,使用有限的资源,在一套基础环境上逻辑隔离出多套环境,支持并行开发、联调的需求。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如下图所示,不同的分支对应着不同的feature,通过流量染色+流量规则路由的方式,使得不同分支拥有逻辑上隔离的环境,支持并行开发。在前端给流量打上橘色标记之后,全链路的请求会走橘色的链路进行访问。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/41/4102e2384758a713936ab9430a07b330.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"5.1.3 基于多路复用的DIFF测试","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有了如上所述的多套逻辑隔离的测试环境之后,每当有新的分支环境拉出并有代码更新时,即可通过将流量在base环境(部署最后一次上线的代码)和新分支环境进行回放,并对比两者的返回是否存在差异来进行回归测试。我们的diff方案如下:","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/bc/bce7ae9880f549ac55035034a26507e0.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"该方案具备如下几个优点:","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基于流量回放的接口diff,最大限度的覆盖线上用户真实场景;","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"全流程自动化,无人工参与;","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"配置化的流量筛选策略和diff策略接入,便于扩展优化;","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"分布式任务运行,支持大批量并发;","attrs":{}}]}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"5.2 保障召回服务间调用问题的契约测试","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"5.2.1 什么是契约测试","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"微服务的架构,服务之间依赖复杂,而且通常每个服务都是独立的团队维护,服务和服务之间,前后端之间大多通过API调用。那么这种情况下可能就会出现如下场景:A 团队开发的 API 同时服务于 B\\C 团队。最开始测试的时候都是通过的。但是后续迭代中,B 团队对字段 A 有一些调整的需求,A 团队根据需求改了,也测试通过了,但是上线后发现 C 团队功能异常了。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"以上问题的本质原因为:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"服务提供方服务的消费者越来越多的情况下,服务的变更影响难以评估,服务的变更也不能及时同步到所有消费者,所以往往是消费方发现问题了反馈,导致损失。为了避免上述问题,我们引入了契约测试。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"契约测试的核心思路是通过消费者驱动的方式,建立服务端和各个消费端之前的契约,在服务端有修改之后,通过测试和所有消费方之前的契约是否被毁坏来保障服务升级的安全性。同时,契约也可以作为双方测试解耦的手段。通过契约测试,团队能以一种离线的方式(不需要消费者、提供者同时在线),通过契约作为中间的标准,验证提供者提供的内容是否满足消费者的期望","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"5.2.2 常见的契约测试方案","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"常见的契约测试方案有真正实践消费者驱动的如pact,契约由消费端生成并维护,提供方代码更新之后,拉取所有消费方契约进行测试,即解决了集成测试解耦问题,又保障了服务方能满足所有消费方需求。(下左图)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"也有非消费者驱动,提供方生产契约,并提供mock服务,消费方可以基于契约文件测试,如Spring Cloud Contract。只能解决集成测试解耦的问题(下右图)","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/1d/1d9350619dcc2c21efb42ea6f8d693ed.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"5.2.3 爱番番的契约测试方案","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爱番番的方案则是取了折中。一方面由于团队习惯,契约一直是服务提供方给出,另一方面又希望保留消费者驱动特性,从而保障服务方能满足所有消费方需求。我们选择了在提供方生成契约,但是通过线上日志和调用链解析的方式来补充模拟消费端契约case。且整个过程全自动化。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/19/19629cf7ff4f41b189d9eb1a8b4fb299.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"5.2.4 契约测试技术实现","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第一步:引入swagger推动全接口接入,保障接口管理平台的接口文档信息与实际代码达到准实时同步,详细的实现步骤如下;","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/a4/a44a595f291433b1286dcb0a152eb653.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第二步: 根据接口文档自动生成契约case","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有了和代码同步的接口信息之后,则根据接口文档信息自动生成基础的契约测试case。在每次接口信息上传平台的时候,会检测本次上传内容,根据内容自动触发新case的生成和老case的验证。验证会运行修改了的接口之前关联的契约测试case来检测本次接口更新是否破坏原有契约,运行结果通过报表记录,并推送到对应团队标注,根据标注结果判断是否更新case。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/fd/fdb9a6eff00309a1fca4c0b8266eae5d.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第三步: 依赖调用链、日志信息智能分析消费端特征,生成模拟消费端的case","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如下图,通过调用链信息,提取出各个服务的消费方有哪些,通过各消费方的日志分析,获取模拟各消费方契约,并自动生成case和接口进行关联;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/f1/f1bc1c2806624488041be5f324a72c0f.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"5.3 问题智能定位降低自动化维护成本","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"自动化虽然是效能提升的好手段,但是长期以来,自动化的稳定性问题、问题跟进排查成本的居高不下都是阻止大家开展自动化建设或者自动化建设半途而废的重要原因。针对自动化的稳定性提升和跟进成本降低,我们建设了case失败自动定位和修复能力,让智能化的小助手帮助大家轻轻松松维护case运行。下面是我们自动定位的一个效果实例:","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/2e/2edfa9fc809daf35509781c899335316.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我们会在自动化case运行失败后,调用自动定位服务,自动对失败的case进行标注,根据标注结果会对失败case进行分类处理。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"比如,环境问题会自动重试,批量未知会发送到自动化小组进行排查,元素找不到会发送到业务QA排查。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以下是实现的方案。包含基础定位能力和基础数据获取。在这些基础能力之上,建设了配置层,实现配置解析和调度能力,让我们可以通过配置的方式,灵活组合不同的定位策略快速支持不同场景的问题定位。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/0c/0c54a4f4fb140324f6f3c7e2358a678b.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"六、高效安全的持续发布","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"6.1 发布困境","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不同类型模块对接了不同的不发平台和流程,统一发布困难,底层发布方式的变更需要各模块升级,迁移成本高","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由于模块众多且复杂拓扑,而且模块间上线有依赖关系,每次上线100+模块,人工控制流程,风险高而且效率低。上线过程的的记录和分析人耗也很高。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"整体上线过程不可见,风险感知滞后","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"如何解决以上问题?","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"6.2 多平台部署引擎","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基于云原生构建多平台统一的部署与发布引擎,无缝集成CICD,实现发布过程的高度标准化,同时支持多种发布策略。如下图:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通过CD发布平台的统一,实现各类型模块统一发布,且底层部署迁移业务无感知。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/36/36ecb00e17024761fc3bdc22597a0faa.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"6.3 发布剧本设计","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有了统一的发布平台之后,为了解决上线过程复杂低效的问题,我们希望实现完全自动化的发布过程。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"分析发布前后需要进行的事项,如下做图所示。基于这些事项,梳理了要自动完成整个发布过程需要收集的数据,如右图所示,包含发布模块封板信息、依赖信息、配置信息等等。基于这些数据,根据固定的编排逻辑,自动生成服务发布拓扑以及本次上线步骤。生成的上线拓扑和步骤信息经人工确认之后,自动调用对应上线发布服务进行发布,并针对发布过程数据自动统计,生成发布过程总结。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/38/3895048e4e4df5e233016cc32bba2e6a.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"6.4 过程可视、可感知、可控的一键发布","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有了自动化分发布过程之后,为了能够及时感知发布过程中的问题,降低发布风险,进行了发布过程可视化建设,并与APM、金丝雀发布等策略结合,保障发布的安全。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"发布过程可视:","attrs":{}},{"type":"text","text":"服务粒度的依赖拓扑已经实时上线进度展现、过程可视可感知;","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/df/df36117cd23995e57d8390fe1c1cfc7e.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"金丝雀发布策略:","attrs":{}},{"type":"text","text":"发布无损、风险及时感知并召回","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/a9/a9285b12095b80ab19bbd5424d75b4ff.webp","alt":"图片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"七、整体收益","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"迭代 story 量增长85.8%,发布周期稳定,研发测试周期下降30%,千行 bug 率从1.5降低到0.5。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"八、未来展望","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1、通过IDE本地插件工具,赋能开发编码测试过程,提升研发环节效能;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2、通过白盒能力,构建质量风险识别体系,应用于准入、准出、灰度等场景;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"推荐阅读:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"http://mp.weixin.qq.com/s?__biz=Mzg5MjU0NTI5OQ==&mid=2247498936&idx=1&sn=777b75ff2b3f85a66240762dcbba1aca&chksm=c03eccc4f74945d299c32433e10055d50821dd74874ba66722a6c9b15b914316298300f1020b&scene=21#wechat_redirect","title":null,"type":null},"content":[{"type":"text","text":"|百度短视频推荐系统的目标设计","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"http://mp.weixin.qq.com/s?__biz=Mzg5MjU0NTI5OQ==&mid=2247497498&idx=1&sn=76aec4723a8ace1c62f84fa69ebd5865&chksm=c03ec766f7494e7018d15106466f3476ce992cdf87de7c063627762598c59b77337a5d3f6e48&scene=21#wechat_redirect","title":null,"type":null},"content":[{"type":"text","text":"|","attrs":{}}]},{"type":"link","attrs":{"href":"http://mp.weixin.qq.com/s?__biz=Mzg5MjU0NTI5OQ==&mid=2247498828&idx=1&sn=70422ee59299dbe640bb9d192579fb43&chksm=c03ecc30f74945262a80f2f04873ea759d56b780a9bff6fcf9ff22880bb8929481fc85589681&scene=21#wechat_redirect","title":null,"type":null},"content":[{"type":"text","text":"百度信誉认证中台架构解析","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"http://mp.weixin.qq.com/s?__biz=Mzg5MjU0NTI5OQ==&mid=2247498745&idx=1&sn=88ab93caf2e8a3662b307206954bbcdb&chksm=c03ecb85f749429346766d992c69ffbe58037d33ae55642693efe497a5da722b5ae484b38d11&scene=21#wechat_redirect","title":null,"type":null},"content":[{"type":"text","text":"|","attrs":{}}]},{"type":"link","attrs":{"href":"http://mp.weixin.qq.com/s?__biz=Mzg5MjU0NTI5OQ==&mid=2247498782&idx=1&sn=20b01f2eccf6ccd827fba5a97f1f333c&chksm=c03ecc62f74945747ad8e8ef207f7a1a140bafe66c93119e5e11889d14f3edfe601b8f8afe0c&scene=21#wechat_redirect","title":null,"type":null},"content":[{"type":"text","text":"图数据库在百度汉语中的应用","attrs":{}}],"marks":[{"type":"underline"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"http://mp.weixin.qq.com/s?__biz=Mzg5MjU0NTI5OQ==&mid=2247498745&idx=1&sn=88ab93caf2e8a3662b307206954bbcdb&chksm=c03ecb85f749429346766d992c69ffbe58037d33ae55642693efe497a5da722b5ae484b38d11&scene=21#wechat_redirect","title":null,"type":null},"content":[{"type":"text","text":"|","attrs":{}}]},{"type":"link","attrs":{"href":"http://mp.weixin.qq.com/s?__biz=Mzg5MjU0NTI5OQ==&mid=2247499032&idx=1&sn=4ae30ea9c39f5d91f174aa4145daeae1&chksm=c03ecd64f7494472abe0790107bf9984f836ed590e6d2c124c09a0121807ad3a74f955ee9696&scene=21#wechat_redirect","title":null,"type":null},"content":[{"type":"text","text":"一年数十万次实验背后的架构与数据科学","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"---------- END ----------","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"百度Geek说","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"百度官方技术公众号上线啦!","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"技术干货 · 行业资讯 · 线上沙龙 · 行业大会","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"招聘信息 · 内推信息 · 技术书籍 · 百度周边","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"欢迎各位同学关注","attrs":{}}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章