在 Cloud 运行 中的何处存储共享缓存对象?

Where to store shared cache objects in Cloud Run?

我正在使用 Cloud 运行 创建数据摄取管道。每次通过 Pub Sub 将文件放入 GCS 存储桶时,My Cloud 运行 api 都会被调用。我需要加载一些元数据,其中包含我正在摄取的数据的文本。此元数据很少更改。我显然不想在每次执行时都将它重新加载到内存中。我最好的选择是什么?到目前为止我能够研究的是:

选项 1

You can also cache objects in memory if they are expensive to recreate on each service request. Moving this from the request logic to global scope results in better performance. https://cloud.google.com/run/docs/tips#run_tips_global_scope-java

在此 link 给出的示例中,heavyComputation 函数是否仅在冷启动时被调用一次?如果我需要在元数据更新时偶尔重新触发此功能怎么办?我还发现以下信息令人不安,因为它似乎说不能保证其他实例会重用该对象。

In Cloud Run, you cannot assume that service state is preserved between requests. However, Cloud Run does reuse individual container instances to serve ongoing traffic, so you can declare a variable in global scope to allow its value to be reused in subsequent invocations. Whether any individual request receives the benefit of this reuse cannot be known ahead of time.

选项 2

使用像 Redis 或 Cloud Memory Store 这样的东西,只要有变化就可以通过云功能更新。并且云的所有实例 运行 api 从 Redis 中拉取元数据信息。这会比选项 1 的性能更低还是更高?这还有其他不利方面吗?

如果有其他更好的方法,我会很感兴趣。

更新 1:我仔细考虑了一下,因为我的元数据对于每个租户都会不同,并且每次调用我的云 运行 代码都会为一个租户提取一个文件,它在每次执行时加载所有租户元数据将是一个坏主意,即使它已缓存。不过,我可能 运行 在每个租户的项目中分离云 运行。

我们从您的初始前提开始,即 "I obviously do not want to reload it in memory on every execution"。对我来说,这并不总是正确的说法。如果我实施缓存技术,那么,作为一名程序员,我已经花时间把它弄对了,并引入了出错和维护的机会。如果我每次执行节省了 100 毫秒,那么与增加执行时间所节省的成本相比,需要执行多少次才能收支平衡?我通常会预先采用最简单的方法,并准备好在未来监控操作并仅在必要时解决改进问题。

综上所述,让我们假设您已确定每秒将发出大量新文件创建请求并希望进行优化。理解如何最好地使用 Cloud 运行 的关键是它运行一个可以处理并发请求的整个容器。我认为默认值为 80。这意味着如果创建了 80 个并发文件,则只会创建一个容器实例并处理 80 个并行事件。如果您在 Java 中编码,这意味着 80 个并发线程都在同一个 JVM 中。每个线程都具有对公共全局变量的并发寻址能力。只有当第 81 个请求到达并且前 80 个中的 none 已经完成时,才会生成新的 Cloud 运行 容器。

这告诉我的是,我的第一个 "improvement" 是在第一次使用时在我的 JVM 中填充缓存数据,并保持它存在以供后续重用。你什么时候填充你的缓存数据?这将是您的设计选择。您可以在容器首次启动时预先填充它……如果您知道数据将用于每个请求,这将是明智的。或者,如果您有多个可缓存的值,请考虑创建一个包含 name/value 对的映射,并有一个访问器 returns 缓存值(如果存在)或从慢速存储、缓存和 returns 一个值(如果最初不存在)。

关于第一个选项(选项 1):

创建heavyComputation()函数here would be called only at cold start, each time a new Cloud Run container instance(当超过可以并行发送给给定容器实例的最大请求数时,因此创建一个新实例)。

为了解决第二个选项(选项2):

截至目前,Cloud 运行(完全托管)不支持无服务器 VPC 访问,因此无法连接到 Cloud Memorystore。监控以下 Feature Request 以从 Cloud 运行 产品团队获取所有相关信息和更新,以检查此功能何时可用。

您可以在此 和已经提到的功能请求中找到一些解决方法。它们基本上包括:

  1. Using a Google Kubernetes Engine cluster with Cloud Run.
  2. 在 Compute Engine 上设置 Redis 实例。