基于位置的 AWS AppSync 事件订阅
Posted
技术标签:
【中文标题】基于位置的 AWS AppSync 事件订阅【英文标题】:AWS AppSync Event Subscription based on Location 【发布时间】:2018-12-20 23:17:10 【问题描述】:我了解如何通过AppSync
执行地理空间查询,以通过附加链接到ElasticSesarch
的解析器(如described here)来查找距gps 坐标距离范围内的事件。
但是,如果我希望我的客户也订阅在此距离范围内创建的新事件,该怎么办?
-
用户订阅了一个位置
如果在该位置附近创建了事件,请通知用户
我知道我可以将解析器附加到订阅类型,但当我只想通过检查 gps 坐标之间的距离来过滤订阅时,它似乎迫使您提供数据源。
【问题讨论】:
【参考方案1】:这是一个很好的问题,我认为有几种方法可以解决这个问题。这里最困难的部分是,您将找到一种方法来提出“哪些订阅对此位置的事件感兴趣”这个问题。这是一种可能的前进道路。
以下假设这些架构部分:
// Whatever custom object has a location
type Post
id: ID!
title: String
location: Location
input PublishPostInput
id: ID!
title: String
location: Location
subscriptionID: ID
type PublishPostOutput
id: ID!
title: String
location: Location
subscriptionID: ID
type Location
lat: Float,
lon: Float
input LocationInput
lat: Float,
lon: Float
# A custom type to hold custom tracked subscription information
# for location discover
type OpenSubscription
subscriptionID: ID!
location: Location
timestamp: String!
type OpenSubscriptionConnection
items: [OpenSubscription]
nextToken: String
type Query
# Query elasticsearch index for relevant subscriptions
openSubscriptionsNear(location: LocationInput, distance: String): OpenSubscriptionConnection
type Mutation
# This mutation uses a local resolver (e.g. a resolver with a None data source) and simply returns the input as is.
publishPostToSubscription(input: PublishPostInput): PublishPostOutput
type Subscription
# Anytime someone passes an object with the same subscriptionID to the "publishPostToSubscription" mutation field, get updated.
listenToSubscription(subscriptionID: ID!): PublishPostOutput
@aws_subscribe(mutations:["publishPostToSubscription"])
假设您使用 DynamoDB 作为主要事实来源,请设置一个调用“PublishIfInRange”lambda 函数的 DynamoDB 流。 “PublishIfInRange”函数看起来像这样
// event - location: lat, lon , id, title, ...
function lambdaHandler(event)
const relevantSubscriptions = await callGraphql(`
query GetSubscriptions($location: LocationInput)
openSubscriptionsNear(location:$location, distance: "10 miles")
subscriptionID
`, variables: location: event.location )
for (const subscription of relevantSubscriptions)
callGraphql(`
mutation PublishToSubscription($subID: ID!, $obj: PublishPostInput)
publishPostToSubscription(input: $obj)
id
title
location lat lon
subscriptionID
`, variables: input: ...subscription, ...event )
您需要维护一个按位置索引的订阅注册表。一种方法是让您的客户端应用程序调用一个突变,该突变创建一个具有位置和订阅 ID 的订阅对象(例如,mutation makeSubscription(loc: $loc) ...
假设您使用 $util.autoId() 在解析器中生成订阅 ID)。获得订阅 ID 后,您可以通过 graphql 进行订阅调用,并将订阅 ID 作为参数传入(例如subscription listenToSubscription(subscriptionID: "my-id") id title location lat lon
)。当您进行上述订阅调用时,AppSync 会创建一个主题并授权当前用户订阅该主题。主题对于被调用的订阅字段和传递给订阅字段的参数集是唯一的。也就是说,主题只接收对象
现在,无论何时创建对象,记录都会通过 DynamoDB 流转到 lambda 函数。 lambda 函数在 elasticsearch 中查询该对象附近的所有开放订阅,然后将记录发布到每个开放订阅。
我相信这应该可以让您走得更远,但如果您有数百万用户处于紧张状态,您可能会遇到扩展问题。希望这会有所帮助
【讨论】:
要扩展它,您可以更明智地了解如何拆分订阅 ID。例如,您可以将地图分成 N 个小块,然后在您的客户端上让它们订阅网格中最近的 Y 个块,并在客户端上进行任何细粒度过滤。这样一来,您最多只能拥有 N 个订阅 ID,因此与每个用户都有自己的订阅相比,扇出过程会小得多。 考虑到扩容问题和用户端维护多个订阅渠道的成本,是否更频繁地查询以确保用户近乎实时地更新? 如果不需要真正的实时性,轮询是一种更简单且经济高效的选择以上是关于基于位置的 AWS AppSync 事件订阅的主要内容,如果未能解决你的问题,请参考以下文章
AWS AppSync 订阅:基于更新文档中的对象的复杂授权
迁移到纯 websocket 后,我在 AWS Appsync 上收到 GraphQL 订阅错误