Google bigquery Bigquery事件流提供了;无法获取url";有时

Google bigquery Bigquery事件流提供了;无法获取url";有时,google-bigquery,Google Bigquery,我们刚刚对直接流式处理事件到bigquery进行了一些测试,这在一定程度上是成功的,但我注意到有一个事件丢失(ca 20),在搜索日志时,我注意到这个特定事件由于以下原因而失败: Caused by: java.io.IOException: Could not fetch URL: https://www.googleapis.com/bigquery/v2/projects/<project-name>/datasets/<datasetname>/tables/ev

我们刚刚对直接流式处理事件到bigquery进行了一些测试,这在一定程度上是成功的,但我注意到有一个事件丢失(ca 20),在搜索日志时,我注意到这个特定事件由于以下原因而失败:

Caused by: java.io.IOException: Could not fetch URL: https://www.googleapis.com/bigquery/v2/projects/<project-name>/datasets/<datasetname>/tables/events_app6_v6_201507/insertAll
    at com.google.appengine.api.urlfetch.URLFetchServiceImpl.convertApplicationException(URLFetchServiceImpl.java:140)
    at com.google.appengine.api.urlfetch.URLFetchServiceImpl.fetch(URLFetchServiceImpl.java:45)
    at com.google.apphosting.utils.security.urlfetch.URLFetchServiceStreamHandler$Connection.fetchResponse(URLFetchServiceStreamHandler.java:502)
原因:java.io.IOException:无法获取URL:https://www.googleapis.com/bigquery/v2/projects//datasets//tables/events_app6_v6_201507/insertAll
位于com.google.appengine.api.urlfetch.URLFetchServiceImpl.convertApplicationException(URLFetchServiceImpl.java:140)
位于com.google.appengine.api.urlfetch.URLFetchServiceImpl.fetch(URLFetchServiceImpl.java:45)
位于com.google.apphosting.utils.security.urlfetch.URLFetchServiceStreamHandler$Connection.fetchResponse(URLFetchServiceStreamHandler.java:502)
因此,我向所有注意到这一点的人提出的问题是:

A) 插入失败的可能性有多大

B) 我们处理此类错误的最佳模式是什么

考虑到我们正在传输大量事件,没有时间进行任何冗长的错误处理

一种方法是简单地忽略错误,但我们不能接受失去5%的事件


提前谢谢

因为流媒体的有效负载大小有限,所以更容易谈论时间,因为有效负载对我们双方都是有限的,但我也会提到其他副作用

我们对每个流式处理请求的测量值在1200-2500毫秒之间,正如您在图表中看到的,这在上个月是一致的

我们看到了一些副作用,尽管:

  • 请求随机失败,类型为“后端错误”
  • 请求随机失败,类型为“连接错误”
  • 请求随机失败,类型为“timeout”(注意这里,因为只有一些行失败,而不是整个负载)
  • 其他一些错误消息是非描述性的,它们非常模糊,对您没有帮助,请重试
  • 我们每天都会看到数百个这样的失败,因此它们几乎是固定不变的,与云健康无关
对于所有这些,我们在付费的谷歌企业支持中打开了案例,但不幸的是,他们没有解决这个问题。对于这些问题,建议采取的方法是使用重试进行指数退避,即使支持人员被告知这样做。就我个人而言,这并不能让我快乐

此外,故障率符合SLA中99.9%的正常运行时间,因此没有理由反对

关于SLA,需要记住一些东西,它是一个非常严格定义的结构,细节如下。99.9%的正常运行时间不能直接转化为故障率。这意味着,如果BQ在一个月内有30分钟的停机时间,然后您在这段时间内插入了10000次,但在一个月的其他时间内没有插入任何内容,这将导致数字出现偏差。这就是为什么我们建议使用指数退避算法。SLA明确基于正常运行时间,而不是错误率,但如果您在一个月内的不同时间使用回退重试设置执行流式插入,则两者在逻辑上密切相关。从技术上讲,如果您已经设置了正确的重试机制,那么您在一个月内都在执行插入操作,那么您应该平均经历大约1/1000的插入失败

您可以查看以下有关项目运行状况的图表:

您需要构建重试机制来对事件重新排队。如前所述,“timeout”类型是特殊的,因为只有一些行是超时的,而有些是成功的。这意味着您需要解析响应,并查看哪个时间路由,然后仅对那些时间路由重新排队。如果您重新获得所有有效负载,您可能会得到重复的负载


您需要重新考虑使用
异步进程的方法。为了更快地完成,您需要并行运行多个worker,流性能将是相同的。只要有10名工人同时工作,就意味着时间将减少10倍

在大多数web应用程序中,在后台IO绑定或cpu绑定任务中进行处理现在是一种常见做法。有很多软件可以帮助构建后台作业,有些基于消息传递系统,如

基本上,您需要在一个封闭的网络中分发插入作业,对它们进行优先级排序,并使用(运行)它们。这正是Beanstalkd提供的

Beanstalkd提供了在管道中组织作业的可能性,每个管道对应一种作业类型

您需要一个API/producer,它可以将作业放在一个管道上,比如说一行的json表示。这是我们用例的杀手级特性。所以我们有一个API来获取行,并将它们放在管道上,这只需要几毫秒,所以您可以实现快速响应时间

另一方面,你现在在一些管子上有很多工作。你需要一个代理人。代理/消费者可以预订工作

它还可以帮助您进行作业管理和重试:成功处理作业后,使用者可以从管道中删除作业。在失败的情况下,消费者可以埋葬工作。此作业不会被推回管道,但可供进一步检查

消费者可以释放作业,Beanstalkd会将此作业推回到试管中,并使其可供其他客户端使用


Beanstalkd客户机可以在大多数常见语言中找到,a对调试非常有用。

实际上,我们最终将所有插入失败添加到推送队列中。这个解决方案其实很简单。到目前为止,我们每小时处理200万个事件,没有任何问题。存在一定数量的插入失败,但它们由推队列处理程序处理。看起来很好。@GunnarEketrapp你们是单独流式处理事件还是分批处理事件?我想知道在流媒体机器上单独播放每个事件会有多大的压力。是的,我们单独播放每个事件。