实时数据
GraphQL 架构订阅指令
在 AWS AppSync 中,订阅是作为更改的响应调用的。这就意味着,您可以在 AWS AppSync 中针对更改指定 GraphQL 架构指令,从而实时更新任何数据源。AWS AppSync 客户端开发工具包自动处理订阅连接管理。此开发工具包使用纯 WebSocket 或 WebSocket 上的 MQTT 作为客户端和服务之间的网络协议。该协议取决于您正在使用的客户端版本。
注意:要将连接时的授权控制为订阅,您可以利用 IAM、Amazon Cognito、身份池或 Amazon Cognito 用户池等控件进行字段级的授权。如需针对订阅进行精细化的访问控制,您可以将解析程序附加到订阅字段,并使用调用者和 AWS AppSync 数据源的身份执行逻辑。有关更多信息,请参阅安全。
订阅由更改触发,并将更改选择集发送给订阅者。
以下示例展示了如何使用 GraphQL 订阅。该示例并未指定数据源,因为数据源可能是 AWS Lambda、Amazon DynamoDB 或 Amazon Elasticsearch Service。
要开始使用订阅,您必须在架构中添加订阅入口点,如下所示:
schema { query: Query mutation: Mutation subscription: Subscription }
假设有一个博客站点,您希望订阅新博文和现有博客的变更。为此,请在架构中添加以下 Subscription
定义:
type Subscription { addedPost: Post updatedPost: Post deletedPost: Post }
进一步假设有以下更改:
type Mutation { addPost(id: ID! author: String! title: String content: String url: String): Post! updatePost(id: ID! author: String! title: String content: String url: String ups: Int! downs: Int! expectedVersion: Int!): Post! deletePost(id: ID!): Post! }
对于希望收到通知的每个订阅,您可以添加 @aws_subscribe(mutations: ["mutation_field_1", "mutation_field_2"])
指令,使这些字段成为实时字段,如下所示:
type Subscription { addedPost: Post @aws_subscribe(mutations: ["addPost"]) updatedPost: Post @aws_subscribe(mutations: ["updatePost"]) deletedPost: Post @aws_subscribe(mutations: ["deletePost"]) }
由于 @aws_subscribe(mutations: ["",..,""])
可接收一组更改输入,您可指定触发订阅的多项更改。如果您从客户端订阅,您的 GraphQL 查询可能是下面这样:
subscription NewPostSub { addedPost { __typename version title content author url } }
客户端连接和工具需要上述的订阅查询。但是,如果您使用 WebSocket 上的 MQTT,则触发更改的客户端将指定订阅者接收的选择集。为了演示这一点,假设其他移动客户端或服务器发生了更改(例如,mutation addPost(...){id author title }
)。在这种情况下,内容、版本和 URL 不会发布给订阅者。而是发布 ID、作者和标题。
如果您使用纯 WebSocket 客户端,则选择集筛选将按每个客户端完成,因为每个客户端都可以定义自己的选择集。在这种情况下,订阅选择集必须是更改选择集的子集。例如,链接到更改
addPost(...){id author title url version}
的订阅 addedPost{author title}
仅接收作者和帖子标题。它不会接收其他字段。但是,如果更改在其选择集中缺少作者,则订阅者将获得作者字段的 null
值(或者,如果在架构中将作者字段定义为必填/非 Null 的情况下,将得到错误)。
此外,如果您在应用程序中使用 WebSocket 上的 MQTT,则需要注意一些更改。如果您未使用必填字段配置关联的订阅选择集,而是依靠更改字段将数据推送到订阅的客户端,则当您转至纯 WebSocket 时,行为将发生变化。在上面的示例中,其选择集中未定义“作者”字段的订阅仍将通过 WebSocket 上的 MQTT 返回作者姓名,因为该字段是在更改中定义的,相同的行为不适用于纯 WebSocket。使用纯 WebSocket 时,订阅选择集非常重要:如果订阅中未明确定义字段,则 AWS AppSync 将不会返回该字段。
在以上示例中,订阅没有参数。假设您的架构看上去与下面类似:
type Subscription { updatedPost(id:ID! author:String): Post @aws_subscribe(mutations: ["updatePost"]) }
在这种情况下,您的客户端定义了订阅,如下所示:
subscription UpdatedPostSub { updatedPost(id:"XYZ", author:"ABC") { title content } }
您的架构中 subscription
字段的返回类型必须与相应的更改字段的返回类型匹配。在上一示例中,addPost
和 addedPost
返回的类型都是 Post
。
要在客户端上设置订阅,请参阅生成客户端应用。
使用订阅参数
使用 GraphQL 订阅时,理解何时及如何使用参数很重要,因为您可通过细微的改动修改如何向客户端通知以及何时通知发生的更改。为此,请参阅快速入门部分启动示例架构中的示例架构,该架构创建了“事件”和“评论”。在示例架构中,将出现以下更改:
type Mutation { createEvent( name: String!, when: String!, where: String!, description: String! ): Event deleteEvent(id: ID!): Event commentOnEvent(eventId: ID!, content: String!, createdAt: String!): Comment }
在默认示例中,客户端可以订阅传递特定 eventId 参数时的评论:
type Subscription { subscribeToEventComments(eventId: String!): Comment @aws_subscribe(mutations: ["commentOnEvent"]) }
但如果您希望允许客户端订阅单次事件或所有事件,可以从订阅原型中移除感叹号 (!),使这一参数成为可选参数:
subscribeToEventComments(eventId: String): Comment
这样更改之后,省略此参数的客户端将收到所有事件的评论。此外,如果您希望客户端显式订阅所有事件的所有评论,应删除参数,如下所示:
subscribeToEventComments: Comment
这些内容可用于一个或多个事件的评论。如果您想要了解创建的所有事件,可以执行以下操作:
type Subscription { subscribeToNewEvents: Event @aws_subscribe(mutations: ["createEvent"]) }
也可传递多个参数。例如,如果您希望获得特定时间和地点发生的新事件的通知,可以执行以下操作:
type Subscription { subscribePlaceDate(where: String! when: String!): Event @aws_subscribe(mutations: ["createEvent"]) }
因此,客户端应用程序现在可以执行以下操作:
subscription myplaces { subscribePlaceDate(where: "Seattle" when: "Saturday"){ id name description } }
参数 null 值具有含义
在 AWS AppSync 中进行订阅查询时,null
参数值将以不同于完全省略参数的方式筛选结果。
让我们用一个例子来说明。让我们回到事件应用程序示例,我们可以在其中创建事件并发布有关事件的评论。请参阅快速入门部分启动示例架构中的示例架构。
让我们修改架构,以在Comment
字段中包含一个新的 location
字段,用于描述评论的发送位置。该值可以是一组坐标或一个位置。请参阅以下架构,请注意我们为了简洁起见已将其删除:
type Comment { # The id of the comment's parent event. eventId: ID! # A unique identifier for the comment. commentId: String! # The comment's content. content: String # Location where the comment was made location: String } type Event { id: ID! name: String where: String when: String description: String } type Mutation { commentOnEvent(eventId: ID!, location: String, content: String): Comment } type Subscription { subscribeToEventComments(eventId: String!, location: String, content: String): Comment @aws_subscribe(mutations: ["commentOnEvent"]) }
请注意新的可选字段 Comment.location
。
现在,假如我们想要获得针对特定事件发布的所有评论的通知,我们将编写以下订阅:
subscribeToEventComments(eventId: "1") { eventId commentId location content }
现在,如果我们要将字段参数 location: null
添加到上面的订阅中,
subscribeToEventComments(eventId: "1" location: null) { eventId commentId location content }
我们现在会问一个不同的问题。此订阅现在注册客户端以获得未提供特定事件位置的所有评论的通知。