【问题标题】:GCM - Could not post JSON requests to GCM after 6 attemptsGCM - 6 次尝试后无法将 JSON 请求发布到 GCM
【发布时间】:2014-09-12 19:14:18
【问题描述】:

我遇到了与this 相同的问题。我会尽力提供更多信息。

我正在使用 Play Framework,用 Java 编写。我写了一个名为 PushNotificationQueue 的插件。 PushNotificationQueue 同时运行 iOS 和 Android 推送消息队列。下面,作为参考,是我的 GCM 实现。

public class AndroidPushNotificationQueue {

  // (constructors and fields not included for brevity)
  // constructor starts a daemon thread

/**
* Sends a notification. 
* @param notifyKeys - device tokens
* @param data - data to send
**/
public void sendNotification(List<String> notifyKeys, Map<String, String> data) {       
    if (notifyKeys.size() == 0) {
        return;
    }

    Builder b = new Message.Builder();
    if (data != null) {
        for (String key : data.keySet()) {
            b.addData(key, data.get(key));
        }
    }
    if (testMode) {
        b.dryRun(true);
    }
    Message message = b.build();
    queue.add(new Notification(notifyKeys, message));
}

public void stop() {
    stopped = true;
    sendingThread.interrupt();
}

private class SendNotificationRunner implements Runnable {

    @Override
    public void run() {
        while (true) {
            try {
                sendNotifications();
                //TODO: handle errors
            } catch (InterruptedException e) {
                if (stopped)    break;
                Logger.error("Error processing android notification", e);
            } catch (InvalidRequestException e) {
                if (stopped)    break;
                Logger.error("Error processing android notification", e);
            } catch (IOException e) {
                if (stopped)    break;
                Logger.error("Error processing android notification", e);
            } catch (Exception e) {
                if (stopped)    break;
                Logger.error("Unexpected Exception in Android Notification thread", e);
            }
        }
        Logger.info("Stopping Android push queue");
    }

    private void sendNotifications() throws IOException, InterruptedException, InvalidRequestException {

        Notification n = queue.take(); // will wait until an element becomes available
        MulticastResult result = sender.send(n.message, n.notifyKeys, NUM_RETRIES);
        List<Result> results = result.getResults();

        for (int i = 0; i < results.size(); ++i) {
            Result r = results.get(i);
            String mId = r.getMessageId();
            String notifyKey = n.notifyKeys.get(i);

            if (mId == null) {
                String error = r.getErrorCodeName();
                if (error.equals(Constants.ERROR_NOT_REGISTERED)) {
                    removeDeadRegistration(notifyKey);
                } else {
                    //TODO: something better when error occurs
                    Logger.error("Error sending android notification to " + notifyKey + ": " + error);
                }
            } else {
                String newNotifyKey = r.getCanonicalRegistrationId();
                if (newNotifyKey != null && !newNotifyKey.equals(notifyKey)) {
                       // do something to handle this error case - not included for brevity
                }
            }
        }
    }

}

这工作......有时。大多数时候我收到以下错误。

java.io.IOException: Could not post JSON requests to GCM after 6 attempts
  at com.google.android.gcm.server.Sender.send(Sender.java:319) ~[classes/:na]
  at utils.AndroidPushNotificationQueue$SendNotificationRunner.sendNotifications(AndroidPushNotificationQueue.java:131) ~[classes/:na]
  at utils.AndroidPushNotificationQueue$SendNotificationRunner.run(AndroidPushNotificationQueue.java:103) ~[classes/:na]
  at java.lang.Thread.run(Thread.java:745) [na:1.7.0_55]
  [debug] application - Endpoint - BaseStationAuth.getUsername

我进行了一些挖掘,并在 GCM 实现中发现了这一点。

/**
   * Sends a message to one device, retrying in case of unavailability.
   *
   * <p>
   * <strong>Note: </strong> this method uses exponential back-off to retry in
   * case of service unavailability and hence could block the calling thread
   * for many seconds.
   *
   * @param message message to be sent, including the device's registration id.
   * @param registrationId device where the message will be sent.
   * @param retries number of retries in case of service unavailability errors.
   *
   * @return result of the request (see its javadoc for more details).
   *
   * @throws IllegalArgumentException if registrationId is {@literal null}.
   * @throws InvalidRequestException if GCM didn't returned a 200 or 5xx status.
   * @throws IOException if message could not be sent.
   */
  public Result send(Message message, String registrationId, int retries)
      throws IOException {
    int attempt = 0;
    Result result = null;
    int backoff = BACKOFF_INITIAL_DELAY;
    boolean tryAgain;
    do {
      attempt++;
      if (logger.isLoggable(Level.FINE)) {
        logger.fine("Attempt #" + attempt + " to send message " +
            message + " to regIds " + registrationId);
      }
      result = sendNoRetry(message, registrationId);
      tryAgain = result == null && attempt <= retries;
      if (tryAgain) {
        int sleepTime = backoff / 2 + random.nextInt(backoff);
        sleep(sleepTime);
        if (2 * backoff < MAX_BACKOFF_DELAY) {
          backoff *= 2;
        }
      }
    } while (tryAgain);
    if (result == null) {
      throw new IOException("Could not send message after " + attempt +
          " attempts");
    }
    return result;
  }

我改变了尝试的次数 - 5、10、15。

  • 还有其他人遇到过这个问题吗?我在网上找了几个人有同样的问题,但目前还没有找到解决办法。
  • 对我可以尝试解决的问题有什么建议吗?
  • 我应该继续增加尝试次数吗?

【问题讨论】:

  • 您要处理多少个收件人,您的邮件有多大?
  • 我也遇到了这个问题。如果你能解决它,请分享。

标签: java playframework-2.0 google-cloud-messaging


【解决方案1】:

我遇到了同样的问题。但修复它。

1。 我认为只需将“Sender.BACKOFF_INITIAL_DELAY = 1000;”的间隔时间变量编辑为“Sender.BACKOFF_INITIAL_DELAY = 10000;”在 com.google.android.gcm.server 上的 Sender.java 中。

您可以读取 Sender.java 文件。它是开源的。

2。 我将 collaps_key 值更改为 gcm 有效负载中的长类型。 我认为谷歌服务器不接受 collaps_key 的特殊字符。 ".", ",", 任何字母。

祝你好运。

【讨论】:

  • 我会试试这个。感谢您调查它!一旦我确认它有效,我会接受你的回答。
【解决方案2】:

清除 GCM 服务器配置中接受的所有 IP 地址(允许来自任何 IP)为我解决了这个问题。由于已经使用了密钥,限制 IP 地址(对于大多数)是不必要的预防措施。

【讨论】:

    【解决方案3】:

    我的应用程序也抛出了异常消息“GCM - 6 次尝试后无法将 JSON 请求发布到 GCM”。因此,我在 sendNoRetry(...) 方法调用中的 post(...) 方法调用(Sender.java 的第 190 行)处设置了一个断点,并四处走动以获取有关响应的一些有用信息。

    在我的例子中,我得到了一个 401 http 状态码,因为我使用了错误的 api 密钥。

    【讨论】:

    • @ZachSaucier - 你太快了,他没有发布新问题,而是他如何在自己的代码中找到解决问题的解决方案。即,他建议 OP 也这样做。
    【解决方案4】:

    此消息的另一个可能原因:Google 云消息传递自 2019 年 5 月 29 日起已弃用

    详情:

    当我收到相同的错误消息时,我偶然发现了这个问题

    尝试 6 次后无法向 GCM 发布 JSON 请求

    调试后发现我使用的库是:https://github.com/google/gcm 一种掩盖了真正的错误是:

    400 – 错误请求错误=DeprecatedEndpoint

    (我猜你也可以提高调试级别来查看真正的错误消息而不是调试它。)

    所以,事实证明端点是旧的,应该迁移到 firebase 消息传递端点。

    【讨论】:

      猜你喜欢
      • 2013-11-20
      • 1970-01-01
      • 1970-01-01
      • 2022-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多