其他
资源成本双优化!看Serverless颠覆编程教育的创新实践
我们先将 Serverless 这个词拆开来看。Server,大家都知道是服务器的意思,说明 Serverless 解决的问题范围在服务端。Less,大家肯定也知道它的意思是较少的。那么 Serverless 连起来,再稍加修饰,那就是较少的关心服务器的意思。
2020 年注定是不平凡的一年,疫情期间,多少家企业如割韭菜般倒下,又有多少家企业如雨后春笋般茁壮成长,比如在线教育行业。
屏幕一侧写代码,执行代码,另一侧显示运行结果。
根据题目编写的代码都是代码块,每道题的代码量不会很大。
运行代码的速度要快。
支持多种编程语言。
能支撑不可预计的流量洪峰冲击。
但是 Java 类中的方法固然只能是 Java 代码,而 FC 中的函数可以设置不同语言的 Runtime 来运行不同的编程语言:
这个结构理解清楚之后,我们来看看如何调用 FC 的函数,这里会引出一个触发器的概念。我们最常使用的 HTTP 请求协议其实就是一种类型的触发器,在 FC 里称为 HTTP 触发器,除了 HTTP 触发器以外,还提供了 OSS (对象存储)触发器、SLS(日志服务)触发器、定时触发器、MNS 触发器、 CDN 触发器等。
从上图可以大概理解,我们可以通过多种途径调用 FC 中的函数。举例两个场景,比如每当我在指定的 OSSBucket 的某个目录下上传一张图片后,就可以触发 FC 中的函数,函数的逻辑是将刚刚上传的图片下载下来,然后对图片做处理,然后再上传回 OSS 。再比如向 MNS 的某个队列发送一条消息,然后触发FC中的函数来处理针对这条消息的逻辑。
给函数设置并发实例数,假如设置为 3 ,那么有三个请求进来时,该函数只启一个实例,但是会启三个线程来运行逻辑。
线程数达到上限后,会再拉起一个函数实例。
工作量和灵活性:我们只需要关注在如何执行代码的业务逻辑上,如果要加新语言,只需要创建一个对应语言 Runtime 的 FC 函数即可。
高可用:多线程运行业务逻辑和多实例运行业务逻辑两层高可用保障,并且函数实例的扩缩完全都是 FC 自动处理,不需要研发和运维同学做任何配置。
成本优化:当没有请求的时候,函数实例是不会被拉起的,此时也不会计费,所以在流量低谷期或者夜间时,整个 FC 的成本消耗是非常低的。可以做到函数实例个数、计费粒度和流量完美的贴合。
下面以运行 Python 代码为例来看看如何用 FC 实现 Python 在线编程 Demo 。
运行环境:这个很好理解,这里选择 Python3 。
函数实例类型:这里有弹性实例和性能实例两种,前者最大支持 2C 3G 规格的实例,后者支持更大的规格,最大到 8C 16G 。
函数入口:详细参见文档-HTTP 触发器认证方式:anonymous 为不需要鉴权, function 是需要鉴权的:
https://help.aliyun.com/document_detail/74756.html?spm=a2c4g.11186623.6.572.195359cdselnzR
# -*- coding: utf-8 -*-
import logging
import urllib.parse
import time
import subprocess
def handler(environ, start_response):
context = environ['fc.context']
request_uri = environ['fc.request_uri']
for k, v in environ.items():
if k.startswith('HTTP_'):
pass
try:
request_body_size = int(environ.get('CONTENT_LENGTH', 0))
except (ValueError):
request_body_size = 0
# 获取用户传入的code
request_body = environ['wsgi.input'].read(request_body_size)
codeStr = urllib.parse.unquote(request_body.decode("GBK"))
# 因为body里的对象里有code和input两个属性,这里分别获取用户code和用户输入
codeArr = codeStr.split('&')
code = codeArr[0][5:]
inputStr = codeArr[1][6:]
# 将用户code保存为py文件,放/tmp目录下,以时间戳为文件名
fileName = '/tmp/' + str(int(time.time())) + '.py'
f = open(fileName, "w")
# 这里预置引入了time库
f.write('import time \r\n')
f = open(fileName, "a")
f.write(code)
f.close()
# 创建子进程,执行刚才保存的用户code py文件
p = subprocess.Popen("python " + fileName, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, encoding='utf-8')
# 通过标准输入传入用户的input输入
if inputStr != '' :
p.stdin.write(inputStr + "\n")
p.stdin.flush()
# 通过标准输出获取代码执行结果
r = p.stdout.read()
status = '200 OK'
response_headers = [('Content-type', 'text/plain')]
start_response(status, response_headers)
return [r.encode('UTF-8')]
从前端传入代码片段,格式是字符串。
在 FC 函数中获取到传入的代码字符串,截取 code 内容和 input 的内容。因为这里简单实现了 Python 中 input 交互的能力。
将代码保存为一个 Python 文件,以时间戳为文件名,保存在 FC 函数的 /tmp 目录下。(每个FC函数都有独立的 /tmp 目录,可以存放临时文件)
然后在文件中追加了引入 time 库的代码,应对 sleep 这种交互场景。
通过 subprocess 创建子进程,以 Shell 的方式通过 Python 命令执行保存在 /tmp 目录下的 Python 文件。如果有用户输入的信息,则通过标准输入输出写入子进程。
最后读取执行结果返回给前端。
这个方法就是调用 FC 中的 PythonRuntime 函数,将前端页面的代码片段传给该函数。这里处理 input 交互的思路是,扫描整个代码片段,以包含 input 代码为标识将整个代码段分成多段。没有包含 input 代码的直接送给 FC 函数执行,包含 input 代码的,请求用户的输入,然后代码片段带着用户输入的信息一起送给 FC 函数执行。
这篇文章洋洋洒洒给大家介绍了 Serverless ,阿里云的 Serverless 产品函数计算(FC)以及基于函数计算(FC)实现的在线编程系统的Demo。大家应该有所体感,基于函数计算(FC)实现在线编程系统时,研发同学只需要专注在如何执行由前端传入的代码即可,整个 Server 端的各个环节都不需要研发同学和运维同学去关心,基本体现了 Serverless 的精髓。