【问题标题】:AWS AppSync Event Subscription based on Location基于位置的 AWS AppSync 事件订阅
【发布时间】:2018-12-20 23:17:10
【问题描述】:

我了解如何通过AppSync 执行地理空间查询,以通过附加链接到ElasticSesarch 的解析器(如described here)来查找距gps 坐标距离范围内的事件。

但是,如果我希望我的客户也订阅在此距离范围内创建的新事件,该怎么办?

  1. 用户订阅了一个位置
  2. 如果在该位置附近创建了事件,请通知用户

我知道我可以将解析器附加到订阅类型,但当我只想通过检查 gps 坐标之间的距离来过滤订阅时,它似乎迫使您提供数据源。

【问题讨论】:

    标签: amazon-web-services elasticsearch graphql aws-appsync aws-elasticsearch


    【解决方案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,因此与每个用户都有自己的订阅相比,扇出过程会小得多。
    • 考虑到扩容问题和用户端维护多个订阅渠道的成本,是否更频繁地查询以确保用户近乎实时地更新?
    • 如果不需要真正的实时性,轮询是一种更简单且经济高效的选择
    猜你喜欢
    • 2018-09-30
    • 2019-04-03
    • 2019-09-16
    • 2019-12-27
    • 2018-12-28
    • 2019-02-14
    • 2019-06-15
    • 2022-07-04
    • 2019-03-21
    相关资源
    最近更新 更多