GCM传统 FCM发送 GOAWAY HTTP/2 帧

问题描述

我们的推送后端使用 GCM API 向 Android 设备发送通知
端点:https://fcm.googleapis.com/fcm/send
HTTP 客户端:Java 11 Http Client(使用 HTTP/2 设置):

var httpClient = HttpClient.newBuilder()
    .version(HttpClient.Version.HTTP_2)
    // ...
    .build();

问题
有时我们会从 GCM 获得 GOAWAY 帧。但是 java http client hides 这些帧的错误代码和有效载荷(只是抛出一些通用异常)。所以我们不知道是什么导致了 GOAWAY

问题

  1. 这是 GCM API 的预期行为吗?
  2. 可能是什么原因造成的?
  3. 如何调试?

解决方法

很难确定 GCM 为何发送 GOAWAY - 只有 GCM 团队才能真正回答这个问题。但是,它的一些常见原因是:

  • 您的客户端所连接的服务器正在停机以进行维护。在此之前,它进入一个耗尽模式,允许完成正在进行的请求,同时阻止新的请求。这是通过发送 GOAWAY 通知客户端不应在该连接上启动新请求来实现的。
  • 服务器希望客户端迁移到不同的连接以实现负载平衡

这意味着发送 GOAWAY 的服务器不是错误,它只是在云设置中可以预料的事情。

HTTP/2 规范提供了一些关于如何处理 GOAWAY 的更多信息:https://tools.ietf.org/html/rfc7540#section-6.8

关于处理它:理想情况下,您的 HTTP/2 客户端可能已经在内部完全做到了:

  • 如果它在没有请求处于活动状态时收到 GOAWAY 帧,它应该为下一个请求创建一个新连接
  • 如果它在发送请求时接收到 GOAWAY 帧,并且该 GOAWAY 帧表明请求尚未处理,则可以创建新客户端并重试请求。即使它是非幂等请求(如 POST),这也能正常工作,因为我们知道服务器尚未处理该请求。

如果 JDK11 客户端没有自动执行此操作,那么您在这里真正能做的就是在应用层重试。

根据is there any way to handle HTTP/2 Goaway received IOException in HttpClient java?,似乎客户端可能会抛出一个IOException,其消息包含GOAWAY received。这可能是重试的好信号。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...