教程

使用流式数据

 
企业

概述

PowerTrack、容量(例如 Decahose、Firehose)和重播流利用流式 HTTP 协议通过开放的流式 API 连接传送数据。它们在应用和 API 之间打开单个连接,只要有新匹配,就会通过该连接发送新结果,而不是从客户端应用重复发出请求来分批传送数据,正如 REST API 那样。这就产生了一个支持极高吞吐量的低延迟传送机制。

应用与针对这些流的 Twitter API 之间的总体交互如下所示:

步骤 1:配置流
如果使用 Decahose 或 Firehose,则无需配置流。

如果使用 PowerTrack 或重播流,则需要设置一些规则来定义应通过流传送哪些内容。你可以阅读高级运算符的相关文档,详细了解 PowerTrack 规则语法。

配置好流之后,就可以进行连接了。

步骤 2:连接到 API
要打开数据流以发送推文,需要向 API 发送连接请求。在流式模型中,此连接打开了一个管道,用于在数据产生时向你传送数据,并且该连接将无限期存在。要了解如何建立连接,请参阅有关特定 API 的文档。

步骤 3:在传送数据时使用它们
建立连接后,流会在新推文发布时通过打开的连接发送这些推文,而客户端应用在接收到数据时应该会离线读取这些数据。客户端应用需要识别和处理各种类型的消息,下文对这些消息进行了介绍。

步骤 4:断开连接后,重新连接到 API
有时,与流的连接将不可避免地关闭,即断开连接。对于实时流,重要的是要了解,当断开与流的连接时,你可能会丢失数据。每当连接断开,客户端应用都必须建立新的连接来重启该过程。
此外,为确保不会丢失任何数据,建议使用冗余连接、回填或重播流来缓解与源断开连接的情况或恢复因此丢失的数据。

 

使用流

与流建立连接后,将开始接收数据流。响应正文由一系列以回车符 ( ) 分隔并以 JSON 编码的动态、系统消息和空白行组成。

客户端从流中读取动态时应使用回车符将其分开。请记住,应用不应等待“记录”结束才开始处理数据。实际上,记录是一个永无休止的过程,客户端需要在收到数据时离线读取数据。

JSON 数据
通过此 API 流式传输的单个数据采用 JSON 编码,并分为以下几类:

  • 推文:单个推文 JSON 对象
  • 持久连接信号:用于防止连接超时的回车
  • 系统消息:例如,连接被强制断开的通知。请注意,连接断开实际上是通过常规 HTTP 协议而不是消息本身完成的。在某些情况下,你可能不会收到连接断开的系统消息,因此监控持久连接信号相当重要(请参见下文了解详细信息)。

请注意,JSON 对象的各个字段未排序,且并非所有字段都会在所有情况下显示。同样,单独的动态不会按排序顺序进行传送,并且可能会遇到重复的消息。请记住,一段时间后,可能会添加新的消息类型并通过流发送。

因此,客户端必须容许:

  • 字段以任何顺序出现
  • 意外或缺失的字段
  • 未分类的推文
  • 重复的消息
  • 随时都有新的任意消息类型传入流

推文
表示给定数据源的推文的 JSON 对象以丰富的 Twitter 原生格式提供。请阅读我们的推文 JSON 简介文档,详细了解此数据格式。

推文将包含在一行中,可能包含换行字符,但不包含回车符。

系统消息
推文流还可能包含系统消息。下面提供了这些消息的基本格式以及一些示例。请注意,传送的消息可能会发生更改,并会引入新的消息。客户端应用程序需要容许变化的系统消息有效负载。

请注意,“sent”时间戳采用 YYYY-MM-DDTHH:mm:ssZZ 格式和 UTC 时区。

消息格式:

{"<message type>":{"message":"<the message>","sent":"<date time sent>"}}

系统消息类型:当前有 3 种消息类型,每种类型都有许多不同的消息。但可能会有变更,恕不另行通知。

  • 信息 - 当重播流请求完成时,发送“重播请求已完成”。见下文。
  • 警告 - 例如,如果连接到不含规则的 PowerTrack 流。
  • 错误 - 在以下情况可能会发送错误:出现某些问题时,例如,“流式传输数据时出错”,或者强制断开连接时。

请注意,对于指示缓冲区满载时强制断开连接的错误消息,如果导致强制断开连接的备份阻止消息通过,则客户端可能永远也不会收到此消息。因此,应用不应依赖这些消息来启动重新连接。

示例:

{"error":{"message":"Forced Disconnect:Too many connections.(Allowed Connections = 2)","sent":"2017-01-11T18:12:52+00:00"}}

{"error":{"message":"Invalid date format for query parameter 'fromDate'.Expected format is 'yyyyMMddHHmm'.For example, '201701012315' for January 1st, 11:15 pm 2017 UTC. ","sent":"2017-01-11T17:04:13+00:00"}}

{"error":{"message":"Force closing connection to because it reached the maximum allowed backup (buffer size is ).","sent":"2017-01-11T17:04:13+00:00"}}

持久连接信号
至少每 10 秒钟,流就会通过打开的连接以回车的形式发送一个持久连接信号或检测信号,以防止客户端超时。客户端应用程序应容许流中的回车符。

如果客户端对 HTTP 库正确地实现了读取超时(如此处所述),则在此期间如果未读取任何数据,应用将能够依靠 HTTP 协议和 HTTP 库引发事件,并且无需显式监控回车符。

该事件通常是正在引发的异常或其他某些事件,具体视所使用的 HTTP 库而定。强烈建议将 HTTP 方法与错误/事件处理程序包装到一起,以检测这些超时。超时后,应用程序应尝试重新连接。

Gzip 压缩
流以压缩的 Gzip 格式传送。客户端在离线读取数据时需要将数据解压缩。如果使用数据量较小的流,则某些库(例如 Java 的 GZIPInputStream 或许多 Ruby 流使用者)在解压缩传入的数据时可能会处理不好,并且需要进行重写才能在接收到推文时立即对其进行解压缩,而无需等待接收到设定的数据阈值。如需查看相关示例,请参阅此处的 Java 代码。

分块编码
流式 API 连接将使用分块传输编码机制进行编码,如响应中 Transfer-Encoding:chunked HTTP 标头所指示。由于大多数 HTTP 库都以透明的方式处理分块传输编码,因此本文档假定你的代码可以访问重组的 HTTP 流,而不必处理这种编码。

如果不是这种情况,则应当注意,推文和其他经过流式消息不一定会到达 HTTP 区块边界。重组流时,请务必使用上文定义的分隔符来确定动态边界。

 

备份缓冲

该流从源 Firehose 收到数据后就会立即将数据发送给你,这在许多情况下可能会产生大量数据。如果 Twitter 的系统无法立即将新数据写入流中(例如,若客户端的读取速度不够快或者存在网络瓶颈等),该系统将在它那端缓冲内容,使客户端能够跟上。但此缓冲区满载时,将启动强制断开连接使连接中断,并且缓冲的推文将被丢弃且不会重新发送。请参阅下文了解更多详情。

识别应用滞后的一种方法是将收到推文的时间戳与当前时间进行比较,并在一段时间内跟踪该情况。

尽管因公共互联网潜在的延迟和小故障,而永远无法完全免去流备份,但通过正确配置应用可以在很大程度上免去流备份。为最大程度地减少备份,请执行以下操作:

  • 确保客户端读取流的速度足够快。通常,在读取流时,不应进行任何实际的处理工作。读取流并将动态传递到另一个线程/进程/数据存储区以进行异步处理。
  • 确保数据中心的入站带宽足以容纳较大的持续数据量以及明显更大的峰值(例如,正常容量的 3-4 倍)。对于像 PowerTrack 这样经过筛选的流,你所需的容量和相应带宽完全取决于所跟踪的内容以及这些筛选条件匹配的推文数量。

测试应用速度的一种简便方法是使用应用连接到流,同时使用 curl 通过冗余连接并行连接。通过 curl 连接,你可以深入了解应用代码从链中取出后会出现的性能类型,并且在调试时还无需使用变量。

数据量监控
请考虑监控流数据量以防出现意外偏差。数据量减少可能是其他问题的征兆,而非流断开连接的问题。在这种情况下,流仍将接收持久连接信号,可能还会接收一些新的动态数据。但如果推文数量大幅减少,则应该调查是否有任何原因导致应用程序或网络的入站数据量减少,请查看 api.twitterstat.us 获取任何相关通知。

要创建此类监控,你可以跟踪在设定的时间内希望看到的新推文数量。如果流的数据量远低于指定的阈值,并且在设定的时间段内未恢复,则应启动警报和通知。我们还建议你监控数据量是否大幅增加,如果你正在修改 PowerTrack 流中的规则,或者发生的事件导致推文动态激增,则尤其需要注意。

由于每位客户对于“正常的”流数据量都有不同的期望值,因此我们就特定的减少/增加百分比或时间段,无法给出一般性建议。我们建议每位客户确定自己的指标,以用于此类监控。

此外,对于 PowerTrack 流,为了密切监视并严格控制应用正在拉取的数据量,应用应根据逐条规则实时或近乎实时地监控使用的数据量。此外,我们还建议你在应用中实施一些可在数据量超出预设阈值时向团队发出警报的措施,并尽可能引入其他措施,例如自动删除引入过多数据的规则或者在极端情况下完全断开与流的连接。这些措施将有助于防止出现可能导致数据费用过高的“数据量失控”情况。

 

断开连接

对于 Twitter 来说,流断开连接分为两类:客户端断开连接和强制断开连接。

客户端断开连接
当应用程序单独终止与数据流的连接时,无论是因为代码主动关闭了连接,还是网络设置或条件终止了连接,都会发生客户端断开连接的情况。

客户端代码中可能导致此行为的常见问题包括:

  • 关闭连接,而不是允许连接无限期地保持打开状态
  • 连接超时,即使仍然正在通过连接发送数据(动态、系统消息或持久连接信号)
  • 使用不正确的预估区块大小来对压缩的流进行解压缩
  • 基础架构中的网络或防火墙限制可能会关闭数据流连接(例如防火墙会话限制),请务必检查是否存在可能会导致不时断开现有连接的类似问题。
  • 同样,使用 curl 和比较连接断开行为也是一种富有成效的做法。如果应用遇到客户端断开连接的情况,但 curl 仍然保持连接,则需要注意你的代码。如果 curl 和应用大概相时断开连接,则可能是网络连接超时。 

强制断开连接
当系统主动将应用与流断开连接时,就会发生强制断开连接的情况。强制断开连接有 3 种不同的类型。

  • 缓冲区满载 - 应用读取数据的速度不够快,或者网络瓶颈使数据流变慢。
  • 连接太多 - 应用建立了太多数据流连接。发生这种情况时,Twitter 将等待 1 分钟,如果仍然超出限制,则会断开最近建立的连接。
  • 服务器维护 - Twitter 团队对系统服务器部署了更改或更新。通常这种情况会显示“Twitter 正在维护,已暂时关闭”的消息。这些部署大约每两周进行一次,我们会在此状态页面中发布相关公告。 

强制断开连接根据标准 HTTP 分块编码惯例发送零字节区块来关闭连接。请参考此页面第 9 节:http://www.httpwatch.com/httpgallery/chunked。请注意,在缓冲区满载的情况下,我们的应用会发送零字节区块,但由于存在导致数据在互联网或应用中进行备份的因素,你的应用可能永远不会收到该区块。

为解决这种情况,请务必将应用设置为在超过 30 秒未看到任何数据(推文动态或持久连接信号)时超时/重新连接。它们在控制台/面板被注册为“强制断开连接”,而不是由 Twitter 服务器启动的“客户端断开连接”。

若要最大程度减少缓冲区满载时的强制断开连接数,请参阅上文的备份缓冲

 

重新连接

建立的连接断开时,请尝试立即重新连接。如果初始重新连接尝试失败,则客户端应继续使用指数退避模式尝试重新连接,直到成功重新连接为止。

无论客户端是如何断开连接的,都应将应用配置为立即重新连接。如果第一次重新连接尝试失败,建议让应用在后续的重新连接尝试中采用指数退避模式(例如等待 1 秒,然后等待 2 秒、4 秒、8 秒、16 秒等),并设置一些合理的上限。如果达到此上限,则应将客户端配置为向团队发送通知,以便你可以进一步调查。

确保应用可以处理以下所有情况:

  • 连接由于你这边的问题被关闭(客户端断开连接)
  • Twitter 使用零字节区块关闭了连接(强制断开连接)
  • 应用通过连接接收到了零数据,即超过 30 秒没有新的推文且没有持久连接回车信号。在这种情况下,应用必须允许连接超时。请注意,默认情况下,即使没有新数据,一些客户端的持久性连接也可以保持打开状态,除非你的代码因上述信号缺失而告诉它关闭。请注意,与上述第三种情况不同,如果你仍然收到持久连接信号,但没有新数据,则应用应仍处于连接状态。出现这种情况可能是由于 Twitter 存在问题,无法通过有线方式发送数据,也可能是由于没有任何与筛选条件匹配的新动态。只要至少收到了持久连接信号,保持连接状态就可以确保在 Twitter 收到新匹配的推文时收到它们。为此,通常将客户端的读取超时设置为 30 秒以上。

连接断开导致数据丢失
每当与流断开连接时,都可能丢失当时将要发送的数据。但 Twitter 提供了多种方法可以缓解这些连接断开问题并在问题发生时恢复数据。请参阅下文了解更多信息。

  • 冗余连接 - 使用来自多个服务器的流,防止在断开连接时丢失数据。
  • 回填 - 在 5 分钟内重新连接,并请求回填丢失的数据。
  • 重播 - 使用单独的流恢复过去 5 天内的数据。
 

重播流的特殊注意事项

借助重播,企业客户能够从历史数据的滚动期内恢复由于技术故障而丢失的动态,并使用流式 API 传送数据。你可以在此处找到有关重播 API 的完整文档。

但是,客户端在使用重播流中的数据时,必须考虑以下要求和特殊注意事项。

重新连接
请注意,如果在重播请求期间与流断开连接,则应用在未更改 fromDate 的情况下,不得重新连接到用于发起请求的同一 URL。那样做的话将会从头开始重启请求,并重复连接断开之前所覆盖的那部分时间。相反,如果在请求完成之前连接断开,则客户端必须将 URL 中的 fromDate 和 toDate 调整为从连接断开前收集最后一条动态的那一刻开始,以便从中断的地方恢复数据,从而最大程度减少重叠的数据量。

重复
在传送重播请求的结果时,我们不会忽略你可能已从先前的请求或正常的 Power Track 流中获得的动态,你的应用应该会相应地删除重复的数据。但请注意,计费时,我们会删除同一天(根据 UTC 时间)发出的 PowerTrack 重播请求中重复的动态数,确保对通过重播传送的非重复动态只计费一次。通过实时 Power Track 流传送的动态与通过重播的动态分开计数。

 

恢复

如上所述,PowerTrack 和容量流提供了重要的功能来为实时流提供帮助。请在此处参阅有关其他流、冗余连接、重播流和回填的文档。

准备好构建你的解决方案了吗?

阅读文件,然后开始吧