【问题标题】:Why http request can take 15 sec with "GCM HTTP Connection Server "为什么使用“GCM HTTP 连接服务器”的 http 请求可能需要 15 秒
【发布时间】:2014-11-12 16:09:59
【问题描述】:

实现gcm第三方服务器,我们决定使用http集成,跟着googleinstructions

它们提供了集成here 的实现。

我们使用它并使用 java 任务向 500 000 个用户发送通知以提高效率(我们需要尽快通知我们的用户)。 我们很惊讶,因为对 GCM 服务器的 http 请求有时可能需要超过 15 秒。我们在 gcm-server 源中设置了登录并找出了这个问题。

带有自定义日志的代码:

public MulticastResult sendNoRetry(Message message, List<String> registrationIds) throws IOException {
    if (nonNull(registrationIds).isEmpty()) {
        throw new IllegalArgumentException("registrationIds cannot be empty");
    }
    Date startDate = new Date();
    Map<Object, Object> jsonRequest = new HashMap<Object, Object>();
    setJsonField(jsonRequest, PARAM_TIME_TO_LIVE, message.getTimeToLive());
    setJsonField(jsonRequest, PARAM_COLLAPSE_KEY, message.getCollapseKey());
    setJsonField(jsonRequest, PARAM_RESTRICTED_PACKAGE_NAME, message.getRestrictedPackageName());
    setJsonField(jsonRequest, PARAM_DELAY_WHILE_IDLE, message.isDelayWhileIdle());
    setJsonField(jsonRequest, PARAM_DRY_RUN, message.isDryRun());
    jsonRequest.put(JSON_REGISTRATION_IDS, registrationIds);
    Map<String, String> payload = message.getData();
    if (!payload.isEmpty()) {
        jsonRequest.put(JSON_PAYLOAD, payload);
    }
    String requestBody = JSONValue.toJSONString(jsonRequest);
    log.debug("JSON request: " + requestBody);
    HttpURLConnection conn;
    int status;
    Date beforeHttpRequest = new Date();
    try {
        conn = post(GCM_SEND_ENDPOINT, "application/json", requestBody);
        status = conn.getResponseCode();
    } catch (IOException e) {
        log.error("IOException posting to GCM", e);
        return null;
    }
    Date afterHttpRequest = new Date();
    String responseBody;
    if (status != 200) {
        try {
            responseBody = getAndClose(conn.getErrorStream());
            log.debug("JSON error response: " + responseBody);
        } catch (IOException e) {
            // ignore the exception since it will thrown an
            // InvalidRequestException
            // anyways
            responseBody = "N/A";
            log.error("Exception reading response: ", e);
        }
        throw new InvalidRequestException(status, responseBody);
    }

    try {
        responseBody = getAndClose(conn.getInputStream());
    } catch (IOException e) {
        log.error("IOException reading response", e);
        return null;
    }
    log.debug("JSON response: " + responseBody);
    JSONParser parser = new JSONParser();
    JSONObject jsonResponse;
    try {
        jsonResponse = (JSONObject) parser.parse(responseBody);
        int success = getNumber(jsonResponse, JSON_SUCCESS).intValue();
        int failure = getNumber(jsonResponse, JSON_FAILURE).intValue();
        int canonicalIds = getNumber(jsonResponse, JSON_CANONICAL_IDS).intValue();
        long multicastId = getNumber(jsonResponse, JSON_MULTICAST_ID).longValue();
        MulticastResult.Builder builder = new MulticastResult.Builder(success, failure, canonicalIds, multicastId);
        @SuppressWarnings("unchecked")
        List<Map<String, Object>> results = (List<Map<String, Object>>) jsonResponse.get(JSON_RESULTS);
        if (results != null) {
            for (Map<String, Object> jsonResult : results) {
                String messageId = (String) jsonResult.get(JSON_MESSAGE_ID);
                String canonicalRegId = (String) jsonResult.get(TOKEN_CANONICAL_REG_ID);
                String error = (String) jsonResult.get(JSON_ERROR);
                Result result = new Result.Builder().messageId(messageId).canonicalRegistrationId(canonicalRegId).errorCode(error)
                        .build();
                builder.addResult(result);
            }
        }
        MulticastResult multicastResult = builder.build();
        log.info("Http Request takes : "
                + (afterHttpRequest.getTime() - beforeHttpRequest.getTime()) / 1000 + " sec");
        return multicastResult;
    } catch (ParseException e) {
        throw newIoException(responseBody, e);
    } catch (CustomParserException e) {
        throw newIoException(responseBody, e);
    }
}

还有日志:

2014-11-12 13:01:54,660 INFO executor-37 Sender:466  - Http Request takes : 4 sec
2014-11-12 13:01:57,383 INFO executor-49 Sender:466  - Http Request takes : 6 sec
2014-11-12 13:01:57,702 INFO executor-31 Sender:466  - Http Request takes : 6 sec
2014-11-12 13:01:58,565 INFO executor-42 Sender:466  - Http Request takes : 9 sec
2014-11-12 13:01:58,602 INFO executor-39 Sender:466  - Http Request takes : 7 sec
2014-11-12 13:01:59,477 INFO executor-45 Sender:466  - Http Request takes : 10 sec
2014-11-12 13:02:00,876 INFO executor-36 Sender:466  - Http Request takes : 20 sec
2014-11-12 13:02:01,018 INFO executor-43 Sender:466  - Http Request takes : 3 sec
2014-11-12 13:02:01,055 INFO executor-40 Sender:466  - Http Request takes : 6 sec
2014-11-12 13:02:02,440 INFO executor-41 Sender:466  - Http Request takes : 11 sec
2014-11-12 13:02:02,846 INFO executor-50 Sender:466  - Http Request takes : 5 sec
2014-11-12 13:02:03,135 INFO executor-47 Sender:466  - Http Request takes : 4 sec
2014-11-12 13:02:03,237 INFO executor-46 Sender:466  - Http Request takes : 4 sec

我们在不同的服务器上进行了尝试,这不是连接问题。 ¿ 有人可能知道为什么一个简单的 http 请求需要这么多时间?

【问题讨论】:

    标签: java http google-cloud-messaging multitasking


    【解决方案1】:

    这段代码一切正常……这只是简单的网络问题。

    我相信我的服务器有 10 Mbytes/s 的上传速率,这可能是真的,但事实上,它离谷歌服务器很远,所以上传速率是瓶颈。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-15
      • 1970-01-01
      • 2011-10-04
      • 2011-12-04
      • 2011-06-29
      • 2020-04-22
      • 1970-01-01
      相关资源
      最近更新 更多