1

public class QuickwitSinkTask extends BkMetricSink<String, String> {

    private static final Logger log = LoggerFactory.getLogger(QuickwitSinkTask.class);

    private final QuickwitSinkConfig config;
    private List<BkSinkRecord<String>> recordList;
    private List<String> valueList;
    private String url;
    private long batchSizeInMb;
    private long totalSize;
    private int batchSize;
    private int retryBackoffMs;
    private int maxRetries;
    private ScheduledExecutorService flushExecutor;

    public QuickwitSinkTask(QuickwitSinkConfig config) {
        this.config = config;
    }

    @Override
    protected void doOpen(BkDatabusContext context) {
        recordList = Lists.newArrayList();
        valueList = Lists.newArrayList();

        url = config.getUrl();
        batchSizeInMb = config.getBatchSizeInMb() << 20;
        batchSize = config.getBatchSize();
        retryBackoffMs = config.getRetryBackoffMs();
        maxRetries = config.getMaxRetries();
        long batchTimeMs = config.getBulkFlushIntervalInMs();
        totalSize = 0L;
        flushExecutor = Executors.newScheduledThreadPool(config.getTaskNum());
    }

    @Override
    protected DataBusResult<String> doWrite(BkSinkRecord<String> record) throws Exception {
        List<String> values = JsonUtils.getValue(record.getValue());
        int currentNum;
        synchronized (this) {
            valueList.addAll(values);
            recordList.add(record);
            currentNum = valueList.size();
            totalSize += values.stream().mapToLong(value -> value.getBytes(StandardCharsets.UTF_8).length).sum();
            if (currentNum >= batchSize || totalSize >= batchSizeInMb) {
                final List<String> value = valueList;
                final List<BkSinkRecord<String>> records = recordList;
                flushExecutor.execute(() -> sendData(value, records));
                valueList = Lists.newArrayList();
                recordList = Lists.newArrayList();
                totalSize = 0L;
            }
        }
        return null;
    }

    @Override
    protected String getClusterType() {
        return "quickwit";
    }

    @Override
    protected void doClose() {
        if (null != flushExecutor) {
            flushExecutor.shutdown();
        }
    }


    private void sendData(List<String> values, List<BkSinkRecord<String>> bkRecordList) {

        String records = String.join("\n", values);

        int retries = 0;
        while (retries < maxRetries) {
            try {
                HttpURLConnection connection = HttpUtils.post(url, records, null);
                int responseCode = connection.getResponseCode();
                if (responseCode >= 200 && responseCode < 300) {
                    bkRecordList.forEach(BkSourceRecord::ack);
                    break;
                } else {
                    throw new IOException("Failed to send data, response code: [" + responseCode + "], "
                            + "content : [" + connection.getErrorStream() + "]");
                }
            } catch (IOException e) {
                retries++;
                if (retries < maxRetries) {
                    try {
                        Thread.sleep(retryBackoffMs);
                    } catch (InterruptedException ex) {
                        bkRecordList.forEach(BkSourceRecord::fail);
                        throw new RuntimeException(ex);
                    }
                } else {
                    bkRecordList.forEach(BkSourceRecord::fail);
                    log.error("Failed to send data after max retries");
                }
            }
        }

        values = null;
        bkRecordList = null;
    }
}
posted @ 2023-05-07 17:00  马晟  阅读(12)  评论(0编辑  收藏  举报