当Appsync订阅通过API网关暴露时,AmplifyJS错误。

问题描述 投票:0回答:1

Appsync已经在一定程度上取代了API Gateway,那为什么还要通过API Gateway来暴露呢。我知道大多数人都会问这个问题。这里是为什么呢?

  1. 支持使用计划
  2. 货币化的可能性。

据我了解,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)

    1. 通过API网关暴露Appsync的方式是否正确?或者我应该使用 AWS 服务(在 API 网关)来调用 Appsync?

    2. 如何解决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 API Gateway invoking AWS Service Appsync

: AWS 子域,是 Appsync API Endpoint 的子域部分。

IAM角色的信任关系

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "appsync.amazonaws.com",
          "apigateway.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

IAM角色权限

API Gateway execution role

aws-api-gateway aws-amplify aws-appsync aws-iot amplifyjs
1个回答
0
投票

我不认为你能够以你想象的方式进行连接。

在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来做到这一点。

我可以想象以下的实现可以适用于您的情况(但我不认为这将是一个好的实现)。

  1. 在AWS API Gateway中实现WebSocket API。
  2. 部署组件以控制 de WebSocket API 后端(必须在实例或容器内)。
  3. 从该组件中,您可以使用amplify连接到AppSync中的websocket端点。
  4. 在该组件中,每次收到AppSync对特定的websocket连接的请求时,你都会调用AWS API网关回调URL来连接WebSocket API,并转发响应。

综上所述,通过这个方案,你除了需要重现AppSync开箱提供的连接控制外,还需要有另一部分基础设施来提供AppSync已经开箱提供的管道。


0
投票

在得到专家的意见后,我终于放弃了暴露的计划。Appsync 通过 API-Gateway.

应用程序同步 & API-网关 属于AWS Stack中的同一层次。通过API-Gateway暴露Appsync不是一个好主意,因为,Appsync端点仍然是公开的(导致后门)。

以下是我的解决方案(考虑到 Appsync 单独)为

  1. 货币化范围: 收集Appsync metrics/trace 日志,并根据Cognito UserId或Apikey计算API Usage。

  2. 使用量计划配额: 设立一个 Lambda Datasource (在Pipeline解析器中)递增Redis缓存中的命中数(键为Apikey,值为命中数,有一个自定义的TTL,比如1天)。

如果有更好的解决方案,欢迎分享。

© www.soinside.com 2019 - 2024. All rights reserved.