在函数计算中,您可以通过配置HTTP触发器让函数响应WebSocket请求。当HTTP触发器配置完成后,相关联的函数便能够作为一个Web Server,对WebSocket请求进行处理,并将处理结果返回给请求端。
前提条件
步骤一:创建函数
步骤二:编写并部署代码
在函数详情页面,单击函数代码页签,在代码编辑器中编写代码。
在控制台WebIDE的当前目录,将下面的代码复制到index.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
,表示服务器将监听所有可用的网络接口。IP地址不能设置为127.0.0.1
或localhost
。WebSocket Server监听的端口号是一个介于0到65535之间的整数,通常会选择一个大于1024的整数。这里
port
的值需要设置为您在创建函数时配置的监听端口,默认值为9000
端口。
此时,WebIDE的目录结构如下图所示:
在WebIDE的终端窗口,执行
npm install ws
命令来安装依赖。安装完成后,会自动生成文件package-lock.json,目录结构如下图所示:
单击部署代码,将您的代码部署到函数计算中。
步骤三:测试函数
在函数详情页面,单击触发器管理页签,查看并复制触发器的公网访问地址。
说明HTTP触发器创建成功后,访问地址不会变更。
使用Postman来测试函数的正确性。更多信息,请参见Postman。
在Postman中创建WebSocket请求。
将该URL复制到Postman中,并将Scheme由HTTPS变更成WSS。
根据需求配置Params及Headers。
连接WebSocket,连接成功后即可以发送消息。
输入要发送的消息并进行发送,然后查看消息接收的情况。
超过执行超时时间后,会断开与WebSocket服务器的连接。
测试过程如下图所示:
(可选)如果您在用Postman工具测试的过程出现FCCommonError的错误,请确认您HTTP触发器的认证方式,如您无需鉴权访问,可在HTTP触发器创建时或创建后选择无需认证进行测试。
更多说明
请求超时
函数计算在执行超时时间上,并不会区分WebSocket请求和HTTP请求。如果您的WebSocket连接存活时间超过了您设置的执行超时时间,WebSocket连接会被强制关闭,您的客户端会收到1006状态码。
连接保活和超时重连
当您的WebSocket连接建立之后,除了在连接时长超过您设置的执行超时时间会断开连接之外,函数计算不会干涉您的任何逻辑。如果在存续期间,您的WebSocket连接在一段时间内没有数据传输,则该连接可能会被网络中的中间节点关闭,比如NAT网关(用户客户端的内网地址到外网地址的映射)、路由器配置等。这种情况下,连接的具体超时时间不是固定的,如果在超时时间范围内没有任何数据传输,NAT可能会断开该WebSocket连接,您可能需要通过WebSocket协议提供的Ping、Pong帧来对连接进行保活或者验证WebSocket连接是否可用。
如果您的业务需要设置超过函数计算能够提供的最大请求超时时间,或者您的应用期望在运行期间保持逻辑上的连接稳定,您可以在客户端代码中加上超时重连机制。您可以借助Reconnecting-WebSocket的库或SocketIO库来实现该机制。
关于粘性会话(会话亲和性)
函数计算是无状态的,当函数的并发请求度较大的时候,函数计算无法保证来自同一客户端的多个请求会被同一个容器处理。您可能需要通过外部存储(Redis、Memcached、Kafka、数据库等)来维持WebSocket请求在多个容器实例之间的状态。
例如,对于聊天室应用,函数计算无法保证所有的用户同时连接到同一个函数实例上。所以用户的函数可以借助Redis的发布订阅功能来实现聊天室,用户加入一个聊天室的时候,会订阅(Sub)该聊天室所在的频道,当用户1发送信息的时候,函数收到该消息,将其发布(Pub)到Redis中聊天室所在的频道,因为在相同的聊天室的用户均已经订阅(Sub)了该聊天室的频道,所以该聊天室的所有用户都会收到用户1刚才发送的消息。
计费方式
使用WebSocket的计费方式与使用HTTP的计费方式完全一致,您可以将WebSocket看作连接时间较长的HTTP调用。关于计费的更多信息,请参见计费概述。
对于并发度设置为1的函数,计费时间从WebSocket连接建立开始到WebSocket连接断开结束。
对于并发度大于1的函数,实例的计费时间从收到第一个WebSocket连接建立开始,到最后一个WebSocket连接断开结束。一个实例中多个连接同时存在期间,不会被重复计费。
如下图所示,一个函数的并发度设置为2,第一个请求到达的时间为T1,结束时间为T3,第二个请求到达时间为T2,结束时间为T4,计费时间为T4-T1,其中T2到T3这段时间只会被计费一次,不会被重复计费。
更多示例
Custom Runtime | Custom Container |
常见问题
相关文档
WebSocket协议在Runtime支持、超时时间、数据传输等方面有使用限制,请参见WebSocket协议使用限制。
HTTP触发器支持同步调用和异步调用,具体使用请参见调用方式。
函数计算允许HTTP函数的调用请求跨域访问,对跨域请求的处理方式请参见CORS请求处理。