全部产品
云市场

函数计算 Custom Runtime 使用集锦

更新时间:2020-02-11 17:54:27

前言

函数计算目前原生支持的开发语言有 nodejs, python, java, php 和 c#, 在实现这些开发语言 runtime 的时候, 函数计算开发团队花了很大的精力去让各自语言的传统应用能够简单快速迁移到函数计算平台:

如上述所列的各自语言的传统应用迁移到函数计算的迁移方案, 虽然已经足够简单, 但是还是需要去理解一下函数计算的接口以及各自语言在函数计算环境中运行起来的原理, 比如 python, 用户需要理解 WSGI 协议, 然后才编写一个符合要求的入口函数。 为了彻底解放生产力, Custom Runtime 应运而生, Custom Runitme 可以解决以下两个重要需求:

  • 可以随心所欲持定制个性化语言执行环境(例如 golang、lua、ruby)以及各种语言的小版本(例如python3.7、Nodejs12)等,打造属于自己的自定义runtime

  • 现有的 web 应用或基于传统开发 web 项目基本不用做任何改造,即可将项目一键迁移到函数计算平台

用户要实现一个最简单的 Custom runtime,只要符合以下两条:

  • 创建一个http server,监听在固定端口(端口可以读取环境变量 FC_SERVER_PORT,默认为 9000)

  • http server 需要在 15s 内完成启动

接下来, 我们梳理一下基于 Custom Runtime 一键迁移案例。

custom 实现注意细节:

  • Custom Runtime 启动的服务一定监听 0.0.0.0:9000 或者 *:9000 端口,不用使用127.0.0.1:9000, 会导致请求超时。{“ErrorCode”:”FunctionNotStarted”,”ErrorMessage”:”The CA’s http server cannot be started:ContainerStartDuration:25000000000. Ping CA failed due to: dial tcp 21.0.5.7:9000: getsockopt: connection refused Logs : 2019-11-29T09:53:30.859837462Z Listening on port 9000\r\n”}

  • Custom Runtime 的 bootstrap 一定需要添加 #!/bin/bash,不然会遇见如下错误{“ErrorCode”:”CAExited”,”ErrorMessage”:”The CA process either cannot be started or exited:ContainerStartDuration:25037266905. CA process cannot be started or exited already: rpc error: code = 106 desc = ContainerStartDuration:25000000000. Ping CA failed due to: dial tcp 21.0.7.2:9000: i/o timeout Logs : 2019-11-29T07:27:50.759658265Z panic: standard_init_linux.go:178: exec user process caused \”exec format error\”

  • bootstrap 一定需要可执行权限

  • bootstrap 代码一定要执行到 http server 启动成功的逻辑, 不能被前面的逻辑阻塞, 比如启动server之前, 尝试连接一个不可达的数据库,造成启动时间 timeout

  • http server 的实现 connection keep alive, request timeout 至少10分钟以上

案例

java

Serverless 实战 —— 快速搭建 SpringBoot 应用

Serverless 实战 —— 移植 spring-petclinic 到函数计算

python

  1. import tornado.ioloop
  2. import tornado.web
  3. import os
  4. class MainHandler(tornado.web.RequestHandler):
  5. def get(self):
  6. rid = self.request.headers.get('x-fc-request-id',None)
  7. print("FC Invoke Start RequestId: " + str(rid));
  8. # your logic
  9. self.write("GET: Hello world")
  10. print("FC Invoke End RequestId: " + str(rid));
  11. def post(self):
  12. rid = self.request.headers.get('x-fc-request-id',None)
  13. print("FC Invoke Start RequestId: " + str(rid));
  14. # your logic
  15. self.write("GET: Hello world")
  16. print("FC Invoke End RequestId: " + str(rid));
  17. def make_app():
  18. return tornado.web.Application([
  19. (r"/.*", MainHandler),
  20. ])
  21. if __name__ == "__main__":
  22. app = make_app()
  23. port = os.environ.get("FC_SERVER_PORT", "9000")
  24. app.listen(int(port))
  25. tornado.ioloop.IOLoop.current().start()

本地安装第三方包 tornado

然后编写一个具有可执行权限的名字为bootstrap (注:#!/bin/bash注释是必需的)文件启动上面代码的 http server:

  1. #!/bin/bash
  2. python server.py

go

基于custom runtime 打造 golang runtime

nodejs

  1. 'use strict';
  2. var express = require('express');
  3. var app = express();
  4. var crypto = require('crypto');
  5. app.post(/.*/, function (req, res) {
  6. var rid = req.headers["x-fc-request-id"];
  7. console.log(`FC Invoke Start RequestId: ${rid}`);
  8. // your logic, for example, get hash
  9. var secret = 'abcdefg';
  10. var hash = crypto.createHmac('sha256', secret)
  11. .update('I love cupcakes')
  12. .digest('hex');
  13. // c0fa1bc00531bd78ef38c628449c5102aeabd49b5dc3a2a516ea6ea959d6658e
  14. console.log(hash);
  15. res.send(hash);
  16. console.log(`FC Invoke End RequestId: ${rid}`);
  17. });
  18. var port = process.env.FC_SERVER_PORT || 9000
  19. app.listen(port, function () {
  20. console.log("FunctionCompute custom-nodejs runtime inited.");
  21. });
  22. app.timeout = 0; // never timeout
  23. app.keepAliveTimeout = 0; // keepalive, never timeout

本地安装第三方包 express

然后编写一个具有可执行权限的名字为bootstrap (注:#!/bin/bash注释是必需的)文件启动上面代码的 http server:

  1. #!/bin/bash
  2. node server.js

php

基于custom runtime + nginx + php-fpm 运行 wordpress:customruntime-php

.NETCORE CSharp

.Net Core 2.1 MVC Web应用迁移到函数计算 custom runtime

教程同样适用于 .netcore 3.0