背景

某一客户想要将现有应用从虚拟机上部署改造成Function化运行。在使用Huaweicloud FunctionGraph 进行代码改造测试时发现了一些比较好玩的东西,这里记录下过程和解决思路。客户线下运行的是python flask 应用框架,这里只实现了2个简单的查询和入库请求,逻辑是比较简单的,但如果直接通过将flask包通过依赖配置在Functiongraph上运行时就会遇到如下图的报错。

functiongraph flask

解析

其实图上的报错内容 ValueError: signal only works in main thread of the main interpreter 已经交代的很明白了,flask 默认会在本地运行一个5000端口的web监听,这是一个无论用户访问与否都不会停止运行的程序,而无论是AWS Lambda还是其他云厂商的函数应用逻辑都是按需运行,最终客户访问完后就停止了,所以才会按调用量 + 资源用量进行付费。

Flask application is meant to run for a long period of time and is always kept alive whereas Lambda is meant to run only for a short period of time and their respective interface and how they work are different.

看到这里后其实已经有思路了,有以下2种解决方法:

  1. 将应用改造成容器化应用,运行在k8s容器化平台,无论哪家云厂商的 k8s 发行版上都可以;
  2. 将函数计算实现长监听;

通过网上查询相关信息发现第2种方式在AWS Lambda上已实可以通过 aws-wsgi 实现,安装完成后,对应的flask代码需要改造成类似如下即可:

 1import awsgi
 2from flask import (
 3    Flask,
 4    jsonify,
 5)
 6
 7app = Flask(__name__)
 8
 9
10@app.route('/')
11def index():
12    return jsonify(status=200, message='Hello Flask!')
13
14
15def handler(event, context):
16    return awsgi.response(app, event, context)

How to run Python Flask application in AWS Lambda

最后通过咨询华为云FunctionGraph研发人员了解到华为内部也在规划以同样的方式实现应用的长监听。