AppSync:本质上是一种 GraphQL 即服务
去年我去参加一个会议时,了解到AWS产品线新增了一项服务,叫做AppSync。它本质上是一种以无服务器方式托管GraphQL服务的方法。上个月我试用了一下,这篇文章我想和大家分享一下我的发现。
总结:如果您已经在使用或想要使用 GraphQL,那么您绝对应该尝试一下 AppSync!
AppSync 能为您做什么?
您只需要两样东西即可开始:一个模式和一些解析器。您上传的模式是一个标准的GraphQL 模式。AppSync 将接受基于此模式的查询和变更。您可以随时更改此模式,甚至无需部署新版本,它就会立即开始使用。
你需要的第二部分是解析器。这些解析器会将查询中的字段映射到该字段的实际数据,这通常意味着从某个数据存储中获取数据。你可以将 Lambda 函数作为解析器,也可以使用各种不同的数据库作为数据源。
一个基本示例
为了更好地理解其工作原理,这里举个简单的例子。假设有一个像这样的网站。网站上有用户,每个用户都有一个 ID,这些用户都有帖子。下面的模式将这些类型结合起来,并提供了一个查询语句来获取用户的数据:
type Query {
user(id: Int): User
}
type User {
id: Int!
name: String!
posts(count: Int): [Post]
}
type Post {
id: Int!
title: String!
content: String!
}
为了解析用户或帖子,我们将运行以下 lambda 解析器:
exports.user = async (event, context) => {
const body = await fetchUser(event.arguments.id);
return {
statusCode: 200,
body: JSON.stringify(body)
};
};
exports.posts = async (event, context) => {
const { id, count } = event.arguments;
const body = await fetchPostsForUser(id, count);
return {
statusCode: 200,
body: JSON.stringify(body)
};
};
这段代码创建了两个 Lambda 函数,接下来我们需要将它们与模式中的字段关联起来。为此,我们需要指定请求和响应映射。
请求映射会将查询中提供的数据(例如用户 ID)转换为 Lambda 函数中可用的事件变量。响应映射会将 Lambda 函数中给出的响应转换回我们在模式中定义的结构。
对于文章解析器来说,它可能看起来像这样:
Request mapping:
{
"version" : "2017-02-28",
"operation": "Invoke",
"payload": {
"arguments": $util.toJson({
"id": $context.source.id,
"count": $context.arguments.count
})
}
}
Response mapping:
#if($ctx.result.statusCode == 200)
$ctx.result.body
#elseif($ctx.result.statusCode == 404)
$util.error("Not found")
#else
$util.error("Error")
#end
你可以在这些映射中添加一些非常巧妙的功能。以下请求映射将直接查询 DynamoDB,而不是使用 Lambda 函数:
Request mapping:
{
"version" : "2017-02-28",
"operation" : "GetItem",
"key" : {
"id" : {
"S" : "${context.arguments.id}"
}
}
}
如果您想尝试一些示例,AWS 提供了示例设置,其中包含了入门所需的一切。
为什么要使用它?
我推荐大家尝试使用 AppSync 的原因有以下几点。
因为它便宜。
与其他无服务器服务一样,您只需为实际使用的资源付费,无需支付任何额外费用。服务启动和运行没有基础成本。这意味着对于用户基数较小的应用程序来说,这是一种非常经济高效的 GraphQL 服务器运行方式。目前,每百万次请求只需支付 4 美元,这与 API Gateway 的定价相当,并且仅比最便宜的 AWS Lambda 函数贵 5 倍左右。
因为它能承受任何负载
即使是黑色星期五,您的服务也能正常运行。无需任何额外设置。在这方面,它与 Lambda 非常相似,您只需提供 GraphQL schema,它就会自动运行。
因为它很容易与 DynamoDB 或 Lambda 集成。
目前,AppSync 提供 DynamoDB、RDS、Elasticsearch、Lambda 和 HTTP 的解析器。对于每种数据源,您都需要将 GraphQL 查询中的数据映射到该数据源适用的格式。每种数据源都有清晰的文档,方便您快速上手。值得一提的是,对于大多数常用数据库,您无需创建 Lambda 函数即可运行查询。
因为它支持实时订阅
AppSync 提供了一系列客户端库,支持实时订阅。有了这些库,客户端可以保持与 AppSync 的连接,并订阅和接收已发生的变更更新。我认为这在某些使用场景下非常强大,您可以在这里了解更多信息。
但它也有缺点吗?
表现
在试用过程中,我们发现 AppSync 内部的开销相当大。即使只连接到一个返回值的 Lambda 函数,响应时间也很少低于 150 毫秒。在大多数情况下,这或许可以接受。但与自行运行 GraphQL 服务器相比,这个速度确实慢了很多。即使与在很多方面提供类似服务的 API Gateway 相比,它的速度也明显更慢。
局限性
AppSync 仍然是一个相当新的功能,去年四月才正式发布。因此,它还有一些不完善的地方。目前对我来说最大的不足是 RDS 解析器仅适用于Aurora Serverless。不过幸运的是,你仍然可以编写自己的 Lambda 函数来从任何类型的 RDS 中获取数据。
需要注意的是,并发性存在限制。当需要解析同一类型的对象列表时,最多只能同时运行 5 个查询/Lambda 函数/HTTP 调用。根据您的具体使用场景,您可能会遇到此限制,也可能不会。
与数据源耦合有点麻烦
我喜欢使用 CloudFormation 来部署我的堆栈。当您想要使用 CloudFormation 部署 AppSync 堆栈时,所有解析器也需要在堆栈模板中定义。这包括您想要执行的任何查询,以及您想要在运行这些查询之前和之后应用的任何业务逻辑。
将查询和逻辑直接放在堆栈定义旁边并非理想之选。这几乎不可能测试你定义的逻辑。此外,业务逻辑的变更部署也会导致堆栈变更。这意味着回滚和金丝雀发布等操作不再简单。
即使您不使用 CloudFormation,也需要指定模式和解析器之间的映射关系。AWS 选择使用Apache Velocity 模板语言来实现这一点。遗憾的是,您在此处添加的逻辑将难以测试和调试。但这并非致命缺陷,而且随着产品的发展,这方面很可能会得到改进。
结论
AppSync 是 AWS 产品线中一个非常实用的补充。它虽然还有一些不足之处,但它满足了一个明确且日益普及的需求。如果您计划使用 GraphQL 构建应用,我建议您不妨试用一下。
文章来源:https://dev.to/raoulmeyer/appsync-basically-graphql-as-a-service-3bp1