Google Cloud Functions Java 11(测试版)运行时 - 性能问题

Google Cloud Functions Java 11 (Beta) Runtime - Performance Issue

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

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

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

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

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

我注意到即使像 String c = a + b; 这样的基本字符串连接在 Cloud Function 上也需要 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 运行时。当 运行 在我的本地计算机上使用此功能时,我也没有看到任何性能问题。

谁能帮我解决性能缓慢的问题?

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

中所述

Several of the recommendations in this document center around what is known as a cold start. Functions are stateless, and the execution environment is often initialized from scratch, which is called a cold start. Cold starts can take significant amounts of time to complete. It is best practice to avoid unnecessary cold starts, and to streamline the cold start process to whatever extent possible (for example, by avoiding unnecessary dependencies).

除了服务器实例本身之外,由于初始化 JVM 所花费的时间,我希望 JVM 语言具有更长的冷启动时间。

除上述建议外,几乎没有其他方法可以有效缓解冷启动。 的努力并没有你想象的那么有效。网上有很多关于这个的讨论,大家搜索一下。

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