基于位置的 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 客户端中的多个事件?

AWS AppSync 订阅:基于更新文档中的对象的复杂授权

AWS Amplify AppSync 订阅无法正常工作

迁移到纯 websocket 后,我​​在 AWS Appsync 上收到 GraphQL 订阅错误

用于 AWS AppSync 中的异步计算的 Graphql 订阅

AWS Appsync 订阅 - “连接失败:连接握手错误”