【问题标题】:Google Cloud Functions Java 11 (Beta) Runtime - Performance IssueGoogle Cloud Functions Java 11(测试版)运行时 - 性能问题
【发布时间】:2020-07-05 02:45:28
【问题描述】:

我使用 Java 11(Beta)运行时创建了一个新的云函数来处理我的静态站点的 HTML 表单提交。这是一个简单的 3 字段表单(姓名、电子邮件、消息)。不涉及文件上传。该函数主要做两件事:

  1. 使用 BitBucket 创建拉取请求
  2. 使用 SendGrid 向我发送电子邮件

注意:它也会验证 recaptcha,但我已将其禁用以进行测试。

在我的本地计算机(基本型号 2019 Macbook Pro 13")上运行该功能大约需要 3 秒。我位于东南亚。部署到 Google Cloud us-central1 时相同的功能大约需要 25 秒(8慢了几倍)。我在生产中运行几乎相同的代码,作为 GAE Java 8 运行时的 Servlet 的一部分,也在美国中部地区运行了几年。包括 recaptcha 验证和发送电子邮件大约需要 2-3 秒。我我尝试将其移植到 Cloud Function 上,但使用 Cloud Function 时,即使没有重新验证,性能也会慢 10 倍左右。

相比之下,Cloud Function 在 256MB / 400GHz 实例上运行,而我的 GAE Java 8 运行时在 F1 (128MB / 600GHz) 实例上运行。该函数仅使用大约 75MB 的内存。该函数配置为接受未经身份验证的请求。

我注意到,即使是基本的字符串连接,如:String c = a + b;,在云函数上也需要 100 毫秒。我已经对调用进行了计时,将大约 15 个字符串连接成一个的简单字符串大约需要 1.5-2.0 秒。

此外,将一条小消息 (~ 1KB) 写入 HTTPUrlConnection 输出流并读回响应大约需要 10 秒(是秒)!

/* Writing < 1KB to output stream takes about 4-5 secs */
wr = new OutputStreamWriter(con.getOutputStream());
wr.write(encodedParams);
wr.flush();
wr.close();

/* Reading response also take about 4-5 secs */
String responseMessage = con.getResponseMessage();

同样,下面的 SendGrid 代码需要另外 10 秒来发送电子邮件。在我的本地机器上大约需要 1 秒。

Email from = new Email(fromEmail, fromName);
Email to = new Email(toEmail, toName);
Email replyTo = new Email(replyToEmail, replyToName);
Content content = new Content("text/html", body);

Mail mail = new Mail(from, subject, to, content);
mail.setReplyTo(replyTo);
SendGrid sg = new SendGrid(SENDGRID_API_KEY);
Request sgRequest = new Request();
Response sgResponse = null;
try {
    sgRequest.setMethod(Method.POST);
    sgRequest.setEndpoint("mail/send");
    sgRequest.setBody(mail.build());
    sgResponse = sg.api(sgRequest);            
} catch (IOException ex) {
    throw ex;
}

云功能明显有问题。由于我的原始代码是在 GAE Java 8 运行时上运行的,因此我很容易将其移植到 Cloud Function 上,只需稍作改动即可。否则我会选择 NodeJS 运行时。在本地机器上运行此功能时,我也没有看到任何性能问题。

有人可以帮我理解性能缓慢的问题吗?

【问题讨论】:

标签: google-cloud-platform google-cloud-functions java-11


【解决方案1】:

您所看到的几乎可以肯定是由于与创建新服务器实例来处理请求相关的“冷启动”成本。如documentation 中所述,这是所有类型的云函数都存在的问题:

本文档中的一些建议以所谓的冷启动为中心。函数是无状态的,执行环境往往是从头开始初始化的,称为冷启动。冷启动可能需要很长时间才能完成。最佳做法是避免不必要的冷启动,并尽可能简化冷启动过程(例如,通过避免不必要的依赖关系)。

我希望 JVM 语言的冷启动时间更长,因为除了服务器实例本身之外,初始化 JVM 所需的时间也更长。

除了上述建议之外,几乎没有什么可以有效缓解冷启动。 keep a function warm 的努力并没有你想象的那么有效。如果你想搜索,网上有很多关于这个的讨论。

请记住,Java 运行时也处于测试阶段,因此您可以期待未来的改进。其他运行时也发生了同样的事情。

【讨论】:

  • 你是对的。这是我第一次使用 GCF。我以为我检查了冷启动时间,但显然没有。我重新测试了它,第二个请求仅在 2.2 秒内完成。我每周只能获得大约 25 cmets,并且每个请求 15-20 秒的冷启动延迟是不可接受的(假设它们分散了几个小时)。我已经在使用 cron 技巧通过每 5 分钟 ping 一次来保持我的 GAE 实例处于活动状态。我会在 GCF 上尝试同样的方法,然后看看。我以为 GCF 至少会保留一个实例,但我错了。非常感谢您的帮助。
猜你喜欢
  • 2020-06-16
  • 2019-07-09
  • 2019-10-06
  • 2020-08-18
  • 2020-07-28
  • 2019-05-10
  • 1970-01-01
  • 2019-12-31
  • 2021-11-18
相关资源
最近更新 更多