结合阿里云 FC 谈谈我对 FaaS 的理解

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"进入主题之前,先从背景简述下最近前端界的热点词汇 Serverless,其实,Serverless 这个概念在其他领域已经提出来很久了。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Serverless"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"概念"}]},{"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":"Serverless 直译为无服务器,代表一种"},{"type":"text","marks":[{"type":"strong"}],"text":"无服务器架构"},{"type":"text","text":"(也被称为“"},{"type":"text","marks":[{"type":"strong"}],"text":"无服务器计算"},{"type":"text","text":"”),并不表示不需要物理服务器,而是指不需要关注和管理服务器,直接使用服务即可,其实就是一种"},{"type":"text","marks":[{"type":"strong"}],"text":"服务外包"},{"type":"text","text":"或者说"},{"type":"text","marks":[{"type":"strong"}],"text":"服务托管"},{"type":"text","text":",这些服务由第三方供应商提供。"}]},{"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":"具体来说,Serverless 就是指服务端逻辑由开发者实现,运行在无状态的计算容器中,由"},{"type":"text","marks":[{"type":"strong"}],"text":"事件驱动"},{"type":"text","text":",完全"},{"type":"text","marks":[{"type":"strong"}],"text":"被第三方管理"},{"type":"text","text":",而业务层面的状态则记录在"},{"type":"text","marks":[{"type":"strong"}],"text":"数据库或存储资源"},{"type":"text","text":"中。"}]},{"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":"目前国内一些大型公司如阿里、腾讯、滴滴都已经将 Serverless 逐步在业务中落地(案例分享:"},{"type":"text","marks":[{"type":"strong"}],"text":"2020.06.19 ServerlessDays · China Online"},{"type":"text","text":" (https:\/\/cloud.tencent.com\/developer\/salon\/live-1224))。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Serverless 与 FaaS 的联系"}]},{"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":"Serverless = "},{"type":"text","marks":[{"type":"strong"}],"text":"FaaS + BaaS"},{"type":"text","text":" ,是目前界内比较公认的定义:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"FaaS(Function as a Service):函数即服务"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"负责"},{"type":"text","marks":[{"type":"strong"}],"text":"服务端业务逻辑场景"},{"type":"text","text":",需要开发者自己实现,服务的粒度比微服务更小,小到以函数为单位"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"事件驱动"},{"type":"text","text":"的 Serverless 服务,毫秒级弹性伸缩"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"无法进行内存或数据共享,是"},{"type":"text","marks":[{"type":"strong"}],"text":"无状态的"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"无需运维"},{"type":"text","text":",部署、运维等都由云平台提供"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"BaaS(Backend as Service):后端即服务"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/e1\/e139bf73ebf8d53dc3b244231163bb01.png","alt":"Image","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":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"负责"},{"type":"text","marks":[{"type":"strong"}],"text":"通用服务场景"},{"type":"text","text":",不需要开发者自己开发,由云厂商提供,比如数据库、身份验证、消息队列、对象存储等服务"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"是"},{"type":"text","marks":[{"type":"strong"}],"text":"有状态"},{"type":"text","text":"的"}]}]}]},{"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":"笔者认为,单看 FaaS 或者 BaaS,都是一种 Serverless ,只是一般我们完整的应用需要两者结合才能实现。"}]},{"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":"好,下面正式介绍 FaaS。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"FaaS"}]},{"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":"作为一个前端,我们平日里很难接触到服务器、运维方面的操作。假设现在给你一个任务,让你自己开发一个有前后端交互的应用,并从 0 到 1 进行部署,是不是觉得光靠自己根本搞不定,这个任务有点难。"}]},{"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":"传统应用的部署,我们需要做很多工作:准备服务器、配置环境、购买域名、配置 Nginx、……。应用发布之后,我们还要考虑运维的问题,线上监控,扩缩容,容灾等等等等。"}]},{"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":"现在,我们运用 FaaS 去开发部署的话,以上都不用考虑,只需要专注于业务逻辑开发即可,因为"},{"type":"text","marks":[{"type":"strong"}],"text":"其它一切都托管给 FaaS 平台"},{"type":"text","text":"帮我们处理了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"概念"}]},{"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":"FaaS  是无服务器计算的一种形式。通过 FaaS,可以快速构建任何类型的应用和服务,它具有开发敏捷特性、自动弹性伸缩能力、免运维和完善的监控设施。因此:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"开发者只需专注于业务逻辑开发,无需管理服务器、运行环境等 IT 基础设施"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"FaaS 平台会为我们准备好计算资源,以弹性、可靠的方式运行我们的代码,实现毫秒级"},{"type":"text","marks":[{"type":"strong"}],"text":"弹性伸缩"},{"type":"text","text":",轻松应对峰值压力"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用户只需根据函数的实际执行时间"},{"type":"text","marks":[{"type":"strong"}],"text":"按量付费"}]}]}]},{"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":"因此,相比传统开发模式,大大提高了开发和交付效率,是未来云服务发展的大趋势。自 2014 年始,在 AWS Lambda 之后,Google、IBM、Microsoft、阿里、腾讯、华为等国内外云厂商相继推出云函数计算平台 FaaS。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"快速创建 FaaS 应用"}]},{"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":"函数计算开发方式有很多种,比如:Fun 工具、函数计算 FC 平台、Serverless VScode、云开发平台。本文借助"},{"type":"text","marks":[{"type":"strong"}],"text":"阿里云函数计算平台"},{"type":"text","text":"(https:\/\/fc.console.aliyun.com\/fc\/overview\/cn-shanghai),通过其提供的模版快速创建、部署一个 Web 应用,向大家更清楚地展示 FaaS 是什么。"}]},{"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":"本文直接基于模版创建,用户也可以选择自己上传应用代码直接部署 Web 应用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/36\/362b67e94d10e17c0fcb906ef2f0916d.png","alt":"Image","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":"我们选择有前后端交互、数据增删改查等行为的 "},{"type":"text","marks":[{"type":"strong"}],"text":"Todo List 应用"},{"type":"text","text":",它是一个"},{"type":"text","marks":[{"type":"strong"}],"text":"前后端一体化"},{"type":"text","text":"(前后端代码共属一个项目中开发、调试、部署,高效且节省资源) FaaS 应用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/f3\/f36b11250edf862d1de5a882cd713ad2.png","alt":"Image","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":3},"content":[{"type":"text","text":"服务\/函数"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"服务"}]},{"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":"一个应用可以拆分为多个服务。从资源使用维度出发,一个服务可以由多个函数组成。先创建服务,再创建函数。"}]},{"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":"可以看到 TodoList 应用部署成功后创建好的服务,我们可以对该服务进行配置、删除、查看指标等操作,还可以对其下的函数进行配置、删除。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/bd\/bdea67ee47b9b1bfc961fd0041313fd7.png","alt":"Image","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":4},"content":[{"type":"text","text":"函数"}]},{"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":"函数是系统调度和运行的单位。函数必须从属于服务,同一个服务下可以有多个函数,同一个服务下的所有函数共享相同的设置,例如服务授权、日志配置,但彼此相互独立,互不影响。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"函数代码"}]},{"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":"FaaS 对"},{"type":"text","marks":[{"type":"strong"}],"text":"多种语言"},{"type":"text","text":"都有良好的支持性,比如阿里云支持 Node.js、Python、PHP、Java 等等,开发者可以使用自己熟悉的语言,根据平台提供的函数接口形式编写代码。这也意味着,团队协作时,大家可以利用多种语言混合开发复杂应用。"}]},{"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":"点击代码执行,可以看到这里有一个在线编辑器,里面就是模板生成的代码,可以在此处进行运行、调试。该应用前端页面用 React 实现,后端服务基于 Node 的 Express 框架。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/68\/68d719bef97752ed74d43ef48b60f116.png","alt":"Image","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":5},"content":[{"type":"text","text":"函数入口"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"template.yml"}]},{"type":"text","text":" 是我们的"},{"type":"text","marks":[{"type":"strong"}],"text":"函数信息配置文件"},{"type":"text","text":",告诉云厂商我们的代码入口函数、触发器类型等操作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/bc\/bcc99142295dfae848af66c8cfcfc2c5.webp","alt":"Image","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":"函数入口为 "},{"type":"codeinline","content":[{"type":"text","text":"src\/index.handler"}]},{"type":"text","text":" ,即 "},{"type":"codeinline","content":[{"type":"text","text":"src\/index.js"}]},{"type":"text","text":" 服务端代码文件中的 handler 方法,该文件代码如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const { Server } = require('@webserverless\/fc-express')\nconst express = require('express');\nconst fs = require('fs');\nconst path = require('path');\nconst bodyParser = require('body-parser');\n\n\/\/ initial todo list\nlet todos = [\n  {\n    id: '123',\n    text: 'Go shopping',\n    isCompleted: false,\n  },\n  {\n    id: '213',\n    text: 'Clean room',\n    isCompleted: true,\n  },\n];\n\n\nconst staticBasePath = path.join('public', 'build');\n\nconst app = express();\n\n\/\/ index.html\napp.all(\"\/\", (req, resp) => {\n  resp.setHeader('Content-Type', 'text\/html');\n  resp.send(fs.readFileSync('.\/public\/build\/index.html', 'utf8'));\n});\n\n\/\/ 静态资源文件:js、css、图片\n\/\/ static js resources  \napp.all('\/*.js', (req, resp) => {\n  const filePath = path.join(staticBasePath, req.path);\n  resp.setHeader('Content-Type', 'text\/javascript');\n  resp.send(fs.readFileSync(filePath, 'utf8'));\n});\n\n\/\/ static css resources\napp.all('\/*.css', (req, resp) => {\n  const filePath = path.join(staticBasePath, req.path);\n  resp.setHeader('Content-Type', 'text\/css');\n  resp.send(fs.readFileSync(filePath, 'utf8'));\n});\n\n\/\/ static svg resources\napp.all('\/*.svg', (req, resp) => {\n  const filePath = path.join(staticBasePath, req.path);\n  resp.setHeader('Content-Type', 'image\/svg+xml');\n  resp.send(fs.readFileSync(filePath, 'utf8'));\n});\n\n\/\/ static png resources\napp.all('\/*.png', (req, resp) => {\n  const filePath = path.join(staticBasePath, req.path);\n  resp.setHeader('Content-Type', 'image\/png');\n  resp.send(fs.readFileSync(filePath, 'utf8'));\n});\n\napp.all('\/manifest.json', (req, resp) => {\n  const filePath = path.join(staticBasePath, req.path);\n  resp.setHeader('Content-Type', 'application\/json');\n  resp.send(fs.readFileSync(filePath, 'utf8'));\n});\n\n\/\/ 增删改查对应的api接口\n\/\/ list api\napp.get('\/api\/listTodos', (req, resp) => {\n  resp.send(JSON.stringify(todos));\n});\n\n\/\/ create api\napp.get('\/api\/createTodo', (req, resp) => {\n  const { todo: todoStr } = req.query;\n  const todo = JSON.parse(todoStr);\n  todos.push({\n    id: todo.id,\n    text: todo.text,\n    isCompleted: todo.isCompleted,\n  });\n  resp.send(JSON.stringify(todos));\n});\n\n\/\/ update api\napp.get('\/api\/updateTodo', (req, resp) => {\n  const { todo: todoStr } = req.query;\n  const targetTodo = JSON.parse(todoStr);\n  const todo = todos.find((todo) => todo.id === targetTodo.id);\n  if (todo) {\n    todo.isCompleted = targetTodo.isCompleted;\n    todo.text = targetTodo.text;\n  }\n  resp.send(JSON.stringify(todos));\n});\n\n\/\/ remove api\napp.get('\/api\/removeTodo', (req, resp) => {\n  const { id } = req.query\n  \/\/ TODO: Implement methods to filter todos, filtering out item with the same id\n  \/\/ todos = todos.filter();\n  const todosIndex = todos.findIndex((todo) => todo.id === id);\n  if (todosIndex !== -1) {\n    todos.splice(todosIndex, 1);\n  } \n  resp.send(JSON.stringify(todos));\n});\n\nconst server = new Server(app);\n\n\/\/ 向外暴露了 http触发器入口\n\/\/ http trigger entry\nmodule.exports.handler = function(req, res, context) {\n  server.httpProxy(req, res, context);\n};\n"}]},{"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":"可以看到,我们不需要自己起服务,FaaS 平台会为我们管理。这个文件,有两个重要的部分:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1.函数入口 handler,也是 HTTP 触发器入口,下文会详细介绍"}]}]}]},{"type":"codeblock","attrs":{"lang":"typescript"},"content":[{"type":"text","text":"\/\/ http trigger entry\nmodule.exports.handler = function(req, res, context) {\n  server.httpProxy(req, res, context);\n};"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2.Web Service 和 API,通过路由调用相应的服务,比如请求路径为\"\/\"时,会返回 Web 应用的 Html 页面;请求\"\/api\/*\"时,调用接口返回数据"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"触发器"}]},{"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":"前面说过,FaaS 是一种"},{"type":"text","marks":[{"type":"strong"}],"text":"事件驱动"},{"type":"text","text":"的计算模型,即函数的执行是由事件驱动的,没有事件触发,函数就不运行。与传统开发模式不同,函数不需要自己启动一个服务去监听数据,而是通过绑定一个(或者多个)触发器。"}]},{"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"}],"text":"触发器"},{"type":"text","text":"就是触发函数执行的方式,我们需要为函数创建指定的触发器。"}]},{"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":"FaaS 应用的触发器有多种(不同云厂商的触发器会有所区别),但基本都支持 HTTP、对象存储、定时任务、消息队列等触发器,其中 HTTP 触发器是最常见的。"}]},{"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":"以阿里云函数计算为例,介绍几个代表类型:"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"触发器类型"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"embedcomp","attrs":{"type":"table","data":{"content":"
名称描述
HTTP 触发器1.HTTP 触发器通过发送 HTTP 请求触发函数执行,主要适用于快速构建 Web 服务等场
2.HTTP 触发器支持 HEAD、POST、PUT、GET 和 DELETE 方式触发函数
3.可以通过绑定自定义域名为 HTTP 函数映射不同的 HTTP 访问路径
4.开发人员可以快速使用 HTTP 触发器搭建 Web Service和 API
OSS 触发器(对象存储)1.OSS 事件能触发相关函数执行,实现对 OSS 中的数据进行自定义处理
日志服务触发器1.当日志服务定时获取更新的数据时,通过日志服务触发器,触发函数消费增量的日志数据,并完成对数据的自定义加工
定时触发器1.在指定的时间点自动触发函数执行
API 网关触发器1.API 网关作为事件源,当有请求到达后端服务设置为函数计算的 API 网关时,API 网关会触发函数的执行。函数计算会将执行结果返回给 API 网关
2.与 HTTP 触发器类似,可应用于搭建 Web 应用。相较于 HTTP 触发器,您可以使用 API 网关进行 IP 白名单或黑名单设置等高级操作"}}},{"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":"开发者在调试时,如果不配置触发器,也可以使用控制台、命令行工具 或者 SDK 等方式直接调用函数执行。"}]},{"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":"我们点开 TodoList 的触发器,可以看到创建的 "},{"type":"text","marks":[{"type":"strong"}],"text":"HTTP 触发器"},{"type":"text","text":",WEB 用户通过 HTTP 请求即可触发函数的执行。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/07\/079a2c3a759a99203e26734afddd7597.webp","alt":"Image","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":"注意这里的提示语:打开链接,会下载一个 Html 附件,这时我们打开,因为找不到静态资源文件,应用不能正常运行。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/8e\/8e15b415089a14b47b9f430b8a3d9db4.webp","alt":"Image","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":"可以点击"},{"type":"text","marks":[{"type":"strong"}],"text":"自定义域名"},{"type":"text","text":"去用平台为我们创建的"},{"type":"text","marks":[{"type":"strong"}],"text":"临时域名"},{"type":"text","text":"打开:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/9f\/9fd0d0f2e8423edc4ae241fb74a65cbe.png","alt":"Image","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":"可以看到,页面和功能都正常了。我们查看、新增、更新、删除,在控制台里可以看到发起的请求和返回结果"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/1f\/1f003682f4f17b015e6db7357c73c3c3.png","alt":"Image","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":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/da\/da09735ffcd524c5d2ff5e73d05c3382.webp","alt":"Image","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":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/21\/21a106b9c614d1dc31034408bf61c36b.png","alt":"Image","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":4},"content":[{"type":"text","text":"HTTP 触发器"}]},{"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":"该应用 "},{"type":"text","marks":[{"type":"strong"}],"text":"HTTP 触发器的入口函数"},{"type":"text","text":"形式如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"\/\/ http trigger entry\nmodule.exports.handler = function(req, res, context) {\n  server.httpProxy(req, res, context);\n};"}]},{"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"}],"text":"配置 HTTP 触发器的函数可以通过 HTTP 请求被触发执行。此时函数可以看做一个 Web Server,对 HTTP 请求进行处理,并将处理结果返回给调用端"},{"type":"text","text":"。"}]},{"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":"访问 Html 页面、请求静态资源文件,以及请求接口,都是通过 HTTP 请求去触发相应函数的执行。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以在这里进行调试:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/92\/922940f0dee33f941d7c8890a5b914f6.png","alt":"Image","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":3},"content":[{"type":"text","text":"FaaS 框架"}]},{"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":"目前市面上已经有一些较为成熟的开源 FaaS 框架,比如 OpenFaaS、Funktion、Kubeless、Fission等等,本文向大家介绍阿里云今年正式发布的 "},{"type":"text","marks":[{"type":"strong"}],"text":"Midway FaaS框架"},{"type":"text","text":" (https:\/\/github.com\/midwayjs\/midway),它是用于构建 Node.js 云函数的 Serverless 框架,它提供了函数的本地"},{"type":"text","marks":[{"type":"strong"}],"text":"开发、调用、测试整个链路"},{"type":"text","text":"。它可以开发新的 Serveless 应用,也提供方案将传统应用迁移至各云厂商的云函数。阿里内部已经使用一年多了。"}]},{"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":"我们可以运用脚手架 "},{"type":"codeinline","content":[{"type":"text","text":"@midwayjs\/faas-cli"}]},{"type":"text","text":" 提供的能力在"},{"type":"text","marks":[{"type":"strong"}],"text":"本地快速创建、调试、Mock、部署"},{"type":"text","text":"一个 FaaS 应用。Serverless 有一个很大的"},{"type":"text","marks":[{"type":"strong"}],"text":"弊端"},{"type":"text","text":",就是"},{"type":"text","marks":[{"type":"strong"}],"text":"和云服务商平台强绑定"},{"type":"text","text":",但是 Midway Serverles 是防平台锁定的,它能"},{"type":"text","marks":[{"type":"strong"}],"text":"一套代码能够运行在不同的平台和运行时之上"},{"type":"text","text":",Midaway Faas 的部署可以"},{"type":"text","marks":[{"type":"strong"}],"text":"跨云厂商"},{"type":"text","text":",默认部署到阿里云 FC,我们也可以修改部署到其它平台,如腾讯云 SCF、AWS Lambda。"}]},{"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":"Midway FaaS 体系也与云工作台进行了结合,使用了和本地同样的能力,这里选择登录 "},{"type":"text","marks":[{"type":"strong"}],"text":"阿里云开发平台"},{"type":"text","text":" (https:\/\/workbench.aliyun.com\/application),用示例库模版再次创建一个 TodoList 应用进行演示,只不过这个是用 Midway FaaS 构建的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/dc\/dc37299818000dbe150cb670ede10816.webp","alt":"Image","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"}],"text":"代码目录结构"},{"type":"text","text":"可以简单抽取为:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"|-- src\n|  |-- apis \/\/函数代码\n|    |-- config \/\/针对不同环境创建配置文件\n|    |-- configuration.ts \/\/扩展能力配置\n|    |-- index.ts \/\/ 函数代码入口文件,里面包括多个函数\n|  |-- components \/\/ 前端组件\n|  |-- index.tsx \/\/ 前端页面入口文件(该应用前端基于React,若是Vue,则是App.vue)\n|-- f.yml \/\/ 函数信息配置文件\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"f.yml 配置文件"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"service: serverless-hello-world\n\n\/\/ 服务提供商\nprovider:\n  name: aliyun\n  runtime: nodejs10 \/\/运行时环境及版本信息\n\n\/\/ 函数具体信息(包括函数入口、触发器等等)\nfunctions:\n  render:\n    handler: render.handler \n    events:\n      - apigw:\n          path: \/*\n  list:\n    handler: todo.list \n    events:\n      - apigw:\n          path: \/api\/list\n  update:\n    handler: todo.update\n    events:\n      - apigw:\n          path: \/api\/update\n  remove:\n    handler: todo.remove\n    events:\n      - apigw:\n          path: \/api\/remove\n  add:\n    handler: todo.add\n    events:\n      - apigw:\n          path: \/api\/add\n          \n\/\/ 构建的配置信息\npackage:\n  include:\n    - build \/\/打包目录\n  artifact: code.zip \/\/打包名称\n"}]},{"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":"函数代码中一个函数对应一个 API 接口:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/cc\/cc1d70fa4a36e07c5932fbfc37b3460e.png","alt":"Image","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":"安装依赖后,我们 "},{"type":"codeinline","content":[{"type":"text","text":"npm run dev"}]},{"type":"text","text":",阿里云为我们创建了一个临时域名用于调试:"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/86\/86e650e931f4c29eb573db4e68d54c92.png","alt":"Image","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":"可以看到请求的这些资源和接口数据:"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/a8\/a89810f17069c666e4f0fbfe702c4d7d.png","alt":"Image","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":"一键部署,非常方便。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/45\/4520dfa1c31d90dcddd7d607b8be11fb.webp","alt":"Image","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":3},"content":[{"type":"text","text":"收费标准"}]},{"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":"传统应用我们的服务是一直占用资源的,而 FaaS 在资源空闲时不收费,"},{"type":"text","marks":[{"type":"strong"}],"text":"按需付费"},{"type":"text","text":",可以大大节省开支。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"收费标准:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"调用函数次数"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"函数运行时间"}]}]}]},{"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":"因为每月都有免费额度,所以在个人日常使用时基本不需要付费。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/54\/5452b7b101bce31afdb70d880a785e3d.webp","alt":"Image","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":"(PS:但还是要特别注意,部署的应用不用时一定要及时下线,否则可能会收取费用,还有开通的服务、功能也一定要仔细留意一下收费标准,比如可能想解决冷启动的问题,会开通预留实例功能,如果我们不用的话,一定要注意手动释放,否则即使它没有执行任何请求,也会从启动开始不断收费,费用可不小)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"冷启动"}]},{"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":"再说说 FaaS 目前备受关注的一个问题——"},{"type":"text","marks":[{"type":"strong"}],"text":"冷启动"},{"type":"text","text":"。"}]},{"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":"FaaS 中的函数"},{"type":"text","marks":[{"type":"strong"}],"text":"首次调用"},{"type":"text","text":"、"},{"type":"text","marks":[{"type":"strong"}],"text":"更新函数或长时间未调用时重新调用函数"},{"type":"text","text":"时,平台会初始化一个函数实例,这个过程就是"},{"type":"text","marks":[{"type":"strong"}],"text":"冷启动"},{"type":"text","text":",平均耗时在几百毫秒。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"延迟问题"}]},{"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":"FaaS 因为冷启动,不能立即调用函数,调用延迟会给应用性能带来影响,针对冷启动的延迟问题,各大云服务商非常关注,正在想办法不断优化。"}]},{"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":"与冷启动相呼应的是热启动,"},{"type":"text","marks":[{"type":"strong"}],"text":"热启动"},{"type":"text","text":"指函数调用时不用重新创建新的函数实例,而是直接复用之前的函数实例。因为 FaaS 函数若在一段时间内没有被事件触发运行,云服务商就会回收运行函数的容器资源,销毁函数实例,所以,在未被回收的这段时间内再次调用函数就是热启动;销毁后,重新创建就是冷启动。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"延迟原因"}]},{"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":"冷启动具体做了哪些操作呢?以阿里云为例,大致包括了调度实例、下载解压代码、启动容器、启动运行时,这一过程结束后,函数才开始执行。所以冷启动的启动消耗时间受到很多因素的影响:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"编程语言"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有专门研究对比,不同语言的冷启动时间不同"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"代码大小"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这个过程在冷启动过程中相对比较耗时,可能几十毫秒,也可能几秒,看代码体积大小"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"容器创建"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这个过程的耗时取决于云服务商"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"配置等"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"如何优化"}]},{"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":"各大云厂商都已经有了一些优化方案的最佳实践,需要开发者和云厂商共同努力:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"减少代码体积:"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"开发者可以通过精简代码,删除无用依赖,加速下载函数代码过程"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"比如腾讯云对代码做了两级的缓存,可以有效降低下载代码时间"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"资源复用,缩短函数执行时间"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"选择冷启动时间较少的语言"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"选择合适的内存:函数内存越大,冷启动表现越优"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"避免不必要的配置"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"降低冷启动频率"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用定时触发器定时访问函数,这样可以防止函数实例一段时间没被使用被销毁"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用 initializer 函数入口,函数计算会异步调用初始化接口,消除初始化用户代码的时间"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"预留实例"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"执行时长"}]},{"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":"FaaS 还有一个局限性,就是平台会限制函数的执行时间,超出时间后执行代码的进程会被强行销毁,所以 FaaS 不适合长时间运行的应用。例如 AWS Lambda 函数不允许运行超过 15 分钟(以前只有 5 分钟),如果超过就会中断。使用时,应该根据自己的预期执行时间来设置超时值,防止函数的运行时间超出预期,并且建议调用函数的 Client 端的 timeout 要稍稍大于函数设置的 timeout,这样才能防止执行环境不会意外退出。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"FaaS 工作流程"}]},{"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":"相信大家读到这里,应该差不多可以明白 FaaS 的工作流程了,我们总结一下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"开发者编写"},{"type":"text","marks":[{"type":"strong"}],"text":"函数代码"},{"type":"text","text":",可以在线编辑或者本地上传,完成后,FaaS 平台为我们部署应用,创建"},{"type":"text","marks":[{"type":"strong"}],"text":"函数服务"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"客户端通过设置的"},{"type":"text","marks":[{"type":"strong"}],"text":"触发器"},{"type":"text","text":",通知"},{"type":"text","marks":[{"type":"strong"}],"text":"函数服务"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"若存在"},{"type":"text","marks":[{"type":"strong"}],"text":"函数实例"},{"type":"text","text":",则直接在该执行环境中调用函数;没有,则先经过"},{"type":"text","marks":[{"type":"strong"}],"text":"冷启动"},{"type":"text","text":"(调度实例、下载代码、启动实例、启动运行时),再执行函数"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"函数根据用户请求量动态扩容响应请求,将内容返回给用户。函数执行完后,若一段时间内无事件触发,函数实例就会被销毁,FaaS 应用快速缩容到 0"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/02\/02b8cd00917911a1c4e3ca0c7c5df662.webp","alt":"Image","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":"对前端的影响"}]},{"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":"Serverless 现在这么热,它对前端到底有什么影响呢?"}]},{"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":"整个实践下来发现,FaaS 帮我们前端扩展了能力边界,作为前端,我们自己一个人也能快速完成前后端开发以及部署工作,完全不用关心服务器以及运维方面我们不擅长的问题。前端也有机会参与服务端业务逻辑开发,更深入业务,创造更大的价值。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"结语"}]},{"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":"本文结合阿里云 FC、Midway FaaS 框架快速创建 FaaS 应用的实践,向大家展示了什么是 FaaS,FaaS 的工作流程,优缺点,展现了 FaaS 颠覆传统开发模式的魅力。现在 FaaS 的应用场景非常广泛,Web 应用及小程序等移动应用、AI 及机器学习、物联网、实时数据处理、……、等等。Serverless 时代,生产效率大大提高,每个人都有更多机会创造无限可能,让我们一起为未来加油!"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"horizontalrule"},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"头图:Unsplash"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"作者:雪霁"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文:https:\/\/mp.weixin.qq.com\/s\/cZm1sdMB7Cid48KD-0mpkA"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文:结合阿里云 FC 谈谈我对 FaaS 的理解"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"来源:政采云前端团队 - 微信公众号 [ID:Zoo-Team]"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"转载:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。"}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章