

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

# 在中使用实时数据应用程序的订阅 Amazon AppSync
<a name="aws-appsync-real-time-data"></a>

**重要**  
从 2025 年 3 月 13 日起， WebSockets 您可以使用 Amazon AppSync 事件构建实时 PubSub API。有关更多信息，请参阅[事件开发者指南 WebSocket中的通过发布Amazon](https://docs.amazonaws.cn/appsync/latest/eventapi/publish-websocket.html)*AppSync 事件*。

Amazon AppSync允许您利用订阅来实现实时应用程序更新、推送通知等。当客户端调用 GraphQL 订阅操作时，由自动建立和维护安全 WebSocket 连接。 Amazon AppSync然后，应用程序可以将数据源中的数据实时分发给订阅者，同时 Amazon AppSync 持续管理应用程序的连接和扩展需求。以下各节将向您展示订阅 Amazon AppSync的工作原理。

## GraphQL 架构订阅指令
<a name="graphql-schema-subscription-directives"></a>

中的订阅 Amazon AppSync 是作为对突变的响应而调用的。这意味着您可以通过在突变上指定 GraphQL 架构指令来 Amazon AppSync 实时创建任何数据源。

 Amazon Amplify 客户端库会自动处理订阅连接管理。这些库使用 pure WebSockets 作为客户端和服务之间的网络协议。

**注意**  
要控制订阅连接时的授权，您可以使用 Amazon Identity and Access Management (IAM)、、Amazon Cognito 身份池或 Amazon Cognito 用户池进行字段级授权。 Amazon Lambda要对订阅进行精细的访问控制，您可以将解析器附加到订阅字段，并使用调用者和 Amazon AppSync 数据源的身份执行逻辑。有关更多信息，请参阅 [配置授权和身份验证以保护您的 GraphQL APIs](security-authz.md)。

订阅由变更触发，并将变更选择集发送给订阅者。

以下示例展示了如何使用 GraphQL 订阅。它没有指定数据源，因为数据源可能是 Lambda、Amazon DynamoDB 或亚马逊服务。 OpenSearch 

要开始使用订阅，您必须将订阅入口点添加到您的架构中，如下所示：

```
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
    }
}
```

客户端连接和工具需要使用该订阅查询。

对于纯 WebSockets 客户端，选择集筛选是针对每个客户机进行的，因为每个客户机都可以定义自己的选择集。在这种情况下，订阅选择集必须是变更选择集的子集。例如，链接到变更 `addPost(...){id author title url version}` 的订阅 `addedPost{author title}` 仅接收文章的作者和标题。它不会接收其他字段。但是，如果变更在其选择集中缺少作者，则订阅者将获得作者字段的 `null` 值（或者，如果在架构中将作者字段定义为必填/非 Null 的情况下，将得到错误）。

使用 pure 时，订阅选择集是必不可少的 WebSockets。如果订阅中未明确定义字段，则 Amazon 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`。

要在客户端上设置订阅，请参阅[使用 Amplify 客户端构建客户端应用程序](building-a-client-app.md)。

## 使用订阅参数
<a name="using-subscription-arguments"></a>

使用 GraphQL 订阅的一个重要部分是，了解何时以及如何使用参数。您可以进行细微的更改，以修改何时以及如何向客户端通知发生的变更。为此，请参阅快速入门章节中创建“Todo”的示例架构。对于该示例架构，定义了以下变更：

```
type Mutation {
    createTodo(input: CreateTodoInput!): Todo
    updateTodo(input: UpdateTodoInput!): Todo
    deleteTodo(input: DeleteTodoInput!): Todo
}
```

在默认示例中，客户端可以使用不带参数的 `onUpdateTodo` `subscription` 订阅任何 `Todo` 的更新：

```
subscription OnUpdateTodo {
  onUpdateTodo {
    description
    id
    name
    when
  }
}
```

您可以使用 `subscription` 的参数对其进行筛选。例如，要仅在更新具有特定 `ID` 的 `todo` 时触发 `subscription`，请指定 `ID` 值：

```
subscription OnUpdateTodo {
  onUpdateTodo(id: "a-todo-id") {
    description
    id
    name
    when
  }
}
```

您也可以传递多个参数。例如，以下 `subscription` 说明了如何在特定地点和时间获取任何 `Todo` 更新的通知：

```
subscription todosAtHome {
  onUpdateTodo(when: "tomorrow", where: "at home") {
    description
    id
    name
    when
    where
  }
}
```

请注意，所有参数都是可选的。如果未在 `subscription` 中指定任何参数，您将订阅应用程序中发生的所有 `Todo` 更新。不过，您可以更新 `subscription` 的字段定义以要求使用 `ID` 参数。这会强制提供特定 `todo` 的响应，而不是提供所有 `todo` 的响应：

```
onUpdateTodo(
  id: ID!,
  name: String,
  when: String,
  where: String,
  description: String
): Todo
```

### 参数 null 值具有含义
<a name="argument-null-value-has-meaning"></a>

在中进行订阅查询时 Amazon AppSync，`null`参数值对结果的筛选方式与完全省略参数的方式不同。

让我们回到创建 Todo 的 Todo API 示例。请参阅快速入门章节中的示例架构。

让我们修改架构以在 `Todo` 类型上包含新的 `owner` 字段，该字段描述所有者是谁。`owner` 字段不是必填字段，只能在 `UpdateTodoInput` 上设置该字段。请参阅以下简化架构版本：

```
type Todo {
  id: ID!
  name: String!
  when: String!
  where: String!
  description: String!
  owner: String
}

input CreateTodoInput {
  name: String!
  when: String!
  where: String!
  description: String!
}

input UpdateTodoInput {
  id: ID!
  name: String
  when: String
  where: String
  description: String
  owner: String
}

type Subscription {
    onUpdateTodo(
        id: ID,
        name: String,
        when: String,
        where: String,
        description: String
    ): Todo @aws_subscribe(mutations: ["updateTodo"])
}
```

以下订阅返回所有 `Todo` 更新：

```
subscription MySubscription {
  onUpdateTodo {
    description
    id
    name
    when
    where
  }
}
```

如果您修改前面的订阅以添加字段参数 `owner: null`，您现在会问一个不同的问题。该订阅现在注册客户端，以获得所有未提供所有者的 `Todo` 更新的通知。

```
subscription MySubscription {
  onUpdateTodo(owner: null) {
    description
    id
    name
    when
    where
  }
}
```

**注意**  
**自 2022 年 1 月 1 日起，MQTT WebSockets 已不再可用作 GraphQL 订阅的协议。 Amazon AppSync APIsPure WebSockets 是中唯一支持的协议 Amazon AppSync。**  
基于 2019 年 11 月之后发布的 Amazon AppSync SDK 或 Amplify 库的客户 WebSockets 默认会自动使用 pure。将客户端升级到最新版本允许他们使用 Amazon AppSync纯 WebSockets 引擎。  
Pur WebSockets e 具有更大的有效载荷大小 (240 KB)、更多的客户端选项和改进的 CloudWatch 指标。有关使用纯 WebSocket 客户端的更多信息，请参阅[在中构建实时 WebSocket 客户端 Amazon AppSync](real-time-websocket-client.md)。