最近在重新整理之前 Webinar 中的例子,其中很典型的一个是 Serverless Websocket 的实现和应用。特地整理一下原理和部署过程,并且通过案例的方式分享出来。
1. 消息实时推送
消息实时推送的技术在很多领域都有广泛的应用。例如实时报价、在线教育、社交订阅、线上游戏等。在这些场景下,需要后台将发生的变化实时,主动地推送给浏览器端,无需用户手动刷新页面。
和移动端的 socket 方式不同,在 web 端实现消息实时推送有几种常见的方案,简要介绍如下:
1.1 短轮询(polling)
轮询指的客户端和服务器端一直进行连接,每隔一段时间就请求一次。其优点是实现简单,对 HTTP 实现无需做过多修改,但缺点也非常明显,即轮询的间隔过长时客户端无法及时收到更新;此外轮询间隔短时又会导致连接数过多,增加服务器端负担。
1.2 长轮询(Long-polling)
长轮询基于短轮询做了改进,即客户端发送 HTTP 给服务端时,如果没有新消息时就会等待,如有新消息时再返回给客户端。从而缓解了服务端的连接压力,并且可以保证比较好的时效性。但缺点也依然存在,因为持续的保持连接会消耗网络带宽,并且当服务端没有数据返回时,会造成请求超时。
1.3 WebSocket
上述两种双向通信的实现方式并不够理想,在此背景下, WebSocket 协议出现了。WebSocket 将 TCP 的 Socket 应用在 webpage上,从而在服务端和客户端中建立了全双工(full-duplex)通信。WebSocket 连接一旦建立,无论客户端或服务端,都可以直接向对方发送报文。
相比于传统的 HTTP 每次请求和应答都需要服务端和客户端建立连接的通信方式,Websocket 在连接建立后,在断开连接前,无需服务端或者客户端重新发起连接请求。因此在并发量大的场景下,可以有效节约带宽资源,并且有显著的性能优势。
基于上述对比可知,WebSocket 协议十分适合实现实时通讯场景,一方面解决了 HTTP 协议中只能服务端发起通讯的被动性,一方面也解决了数据推送延迟的问题,并且具有明显的性能优势。
2. 基于 Serverless 实现 WebSocket 协议
以腾讯云为例,基于 Serverless 实现 WebSocket 协议可以参考WebSocket 原理介绍。
对应到具体实现上,Websocket 在网关+函数中的实现,可以参考下图中的架构。一个 WebSocket API 会对应三个函数:
- 注册函数: 在客户端发起和 API 网关之间建立 WebSocket 连接时触发该函数,通知云函数 WebSocket 连接的 secConnectionID。通常会在该函数中记录 secConnectionID 到持久存储中,用于后续数据的反向推送。
- 清理函数:在客户端主动发起 WebSocket 连接中断请求时触发该函数,通知 云函数准备断开连接的 secConnectionID。通常会在该函数清理持久存储中记录的该 secConnectionID。
- 传输函数:在客户端通过 WebSocket 连接发送数据时触发该函数,告知云函数连接的 secConnectionID 以及发送的数据。通常会在该函数处理业务数据。例如,是否将数据推送给持久存储中的其他 secConnectionID。
关于用 Websocket 实现匿名聊天室的 Node.js 版本,也可以参考下面的 Github Repo。
3. 部署 Serverless WebSocket 的外卖订单系统
3.1 订单系统演示
基于上述理论,我们可以在 Serverless 架构上部署一个 WebSocket 的点单系统。这里也有一个线上 demo 供大家参考。
分别打开点单系统和店铺系统,在店铺系统中点击营业,之后在点单系统中选取对应的店铺,进行下单。如下述动图所示。
3.2 部署流程
因为在控制台配置和部署比较麻烦,所以直接选择用 Serverless Framework 进行部署。
1. 安装和初始化
通过 npm 安装 serverless cli
1 | npm install -g serverless |
直接通过 Serverless registry 获取对应的模板
1 | serverless init websocket-order |
2. 查看目录
查看对应目录,可以看到项目中包含数据库、网关、云函数等多个子模块,说明如下:
- db 目录用于创建 PG Serverless 数据库实例
- apigateway 用于创建对应的 API :
- /bill 外卖下单 API
- /get_shop_info,主要用于实现获取店铺菜单的 API
- /pgws,用于做消息推送的 websocket API
函数列表如下:
- 消息推送相关函数:
- 注册函数 ws_register.py
- 传输函数 ws_trans.py
- 注销函数 ws_unregister.py
- 下单函数 bill.py
- 拉取店铺信息函数 get_shop_info.py
- 初始化DB函数 init_db.py
3. 部署
执行 serverless deploy
进行项目的部署,查看对应的输出信息。
4. 其余配置
a. 在控制台或者 vscode 插件中,点击测试 init_db-dev 函数,对数据库进行初始化的建表等操作
b. 查看输出信息,在 function_bill 目录和 function_ws_trans 目录的 serverless.yml 中,分别配置 websocket API 的 apiid ,并重新部署两个函数,刷新环境变量配置。
1 | sls deploy --target=./function_ws_trans |
c. 本地更改客户端与厨房订单系统的地址并测试App点单系统.html
中更改第29行以及第88行中的 url 为生成的API网关服务域名店家厨房系统.html
更改第17行 url 为API网关服务域名
url 示例:ws://service-xxxxx-xxxx.sh.apigw.tencentcs.com:80/pgws