Bigquery 事件流有时会给出 "Could not fetch url"
Bigquery event streaming gives "Could not fetch url" sometimes
我们刚刚将流式事件直接发送到 bigquery 进行了一些测试,这在一定程度上是成功的,但我注意到一个事件丢失了(大约 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)
所以我对任何人的问题都注意到了相同的是:
A) 插入失败的可能性有多大?
B) 我们处理此类错误的最佳模式是什么。
考虑到我们正在传输大量事件并且没有时间进行任何冗长的错误处理。
一种方法是简单地忽略错误,但我们不能接受丢失 5% 的事件。
提前致谢!
由于流式传输的有效负载大小有限,请参阅 Quota policy 谈论时间更容易,因为有效负载对我们双方的限制方式相同,但我也会提到其他副作用。
我们测量每个流媒体请求的时间在 1200-2500 毫秒之间,这在上个月是一致的,如您在图表中所见。
虽然我们看到了一些副作用:
- 请求随机失败,类型为 'Backend error'
- 请求随机失败,类型为 'Connection error'
- 请求随机失败,类型为 'timeout'(注意这里,因为只有一些行失败,而不是整个负载)
- 其他一些错误消息是非描述性的,它们非常模糊,对您没有帮助,请重试。
- 我们每天都会看到数百次此类故障,因此它们几乎是恒定的,与云运行状况无关。
对于所有这些,我们在付费 Google 企业支持中打开了案例,但遗憾的是他们没有解决。推荐的选项是带重试的指数退避,即使支持人员被告知这样做。就个人而言,这并不能让我开心。
此外,故障率符合我们在 SLA 中规定的 99.9% 的正常运行时间,因此没有理由反对。
关于 SLA 有一些需要注意的地方,它是一个定义非常严格的结构,详情请见 here。 99.9% 是正常运行时间,不会直接转化为故障率。这意味着,如果 BQ 在一个月内有 30 分钟的停机时间,然后您在此期间进行了 10,000 次插入,但在该月的其他时间没有进行任何插入,这将导致数字出现偏差。这就是我们建议使用指数退避算法的原因。 SLA 明确基于正常运行时间而不是错误率,但如果您在整个月的不同时间使用退避重试设置进行流式插入,那么从逻辑上讲,这两者密切相关。从技术上讲,如果您设置了正确的重试机制,那么如果您整个月都在进行插入操作,您应该平均经历大约 1/1000 次插入失败。
您可以查看这张关于您的项目健康状况的图表:
https://console.developers.google.com/project/YOUR-APP-ID/apiui/apiview/bigquery?tabId=usage&duration=P1D
您需要建立一个重试机制来重新排队您的事件。如前所述,'timeout' 类型是特殊的,因为只有一些行超时,而一些是成功的。这意味着您需要解析响应,并查看哪些超时并仅重新排队。如果您重新排队所有有效载荷,您可能会得到重复项。
您需要重新考虑 async processes
的方法。为了尽快完成,你需要 运行 并行多个 worker,streaming 性能将是相同的。只要有 10 个 worker 并行,就意味着时间会减少 10 倍。
在后台 IO 绑定或 cpu 绑定任务中处理现在是大多数 Web 应用程序中的常见做法。有很多软件可以帮助构建后台作业,其中一些基于 Beanstalkd.
等消息系统
基本上,您需要在一个封闭的网络中分配插入作业,确定它们的优先级,然后使用 (运行) 它们。嗯,这正是 Beanstalkd 提供的。
Beanstalkd 提供了在管中组织作业的可能性,每个管对应一种作业类型。
您需要一个 API/producer 可以将作业放在管子上,假设是行的 json 表示。这是我们用例的杀手级功能。所以我们有一个 API 获取行,并将它们放在管子上,这只需要几毫秒,因此您可以实现快速响应时间。
另一方面,你现在在一些管子上有很多工作。你需要一个代理人。一个agent/consumer可以预约工作
它还可以帮助您进行作业管理和重试:成功处理作业后,消费者可以从管中删除该作业。在失败的情况下,消费者可以埋头工作。此作业不会被推回管中,但可以供进一步检查。
一个消费者可以释放一个作业,Beanstalkd 会把这个作业推回管中,让另一个客户端可以使用它。
可以在大多数常用语言中找到 Beanstalkd 客户端,web interface 可用于调试。
我们刚刚将流式事件直接发送到 bigquery 进行了一些测试,这在一定程度上是成功的,但我注意到一个事件丢失了(大约 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)
所以我对任何人的问题都注意到了相同的是:
A) 插入失败的可能性有多大?
B) 我们处理此类错误的最佳模式是什么。
考虑到我们正在传输大量事件并且没有时间进行任何冗长的错误处理。
一种方法是简单地忽略错误,但我们不能接受丢失 5% 的事件。
提前致谢!
由于流式传输的有效负载大小有限,请参阅 Quota policy 谈论时间更容易,因为有效负载对我们双方的限制方式相同,但我也会提到其他副作用。
我们测量每个流媒体请求的时间在 1200-2500 毫秒之间,这在上个月是一致的,如您在图表中所见。
虽然我们看到了一些副作用:
- 请求随机失败,类型为 'Backend error'
- 请求随机失败,类型为 'Connection error'
- 请求随机失败,类型为 'timeout'(注意这里,因为只有一些行失败,而不是整个负载)
- 其他一些错误消息是非描述性的,它们非常模糊,对您没有帮助,请重试。
- 我们每天都会看到数百次此类故障,因此它们几乎是恒定的,与云运行状况无关。
对于所有这些,我们在付费 Google 企业支持中打开了案例,但遗憾的是他们没有解决。推荐的选项是带重试的指数退避,即使支持人员被告知这样做。就个人而言,这并不能让我开心。
此外,故障率符合我们在 SLA 中规定的 99.9% 的正常运行时间,因此没有理由反对。
关于 SLA 有一些需要注意的地方,它是一个定义非常严格的结构,详情请见 here。 99.9% 是正常运行时间,不会直接转化为故障率。这意味着,如果 BQ 在一个月内有 30 分钟的停机时间,然后您在此期间进行了 10,000 次插入,但在该月的其他时间没有进行任何插入,这将导致数字出现偏差。这就是我们建议使用指数退避算法的原因。 SLA 明确基于正常运行时间而不是错误率,但如果您在整个月的不同时间使用退避重试设置进行流式插入,那么从逻辑上讲,这两者密切相关。从技术上讲,如果您设置了正确的重试机制,那么如果您整个月都在进行插入操作,您应该平均经历大约 1/1000 次插入失败。
您可以查看这张关于您的项目健康状况的图表: https://console.developers.google.com/project/YOUR-APP-ID/apiui/apiview/bigquery?tabId=usage&duration=P1D
您需要建立一个重试机制来重新排队您的事件。如前所述,'timeout' 类型是特殊的,因为只有一些行超时,而一些是成功的。这意味着您需要解析响应,并查看哪些超时并仅重新排队。如果您重新排队所有有效载荷,您可能会得到重复项。
您需要重新考虑 async processes
的方法。为了尽快完成,你需要 运行 并行多个 worker,streaming 性能将是相同的。只要有 10 个 worker 并行,就意味着时间会减少 10 倍。
在后台 IO 绑定或 cpu 绑定任务中处理现在是大多数 Web 应用程序中的常见做法。有很多软件可以帮助构建后台作业,其中一些基于 Beanstalkd.
等消息系统基本上,您需要在一个封闭的网络中分配插入作业,确定它们的优先级,然后使用 (运行) 它们。嗯,这正是 Beanstalkd 提供的。
Beanstalkd 提供了在管中组织作业的可能性,每个管对应一种作业类型。
您需要一个 API/producer 可以将作业放在管子上,假设是行的 json 表示。这是我们用例的杀手级功能。所以我们有一个 API 获取行,并将它们放在管子上,这只需要几毫秒,因此您可以实现快速响应时间。
另一方面,你现在在一些管子上有很多工作。你需要一个代理人。一个agent/consumer可以预约工作
它还可以帮助您进行作业管理和重试:成功处理作业后,消费者可以从管中删除该作业。在失败的情况下,消费者可以埋头工作。此作业不会被推回管中,但可以供进一步检查。
一个消费者可以释放一个作业,Beanstalkd 会把这个作业推回管中,让另一个客户端可以使用它。
可以在大多数常用语言中找到 Beanstalkd 客户端,web interface 可用于调试。