【问题标题】:Data Studio connector making multiple calls to API when it should only be making 1Data Studio 连接器在应该只进行 1 次时对 API 进行多次调用
【发布时间】:2021-07-08 01:17:48
【问题描述】:

我正在完成一个 Data Studio 连接器,并注意到 API 调用数量的一些奇怪行为。

在我期望看到单个 API 调用的地方,我看到了多个调用。

在我的应用程序脚本中,我保留了一个简单的计数,每次获取 url 都会增加 1,这给了我希望通过 getData() 看到的正确数字。

但是,在我的 API 监控日志(使用 Runscope)中,我看到对同一端点的多个 API 请求,以及在单个 getData() 调用中不同端点的不同数量(它们应该都是相同的)。例如

我无法在此处发布代码(客户端项目),但它与 Google 文档中的数据连接器代码基本相同。我已经实现了缓存和退避。

正在寻找任何想法或是否有人经历过类似的事情?

谢谢

【问题讨论】:

  • 如果您希望尽量减少获得答案的机会,那么不发布任何代码可能会成功。

标签: google-apps-script google-data-studio


【解决方案1】:

根据this reference,如果您没有为您的字段明确定义此属性,GDS 还将执行语义类型检测。如果查询是语义类型检测,则请求特征为sampleExtraction: true

当 Data Studio 执行社区连接器的 getData 函数以进行语义检测时,传入的请求将包含一个 sampleExtraction 属性,该属性将设置为 true。

【讨论】:

    【解决方案2】:

    如果 GDS 报告包含具有不同维度/指标配置的多个小部件,则 GDS 可能会为每个小部件触发多个 getData 调用。

    【讨论】:

      【解决方案3】:

      有点晚的答案,但这可能会帮助面临同样问题的其他人。

      附加到图表的小部件/搜索过滤器会发出自己的 getData 调用。如果您的自定义适配器被构建为通过来自第三方服务的 API 调用来检索数据,这些数据与 GDS 转发的 request.fields 属性无关 => 那么这些 API 调用乘以 N+1(其中 N =您的报告正在实施的小部件/搜索过滤器)。

      我也找不到官方的解决方案,所以我发明了一种使用缓存的解决方法。

      图表对 getData 的请求(通常请求比搜索过滤器更多的字段)将是唯一允许查询 API 端点的请求。在开始这样做之前,它将在缓存中存储一​​个键“cache_{hashOfReportParameters}_building”=> true。

      if (enableCache) {
          cache.putString("cache_{hashOfReportParameters}_building", 'true');
          Logger.log("Cache is being built...");
      }
      

      它将检索 API 响应、分页并缓冲结果。

      一旦完成,它将删除缓存键“cache_{hashOfReportParameters}building”,并将其缓存的最终合并结果缓存在“cache{hashOfReportParameters}_final”中。


      当涉及到过滤器时,它们也会调用:getData,但通常最多只有 3 个请求的字段。我们要做的第一件事是确保它们不能在主 getData 调用之前开始执行......所以我们为可能是相同数据集之后的搜索过滤器/小部件添加一点延迟:

          if (enableCache) {
            var countRequestedFields = requestedFields.asArray().length;
            Logger.log("Total Requested fields: " + countRequestedFields);
            if (countRequestedFields <= 3) {
                Logger.log('This seams to be a search filters.');
                Utilities.sleep(1000);
            }
          }
      

      之后,我们对报告的所有移动部分(日期范围,加上您设置的所有其他可能影响从 API 端点检索到的数据的参数)计算哈希值:

      现在最好的部分是,只要主图仍在构建缓存,我们就让这些 getData 调用等待:

              while (cache.getString('cache_{hashOfReportParameters}_building') === 'true') {
                 Logger.log('A similar request is already executing, please wait...');
                 Utilities.sleep(2000);
              }
      

      在这个循环之后,我们尝试检索“cache_{hashOfReportParameters}_final”的内容——万一我们失败了,有一个备份计划总是一个好主意——允许它再次遍历 API .我们在检索缓存的数据时遇到了大约 2% 的错误率...

      使用缓存的结果(或缓冲的 API 响应),您只需根据 GDS 需要的架构转换您的响应(这在图表和过滤器之间有所不同)。


      当您开始实现此功能时,您会注意到另一个问题... Google 缓存被限制为每个键最大 100KB。但是,您可以缓存的键的数量没有限制......幸运的是,其他人过去也遇到过类似的需求,并提出了一种智能解决方案,将您需要缓存的一大块拆分为多个缓存键,然后粘合当需要检索时,它们会重新组合成一个对象。

      见:https://github.com/lwbuck01/GASs/blob/b5885e34335d531e00f8d45be4205980d91d976a/EnhancedCacheService/EnhancedCache.gs


      我无法与您分享我们实施的最终解决方案,因为它对客户来说太具体了 - 但我希望这至少能让您对如何解决问题有一个好主意。

      如果近实时足以满足您的需求,缓存完整的 API 结果通常是一个好主意,可以避免无缘无故的往返和服务器负载。

      【讨论】:

      • 感谢您分享这一点 - 我不得不通读两遍,这似乎很有希望,但非常复杂(尤其是对 EnhancedCache 的潜在需求)。有没有更简单的方法来错开 getData() 调用而不是使用 LockService()?
      猜你喜欢
      • 2022-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-28
      • 1970-01-01
      相关资源
      最近更新 更多