聚焦弹性问题,杭州铭师堂的 Serverless 之路
作者:王彬、朱磊、史明伟
得益于互联网的发展,知识的传播有了新的载体,使用在线学习平台的学生规模逐年增长,越来越多学生在线上获取和使用学习资源,其中教育科技企业是比较独特的存在,他们担当的不仅仅是教育者的角色,更是让新技术的创新者和实践者。作为一家在线教育高科技企业,杭州铭师堂成立十余年来一致致力于用“互联网+教育”的科技手段让更多的学生能享有优质的教育,促进他们的全面成长,在不断汇聚优质的全国各地教育资源的同时,杭州铭师堂深度聚焦教学效率的提升,深耕先进技术,促进其在学校教育智能化领域、个性化学习领域广泛应用。
目前网上教学需求的常态化,教师在线审阅作业需求量急剧增大,为了减轻老师的审批工作量,提升教学效率,杭州铭师堂教育基于 Serverless 创造性的开发了学习笔记评优系统, 提升弹性效率,并大幅度降低成本。
01 峰值流量破万后,如何更好处理任务处理的实时性问题?
杭州铭师堂业务涵盖全国 20 多个省份,成立十余年来,杭州铭师堂不断汇聚优质的全国各地教育资源,并展开先进科学技术在学校教育智能化领域、个性化学习领域的应用研究。在教育信息化 2.0 趋势下,公司致力于促进线上教育与线下教育的高度融合,以学校为核心场景,与学校携手共建互联网学习空间,为学校与学生提供学习解决方案,极大促进教学效率的提升。
K8s+ 消息,系统难以处理数据并行度问题
学生做完作业后,会将作业拍照,然后上传到作业批阅系统,后端系统此时会有多个动作:
-
将作业照片上传到 OSS
-
将用户作业信息落到数据库
-
发送一条消息到阿里云消息队列 Kafka
其中第 3 步发送消息到阿里云消息队列 Kafka 后,通过消息队列 Kafka 的 connector 功能,驱动函数计算(简称 FC) 进行数据处理。函数计算作为业务的计算平台,承载了所有的处理逻辑,通过图像识别和数据分类算法,自动识别作业的完成情况。
在一年的大多数时间里,业务流量都比较平稳,但在寒暑假时,一般会迎来一年中的高峰,在过去的 2022 年暑假期间,平均每天需要处理 100 多万的作业图片处理,峰值流量更是达到了万级别。
作业图片的处理程序原先部署在 Kubernetes(简称 K8s),程序通过订阅 Kafka 的 topic,获取数据路径,从 OSS 获取数据进行处理,这一部分涉及到数据并行度的处理,主要存在两方面问题:
-
Kafka 的消费端并发度受限于 topic 的 partition,消费端个数最多只能跟 partition 数齐平,消费端数量超过 Kafka topic partition 数会导致超过 partition 数目的消费端没法订阅数据,也就没有实际的意义;
-
每个消费端消费到数据之后会将数据发到处理线程处理,处理线程在最好的情况下是可以根据业务流量动态调整,当然更多的线程就需要更多的资源,这又涉及到任务资源的水平扩容和垂直扩容问题。实际实现时杭州铭师堂消费端个数与 topic partition 保持一致,消费线程数经过调优之后保持了固定数量,在绝大多数时间里,程序能够很好的满足数据处理的的实时性要求,但对于高峰期,由于处理能力的限制,还是会经常出现任务积压的情况。
为了能够更好的实现任务处理的实时性要求,杭州铭师堂架构组寻求新的架构,经过对云产品的对比之后,最终选择了阿里云函数计算 FC。
02 兼顾弹性和成本,选定函数计算新方案
通过基于函数计算的新方案,很好的解决了老架构存在的问题,同时,开发迭代速度,运维效率和成本都得到了很大的优化,新老方案对比如下:

通过以上对比可以看出,函数计算对于杭州铭师堂学习笔记评优系统还是非常合适,在解决弹性痛点的同时,资源成本,开发运维效率都得到了一定的提升。
03 杭州铭师堂的 Serverless 落地之路
在技术架构的实施过程中,最初也遇到了一点问题:
Java 冷启动的问题:第一个问题是语言的问题,原来的后端程序采用 Java 微服务框架,整个服务中有多个接口,刚开始直接将整个服务部署到函数计算。由于 Java 程序启动的特性,加上整个服务框架加载的模块和数据较多,导致冷启动时间比较长,触发冷启动时没法很好的满足业务接口响应要求。
对于这个问题,杭州铭师堂开发同学主要做了两个迭代,首先将代码粒度拆细,在函数计算平台部署真正的处理代码,第二步,将 Java 语言的代码替换成 TypeScript。替换成 TypeScript 一是因为开发同学比较熟悉 TypeScript,二是因为 Node.js 启动速度很快。通过这两次迭代,使得函数的弹性效率大大提升,冷启动的情况下也能够达到 50ms 内完成单次请求。
资源利用率问题:第二个问题是资源的利用率,由于把函数逻辑拆分很细,单个请求对 CPU 和 Memory 的需求都很小,微了提高利用率,选择开启函数计算的单实例多并发,通过 PTS 的压测,在并发度和资源上的到了很好的平衡,资源利用率高达 70%+。
超出预期的惊喜:执行时间快和弹性效率高
通过解决这两个问题,整体开发流程顺利,项目上线后也达到不错的效果,在一些小的方面还有超出预期的表现,主要惊喜来自于执行时间快和弹性效率高。
执行时间快:在原来服务部署在 K8s 时,业务高峰期,单个请求响应时间在 100~200ms 左右,放到函数计算后,在高峰期,请求处理时间也能够维持在 50ms 左右,这是大大超出预期的,分析其中的原因主要是函数计算运行资源比较独立,每个实例处理固定的并发上限,超过部分通过弹出新的实例承载,所以高峰期请求脉冲到来时,也不会出现资源争抢。
弹性效率高:之前在架构设计时,很担心函数计算的冷启动问题,因为冷启动涉及到软硬件资源的初始化。但在实际运行表现看,这点担心也是可以忽略的。函数计算后端机器是神龙服务器,单台机器配置很高,单台机器可以切分出很多的运行实例,并且函数计算在镜像拉取,实例热备方面都有优化,运行实例拉起速度非常快,再加上 Node.js 启动速度的优势,在遇到冷启动时,请求也能够在 100ms 以内响应,这一点对于实时业务非常友好。
业务接口上线到函数计算后,很好的解决了之前高峰期的堆积问题,并且通过函数计算内置的监控和日志服务,在出现问题时,可以更好的辅助问题的排查,最重要的一点,通过函数计算的实时弹性,不再需要提前规划资源和部署冗余服务,使得资源成本也有一定降低。
04 为客户带来更多价值,杭州铭师堂继续探索 Serverless
通过这次项目,函数计算在杭州铭师堂内部的应用得到了更大的推广,将高脉冲和高资源要求的接口剥离出原服务,统一放到函数计算平台承载,对内部系统完成了一次 Serverless 架构的升级。
在整体使用过程中,杭州铭师堂架构团队也对函数计算提出了一些不足点:
产品集成割裂:在调用链路中,Kafka 数据通过 Kafka connector 触发函数计算的调用,Kafka 触发器与函数计算的使用界面有点割裂,具体表现为 Kafka 侧的订阅消费情况在 Kafka 控制台显示,函数计算的调用和监控需要跳转到函数计算,当出现问题时,排查问题需要两边控制台跳转,使用体验很不友好。
部署系统对接不够顺滑:杭州铭师堂经过多年发展,内部有成熟的 CICD 系统,中间加入函数计算之后,需要将函数计算纳入到自有的 CICD 系统中,这方面起初采用函数计算的 Open api,后来经过升级采用了 Serverless Devs 工具,虽然对接体验有了一定提升,细节方面还需要继续打磨。
未来,杭州铭师堂将与阿里云函数计算团队一道在集成,体验和技术深度等方面持续深耕,一起探索 Serverless 在实际业务的落地,以科技服务教育,用互联网改变教育,让中国人都有好书读。
开始使用函数计算
函数计算是事件驱动的全托管计算服务。使用函数计算,客户无需采购与管理服务器等基础设施,只需编写并上传代码或镜像。函数计算即可准备好计算资源,弹性地、可靠地运行任务,并提供日志查询、性能监控和报警等功能。
函数计算主要包含服务、函数、运行环境、触发器、层、应用中心等功能组件,具体产品组件架构图如下所示。

函数计算底层借助阿里云基础设施,如神龙服务器,网络通信,存储,安全组件等,构建安全,可靠,高性能的服务。弹性伸缩,负载均衡,流量控制,租户隔离,容灾等能力采用自研系统,保证了函数计算的计算密度,弹性效率,计费精度等核心竞争力。
函数计算的使用流程如下:

-
创建函数,编写代码。
-
将第 1 步中编写好的代码以函数的形式部署到函数计算。
-
函数计算支持通过触发器快速构建事件驱动架构业务流程的能力。
-
函数计算支持按请求付费的模式,在函数有调用时,后端会弹出真实的计算资源,当同时有多个请求打到函数计算,函数计算会并发的弹出多个计算实例进行并行处理,每个启动计算实例都会保持一定时间的在线,超过一定时间,系统会回收计算实例。
-
最终收费时,按照实际函数运行的时间收费。
通过函数计算的平台,客户只需要专注业务代码,面向函数极简编程(可选多种编程语言),通过函数计算提供的 SDK,Serverless Devs 工具,丰富的云产品事件驱动触发器,可以快速构建完整的调用链路。开发者不再需要直面 IaaS 资源和容器资源,通过将云上业务拆分到函数级别,多个函数组成服务,多个服务构建应用,让开发者从小处处着手,快速实现业务落地。
整体调用链路如下:

处理步骤细节:
-
用户提交作业出发提交流程,将请求打到后端服务。
-
后端服务将用户提交的作业图片上传到 OSS,并将 OSS 地址作为一条消息发送到 Kafka。
-
函数计算的 Kafka 触发器实时的感知 Kafka topic,当有新数据到达,实时触发函数处理。
-
函数计算函数获取到触发请求中的数据,从 OSS 获取数据,并对数据进行处理,将处理结果发回到 Kafka topic。
-
后端程序订阅 Kafka topic,对处理结果进行存储和下一步的展示。
点击此处,直达函数计算!
相关文章:
聚焦弹性问题,杭州铭师堂的 Serverless 之路
作者:王彬、朱磊、史明伟 得益于互联网的发展,知识的传播有了新的载体,使用在线学习平台的学生规模逐年增长,越来越多学生在线上获取和使用学习资源,其中教育科技企业是比较独特的存在,他们担当的不仅仅是…...
NDK RTMP直播客户端二
在之前完成的实战项目【FFmpeg音视频播放器】属于拉流范畴,接下来将完成推流工作,通过RTMP实现推流,即直播客户端。简单的说,就是将手机采集的音频数据和视频数据,推到服务器端。 接下来的RTMP直播客户端系列ÿ…...
Python3--垃圾回收机制
一、概述 Python 内部采用 引用计数法,为每个对象维护引用次数,并据此回收不在需要的垃圾对象。由于引用计数法存在重大缺陷,循环引用时由内存泄露风险,因此Python还采用 标记清除法 来回收在循环引用的垃圾对象。此外,…...
C/C++开发,认识opencv各模块
目录 一、opencv模块总述 二、opencv主要模块 2.1 opencv安装路径及内容 2.2 opencv模块头文件说明 2.3 成熟OpenCV主要模块 2.4 社区支持的opencv_contrib扩展主要模块 2.5 关于库文件的引用 一、opencv模块总述 opencv的主要能力在于图像处理,尤其是针对二维图…...
【WLSM、FDM状态估计】电力系统状态估计研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
准备2023(2024)蓝桥杯
前缀和 一维前缀和 s[i]s[i-1]a[i]二维前缀和(子矩阵的和) s[i][j]s[i-1][j]s[i][j-1]-s[i-1][j-1]a[i][j] 差分 一维数组 //b是差分数组b[i]c;b[j1]-c;例题 #include<iostream> using namespace std; int n,m; int b[100002],a[100002]; vo…...
剑指 Offer 60. n个骰子的点数
剑指 Offer 60. n个骰子的点数 难度:middle\color{orange}{middle}middle 题目描述 把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。 你需要用一个浮点数数组返回答案,其中第 i 个…...
阿里巴巴-淘宝搜索排序算法学习
模型效能:模型结构优化 模型效能:减枝 FLOPS:每秒浮点运算的次数 模型效能:量化 基于统计阈值限定,基于学习阈值限定。 平台效能:一站式DL训练平台 平台效能:搜索模型的系统流程 协同关系…...
〖Python网络爬虫实战⑮〗- pyquery的使用
订阅:新手可以订阅我的其他专栏。免费阶段订阅量1000python项目实战 Python编程基础教程系列(零基础小白搬砖逆袭) 说明:本专栏持续更新中,目前专栏免费订阅,在转为付费专栏前订阅本专栏的,可以免费订阅付费…...
SQL综合查询下
SQL综合查询下 目录SQL综合查询下18、查询所有人都选修了的课程号与课程名题目代码题解19、SQL查询:查询没有参加选课的学生。题目代码20、SQL查询:统计各门课程选修人数,要求输出课程代号,课程名,有成绩人数ÿ…...
全连接层FC
lenet结构: 输入层(Input Layer):接收手写数字的图像数据,通常是28x28的灰度图像。 卷积层1(Convolutional Layer 1):对输入图像进行卷积操作,提取低级别的特征,使用 6 个大小为 5x5 的卷积核进行卷积,得到 6 个输出特征图,激活函数为 Sigmoid。 平均池化层1(Aver…...
图的遍历及连通性
文章目录 图的遍历及连通性程序设计程序分析图的遍历及连通性 【问题描述】 根据输入的图的邻接矩阵A,判断此图的连通分量的个数。 【输入形式】 第一行为图的结点个数n,之后的n行为邻接矩阵的内容,每行n个数表示。其中A[i][j]=1表示两个结点邻接,而A[i][j]=0表示两个结点无…...
DJ3-4 实时调度
目录 3.4.1 实现实时调度的基本条件 1. 提供必要的信息 2. 系统的处理能力强 3. 采用抢占式调度机制 4. 具有快速切换机制 3.4.2 实时调度算法的分类 1. 非抢占式调度算法 2. 抢占式调度算法 3.4.3 常用的几种实时调度算法 1. 最早截止时间优先 EDF(Ea…...
Oracle之PL/SQL游标练习题(三)
游标练习题目1、定义游标:列出每个员工的姓名部门名称并编程显示第10个到第20个记录2、定义游标:从雇员表中显示工资大于3000的记录,只要姓名、部门编号和工资,编程显示其中的奇数记录3、用游标显示所有部门编号与名称,…...
docker运行服务端性能监控系统Prometheus和数据分析系统Grafana
文章目录一、Prometheus的安装和运行1、使用docker拉取镜像2、创建prometheus.yml文件3、启动容器4、查看启动是否成功5、记录安装过程中出现的错误二、Grafana的安装和运行1、使用docker拉取镜像2、创建grafana3、运行grafana4、查看grafana运行日志5、登录grafana一、Prometh…...
【Linux】【应用层】多线程编程
一、线程创建 Linux 中的 pthread_create() 函数用来创建线程,它声明在<pthread.h>头文件中,语法格式如下: int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void *(*start_routine) (void *),void *arg);各个参数…...
GameFramework 框架详解之 如何接入热更框架HybridCLR
一.前言 HybridCLR是一个特性完整、零成本、高性能、低内存的近乎完美的c#热更新方案 GameFramework是一个非常出色完整的基于Unity引擎的游戏框架,里面包含了非常多的模块,封装非常完整。 以前市面上的热更大多数都是Lua为主,后来出了一个ILRuntime的C#热更框架,虽然性能…...
全国青少年软件编程(Scratch)等级考试二级考试真题2023年3月——持续更新.....
一、单选题(共25题,共50分) 1. 小猫的程序如图所示,积木块的颜色与球的颜色一致。点击绿旗执行程序后,下列说法正确的是?( ) A.小猫一直在左右移动,嘴里一直说着“抓到了”。 B.小猫会碰到球,然后停止。 C.小猫一直在左右移动,嘴里一直说着“别跑” D.小猫会碰到球,…...
HTML2.1列表标签
列表标签种类 无序列表 有序列表 自定义列表 使用场景:在列表中按照行展示关联性内容。 特点:按照行的形式,整齐显示内容。 一、无序列表 标签名说明ul无序列表整体,用于包裹li标签li表示无序列表的每一项,用于包…...
在 Flutter 多人视频通话中实现虚拟背景、美颜与空间音效
前言 在之前的「基于声网 Flutter SDK 实现多人视频通话」里,我们通过 Flutter 声网 SDK 完美实现了跨平台和多人视频通话的效果,那么本篇我们将在之前例子的基础上进阶介绍一些常用的特效功能,包括虚拟背景、色彩增强、空间音频、基础变声…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
