All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.aliyun.openservices.aliyun.log.producer.internals.SendProducerBatchTask Maven / Gradle / Ivy

The newest version!
package com.aliyun.openservices.aliyun.log.producer.internals;

import com.aliyun.openservices.aliyun.log.producer.Attempt;
import com.aliyun.openservices.aliyun.log.producer.ProducerConfig;
import com.aliyun.openservices.aliyun.log.producer.errors.Errors;
import com.aliyun.openservices.aliyun.log.producer.errors.RetriableErrors;
import com.aliyun.openservices.log.Client;
import com.aliyun.openservices.log.common.Consts;
import com.aliyun.openservices.log.common.TagContent;
import com.aliyun.openservices.log.exception.LogException;
import com.aliyun.openservices.log.request.PutLogsRequest;
import com.aliyun.openservices.log.response.PutLogsResponse;
import com.google.common.math.LongMath;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SendProducerBatchTask implements Runnable {

  private static final Logger LOGGER = LoggerFactory.getLogger(ProducerBatch.class);

  private static final String TAG_PACK_ID = "__pack_id__";

  private final ProducerBatch batch;

  private final ProducerConfig producerConfig;

  private final Map clientPool;

  private final RetryQueue retryQueue;

  private final BlockingQueue successQueue;

  private final BlockingQueue failureQueue;

  private final AtomicInteger batchCount;

  public SendProducerBatchTask(
      ProducerBatch batch,
      ProducerConfig producerConfig,
      Map clientPool,
      RetryQueue retryQueue,
      BlockingQueue successQueue,
      BlockingQueue failureQueue,
      AtomicInteger batchCount) {
    this.batch = batch;
    this.producerConfig = producerConfig;
    this.clientPool = clientPool;
    this.retryQueue = retryQueue;
    this.successQueue = successQueue;
    this.failureQueue = failureQueue;
    this.batchCount = batchCount;
  }

  @Override
  public void run() {
    try {
      sendProducerBatch(System.currentTimeMillis());
    } catch (Throwable t) {
      LOGGER.error(
          "Uncaught error in send producer batch task, project="
              + batch.getProject()
              + ", logStore="
              + batch.getLogStore()
              + ", e=",
          t);
    }
  }

  private void sendProducerBatch(long nowMs) throws InterruptedException {
    LOGGER.trace("Prepare to send producer batch, batch={}", batch);
    String project = batch.getProject();
    Client client = getClient(project);
    if (client == null) {
      LOGGER.error("Failed to get client, project={}", project);
      Attempt attempt =
          new Attempt(
              false,
              "",
              Errors.PROJECT_CONFIG_NOT_EXIST,
              "Cannot get the projectConfig for project " + project,
              nowMs);
      batch.appendAttempt(attempt);
      failureQueue.put(batch);
    } else {
      PutLogsResponse response;
      try {
        PutLogsRequest request = buildPutLogsRequest(batch);
        if (producerConfig.getCompressType() != null) {
          Consts.CompressType compressType =
              Consts.CompressType.fromString(producerConfig.getCompressType());
          if (compressType != null && compressType != Consts.CompressType.NONE) {
            request.setCompressType(compressType);
          }
        }
        response = client.PutLogs(request);
      } catch (Exception e) {
        LOGGER.error(
            "Failed to put logs, project="
                + batch.getProject()
                + ", logStore="
                + batch.getLogStore()
                + ", e=",
            e);
        Attempt attempt = buildAttempt(e, nowMs);
        batch.appendAttempt(attempt);
        if (meetFailureCondition(e)) {
          LOGGER.debug("Prepare to put batch to the failure queue");
          failureQueue.put(batch);
        } else {
          LOGGER.debug("Prepare to put batch to the retry queue");
          long retryBackoffMs = calculateRetryBackoffMs();
          LOGGER.debug(
              "Calculate the retryBackoffMs successfully, retryBackoffMs=" + retryBackoffMs);
          batch.setNextRetryMs(System.currentTimeMillis() + retryBackoffMs);
          try {
            retryQueue.put(batch);
          } catch (IllegalStateException e1) {
            LOGGER.error(
                "Failed to put batch to the retry queue, project="
                    + batch.getProject()
                    + ", logStore="
                    + batch.getLogStore()
                    + ", e=",
                e);
            if (retryQueue.isClosed()) {
              LOGGER.info(
                  "Prepare to put batch to the failure queue since the retry queue was closed");
              failureQueue.put(batch);
            }
          }
        }
        return;
      }
      Attempt attempt = new Attempt(true, response.GetRequestId(), "", "", nowMs);
      batch.appendAttempt(attempt);
      successQueue.put(batch);
      LOGGER.trace("Send producer batch successfully, batch={}", batch);
    }
  }

  private Client getClient(String project) {
    return clientPool.get(project);
  }

  private PutLogsRequest buildPutLogsRequest(ProducerBatch batch) {
    PutLogsRequest request;
    if (batch.getShardHash() != null && !batch.getShardHash().isEmpty()) {
      request =
          new PutLogsRequest(
              batch.getProject(),
              batch.getLogStore(),
              batch.getTopic(),
              batch.getSource(),
              batch.getLogItems(),
              batch.getShardHash());
    } else {
      request =
          new PutLogsRequest(
              batch.getProject(),
              batch.getLogStore(),
              batch.getTopic(),
              batch.getSource(),
              batch.getLogItems());
    }
    List tags = new ArrayList();
    tags.add(new TagContent(TAG_PACK_ID, batch.getPackageId()));
    request.SetTags(tags);
    if (producerConfig.getLogFormat() == ProducerConfig.LogFormat.PROTOBUF) {
      request.setContentType(Consts.CONST_PROTO_BUF);
    } else {
      request.setContentType(Consts.CONST_SLS_JSON);
    }
    request.setProcessor(producerConfig.getProcessor());
    return request;
  }

  private Attempt buildAttempt(Exception e, long nowMs) {
    if (e instanceof LogException) {
      LogException logException = (LogException) e;
      return new Attempt(
          false,
          logException.GetRequestId(),
          logException.GetErrorCode(),
          logException.GetErrorMessage(),
          nowMs);
    } else {
      return new Attempt(false, "", Errors.PRODUCER_EXCEPTION, e.getMessage(), nowMs);
    }
  }

  private boolean meetFailureCondition(Exception e) {
    if (!isRetriableException(e)) {
      return true;
    }
    if (retryQueue.isClosed()) {
      return true;
    }
    return batch.getRetries() >= producerConfig.getRetries();
  }

  private boolean isRetriableException(Exception e) {
    if (e instanceof LogException) {
      LogException logException = (LogException) e;
      return (logException.GetErrorCode().equals(RetriableErrors.REQUEST_ERROR)
          || logException.GetErrorCode().equals(RetriableErrors.UNAUTHORIZED)
          || logException.GetErrorCode().equals(RetriableErrors.WRITE_QUOTA_EXCEED)
          || logException.GetErrorCode().equals(RetriableErrors.SHARD_WRITE_QUOTA_EXCEED)
          || logException.GetErrorCode().equals(RetriableErrors.EXCEED_QUOTA)
          || logException.GetErrorCode().equals(RetriableErrors.INTERNAL_SERVER_ERROR)
          || logException.GetErrorCode().equals(RetriableErrors.SERVER_BUSY)
          || logException.GetErrorCode().equals(RetriableErrors.BAD_RESPONSE)
          || logException.GetErrorCode().equals(RetriableErrors.PROJECT_NOT_EXISTS)
          || logException.GetErrorCode().equals(RetriableErrors.LOGSTORE_NOT_EXISTS)
          || logException.GetErrorCode().equals(RetriableErrors.SOCKET_TIMEOUT)
          || logException.GetErrorCode().equals(RetriableErrors.SIGNATURE_NOT_MATCH));
    }
    return false;
  }

  private long calculateRetryBackoffMs() {
    int retry = batch.getRetries();
    long retryBackoffMs = producerConfig.getBaseRetryBackoffMs() * LongMath.pow(2, retry);
    if (retryBackoffMs <= 0) {
      retryBackoffMs = producerConfig.getMaxRetryBackoffMs();
    }
    return Math.min(retryBackoffMs, producerConfig.getMaxRetryBackoffMs());
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy