函数计算目前原生支持的开发语言有 nodejs, python, java, php 和 c#, 在实现这些开发语言 runtime 的时候, 函数计算开发团队花了很大的精力去让各自语言的传统应用能够简单快速迁移到函数计算平台:
nodejs
开发函数计算的正确姿势——移植 Express
python , 支持 WSGI 协议的框架可以一键迁移到函数计算
部署基于 python wsgi web 框架的工程到函数计算 十分钟上线-在函数计算上部署基于django开发的个人博客系统 java
Java Http 触发器极速迁移传统 Spring 应用
php
一元建站-基于函数计算 + wordpress 构建 serverless 网站
C#
十分钟上线-基于函数计算开发 Restful web api & asp.net core web app
如上述所列的各自语言的传统应用迁移到函数计算的迁移方案, 虽然已经足够简单, 但是还是需要去理解一下函数计算的接口以及各自语言在函数计算环境中运行起来的原理, 比如 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 import tornado.ioloop import tornado.web import os class MainHandler(tornado.web.RequestHandler): def get(self): rid = self.request.headers.get('x-fc-request-id',None) print("FC Invoke Start RequestId: " + str(rid));
# your logic self.write("GET: Hello world") print("FC Invoke End RequestId: " + str(rid));
def post(self): rid = self.request.headers.get('x-fc-request-id',None) print("FC Invoke Start RequestId: " + str(rid));
# your logic self.write("GET: Hello world") print("FC Invoke End RequestId: " + str(rid));
def make_app(): return tornado.web.Application([ (r"/.*", MainHandler), ]) if name == "main": app = make_app() port = os.environ.get("FC_SERVER_PORT", "9000") app.listen(int(port)) tornado.ioloop.IOLoop.current().start() 本地安装第三方包 tornado
然后编写一个具有可执行权限的名字为bootstrap (注:#!/bin/bash注释是必需的)文件启动上面代码的 http server:
#!/bin/bash python server.py go 基于custom runtime 打造 golang runtime
nodejs 'use strict';
var express = require('express');
var app = express();
var crypto = require('crypto');
app.post(/.*/, function (req, res) { var rid = req.headers["x-fc-request-id"];
console.log(FC Invoke Start RequestId: ${rid});
// your logic, for example, get hash var secret = 'abcdefg';
var hash = crypto.createHmac('sha256', secret) .update('I love cupcakes') .digest('hex');
// c0fa1bc00531bd78ef38c628449c5102aeabd49b5dc3a2a516ea6ea959d6658e console.log(hash);
res.send(hash);
console.log(FC Invoke End RequestId: ${rid});
});
var port = process.env.FC_SERVER_PORT || 9000 app.listen(port, function () { console.log("FunctionCompute custom-nodejs runtime inited.");
});
app.timeout = 0;
// never timeout app.keepAliveTimeout = 0;
// keepalive, never timeout 本地安装第三方包 express
然后编写一个具有可执行权限的名字为bootstrap (注:#!/bin/bash注释是必需的)文件启动上面代码的 http server:
#!/bin/bash node server.js php 基于custom runtime + nginx + php-fpm 运行 wordpress:customruntime-php
.NETCORE CSharp .Net Core 2.1 MVC Web应用迁移到函数计算 custom runtime
【linux内核sha256,linux 计算sha256】教程同样适用于 .netcore 3.0