华为云函数工作流 FunctionGraph 写一个简单 HTTP 触发器函数的实践

举报
yd_285284254 发表于 2026/10/28 13:20:24 2026/10/28
【摘要】 很多内部小接口并不值得单独买一台常驻云服务器。查询一段配置、做健康检查、把一次表单提交收成一条记录,这类请求量不稳定、逻辑又很短的接口,更适合放到函数工作流 FunctionGraph 上:没有调用时不计运行时长,有请求时由 HTTP 触发器拉起函数并返回响应。下面按控制台的真实顺序,写一个只做参数校验和回显的 Python 函数,骨架可以直接换成自己的业务。 先确认用的是 HTTP 函数函...

很多内部小接口并不值得单独买一台常驻云服务器。查询一段配置、做健康检查、把一次表单提交收成一条记录,这类请求量不稳定、逻辑又很短的接口,更适合放到函数工作流 FunctionGraph 上:没有调用时不计运行时长,有请求时由 HTTP 触发器拉起函数并返回响应。下面按控制台的真实顺序,写一个只做参数校验和回显的 Python 函数,骨架可以直接换成自己的业务。

先确认用的是 HTTP 函数

函数工作流里有两类函数。事件函数靠定时器、对象存储、消息通知等事件拉起,入口参数是各服务自己的事件结构。HTTP 函数专门接收 HTTP h��求,创建完成后就会有调用地址,不必再单独买一台云服务器,也不必先学完整的网关配置。本文只写 HTTP 函数。

打开函数工作流控制台,进入「函数」列表,选择「创建函数」,类型选 HTTP 函数,不要选事件函数。运行时选择 Python 3.9。Python 3.6 已不适合新函数,官方依赖和示例都在往 3.9 及更新版本收。内存先用 128 MB,执行超时设为 3 秒。函数名用业务前缀,例如 http_echo_demo,避免以后列表里全是 test、demo1 这类分不清用途的名字。

执行入口填 index.handler。这表示平台去加载文件 index.py,并调用其中名为 handler 的函数。入口和文件名必须一致:入口是 index.handler 时,在线编辑里的文件就要是 index.py;如果改成 main.handler,文件也要改成 main.py。两边不一致时,测试会报找不到模块,日志里看不到你的业务打印,容易误以为是触发器没配对。

请求在 event 里长什么样

HTTP 触发器把一次请求装进字典交给 handler,签名是 handler(event, context)。和定时触发器相比,这里要读的是方法、路径、查询参数和请求体:

  • 方法在 httpMethod,取值如 GET、POST。
  • 查询参数在 queryStringParameters。调用方没带任何参数时,这个字段可能是空值,而不是空字典,取之前要先兜底。
  • 请求体在 body,通常是字符串。JSON 要自己解析。
  • 如果调用方或平台用了 Base64,以 isBase64Encoded 为准,为真时要先解码再解析。

返回值不要只 return 一段普通字符串。平台认的是一个字典,里面至少有 statusCode 和 body。body 必须已经是字符串,业务字典要先序列化。响应头建议写上 Content-Type,并带上 charset=utf-8,否则部分客户端里的中文会乱码。序列化时使用 ensure_ascii=False,响应里就是中文,而不是一长串转义。

把下面的代码保存为 index.py:

import json

def handler(event, context):
    event = event or {}
    method = (event.get("httpMethod") or "GET").upper()
    query = event.get("queryStringParameters") or {}
    name = str(query.get("name") or "").strip()
    if method != "GET":
        return _resp(405, {"error": "only GET is allowed"})
    if not name:
        return _resp(400, {"error": "missing query name"})
    if len(name) > 32:
        return _resp(400, {"error": "name too long"})
    return _resp(200, {"message": "hello", "name": name})

def _resp(code, payload):
    return {
        "statusCode": code,
        "isBase64Encoded": False,
        "headers": {"Content-Type": "application/json; charset=utf-8"},
        "body": json.dumps(payload, ensure_ascii=False),
    }

这段逻辑故意做得很小:只接受 GET,查询参数 name 必填且不超过 32 个字符,合法时回显。先把协议跑通,再把 name 的判断换成真实查询。

用测试事件确认,再打开外网调用

函数保存后,不要立刻把地址发给别人。在函数详情的测试里选择 HTTP 或 API 网关事件模板,把 queryStringParameters 改成只含 name 的对象,例如 name 的值写 huawei,然后执行。期望状态码 200,body 里 message 为 hello,name 为刚才传入的值。再执行一次去掉 name 的事件,应返回 400,错误信息是 missing query name。把方法改成 POST,应返回 405。

这三次分别覆盖成功、缺参、方法不对。三次都符合预期,才说明入口、返回结构、字符集都没问题。如果测试直接失败且日志里是模块找不到,回到入口和文件名;如果平台报执行失败而不是你返回的 400,多半是返回值不是字典,或者 body 里塞了字典而不是字符串。

测试通过后再看调用地址。HTTP 函数的触发器页会给出 URL,认证方式调试阶段可以先选「无认证」,用浏览器或命令行带上查询参数 name 访问路径。确认通了以后,再改成 IAM 或应用认证。无认证只适合内测,不要带着无认证的地址长期放在公网,否则任何人都能触发函数,调用次数和日志都会上来。

上线前值得看的五个细节

第一,冷启动。函数闲置一段时间后,下一次调用要重新初始化运行时,耗时会比热调用长。健康检查如果把超时卡在几百毫秒,可能把冷启动误判成故障。执行超时留 3 秒一般够用。流量本来就很小的时候,不必再加定时触发器去预热,预热本身也会计入调用。

第二,依赖不要把本机虚拟环境整包塞进在线编辑。只用标准库时,上面的 index.py 就够了。需要第三方库时,使用函数的依赖包,并保证依赖包的 Python 版本和函数运行时一致。3.9 打出来的包不要挂到别的运行时上,否则导入阶段就会失败,业务代码一行都走不到。

第三,不要把口令、访问密钥写进 index.py,也不要写进测试事件。函数需要访问其他云服务时,在配置里绑定委托,代码使用运行环境提供的临时凭证。测试事件经常会被人复制到工单或博客里,里面出现过一次真实密钥,就等于公开了。

第四,看日志要分清两类失败。函数返回 400 或 405,说明代码已经执行,只是参数或方法不合法,去对调用方。平台返回 502 一类错误,或者日志里完全没有这次调用,优先检查入口名、返回结构,以及触发器是否允许了对应的方法。触发器没放开 GET 时,请求在入口层就被拒绝,函数日志里不会出现你的 print。

第五,路径、方法和函数内的判断要一起改。函数拒绝 POST,但触发器仍开放 POST,调用方拿到的 405 是函数主动返回的,这是预期。反过来,函数支持了新方法,触发器忘了勾选,调用方看到的是网关或平台错误,怎么改 index.py 都不会生效。改协议时两处一起改,并再用测试事件走一遍。

按这个顺序,一个只做校验和回显的 HTTP 函数就可以稳定跑通。下一步把校验通过之后的分支换成真实逻辑,例如读取函数环境变量里的配置项,或通过委托访问其他云服务。handler 的签名、_resp 的返回结构、测试三次的习惯都可以留着,不必推倒重来。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。