背景
最近用aws的api网关对外暴露服务,后来业务需要用到websocket连接。刚好aws的api Gateway带了websocket服务。由于没有中文文档,google那里也找不到太多的东西,所以写个文章记录一下。
一、概念原理
- API Gateway的连接(最重要)
- 客户端到API Gateway连接是websocket
- 然后 API Gateway接收到客户端信息后会转换成restful请求发送到后端(我用的VPC Link)
- 因此,后端的程序应该是一个Restful的程序,所有的客户端的信息都会被API Gateway 转换成 Restful信息传递到后端程序。
- 后端程序如何响应客户端的信息
- 第一种是服务端收到客户端信息之后,马上响应和返回信息给客户端,这种可以直接用 http的response来出来
- 第二种是,服务端主动去找客户端。服务端是不知道客户端的IP地址和端口的,而API Gateway和客户端保持着长连接,所以API Gateway是知道的。所以服务端必须要通过API Gateway帮忙把信息转发给客户端。
- 具体的方法是,服务端发起一个POST请求,告诉API Gateway需要发送什么信息。至于发送到哪个客户端,是通过connectionID来确定的。(connectionID是 API Gateway建立websocket连接的时候生成的,并且会在websocket创建那瞬间,通过Restful告诉后端的程序,后端程序可以把connectionID记录下来)
- 路由Route的概念
- Websocket API Gateway 的路由,指的是API Gateway 会对客户端传递过来的信息进行文本分析(只支持json格式),然后根据json数据中字段的不同,分别转发给后端不同的程序。起到一个路由分发的功能。
- 如果不需要做路由分发,全部数据都传到后端同一个地址的话,那就不要配置任何的路由,那样子API Gateway匹配不到任何的路由规则,就会使用 Default路由。我们需要做的就是配置一下default路由就行了。
二、验证一下
- 搭建一个前后端的测试环境
我这边的测试环境是这样的:
公网客户端-->aws websocket api gateway-->VPC Link-->NLB 负载均衡器->后端服务器的12345端口
- 在后端起一个服务
var http = require("http");
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('Hello World 1234\n');
console.log(`$message`);
}).listen(12345);
console.log('Server running at http://127.0.0.1:12345/')
- 用awscurl往客户端发一条信息
awscurl --service execute-api -X POST -d "hello world" https://dpgsgfvi1.execute-api.ap-northeast-1.amazonaws.com/test/@connections/TOkqFe73AewCFDA=
- 注意事项
- 服务名称是 execute-api,而不是 api Gateway
- url要做转码 %40connections/TRFeGeb8gewCI-g%3D,上面那个url是为了直观而没有做转码
- 建议先用postman 和 awscurl测试一下再写代码
- https://dpgsgfvi1.execute-api.ap-northeast-1.amazonaws.com/test/@connections 是api Gateway部署的时候自动生成的,可以在aws 页面上看到。
三、参考文档
apigateway-websocket-api
announcing-websocket-apis-in-amazon-api-gateway
Sending Data from Backend Services to Connected Clients
http://xzh.i3geek.com
0 条评论