Appsync已经在一定程度上取代了API Gateway,那为什么还要通过API Gateway来暴露呢。我知道大多数人都会问这个问题。这里是为什么呢?
据我了解,Appsync是GrapQL+Apollo服务器实现的。露出的API支持POST请求。甚至订阅请求也是一个post请求,以Websocket MQTT(AWS IoT)URL作为响应。(下面提供的Eg)
{
"extensions": {
"subscription": {
"mqttConnections": [
{
"url": "wss://something-ats.iot.ap-northeast-1.amazonaws.com/mqtt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...",
"topics": [
".../.../subscribeToVehicleLocation/..."
],
"client": "..."
}
],
"newSubscriptions": {
"subscribeToVehicleLocation": {
"topic": ".../../subscribeToVehicleLocation/..",
"expireTime": null
}
}
}
},
"data": {
"subscribeToVehicleLocation": null
}
}
如果是这样的话,我们可以通过API-Gateway(POST方法)暴露Appsyn端点吗?
为了简单起见,我试着用 HTTP API 在API-Gateway中。
但对于 订阅 请求,我得到一个握手异常。(在我的angular amplify项目中,连接失败。Connection handshake error, in my angular amplify project)
通过API网关暴露Appsync的方式是否正确?或者我应该使用 AWS 服务(在 API 网关)来调用 Appsync?
如何解决Angular Amplify项目中的Websocket连接握手错误?
PS:
我之前能够使用原始的 Appsync URL 订阅数据(在 Angular 7 中使用 AmplifyJS)。使用API-Gateway URL,我得到了这个WS Handshake异常(使用Amplify)。
WebSocket connection to 'wss://....execute-api.ap-northeast-1.amazonaws.com/graphql?header=...&payload=e30=' failed: Error during WebSocket handshake: Unexpected response code: 400
in AWSAppSyncRealTimeProvider.js:603
24-04-2020更新
我可以通过API-Gateway中的AWS Service invoke调用Appsync,设置如下。(使用API网关提供的REST协议)
但我还是在Amplify中遇到了Web Socket错误。
API-网关配置
注: AWS 子域,是 Appsync API Endpoint 的子域部分。
IAM角色的信任关系
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"appsync.amazonaws.com",
"apigateway.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
IAM角色权限
我不认为你能够以你想象的方式进行连接。
在AppSync中,查询和突变是使用普通的HTTP连接(REST)来传递的。在另一边,订阅是基于websockets的。这两种协议都是基于TCP的,但服务器和客户端(浏览器和sdk,如amplify)对它们的处理方式不同。
AWS API Gateway支持WebSockets但使用了不同的配置。
您告诉我们,您为了简单起见,将 API Gateway 配置为使用 HTTP API,但在这种情况下,它将无法工作,因为您在 API Gateway 内创建的端点没有准备好与客户端(Amplify)进行 websocket 握手。在这种情况下,它将无法工作,因为您在 API Gateway 内创建的端点没有准备好与客户端(Amplify)执行 websocket 握手。
要接受和控制握手,您必须将 API 创建为 Websocket API。但问题是:使用该 API,您不能只将调用转发给 AppSync。您将需要部署一个组件来实现连接控制,以满足您的期望。API网关WebSocket实现.
一个Lambda函数将是第一个想法,但随后,有一个问题。你将如何控制和持久化websocket连接 从你的Lambda到AppSync API. 你不能指望Lambda来做到这一点。
我可以想象以下的实现可以适用于您的情况(但我不认为这将是一个好的实现)。
综上所述,通过这个方案,你除了需要重现AppSync开箱提供的连接控制外,还需要有另一部分基础设施来提供AppSync已经开箱提供的管道。
在得到专家的意见后,我终于放弃了暴露的计划。Appsync
通过 API-Gateway
.
应用程序同步 & API-网关 属于AWS Stack中的同一层次。通过API-Gateway暴露Appsync不是一个好主意,因为,Appsync端点仍然是公开的(导致后门)。
以下是我的解决方案(考虑到 Appsync
单独)为
货币化范围: 收集Appsync metrics/trace
日志,并根据Cognito UserId或Apikey计算API Usage。
使用量计划配额: 设立一个 Lambda Datasource
(在Pipeline解析器中)递增Redis缓存中的命中数(键为Apikey,值为命中数,有一个自定义的TTL,比如1天)。
如果有更好的解决方案,欢迎分享。