【问题标题】:How can I create a Twitter-like streaming API with parameterized filtering?如何使用参数化过滤创建类似于 Twitter 的流 API?
【发布时间】:2016-05-31 04:26:03
【问题描述】:

我正在尝试开发与 Twitter 的流 API (https://dev.twitter.com/streaming/reference/post/statuses/filter) 具有相同功能的数据流 API,即具有过滤功能的数据流。我正在生成大量数据并希望将其提供给客户。

我了解如何制作一个为所有客户提供相同数据的应用。这相对容易。我遇到的困难来自于允许客户指定数据过滤器并为每个客户提供独特的数据。

我的想法:

首先我想打开一个流式 http 请求(比如 Twitter)。我可以创建一个接受带有参数的 GET 请求的端点(例如https://stream.example.com/v1/filter.json?track=twitter)。根据这个答案Streaming API vs Rest API?,这不容易扩展并且需要大量资源。

然后我想使用 websockets 并让客户端提供过滤消息(例如位置=-122.75,36.8,-121.75,37.8)。但是,我找不到一个 WS 服务器向每个客户端发送唯一数据的好例子。如果这个类继承了 tornado.websocket.WebSocketHandler 或类似的实现会是什么样子?

我还考虑将数据推送到消息传递服务 (RabbitMQ) 或数据库 (Redis) 并在客户端连接到其唯一通道时订阅它们。 (我想像这个问题Any ideas how to create parameterised streaming api?)。我不知道创建独特频道的有效方法。这似乎也过于复杂了。

我更喜欢在 Python 中执行此操作,但我也会考虑使用 Ruby 和 JS 实现。

【问题讨论】:

    标签: python ruby node.js api tornado


    【解决方案1】:

    对 Python 不太熟悉,但我认为这应该可以使用 Websockets。这是我对 Ruby 的看法,希望对您有所帮助。这些是精简版本,删除了大部分 websocket 功能只是为了演示。

    但是,对于有关使用流式 API 的最佳实践,恐怕我帮不上什么忙。

    服务器

    require 'em-websocket'
    require 'json'
    
    def filtered_stream(filter, ws)
      loop do 
        # do something with filter, transform or send different kinds of data
        ws.send "#{filter} - hello"
        sleep 2
      end
    end
    
    EM.run {
      EM::WebSocket.run(:host => "127.0.0.1", :port => 9999) do |ws|
        ws.onopen { |handshake|
          # We can access some information in the handshake object such as headers
          # Perhaps even add the client to a list / table
        }
    
        ws.onmessage { |msg|
          # use ws.close to close the connection if needed
          # for example if the client attempts to send an invalid message or multiple messages?
    
          filter = JSON.parse(msg)['locations']
          Thread.new { filtered_stream(filter, ws) }
        }
      end
    }
    

    客户

    require 'websocket-eventmachine-client'
    
    EM.run do
      ws = WebSocket::EventMachine::Client.connect(
        :uri => 'ws://localhost:9999',
       )
    
      ws.onopen do
        # Unsure on how to supply the filter, headers is an option too
    
        ws.send "{\"locations\":\"-122.75,36.8,-121.75,37.8\"}"
      end
    
      ws.onmessage do |msg|
        p msg
      end
    end
    

    【讨论】:

      猜你喜欢
      • 2014-08-09
      • 1970-01-01
      • 2011-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-20
      • 2016-08-01
      相关资源
      最近更新 更多