函数计算支持HTTP触发器,配置HTTP触发器的函数可以通过WebSocket请求被触发执行。此时函数可以看做一个Web Server,对WebSocket请求进行处理,并将处理结果返回给调用端。本文介绍如何在函数计算控制台配置HTTP触发器并使用WebSocket请求触发。
前提条件
已创建函数,其运行环境为Node.js 14。具体操作,请参见创建函数。
步骤一:创建触发器
-
登录函数计算控制台,在左侧导航栏,选择。
-
在顶部菜单栏,选择地域,然后在函数列表页面,单击目标函数。
在函数详情页面,选择触发器页签,然后单击创建触发器。
在创建触发器面板,填写相关信息,然后单击确定。
配置项
操作
本文示例
触发器类型
选择HTTP 触发器。
HTTP 触发器
名称
填写自定义的触发器名称。
http-trigger
版本或别名
默认值为LATEST,如果您需要创建其他版本或别名的触发器,需先在函数详情页的版本或别名下拉列表选择该版本。关于版本和别名的简介,请参见版本管理和别名管理。
LATEST
请求方法
指定可以通过哪些方法触发该HTTP触发器。
GET, POST, PUT, DELETE
禁用公网访问 URL
默认不开启,即允许公网域名访问该触发器。
如果选择开启,创建的HTTP触发器将不提供默认的公网域名。此时,如果通过公网域名来调用函数,将会提示错误
access denied due to function internet URL is disable。通过自定义域名的访问,则不受影响。否
认证方式
选择函数计算对HTTP请求的认证方式。取值说明如下:
无需认证:无需对HTTP请求进行身份认证,支持匿名访问,任何人可发起HTTP请求调用您的函数。
签名认证:需要对HTTP请求进行身份认证。关于签名认证的示例代码,请参见通过签名访问HTTP触发器地址。
Bearer 认证:需要对HTTP请求进行身份认证。关于Basic认证的示例代码,请参见为HTTP触发器配置Basic认证鉴权。
JWT 认证:需要对HTTP请求进行JWT认证。更多信息,请参见为HTTP触发器配置JWT认证鉴权。
Bearer 认证:需要对HTTP请求进行Bearer认证。更多信息,请参见为HTTP触发器开启Bearer认证鉴权。
无需认证
创建完成后,您可以根据情况对HTTP触发器的配置项进行修改,包括版本或别名、请求方法和认证方式等。
步骤二:编写并部署代码
在函数详情页面的代码页签,在代码编辑器中编写代码,然后单击部署代码。
在控制台WebIDE的当前目录,将下面的代码复制到index.js文件中。本文以Node.js代码为例。
const WebSocket = require('ws'); const WebSocketServer = WebSocket.Server; const wss = new WebSocketServer({ host: "0.0.0.0", port: 9000, }); wss.on('connection', function (ws, req) { console.log(`[SERVER] connection()`); ws.on('message', function (message) { ws.send(`${message}`, (err) => { if (err) { console.log(`[SERVER] error: ${err}`); } }); }) });说明WebSocket Server监听的IP地址是
0.0.0.0,不能是127.0.0.1或localhost。如果您没有配置自定义监听端口,默认使用9000端口。此时,WebIDE的目录结构如下图所示:

在WebIDE的终端窗口,执行
npm install ws命令来安装依赖。安装完成后,会自动生成文件package-lock.json,目录结构如下图所示:

单击部署代码,将您的代码部署到函数计算中。
步骤三:测试函数
在函数详情页面,单击触发器管理页签,查看并复制触发器的公网访问地址。

使用Postman来测试函数的正确性。
将该URL复制到Postman中,并将Scheme由HTTPS变更成WSS。更多信息,请参见Postman。
计费方式
使用WebSocket的计费方式与使用HTTP的计费方式完全一致,您可以将WebSocket看作连接时间较长的HTTP调用。
对于并发度设置为1的函数,计费时间从WebSocket连接建立开始到WebSocket连接断开结束。
对于并发度大于1的函数,实例的计费时间从收到第一个WebSocket连接建立开始,到最后一个WebSocket连接断开结束。一个实例中多个连接同时存在期间,不会被重复计费。
如下图所示,一个函数的并发度设置为2,第一个请求到达的时间为T1,结束时间为T3,第二个请求到达时间为T2,结束时间为T4,计费时间为T4-T1,其中T2到T3这段时间只会被计费一次,不会被重复计费。

更多说明
请求超时
函数计算在执行超时时间上,并不会区分WebSocket请求和HTTP请求。如果您的WebSocket连接存活时间超过了您设置的执行超时时间,WebSocket连接会被强制关闭,您的客户端会收到1006状态码。
连接保活和超时重连
当您的WebSocket连接建立之后,除了在连接时长超过您设置的执行超时时间会断开连接之外,函数计算不会干涉您的任何逻辑。如果在存续期间,您的WebSocket连接在一段时间内没有数据传输,则该连接可能会被网络中的中间节点(比如NAT网关)关闭。这种情况下,您可能需要通过WebSocket协议提供的Ping、Pong帧来对连接进行保活或者验证WebSocket连接是否可用。
如果您的业务需要设置超过函数计算能够提供的最大请求超时时间,或者您的应用期望在运行期间保持逻辑上的连接稳定,您可以在客户端代码中加上超时重连机制。您可以借助Reconnecting-WebSocket的库或SocketIO库来实现该机制。
关于粘性会话(会话亲和性)
函数计算是无状态的,当函数的并发请求度较大的时候,函数计算无法保证来自同一客户端的多个请求会被同一个容器处理。您可能需要通过外部存储(Redis、Memcached、Kafka、数据库等)来维持WebSocket请求在多个容器实例之间的状态。
例如,对于聊天室应用,函数计算无法保证所有的用户同时连接到同一个函数实例上。所以用户的函数可以借助Redis的发布订阅功能来实现聊天室,用户加入一个聊天室的时候,会订阅(Sub)该聊天室所在的频道,当用户1发送信息的时候,函数收到该消息,将其发布(Pub)到Redis中聊天室所在的频道,因为在相同的聊天室的用户均已经订阅(Sub)了该聊天室的频道,所以该聊天室的所有用户都会收到用户1刚才发送的消息。
更多示例
Custom Runtime | Custom Container |
常见问题
为什么WebSocket函数无法执行?
如果是您新创建的触发器,会有10s左右的缓存更新时间,请稍后再试。
请检查函数代码中的依赖包是否正确安装,更多信息,请参见为函数安装第三方依赖。
请检查函数监听的端口和IP地址是否正确。监听的IP地址可以是
0.0.0.0,不能是127.0.0.1或localhost。如果您没有配置自定义监听端口,默认使用9000端口。
错误排查
WebSocket握手完成之前发生的错误主要分为以下两种:
请求错误是指发送的Request不符合标准,在Response里报错状态码为4xx。
函数错误,即编写的函数有问题,会报5xx状态码。
错误类型 | HTTP状态码 | 原因分析 | 是否计费 |
请求错误 | 400 | 您的请求超过Request限制项的限制。更多信息,请参见HTTP触发器概述。 | 否 |
400 | 调用需要身份认证的函数的Request没有传入Date信息或Authorization信息。 | 否 | |
403 | 调用需要身份认证的函数的Request的签名错误,即Authorization不正确。由于Date参与签名计算,且超过15 min,签名失效,一种常见的原因是使用需要访问认证的HTTP触发器,Request header中发送的Date据当前时间超过15 min,导致签名失效。 | 否 | |
403 | 您的Request请求使用了HTTP触发器中未配置的请求方法。WebSocket函数要求HTTP触发器必须支持GET方法,如果没有配置该方法,会报该错误 | 否 | |
404 | 向没有设置HTTP触发器的函数发送WebSocket请求。 | 否 | |
用户流控 | 429 | 用户被流控,可减小并发量或者联系阿里云函数计算团队提高并发度。 | 否 |
系统错误 | 500 | 函数计算系统错误,可重试解决。 | 否 |
系统流控 | 503 | 函数计算系统流控。可用指数退避方式重试。 | 否 |
WebSocket握手完成之后的错误,均为函数代码产生或引起的错误,您可以仔细检查您的代码,或者查看代码运行中产生的日志。更多信息,请参见查看调用日志。
更多信息
除了函数计算控制台,您还可以通过以下方式配置触发器:
-
通过Serverless Devs工具配置触发器。更多操作,请参见Serverless Devs常用命令。
-
通过SDK配置触发器。更多操作,请参见SDK列表。
如需对创建的触发器进行修改或删除,具体操作,请参见触发器管理。