嘉宾 | 董晓聪

出品 | CSDN云原生

2022年9月1日,在中国信通院、腾讯云、FinOps产业标准工作组联合发起的《原动力x云原生正发声 降本增效大讲堂》系列直播活动第7讲上,作业帮基础架构负责人董晓聪分享了作业帮的云原生降本增效实践。本文整理自董晓聪的分享。

作业帮怎么设置版本自动更新(作业帮云原生降本增效实践之路)(1)

为什么要进行降本增效

作业帮的技术现状可以归纳为两点,分别是规模化和复杂化。

作业帮于2020年初开始走一条云原生的道路,来解决发展过程中所遇到的稳定性、成本、效率及安全方面的问题。通过云原生的改造,用基础设施接管业务当中大量的非功能逻辑,以此实现弹性、可观测性、韧性、自动化及可持续性。

为什么要进行降本增效?

在降本增效的过程中,我们需要明确一点:降本但不能降质,在降低成本的同时,稳定性、效率、安全等均不能为此打折扣。

作业帮怎么设置版本自动更新(作业帮云原生降本增效实践之路)(2)

降本增效的关键点

在多种限制条件存在的情况下,该如何开展降本增效的工作呢?

作业帮怎么设置版本自动更新(作业帮云原生降本增效实践之路)(3)

应用层首先要做的是提升性能,即提升单位资源能够支撑的业务并发量。对于作业帮来说,多元的技术栈给应用层的效能提升带来了挑战。

资源层降本增效的重点在于计算层面的优化,存在两大挑战:

资源调度层有着巨大的优化空间,同样也面临诸多挑战:

作业帮怎么设置版本自动更新(作业帮云原生降本增效实践之路)(4)

应用层降本增效

应用技术栈改造

作业帮怎么设置版本自动更新(作业帮云原生降本增效实践之路)(5)

起初,作业帮采用PHP为服务端的主要开发语言,并使用ODP框架,能够有效地支撑新业务的快速构建及发展迭代。但随着业务的发展,以ODP为代表的PHP服务端技术栈遇到了诸多问题:

于是我们选择使用Go语言代替PHP作为服务端的主要开发语言。Go语言框架ZGIN基于GIN衍生而来,是面向Web服务的开发框架,提供了开箱即用的常见组件和功能,侧重通用性和稳定性,兼顾性能和时延。

作业帮怎么设置版本自动更新(作业帮云原生降本增效实践之路)(6)

应用技术栈——整体设计

GIN是一个通用性应用框架,我们在GIN的基础上做了性能优化,用来适配底层基础架构技术方案,同时带来业务场景下的性能提升。

与GIN相比,HttpServer中一直以性能著称的fasthttp具有一个显著的优势:复用连接池。但我们并未在GIN的二次开发中实现连接池,而是将能力下移,借助底层架构的能力使多语言栈保持同等能力。大多数服务模块目前已经接入Service Mesh,上游请求与Mesh-Proxy建立连接,Mesh-Proxy和服务模块之间通过UDS通信且保持长链接,同时优化UDS的零拷贝问题。

效率工具方面,提供简单易用的代码生成工具,根据脚手架快速地生成服务代码。通过代码生成工具,规范业务对框架的使用,减少业务后期追查及维护问题的成本。

测试环境互通工具方面,提供简单的命令工具,将远端测试环境的流量代理到本地端口,也可以将本地模块的出流量转发到测试环境之上。

作业帮怎么设置版本自动更新(作业帮云原生降本增效实践之路)(7)

应用技术栈——成果

经过两年的发展,Go语言已演变成为作业帮使用最多的服务端语言,当前基于Go语言构建的模块总计已达600 ,性能提升十分明显。如上图所示,使用Go语言重构应用模块后能够带来五倍以上的性能提升。

核心系统云原生改造

检索系统作为公司最底层的核心系统之一,是C语言栈下的倒排索引和综合策略索引,为智能推荐、资料智能分析以及搜索等提供底层支持。机器规模千台级别,计算核心达千万核以上,时效数据达百TB,数据日增量为TB级别。

作业帮怎么设置版本自动更新(作业帮云原生降本增效实践之路)(8)

检索系统——架构

检索系统底层设施主要包括两部分:数据产出服务与数据存储服务。

由于检索系统对低时延、高稳定性以及高吞吐性能的要求,早期选择使用本地存储,带来了计算与存储的耦合问题。随着数据量的增大,单机无法承载所有数据量,需要对数据进行切片,每个节点存储部分数据。出于高并发、高可用的要求,每个切片还需有多个副本。

当数据需要更新时,由于数据量庞大,数据产出服务无法一次将全量的数据存至线上的节点中,只能选择部分数据进行同步,随后以该部分节点为基准进行二次、三次分发。这就导致数据更新时间长、运维成本高、占用资源多等问题。

通过对检索系统架构的分析,可以看出,当前的关键问题都是由于计算存储耦合所导致。只有引入计算存储分离的架构,才能从根本上解决复杂度的问题。而新的解决方案应该具备以下能力:

基于上述要求,在技术选型方面,我们选择了Fluid与JindoRuntime的组合。Fluid是开源的Kubernetes原生的分布式数据集编排和加速引擎,它通过数据的编排、应用数据的调度,解决云原生过程中所遇到的一些列数据问题,如访问数据的时延过高、多数据联合查询困难等。JindoRuntime是Fluid的一种分布式缓存Runtime实现,实现了HDFS、S3协议的访问与缓存加速。

作业帮怎么设置版本自动更新(作业帮云原生降本增效实践之路)(9)

检索系统——云原生架构

通过云原生改造,检索系统变成了一个标准的无状态容器应用,数据应用的过程得到简化。

数据产出服务将数据传到对象存储中,Fluid驱动JindoRuntime完成对数据的加载。检索的进程通过Fluid挂载的PVC访问fuse,fuse将POSIX协议转化为对远端JindoRuntime的RPC访问。

完成架构改造后,对检索系统的瓶颈进行分析,发现导致性能无法提升的原因在于跨NUMA的内存访问带宽存在上限。

通过添加调度器,使进程绑定NUMA,保证CPU和内存的访问不跨NUMA,能够使该问题得到妥善解决。

作业帮怎么设置版本自动更新(作业帮云原生降本增效实践之路)(10)

资源调度层降本增效

资源调度层降本增效的核心在于解决上文所提到的在线集群负载不高、资源空间及时间分布不均等一系列问题。

自定义调度器

容器化改造使得机器的平均负载得到显著提升,但不同的机器之间差异较大,部分机器在业务高峰阶段还需进行额外的运维工作,如人工封锁高负载机器、人工驱逐不均衡Pod等。为什么会出现这样的问题呢?

作业帮怎么设置版本自动更新(作业帮云原生降本增效实践之路)(11)

主要原因在于Kubernetes原生调度器的调度依据以request为主,只考虑简单的指标,没有考虑未来的变化。于是我们通过自定义调度器来解决此问题:

在离线混部

互联网业务都有明显的波峰、波谷,波谷时段有大量的剩余资源处在空闲状态,考虑到大数据离线计算需要大量计算资源并对实时性的要求较弱,我们可以在在线集群的波谷时期运行大数据离线任务,达到节省计算资源的目的,实现双赢。但在实际实施中,存在资源隔离无法避免干扰、隔离效果差等问题。

作业帮怎么设置版本自动更新(作业帮云原生降本增效实践之路)(12)

对此,我们使用腾讯TLinux的新特性,在内核的CFS之间,添加一个新的调度器Offline,实现CPU避让,并对空闲资源做预测调度。

Serveless广泛使用

Serverless一直是作业帮技术架构探索的核心方向之一,用于解决资源分布时间不均的问题。Serverless的主要运行方案有两种,一种是函数计算,另一种是K8s虚拟节点。K8s虚拟节点具有对现有服务无使用差异、用户体验较好、业务服务无感知的特点,可以基于现有基础架构进行迁移。

Serverless技术挑战——调度

Serverless具有较强的成本优势,将在线服务高峰期弹性调度到Serverless上,可以大量节省资源成本。在推进Serveless的过程中存在诸多挑战,在调度层需要解决两个主要问题:

有三种方案可以解决上述两个问题。

Serverless技术挑战——观测

作业帮怎么设置版本自动更新(作业帮云原生降本增效实践之路)(13)

日志采集方面,采用CRD配置日志采集,将日志发送到统一的Kafka,通过资源的日志消费服务,消费云厂商的自有节点日志,实现虚拟节点和正常节点上的日志统一。

作业帮怎么设置版本自动更新(作业帮云原生降本增效实践之路)(14)

监控方面,云厂商虚拟节点实现的Metrics接口和Kubelet完全兼容,可以无缝接入 Prometheus,完成对Pod实时CPU、内存、磁盘及网络流量等的监控。

在分布式追踪方面,由于无法部署Daemonset形式的jeager-agent,我们在jeager-client端做了改造,通过环境变量识别Pod的运行环境,如果是在虚拟节点上运行,则跳过jeager-agent,直接将分布式追踪的数据推送到jeager-collector。

作业帮怎么设置版本自动更新(作业帮云原生降本增效实践之路)(15)

总结

作业帮基于云原生进行了一系列改造,最终实现了降本增效,整体的降本服务度已达到40%,未来会继续探索更具性价比的降本增效方式。此外,作业帮运营工作当前已实现从靠人到靠平台的过渡,将进一步向BI化、AI化演进。

,