构建实时 WebSocket 客户端 - Amazon AppSync
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 Amazon Web Services 服务入门

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

构建实时 WebSocket 客户端

AmazonGraphQL 订阅的实时 AppSync WebSocket 客户端实施指南

以下顺序图和步骤显示了 WebSocket 客户端、HTTP 客户端以及AmazonAppSync 服务。

  1. 客户端建立与 WebSocket 连接AmazonAppSync 实施终端节点。如果存在网络错误,则客户端应该执行抖动指数退避。有关更多信息,请参阅 。指数退避和抖动中的Amazon建筑博客。

  2. 成功建立 WebSocket 连接后,客户端会发送一 connection_init 条消息。

  3. 客户端等待connection_ack来自的消息AmazonAppSync。此消息包含一个 connectionTimeoutMs 参数,这是消息 "ka"(即,保持活动状态)的最长等待时间,以毫秒为单位。

  4. AmazonAppSync 发送保持活着消息,"ka",定期。客户端跟踪收到每条 "ka" 消息的时间。如果在 connectionTimeoutMs 毫秒内未收到 "ka" 消息,则客户端应终止连接。

  5. 客户端通过发送 start 订阅消息来注册订阅。单个 WebSocket 连接可以支持多个订阅,即使它们处于不同的授权模式。

  6. 客户端等待Amazon发送 AppSyncstart_ack确认成功订阅的消息。如果有错误,AmazonAppSync 返回"type": "error"消息。

  7. 客户端侦听订阅事件。这些是在调用对应的更改之后发送的。查询和突变通常是通过https://到AmazonAppSync GraphQL 终端节点。订阅流通过AmazonAppSync 实施终端节点使用安全 WebSocket (wss://)。

  8. 客户端通过发送 stop 订阅消息来取消注册订阅。

  9. 取消注册所有订阅并检查没有通过 WebSocket 传输的消息后,客户端可以从 WebSocket 连接断开。

建立 WebSocket 连接的握手详细信息

要使用进行连接并启动成功的握手AmazonWebSocket 客户端 AppSync,需要以下信息:

  • AppSync 实施终端节点

  • 包含以下参数的查询字符串:headerpayload

    • header:包含与AmazonAppSync 终端节点和授权。这是一个从字符串化的 JSON 对象编码的 base64 字符串。JSON 对象内容因授权模式而异。

    • payloadpayload 的 Base64 编码字符串。

使用这些必需的详细信息,WebSocket 客户端可以连接到 URL,该 URL 包含带有查询字符串的 API 实时终端节点,将 graphql-ws 用作 WebSocket 协议。

发现Amazon来自的 AppSync 实施终端节点AmazonAppSync GraphQL 终端

这些区域有:AmazonappSync GraphQL 终端节点和AmazonAppSync 实时终端节点在协议和域方面略有不同。您可以检索AmazonAppSync GraphQL 端点使用Amazon CLI命令aws appsync get-graphql-api.

AmazonAppSync GraphQL 终端节点:

https://example1234567890000.appsync-api.us-east-1.amazonaws.com/graphql

AmazonAppSync 实施终端节点:

wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql

应用程序可以连接到AmazonAppSync GraphQL 终端节点https://) 使用任何 HTTP 客户端进行查询和突变。应用程序可以连接到AmazonAppSync 实施终端节点 (wss://) 使用任何 WebSocket 客户端进行订阅。

基于的标头参数格式AmazonAppSync API 授权模式

的格式header连接查询字符串中使用的对象因AmazonAppSync API 授权模式。这些区域有:host对象中的字段引用AmazonAppSync GraphQL 终端节点用于验证连接,即使wss://调用针对实时终端节点。要启动握手并建立授权连接,payload 应为空 JSON 对象。

API 键

标头内容:

  • "host": <string>: 这是主持人AmazonAppSync GraphQL 终端节点。

  • "x-api-key": <string>:配置的 API 密钥AmazonAppSync API。

例如:

{ "host":"example1234567890000.appsync-api.us-east-1.amazonaws.com", "x-api-key":"da2-12345678901234567890123456" }

负载内容:

{}

请求 URL:

wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql?header=eyJob3N0IjoiZXhhbXBsZTEyMzQ1Njc4OTAwMDAuYXBwc3luYy1hcGkudXMtZWFzdC0xLmFtYXpvbmF3cy5jb20iLCJ4LWFtei1kYXRlIjoiMjAyMDA0MDFUMDAxMDEwWiIsIngtYXBpLWtleSI6ImRhMi16NHc0NHZoczV6Z2MzZHRqNXNranJsbGxqaSJ9&payload=e30=

Amazon Cognito 用户池和 OpenID Connect (OIDC)

标头内容:

  • "Authorization": <string>:JWT 访问令牌。

  • "host": <string>: 这是主持人AmazonAppSync GraphQL 终端节点。

例如:

{ "Authorization":"eyEXAMPLEiJjbG5xb3A5eW5MK09QYXIrMTJHWEFLSXBieU5WNHhsQjEXAMPLEnM2WldvPSIsImFsZyI6IlEXAMPLEn0.eyEXAMPLEiJhNmNmMjcwNy0xNjgxLTQ1NDItOWYxOC1lNjY0MTg2NjlkMzYiLCJldmVudF9pZCI6ImVkMzM5MmNkLWNjYTMtNGM2OC1hNDYyLTJlZGI3ZTNmY2FjZiIsInRva2VuX3VzZSI6ImFjY2VzcyIsInNjb3BlIjoiYXdzLmNvZ25pdG8uc2lnbmluLnVzZXIuYWRtaW4iLCJhdXRoX3RpbWUiOjE1Njk0NTc3MTgsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC5hcC1zb3V0aGVhc3QtMi5hbWF6b25hd3MuY29tXC9hcC1zb3V0aGVhc3QtMl83OHY0SVZibVAiLCJleHAiOjE1Njk0NjEzMjAsImlhdCI6MTU2OTQ1NzcyMCwianRpIjoiNTgzZjhmYmMtMzk2MS00YzA4LWJhZTAtYzQyY2IxMTM5NDY5IiwiY2xpZW50X2lkIjoiM3FlajVlMXZmMzd1N3RoZWw0dG91dDJkMWwiLCJ1c2VybmFtZSI6ImVsb3EXAMPLEn0.B4EXAMPLEFNpJ6ikVp7e6DRee95V6Qi-zEE2DJH7sHOl2zxYi7f-SmEGoh2AD8emxQRYajByz-rE4Jh0QOymN2Ys-ZIkMpVBTPgu-TMWDyOHhDUmUj2OP82yeZ3wlZAtr_gM4LzjXUXmI_K2yGjuXfXTaa1mvQEBG0mQfVd7SfwXB-jcv4RYVi6j25qgow9Ew52ufurPqaK-3WAKG32KpV8J4-Wejq8t0c-yA7sb8EnB551b7TU93uKRiVVK3E55Nk5ADPoam_WYE45i3s5qVAP_-InW75NUoOCGTsS8YWMfb6ecHYJ-1j-bzA27zaT9VjctXn9byNFZmEXAMPLExw", "host":"example1234567890000.appsync-api.us-east-1.amazonaws.com" }

负载内容:

{}

请求 URL:

wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql?header=eyJBdXRob3JpemF0aW9uIjoiZXlKcmFXUWlPaUpqYkc1eGIzQTVlVzVNSzA5UVlYSXJNVEpIV0VGTFNYQmllVTVXTkhoc1FqaFBWVzlZTW5NMldsZHZQU0lzSW1Gc1p5STZJbEpUTWpVMkluMC5leUp6ZFdJaU9pSmhObU5tTWpjd055MHhOamd4TFRRMU5ESXRPV1l4T0MxbE5qWTBNVGcyTmpsa016WWlMQ0psZG1WdWRGOXBaQ0k2SW1Wa016TTVNbU5rTFdOallUTXROR00yT0MxaE5EWXlMVEpsWkdJM1pUTm1ZMkZqWmlJc0luUnZhMlZ1WDNWelpTSTZJbUZqWTJWemN5SXNJbk5qYjNCbElqb2lZWGR6TG1OdloyNXBkRzh1YzJsbmJtbHVMblZ6WlhJdVlXUnRhVzRpTENKaGRYUm9YM1JwYldVaU9qRTFOamswTlRjM01UZ3NJbWx6Y3lJNkltaDBkSEJ6T2x3dlhDOWpiMmR1YVhSdkxXbGtjQzVoY0MxemIzVjBhR1ZoYzNRdE1pNWhiV0Y2YjI1aGQzTXVZMjl0WEM5aGNDMXpiM1YwYUdWaGMzUXRNbDgzT0hZMFNWWmliVkFpTENKbGVIQWlPakUxTmprME5qRXpNakFzSW1saGRDSTZNVFUyT1RRMU56Y3lNQ3dpYW5ScElqb2lOVGd6WmpobVltTXRNemsyTVMwMFl6QTRMV0poWlRBdFl6UXlZMkl4TVRNNU5EWTVJaXdpWTJ4cFpXNTBYMmxrSWpvaU0zRmxhalZsTVhabU16ZDFOM1JvWld3MGRHOTFkREprTVd3aUxDSjFjMlZ5Ym1GdFpTSTZJbVZzYjNKNllXWmxJbjAuQjRjZEp0aDNLRk5wSjZpa1ZwN2U2RFJlZTk1VjZRaS16RUUyREpIN3NIT2wyenhZaTdmLVNtRUdvaDJBRDhlbXhRUllhakJ5ei1yRTRKaDBRT3ltTjJZcy1aSWtNcFZCVFBndS1UTVdEeU9IaERVbVVqMk9QODJ5ZVozd2xaQXRyX2dNNEx6alhVWG1JX0syeUdqdVhmWFRhYTFtdlFFQkcwbVFmVmQ3U2Z3WEItamN2NFJZVmk2ajI1cWdvdzlFdzUydWZ1clBxYUstM1dBS0czMktwVjhKNC1XZWpxOHQwYy15QTdzYjhFbkI1NTFiN1RVOTN1S1JpVlZLM0U1NU5rNUFEUG9hbV9XWUU0NWkzczVxVkFQXy1Jblc3NU5Vb09DR1RzUzhZV01mYjZlY0hZSi0xai1iekEyN3phVDlWamN0WG45YnlORlptS0xwQTJMY3h3IiwiaG9zdCI6ImV4YW1wbGUxMjM0NTY3ODkwMDAwLmFwcHN5bmMtYXBpLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tIn0=&payload=e30=

IAM

标头内容如下:

  • "accept": "application/json, text/javascript":常量 <string> 参数。

  • "content-encoding": "amz-1.0":常量 <string> 参数。

  • "content-type": "application/json; charset=UTF-8":常量 <string> 参数。

  • "host": <string>: 这是主持人AmazonAppSync GraphQL 终端节点。-"x-amz-date": <string>:时间戳必须采用 UTC 表示,并具有以下 ISO 8601 格式:YYYYMMDD''HHMMSS'Z '。例如,20150830T123600Z 是一个有效的时间戳。请勿在时间戳中包含毫秒。有关更多信息,请参阅 。处理签名版本 4 中的日期中的Amazon一般参考.

    • "X-Amz-Security-Token":<string>: 这些区域有:Amazon会话令牌,使用临时安全证书时必需。有关更多信息,请参阅 。将临时凭证用于Amazon资源中的IAM 用户指南.

    • "Authorization": <string>:Sigv4 签名信息AmazonAppSync 终端节点。有关签名过程的更多信息,请参阅任务 4:将签名添加到 HTTP 请求中的Amazon一般参考.

Sigv4 签名 HTTP 请求包含一个规范 URL,它是AmazonAppSync GraphQL 终端节点/connect附加。服务终端节点Amazon地区是你正在使用AmazonAppSync API,服务名称为 “appsync”。要签名的 HTTP 请求如下所示:

{ url: "https://example1234567890000.appsync-api.us-east-1.amazonaws.com/graphql/connect", data: "{}", method: "POST", headers: { "accept": "application/json, text/javascript", "content-encoding": "amz-1.0", "content-type": "application/json; charset=UTF-8", } }

例如:

{ "accept": "application/json, text/javascript", "content-encoding": "amz-1.0", "content-type": "application/json; charset=UTF-8", "host": "example1234567890000.appsync-api.us-east-1.amazonaws.com", "x-amz-date": "20200401T001010Z", "X-Amz-Security-Token": "AgEXAMPLEZ2luX2VjEAoaDmFwLXNvdXRoZWFEXAMPLEcwRQIgAh97Cljq7wOPL8KsxP3YtDuyc/9hAj8PhJ7Fvf38SgoCIQDhJEXAMPLEPspioOztj++pEagWCveZUjKEn0zyUhBEXAMPLEjj//////////8BEXAMPLExODk2NDgyNzg1NSIMo1mWnpESWUoYw4BkKqEFSrm3DXuL8w+ZbVc4JKjDP4vUCKNR6Le9C9pZp9PsW0NoFy3vLBUdAXEXAMPLEOVG8feXfiEEA+1khgFK/wEtwR+9zF7NaMMMse07wN2gG2tH0eKMEXAMPLEQX+sMbytQo8iepP9PZOzlZsSFb/dP5Q8hk6YEXAMPLEYcKZsTkDAq2uKFQ8mYUVA9EtQnNRiFLEY83aKvG/tqLWNnGlSNVx7SMcfovkFDqQamm+88y1OwwAEYK7qcoceX6Z7GGcaYuIfGpaX2MCCELeQvZ+8WxEgOnIfz7GYvsYNjLZSaRnV4G+ILY1F0QNW64S9Nvj+BwDg3ht2CrNvpwjVYlj9U3nmxE0UG5ne83LL5hhqMpm25kmL7enVgw2kQzmU2id4IKu0C/WaoDRuO2F5zE63vJbxN8AYs7338+4B4HBb6BZ6OUgg96Q15RA41/gIqxaVPxyTpDfTU5GfSLxocdYeniqqpFMtZG2n9d0u7GsQNcFkNcG3qDZm4tDo8tZbuym0a2VcF2E5hFEgXBa+XLJCfXi/77OqAEjP0x7Qdk3B43p8KG/BaioP5RsV8zBGvH1zAgyPha2rN70/tT13yrmPd5QYEfwzexjKrV4mWIuRg8NTHYSZJUaeyCwTom80VFUJXG+GYTUyv5W22aBcnoRGiCiKEYTLOkgXecdKFTHmcIAejQ9Welr0a196Kq87w5KNMCkcCGFnwBNFLmfnbpNqT6rUBxxs3X5ntX9d8HVtSYINTsGXXMZCJ7fnbWajhg/aox0FtHX21eF6qIGT8j1z+l2opU+ggwUgkhUUgCH2TfqBj+MLMVVvpgqJsPKt582caFKArIFIvO+9QupxLnEH2hz04TMTfnU6bQC6z1buVe7h+tOLnh1YPFsLQ88anib/7TTC8k9DsBTq0ASe8R2GbSEsmO9qbbMwgEaYUhOKtGeyQsSJdhSk6XxXThrWL9EnwBCXDkICMqdntAxyyM9nWsZ4bL9JHqExgWUmfWChzPFAqn3F4y896UqHTZxlq3WGypn5HHcem2Hqf3IVxKH1inhqdVtkryEiTWrI7ZdjbqnqRbl+WgtPtKOOweDlCaRs3R2qXcbNgVhleMk4IWnF8D1695AenU1LwHjOJLkCjxgNFiWAFEPH9aEXAMPLExA==", "Authorization": "AWS4-HMAC-SHA256 Credential=XXXXXXXXXXXXXXXXXXX/20200401/us-east-1/appsync/aws4_request, SignedHeaders=accept;content-encoding;content-type;host;x-amz-date;x-amz-security-token, Signature=83EXAMPLEbcc1fe3ee69f75cd5ebbf4cb4f150e4f99cec869f149c5EXAMPLEdc" }

负载内容:

{}

请求 URL:

wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql?header=eyEXAMPLEHQiOiJhcHBsaWNhdGlvbi9qc29uLCB0ZXh0L2phdmFEXAMPLEQiLCJjb250ZW50LWVuY29kaW5nIjoEXAMPLEEuMCIsImNvbnRlbnQtdHlwZSI6ImFwcGxpY2F0aW9EXAMPLE47IGNoYXJzZXQ9VVRGLTgiLCJob3N0IjoiZXhhbXBsZEXAMPLENjc4OTAwMDAuYXBwc3luYy1hcGkudXMtZWFzdC0xLmFtYEXAMPLEcy5jb20iLCJ4LWFtei1kYXRlIjoiMjAyMDA0MDFUMDAxMDEwWiIsIlgtEXAMPLElY3VyaXR5LVRva2VuIjoiQWdvSmIzSnBaMmx1WDJWakVBb2FEbUZ3TFhOdmRYUm9aV0Z6ZEMweUlrY3dSUUlnQWg5N0NsanE3d09QTDhLc3hQM1l0RHV5Yy85aEFqOFBoSjdGdmYzOFNnb0NJUURoSllKYkpsbmpQc3Bpb096dGorK3BFYWdXQ3ZlWlVqS0VuMHp5VWhCbXhpck5CUWpqLy8vLy8vLy8vLzhCRUFBYUREY3hPRGsyTkRneU56ZzFOU0lNbzFtV25wRVNXVW9ZdzRCa0txRUZTcm0zRFh1TDh3K1piVmM0SktqRFA0dlVDS05SNkxlOUM5cFpwOVBzVzBOb0Z5M3ZMQlVkQVh3dDZQSld1T1ZHOGZlWGZpRUVBKzFraGdGSy93RXR3Uis5ekY3TmFNTU1zZTA3d04yZ0cydEgwZUtNVFhuOEF3QVFYK3NNYnl0UW84aWVwUDlQWk96bFpzU0ZiL2RQNVE4aGs2WWpHVGFMMWVZY0tac1RrREFxMnVLRlE4bVlVVkE5RXRRbk5SaUZMRVk4M2FLdkcvdHFMV05uR2xTTlZ4N1NNY2ZvdmtGRHFRYW1tKzg4eTFPd3dBRVlLN3Fjb2NlWDZaN0dHY2FZdUlmR3BhWDJNQ0NFTGVRdlorOFd4RWdPbklmejdHWXZzWU5qTFpTYVJuVjRHK0lMWTFGMFFOVzY0UzlOdmorQndEZzNodDJDck52cHdqVllsajlVM25teEUwVUc1bmU4M0xMNWhocU1wbTI1a21MN2VuVmd3MmtRem1VMmlkNElLdTBDL1dhb0RSdU8yRjV6RTYzdkpieE44QVlzNzMzOCs0QjRIQmI2Qlo2T1VnZzk2UTE1UkE0MS9nSXF4YVZQeHlUcERmVFU1R2ZTTHhvY2RZZW5pcXFwRk10WkcybjlkMHU3R3NRTmNGa05jRzNxRFptNHREbzh0WmJ1eW0wYTJWY0YyRTVoRkVnWEJhK1hMSkNmWGkvNzdPcUFFalAweDdRZGszQjQzcDhLRy9CYWlvUDVSc1Y4ekJHdkgxekFneVBoYTJyTjcwL3RUMTN5cm1QZDVRWUVmd3pleGpLclY0bVdJdVJnOE5USFlTWkpVYWV5Q3dUb204MFZGVUpYRytHWVRVeXY1VzIyYUJjbm9SR2lDaUtFWVRMT2tnWGVjZEtGVEhtY0lBZWpROVdlbHIwYTE5NktxODd3NUtOTUNrY0NHRm53Qk5GTG1mbmJwTnFUNnJVQnh4czNYNW50WDlkOEhWdFNZSU5Uc0dYWE1aQ0o3Zm5iV2FqaGcvYW94MEZ0SFgyMWVGNnFJR1Q4ajF6K2wyb3BVK2dnd1Vna2hVVWdDSDJUZnFCaitNTE1WVnZwZ3FKc1BLdDU4MmNhRktBcklGSXZPKzlRdXB4TG5FSDJoejA0VE1UZm5VNmJRQzZ6MWJ1VmU3aCt0T0xuaDFZUEZzTFE4OGFuaWIvN1RUQzhrOURzQlRxMEFTZThSMkdiU0VzbU85cWJiTXdnRWFZVWhPS3RHZXlRc1NKZGhTazZYeFhUaHJXTDlFbndCQ1hEa0lDTXFkbnRBeHl5TTluV3NaNGJMOUpIcUV4Z1dVbWZXQ2h6UEZBcW4zRjR5ODk2VXFIVFp4bHEzV0d5cG41SEhjZW0ySHFmM0lWeEtIMWluaHFkVnRrcnlFaVRXckk3WmRqYnFucVJibCtXZ3RQdEtPT3dlRGxDYVJzM1IycVhjYk5nVmhsZU1rNElXbkY4RDE2OTVBZW5VMUx3SGpPSkxrQ2p4Z05GaVdBRkVQSDlhTklhcXMvWnhBPT0iLCJBdXRob3JpemF0aW9uIjoiQVdTNC1ITUFDLVNIQTI1NiBDcmVkZW50aWFsPVhYWFhYWFhYWFhYWFhYWFhYWFgvMjAxOTEwMDIvdXMtZWFzdC0xEXAMPLE5bmMvYXdzNF9yZXF1ZXN0LCBTaWduZWRIZWFkZXJzPWFjY2VwdDtjb250ZWEXAMPLE29kaW5nO2NvbnRlbnQtdHlwZTtob3EXAMPLEW16LWRhdGU7eC1hbXotc2VjdXJpdHktdG9rZW4sIFNpZ25hdHVyZT04MzE4EXAMPLEiY2MxZmUzZWU2OWY3NWNkEXAMPLE0Y2I0ZjE1MGU0Zjk5Y2VjODY5ZjE0OWM1ZDAzNDEXAMPLEn0=&payload=e30=

注意:一个 WebSocket 连接可以有多个订阅(即使使用不同的身份验证模式)。实施这一点的一种方法是,为第一个订阅创建 WebSocket 连接,并在取消注册最后一个订阅时关闭它。这可以通过等待几秒钟再关闭 WebSocket 连接进行优化,以避免在取消注册最后一个订阅之后立即订阅应用程序。对于移动应用程序示例,在从一个屏幕更改到另一个屏幕时,在卸载 事件时,它会停止订阅,而在挂载 事件时,将启动另一个订阅。

Lambda 授权

标头内容:

  • "Authorization": <string>:将作为传递的值authorizationToken.

  • "host": <string>: 这是主持人AmazonAppSync GraphQL 终端节点。

例如:

{ "Authorization":"M0UzQzM1MkQtMkI0Ni00OTZCLUI1NkQtMUM0MTQ0QjVBRTczCkI1REEzRTIxLTk5NzItNDJENi1BQjMwLTFCNjRFNzQ2NzlCNQo=", "host":"example1234567890000.appsync-api.us-east-1.amazonaws.com" }

负载内容:

{}

请求 URL:

wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql?header=eyJBdXRob3JpemF0aW9uIjoiZXlKcmFXUWlPaUpqYkc1eGIzQTVlVzVNSzA5UVlYSXJNVEpIV0VGTFNYQmllVTVXTkhoc1FqaFBWVzlZTW5NMldsZHZQU0lzSW1Gc1p5STZJbEpUTWpVMkluMC5leUp6ZFdJaU9pSmhObU5tTWpjd055MHhOamd4TFRRMU5ESXRPV1l4T0MxbE5qWTBNVGcyTmpsa016WWlMQ0psZG1WdWRGOXBaQ0k2SW1Wa016TTVNbU5rTFdOallUTXROR00yT0MxaE5EWXlMVEpsWkdJM1pUTm1ZMkZqWmlJc0luUnZhMlZ1WDNWelpTSTZJbUZqWTJWemN5SXNJbk5qYjNCbElqb2lZWGR6TG1OdloyNXBkRzh1YzJsbmJtbHVMblZ6WlhJdVlXUnRhVzRpTENKaGRYUm9YM1JwYldVaU9qRTFOamswTlRjM01UZ3NJbWx6Y3lJNkltaDBkSEJ6T2x3dlhDOWpiMmR1YVhSdkxXbGtjQzVoY0MxemIzVjBhR1ZoYzNRdE1pNWhiV0Y2YjI1aGQzTXVZMjl0WEM5aGNDMXpiM1YwYUdWaGMzUXRNbDgzT0hZMFNWWmliVkFpTENKbGVIQWlPakUxTmprME5qRXpNakFzSW1saGRDSTZNVFUyT1RRMU56Y3lNQ3dpYW5ScElqb2lOVGd6WmpobVltTXRNemsyTVMwMFl6QTRMV0poWlRBdFl6UXlZMkl4TVRNNU5EWTVJaXdpWTJ4cFpXNTBYMmxrSWpvaU0zRmxhalZsTVhabU16ZDFOM1JvWld3MGRHOTFkREprTVd3aUxDSjFjMlZ5Ym1GdFpTSTZJbVZzYjNKNllXWmxJbjAuQjRjZEp0aDNLRk5wSjZpa1ZwN2U2RFJlZTk1VjZRaS16RUUyREpIN3NIT2wyenhZaTdmLVNtRUdvaDJBRDhlbXhRUllhakJ5ei1yRTRKaDBRT3ltTjJZcy1aSWtNcFZCVFBndS1UTVdEeU9IaERVbVVqMk9QODJ5ZVozd2xaQXRyX2dNNEx6alhVWG1JX0syeUdqdVhmWFRhYTFtdlFFQkcwbVFmVmQ3U2Z3WEItamN2NFJZVmk2ajI1cWdvdzlFdzUydWZ1clBxYUstM1dBS0czMktwVjhKNC1XZWpxOHQwYy15QTdzYjhFbkI1NTFiN1RVOTN1S1JpVlZLM0U1NU5rNUFEUG9hbV9XWUU0NWkzczVxVkFQXy1Jblc3NU5Vb09DR1RzUzhZV01mYjZlY0hZSi0xai1iekEyN3phVDlWamN0WG45YnlORlptS0xwQTJMY3h3IiwiaG9zdCI6ImV4YW1wbGUxMjM0NTY3ODkwMDAwLmFwcHN5bmMtYXBpLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tIn0=&payload=e30=

实时 WebSocket 操作

在启动成功的 WebSocket 握手后AmazonAppSync,客户端需要发送后续消息才能完成与进行连接的步骤。AmazonAppSync 适用于不同的操作。这些消息需要以下数据:

  • type:操作的类型。

  • id:订阅的唯一标识符。我们建议为此目的使用 UUID。

  • payload:关联的负载取决于操作类型。

type 字段是唯一的必填字段,idpayload 可选。

事件序列

要成功启动、建立、注册和处理订阅请求,客户端必须逐步完成以下序列:

  1. 初始化连接 (connection_init)

  2. 连接确认 (connection_ack)

  3. 订阅注册 (start)

  4. 订阅确认 (start_ack)

  5. 处理订阅 (data)

  6. 订阅取消注册 (stop)

连接启动消息

成功握手后,客户端必须发送connection_init用于开始与AmazonAppSync 实施终端节点。如果没有此步骤,将忽略所有其他消息。该消息是通过将下列 JSON 对象字符串化获得的字符串,如下所示:

{ "type": "connection_init" }

连接确认消息

发送 connection_init 消息后,客户端必须等待 connection_ack 消息。接收 connection_ack 前发送的所有消息都将忽略。该消息具体如下:

{ "type": "connection_ack", "payload": { // Time in milliseconds waiting for ka message before the client should terminate the WebSocket connection "connectionTimeoutMs": 300000 } }

保持活动消息

除了连接确认消息外,客户端还会定期接收保持活动消息。如果在连接超时期间未收到保持活动消息,则客户端应终止连接。AmazonAppSync 将继续发送这些消息并为注册的订阅提供服务,直到连接自动关闭(24 小时后)。保持活动状态消息是检测信号,无需由客户端确认。

{ "type": "ka" }

订阅注册消息

晚于connection_ack客户端收到消息后,可以将订阅注册消息发送到AmazonAppSync。此消息是包含以下字段的字符串化 JSON 对象:

  • "id": <string>:订阅的 ID。此 id 对于每个订阅都必须唯一,否则服务器将返回一个错误,指示订阅 id 重复。

  • "type": "start":常量 <string> 参数。

  • "payload": <Object>:此项包含与订阅相关的信息。

    • "data": <string>:包含 GraphQL 查询和变量的字符串化 JSON 对象。

      • "query": <string>:GraphQL 操作。

      • "variables": <Object>:包含查询的变量。

    • "extensions": <Object>:此项包含授权对象。

  • "authorization": <Object>:此项包含授权所需的字段。

订阅注册的授权对象

基于的标头参数格式AmazonAppSync API 授权模式部分中的相同规则适用于授权对象。唯一的例外是 IAM,此时 Sigv4 签名信息略有不同。有关详细信息,请参阅 IAM 示例。

使用 Amazon Cognito 用户池的示例:

{ "id": "ee849ef0-cf23-4cb8-9fcb-152ae4fd1e69", "payload": { "data": "{\"query\":\"subscription onCreateMessage {\\n onCreateMessage {\\n __typename\\n message\\n }\\n }\",\"variables\":{}}", "extensions": { "authorization": { "Authorization": "eyEXAMPLEiJjbG5xb3A5eW5MK09QYXIrMTJEXAMPLEBieU5WNHhsQjhPVW9YMnM2WldvPSIsImFsZyI6IlEXAMPLEn0.eyJzdWIiOiJhNmNmMjcwNy0xNjgxLTQ1NDItEXAMPLENjY0MTg2NjlkMzYiLCJldmVudF9pZCI6ImU3YWVmMzEyLWUEXAMPLEY0Zi04YjlhLTRjMWY5M2Q5ZTQ2OCIsInRva2VuX3VzZSI6ImFjY2VzcyIsIEXAMPLEIjoiYXdzLmNvZ25pdG8uc2lnbmluLnVzZXIuYWRtaW4iLCJhdXRoX3RpbWUiOjE1Njk2MTgzMzgsImlzcyI6Imh0dEXAMPLEXC9jb2duaXRvLWlkcC5hcC1zb3V0aGVhc3QtMi5hbWF6b25hd3MuY29tXC9hcC1zbEXAMPLEc3QtMl83OHY0SVZibVAiLCJleHAiOjE1NzAyNTQ3NTUsImlhdCI6MTU3MDI1MTE1NSwianRpIjoiMmIEXAMPLEktZTVkMi00ZDhkLWJiYjItNjA0YWI4MDEwOTg3IiwiY2xpZW50X2lkIjoiM3FlajVlMXZmMzd1EXAMPLE0dG91dDJkMWwiLCJ1c2VybmFtZSI6ImVsb3J6YWZlIn0.CT-qTCtrYeboUJ4luRSTPXaNewNeEXAMPLE14C6sfg05tO0fOMpiUwj9k19gtNCCMqoSsjtQoUweFnH4JYa5EXAMPLEVxOyQEQ4G7jQrt5Ks6STn53vuseR3zRW9snWgwz7t3ZmQU-RWvW7yQU3sNQRLEXAMPLEcd0yufBiCYs3dfQxTTdvR1B6Wz6CD78lfNeKqfzzUn2beMoup2h6EXAMPLE4ow8cUPUPvG0DzRtHNMbWskjPanu7OuoZ8iFO_Eot9kTtAlVKYoNbWkZhkD8dxutyoU4RSH5JoLAnrGF5c8iKgv0B2dfEXAMPLEIihxaZVJ9w9w48S4EXAMPLEcA", "host": "example1234567890000.appsync-api.us-east-1.amazonaws.com" } } }, "type": "start" }

使用 IAM 的示例:

{ "id": "eEXAMPLE-cf23-1234-5678-152EXAMPLE69", "payload": { "data": "{\"query\":\"subscription onCreateMessage {\\n onCreateMessage {\\n __typename\\n message\\n }\\n }\",\"variables\":{}}", "extensions": { "authorization": { "accept": "application/json, text/javascript", "content-type": "application/json; charset=UTF-8", "X-Amz-Security-Token": "AgEXAMPLEZ2luX2VjEAoaDmFwLXNvdXRoZWFEXAMPLEcwRQIgAh97Cljq7wOPL8KsxP3YtDuyc/9hAj8PhJ7Fvf38SgoCIQDhJEXAMPLEPspioOztj++pEagWCveZUjKEn0zyUhBEXAMPLEjj//////////8BEXAMPLExODk2NDgyNzg1NSIMo1mWnpESWUoYw4BkKqEFSrm3DXuL8w+ZbVc4JKjDP4vUCKNR6Le9C9pZp9PsW0NoFy3vLBUdAXEXAMPLEOVG8feXfiEEA+1khgFK/wEtwR+9zF7NaMMMse07wN2gG2tH0eKMEXAMPLEQX+sMbytQo8iepP9PZOzlZsSFb/dP5Q8hk6YEXAMPLEYcKZsTkDAq2uKFQ8mYUVA9EtQnNRiFLEY83aKvG/tqLWNnGlSNVx7SMcfovkFDqQamm+88y1OwwAEYK7qcoceX6Z7GGcaYuIfGpaX2MCCELeQvZ+8WxEgOnIfz7GYvsYNjLZSaRnV4G+ILY1F0QNW64S9Nvj+BwDg3ht2CrNvpwjVYlj9U3nmxE0UG5ne83LL5hhqMpm25kmL7enVgw2kQzmU2id4IKu0C/WaoDRuO2F5zE63vJbxN8AYs7338+4B4HBb6BZ6OUgg96Q15RA41/gIqxaVPxyTpDfTU5GfSLxocdYeniqqpFMtZG2n9d0u7GsQNcFkNcG3qDZm4tDo8tZbuym0a2VcF2E5hFEgXBa+XLJCfXi/77OqAEjP0x7Qdk3B43p8KG/BaioP5RsV8zBGvH1zAgyPha2rN70/tT13yrmPd5QYEfwzexjKrV4mWIuRg8NTHYSZJUaeyCwTom80VFUJXG+GYTUyv5W22aBcnoRGiCiKEYTLOkgXecdKFTHmcIAejQ9Welr0a196Kq87w5KNMCkcCGFnwBNFLmfnbpNqT6rUBxxs3X5ntX9d8HVtSYINTsGXXMZCJ7fnbWajhg/aox0FtHX21eF6qIGT8j1z+l2opU+ggwUgkhUUgCH2TfqBj+MLMVVvpgqJsPKt582caFKArIFIvO+9QupxLnEH2hz04TMTfnU6bQC6z1buVe7h+tOLnh1YPFsLQ88anib/7TTC8k9DsBTq0ASe8R2GbSEsmO9qbbMwgEaYUhOKtGeyQsSJdhSk6XxXThrWL9EnwBCXDkICMqdntAxyyM9nWsZ4bL9JHqExgWUmfWChzPFAqn3F4y896UqHTZxlq3WGypn5HHcem2Hqf3IVxKH1inhqdVtkryEiTWrI7ZdjbqnqRbl+WgtPtKOOweDlCaRs3R2qXcbNgVhleMk4IWnF8D1695AenU1LwHjOJLkCjxgNFiWAFEPH9aEXAMPLExA==", "Authorization": "AWS4-HMAC-SHA256 Credential=XXXXXXXXXXXXXXXXXXXX/20200401/us-east-1/appsync/aws4_request, SignedHeaders=accept;content-encoding;content-type;host;x-amz-date;x-amz-security-token, Signature=b90131a61a7c4318e1c35ead5dbfdeb46339a7585bbdbeceeaff51f4022eb1fd", "content-encoding": "amz-1.0", "host": "example1234567890000.appsync-api.us-east-1.amazonaws.com", "x-amz-date": "20200401T001010Z" } } }, "type": "start" }

Sigv4 签名不需要将 /connect 附加到 URL,并使用 JSON 字符串化 GraphQL 操作替换 data。以下是 Sigv4 签名请求的示例:

{ url: "https://example1234567890000.appsync-api.us-east-1.amazonaws.com/graphql", data: "{\"query\":\"subscription onCreateMessage {\\n onCreateMessage {\\n __typename\\n message\\n }\\n }\",\"variables\":{}}", method: "POST", headers: { "accept": "application/json, text/javascript", "content-encoding": "amz-1.0", "content-type": "application/json; charset=UTF-8", } }

订阅确认消息

发送订阅开始消息后,客户端应等待AmazonAppSync 发送start_ack消息。start_ack表示订阅成功。该消息是以下字符串:

订阅成功示例:

{ "type": "start_ack", "id": "eEXAMPLE-cf23-1234-5678-152EXAMPLE69" }

错误消息

如果连接启动或订阅注册失败,或者从服务器终止订阅,服务器将向客户端发送以下错误消息:

  • "type": "error":常量 <string> 参数。

  • "id": <string>:对应已注册订阅的 id(如果相关)。

  • "payload" <Object>:此对象包含对应的错误信息。

例如:

{ "type": "error", "payload": { "errors": [ { "errorType": "LimitExceededError", "message": "Rate limit exceeded" } ] } }

处理数据消息

当客户提交突变时AmazonAppSync 识别对其感兴趣的所有订阅者并发送"type":"data"使用相应的订阅向每个人发送消息id用于"start"订阅操作。客户端应跟踪它发送的订阅 id,这样在收到数据消息时,客户端可以将其与对应的订阅匹配。

  • "type": "data":常量 <string> 参数。

  • "id": <string>:对应已注册订阅的 id

  • "payload" <Object>:此对象包含具有订阅信息的数据对象。

例如:

{ "type": "data", "id": "ee849ef0-cf23-4cb8-9fcb-152ae4fd1e69", "payload": { "data": { "onCreateMessage": { "__typename": "Message", "message": "test" } } } }

订阅取消注册消息

当应用程序希望停止侦听订阅事件时,客户端应该发送带有以下字符串化 JSON 对象的消息:

  • "type": "stop":常量 <string> 参数。

  • "id": <string>:将取消注册的订阅的 id

例如:

{ "type":"stop", "id":"ee849ef0-cf23-4cb8-9fcb-152ae4fd1e69" }

AmazonAppSync 发回带有以下字符串化 JSON 对象的确认消息:

  • "type": "complete":常量 <string> 参数。

  • "id": <string>:取消注册的订阅的 ID。

收到该消息后,将不再为此特定订阅发送任何消息。

例如:

{ "type":"complete", "id":"eEXAMPLE-cf23-1234-5678-152EXAMPLE69" }

断开 WebSocket 连接

在断开连接之前,客户端应具有必要的逻辑,检查当前没有通过 WebSocket 连接执行任何操作,以避免数据丢失。在断开与 WebSocket 的连接之前,应先取消注册所有订阅。