【问题标题】:AmplifyJS error when Appsync subscribe is exposed via API Gateway通过 API 网关公开 Appsync 订阅时的 AmplifyJS 错误
【发布时间】:2020-08-02 23:53:06
【问题描述】:

Appsync 已经在某种程度上取代了 API Gateway,那你为什么需要通过 API Gateway 公开它。我知道大多数人都会问这个问题。这是为什么?

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

据我了解,Appsync 是 GrapQL + Apollo 服务器实现。公开的 API 支持 POST 请求。甚至订阅请求也是以 Websocket MQTT (AWS IoT) URL 作为响应的发布请求。 (例如下面提供)

{
  "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 端点吗?

为简单起见,我尝试在 API-Gateway 中使用 HTTP API

  • 它适用于 QueryMutate 请求。
  • 但是对于 订阅 请求,我收到了握手异常。 (连接失败:连接握手错误,在我的角度放大项目中)

    1. 这是通过 API-Gateway 公开 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 

2020 年 4 月 24 日更新

我能够使用以下设置通过 API-Gateway 中的 AWS 服务调用来调用 Appsync。 (使用 API Gateway 提供的 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 角色权限

【问题讨论】:

  • API网关的角色有appsync吗?
  • 嘿@RobertNavado,更新了问题。请注意,我没有使用 AWS Service Integrate 来调用 Appsync。但想知道,这是推荐的方法。
  • 我不明白为什么您仍然不能使用 AppSync 提供的订阅 URL 并且必须通过 API 网关代理它。您基本上可以通过 API Gateway 代理查询/突变,并自行使用 Web 套接字 URL。
  • @IonutTrestian 谢谢。但这不符合我的配额要求

标签: aws-api-gateway aws-amplify aws-appsync aws-iot amplifyjs


【解决方案1】:

我不认为你能够以你想象的方式建立联系。

在 AppSync 中,查询和变更是使用普通 HTTP 连接 (REST) 交付的。另一方面,订阅是基于 websockets 的。这两种协议都是基于 TCP 的,但服务器和客户端(浏览器和 sdk,如 amplify)对它们的处理方式不同。

AWS API Gateway supports WebSockets,但使用不同的配置。

您告诉我们,为简单起见,您将 API 网关配置为使用 HTTP API。在这种情况下,它将不起作用,因为您在 API Gateway 中创建的端点尚未准备好与客户端(Amplify)执行 websocket 握手。

要接受和控制握手,您必须将 API 创建为 Websocket API。但问题是:使用此 API,您不能只将调用转发到 AppSync。您将需要部署一个组件来实现API Gateway WebSocket Implementation 所期望的连接控制。

第一个想法是 Lambda 函数,但随之而来的问题是:如何控制和保持从 Lambda 到 AppSync API 的 websocket 连接。你不能指望 Lambda 做到这一点。

我可以想象以下实现来处理您的情况(但我认为这不是一个好的实现):

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

总之,使用此解决方案,您需要重现 AppSync 开箱即用提供的连接控制,此外还有另一部分基础架构来提供 AppSync 开箱即用的管道。

【讨论】:

  • 谢谢。 But In that case, it will not work because the endpoint that you created inside API Gateway is not prepared to perform the websocket handshake with the client (Amplify). 如果您看到,订阅响应只不过是 AWS IoT Websocket 的回调 URL。在 Amplify 库中,它使用回调 URL,然后使用该回调 URL 连接到 WebSocket。与 API-Gateway URL 无关。即使订阅(通过 API-Gateway 公开),我也得到了相同的响应。只是 IoT 中心 URL 的某些握手失败。
  • 我不知道这是如何在 API Gateway 中实现的。但是 WebSocket 握手与普通的 HTTP 握手不同。您可以找到更多信息here
  • 此外,REST 和 HTTP API 有一个 downstream integration timeout of 30 seconds
  • 我想由于这两个原因,websocket 连接不会在 AWS API Gateway 内的 REST 或 HTTP API api 中实现。仅适用于 WebSocket API。当然我可能是错的......但是如果同一产品为这种情况提供了替代方案(WebSocket API),那么实现所需的握手对我来说没有太大意义。
【解决方案2】:

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

AppsyncAPI-Gateway 在 AWS Stack 中属于同一层次结构。通过 API-Gateway 公开 Appsync 不是一个好主意,因为 Appsync 端点仍然是公共的(导致后门)。

以下是我的解决方案(仅考虑Appsync

  1. 变现范围:收集 Appsync metrics/trace 日志并根据 Cognito UserId 或 Apikey 计算 API 使用情况。

  2. 使用计划/配额:设置Lambda Datasource(在管道解析器中)增加 Redis 缓存中的命中计数(键作为 Apikey,值作为命中计数,具有自定义 TTL说 1 天)。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-22
    • 2020-05-03
    • 2021-07-14
    • 2014-12-02
    • 2014-05-03
    • 2021-06-03
    • 2016-04-08
    相关资源
    最近更新 更多