【问题标题】:Unable to complete the HTTP request when using SpreadSheet API使用 SpreadSheet API 时无法完成 HTTP 请求
【发布时间】:2014-02-28 15:54:15
【问题描述】:

我正在开发一个 Google App Engine 应用程序,它可以读取和编辑一个包含大约 150 列和 500 行的大型电子表格。除了特定大小(可能会有所不同)之外,我还在寻找一种提高性能的方法,因为大多数时候我都会收到 500 内部服务器错误(如下所示)。

java.lang.RuntimeException: 无法完成 HTTP 请求导致 作者:java.net.SocketTimeoutException:获取 URL 时超时: https://spreadsheets.google.com/feeds/worksheets/xxxxxxxxxxxxxxxxxxxxxxx/private/full

在下面的代码 sn-p 中,您可以看到我如何阅读我的 SpreadSheet 以及哪一行引发了异常。

for (SpreadsheetEntry entry : spreadsheets) {
    if (entry.getTitle().getPlainText().compareTo(spreadsheetname) == 0) {
        spreadsheet = entry;
    }
}

WorksheetFeed worksheetFeed = service.getFeed(spreadsheet.getWorksheetFeedUrl(), WorksheetFeed.class);
List<WorksheetEntry> worksheets = worksheetFeed.getEntries();
WorksheetEntry worksheet = worksheets.get(0);

URL listFeedUrl = worksheet.getListFeedUrl();
// The following line is the one who generates the error
ListFeed listFeed = service.getFeed(listFeedUrl, ListFeed.class);

for (ListEntry row : listFeed.getEntries()) {
    String content = row.getCustomElements().getValue("rowname");
    String content2 = row.getCustomElements().getValue("rowname2");
}

我已经使用结构化查询提高了性能。基本上我在 URL 中应用过滤器,这样我就可以只检索我需要的几行。请注意,无论如何,有时我仍然会收到上述错误。

URL listFeedUrl = new URI(worksheet.getListFeedUrl().toString() + "?sq=rowname=" + URLEncoder.encode("\"" + filter+ "\"").toString()).toURL();

然而我的问题是不同的,首先在某些时候我必须读取所有行但只有少数列(大约 5 列)。我仍然需要找到一种方法来实现这一点,我知道还有另一个参数“tq”允许选择列,但该语句需要字母表示法(例如 A、B、AA),我想使用而是列名。

最重要的是我需要摆脱 500 Internal Server Error。由于这听起来像是超时问题,我想将该值增加到合理的时间量。我的用户也可以等待几秒钟,因为它看起来完全随机。当它工作时,它会在大约 2-3 秒内加载页面。但是,当它不起作用时,我会收到 500 内部服务器错误,这对最终用户来说真的很令人沮丧。

有什么想法吗?我在 App Engine 设置中找不到任何内容。到目前为止,我唯一的想法是将电子表格拆分为多个电子表格(或工作表),以便读取更少的列。但是,如果有一个选项可以让我增加超时时间,那就太棒了。

编辑:我在互联网上四处寻找,我可能发现了一些可以帮助我的东西。我刚刚发现服务对象提供了一个 setConnectionTimeout 方法,马上测试它。

// Set timeout

int timeout = 60000;
service.setConnectTimeout(timeout);

【问题讨论】:

    标签: java google-app-engine google-spreadsheet-api


    【解决方案1】:

    超时

    我使用 10 秒超时重试。它对我来说没问题。

    图纸尺寸

    我一次使用了 80,000 个单元格。它工作正常,我没有看到重试失败。我使用的是 CellFeed,而不是 ListFeed。

    是的,它不喜欢大张,1000 个左右的小张要快得多。即使我只写了部分工作表,小工作表也快得多。 (感觉它会重新计算整个工作表,因为看起来并不取决于数据量,但我不确定)

    指数退避

    Zig 建议使用指数退避 - 对数字感兴趣 - 人们通过指数退避获得的超时值和故障率 - 以及工作表大小的影响。

    我怀疑从 3 秒超时开始,每次重试加倍可能有效,但尚未测试。

    【讨论】:

    • 它将如何工作?我的意思是,我将超时设置为 3 秒并执行 service.getFeed,如果它抛出异常,我会在 6 秒内重试,然后在 9 秒内抛出异常。像这样的东西?仅供参考,现在它就像一个魅力,听起来 5 秒还不够,但 7-8 秒就足够了。大多数请求在 10 秒内完成。
    • 是的,正如您所描述的那样。我确实需要重试,因为我遇到了少量失败。
    【解决方案2】:

    真正的问题是您不应该为此使用电子表格。如果您尝试大量使用,它将引发许多错误,包括速率限制。 至少您需要使用指数退避来重试错误,但仍然会很慢。通过 url 进行查询也效率不高。 解决方案是将 spresdsheet 转储到数据存储中,然后从那里进行查询。由于您还编辑了电子表格,因此要使其与数据存储数据保持同步并不容易。通用解决方案需要任务队列正确处理超时和大量数据(单元格)

    【讨论】:

    • Re:exponential backoff - 对数字感兴趣 - 什么超时值和失败率?还有纸张尺寸的影响。
    • 谷歌搜索,他们有经验。我认为用于驱动器 api 示例的退避。例如,每次循环重试 5 次,等待时间加倍。 Stsrt 等待 1 秒。工作表大小会产生影响,因为您通过 url 对其进行查询。
    猜你喜欢
    • 2019-05-08
    • 2022-10-18
    • 2017-11-23
    • 2011-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-21
    • 1970-01-01
    相关资源
    最近更新 更多