This is an automated email from the ASF dual-hosted git repository.
dockerzhang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/inlong.git
The following commit(s) were added to refs/heads/master by this push:
new 641a5c9c0 [INLONG-7519][Audit] Proxy support Kafka (#7524)
641a5c9c0 is described below
commit 641a5c9c03bb72c32db77e8b95d0968dd86d5f0b
Author: haifxu <[email protected]>
AuthorDate: Tue Mar 7 16:39:06 2023 +0800
[INLONG-7519][Audit] Proxy support Kafka (#7524)
---
inlong-audit/audit-proxy/pom.xml | 4 +
.../audit/sink/{PulsarSink.java => KafkaSink.java} | 485 +++++++++------------
.../org/apache/inlong/audit/sink/PulsarSink.java | 18 +-
.../org/apache/inlong/audit/sink/TubeSink.java | 8 +-
.../apache/inlong/audit/sink/KafkaSinkTest.java | 84 ++++
inlong-audit/conf/audit-proxy-kafka.conf | 75 ++++
6 files changed, 387 insertions(+), 287 deletions(-)
diff --git a/inlong-audit/audit-proxy/pom.xml b/inlong-audit/audit-proxy/pom.xml
index 1df74fff6..8fdeef909 100644
--- a/inlong-audit/audit-proxy/pom.xml
+++ b/inlong-audit/audit-proxy/pom.xml
@@ -73,6 +73,10 @@
<groupId>org.apache.pulsar</groupId>
<artifactId>pulsar-client</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.kafka</groupId>
+ <artifactId>kafka-clients</artifactId>
+ </dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
diff --git
a/inlong-audit/audit-proxy/src/main/java/org/apache/inlong/audit/sink/PulsarSink.java
b/inlong-audit/audit-proxy/src/main/java/org/apache/inlong/audit/sink/KafkaSink.java
similarity index 51%
copy from
inlong-audit/audit-proxy/src/main/java/org/apache/inlong/audit/sink/PulsarSink.java
copy to
inlong-audit/audit-proxy/src/main/java/org/apache/inlong/audit/sink/KafkaSink.java
index c8c120537..1f357bec5 100644
---
a/inlong-audit/audit-proxy/src/main/java/org/apache/inlong/audit/sink/PulsarSink.java
+++
b/inlong-audit/audit-proxy/src/main/java/org/apache/inlong/audit/sink/KafkaSink.java
@@ -19,223 +19,136 @@ package org.apache.inlong.audit.sink;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.RateLimiter;
-import io.netty.handler.codec.TooLongFrameException;
-import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
+import org.apache.commons.lang3.StringUtils;
import org.apache.flume.Channel;
import org.apache.flume.Context;
import org.apache.flume.Event;
-import org.apache.flume.EventDeliveryException;
import org.apache.flume.Transaction;
import org.apache.flume.conf.Configurable;
import org.apache.flume.instrumentation.SinkCounter;
import org.apache.flume.sink.AbstractSink;
import org.apache.inlong.audit.base.HighPriorityThreadFactory;
-import org.apache.inlong.audit.sink.pulsar.CreatePulsarClientCallBack;
-import org.apache.inlong.audit.sink.pulsar.PulsarClientService;
-import org.apache.inlong.audit.sink.pulsar.SendMessageCallBack;
import org.apache.inlong.audit.utils.FailoverChannelProcessorHolder;
+import org.apache.inlong.common.util.NetworkUtils;
+import org.apache.kafka.clients.producer.KafkaProducer;
+import org.apache.kafka.clients.producer.ProducerConfig;
+import org.apache.kafka.clients.producer.ProducerRecord;
+import org.apache.kafka.common.serialization.ByteArraySerializer;
+import org.apache.kafka.common.serialization.StringSerializer;
import org.apache.pulsar.client.api.PulsarClientException;
-import
org.apache.pulsar.client.api.PulsarClientException.AlreadyClosedException;
-import
org.apache.pulsar.client.api.PulsarClientException.NotConnectedException;
-import
org.apache.pulsar.client.api.PulsarClientException.ProducerQueueIsFullError;
-import
org.apache.pulsar.client.api.PulsarClientException.TopicTerminatedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-/**
- * pulsar sink
- *
- * send to one pulsar cluster
- */
-public class PulsarSink extends AbstractSink
- implements
- Configurable,
- SendMessageCallBack,
- CreatePulsarClientCallBack {
-
- private static final Logger logger =
LoggerFactory.getLogger(PulsarSink.class);
-
- /*
- * properties for header info
- */
- private static String TOPIC = "topic";
-
- /*
- * default value
- */
- private static int BAD_EVENT_QUEUE_SIZE = 10000;
- private static int BATCH_SIZE = 10000;
- private static final int DEFAULT_LOG_EVERY_N_EVENTS = 100000;
-
- /*
- * properties for stat
- */
- private static String LOG_EVERY_N_EVENTS = "log_every_n_events";
-
- private static String DISK_IO_RATE_PER_SEC = "disk_io_rate_per_sec";
-
- private static final String SINK_THREAD_NUM = "thread_num";
-
- /*
- * for log
- */
- private Integer logEveryNEvents;
-
- private long diskIORatePerSec;
-
- private RateLimiter diskRateLimiter;
-
- /*
- * for stat
- */
- private AtomicLong currentSuccessSendCnt = new AtomicLong(0);
-
- private AtomicLong lastSuccessSendCnt = new AtomicLong(0);
-
- private long t1 = System.currentTimeMillis();
-
- private long t2 = 0L;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
- private static AtomicLong totalPulsarSuccSendCnt = new AtomicLong(0);
+public class KafkaSink extends AbstractSink implements Configurable {
- private static AtomicLong totalPulsarSuccSendSize = new AtomicLong(0);
- /*
- * for control
- */
- private boolean overflow = false;
+ private static final Logger logger =
LoggerFactory.getLogger(KafkaSink.class);
- private LinkedBlockingQueue<EventStat> resendQueue;
+ // for kafka producer
+ private static Properties properties = new Properties();
+ private static final String BOOTSTRAP_SERVER = "bootstrap_servers";
+ private static final String TOPIC = "topic";
+ private static final String RETRIES = "retries";
+ private static final String BATCH_SIZE = "batch_size";
+ private static final String LINGER_MS = "linger_ms";
+ private static final String BUFFER_MEMORY = "buffer_memory";
+ private static final String defaultRetries = "0";
+ private static final String defaultBatchSize = "16384";
+ private static final String defaultLingerMs = "0";
+ private static final String defaultBufferMemory = "33554432";
+ private static final String defaultAcks = "all";
- private long logCounter = 0;
-
- private final AtomicLong currentInFlightCount = new AtomicLong(0);
+ private static final Long PRINT_INTERVAL = 30L;
+ private static final KafkaPerformanceTask kafkaPerformanceTask = new
KafkaPerformanceTask();
+ private static ScheduledExecutorService scheduledExecutorService =
Executors.newScheduledThreadPool(1,
+ new HighPriorityThreadFactory("kafkaPerformance-Printer-thread"));
- /*
- * whether the SendTask thread can send data to pulsar
- */
+ private KafkaProducer<String, byte[]> producer;
+ public Map<String, KafkaProducer<String, byte[]>> producerMap;
+ private SinkCounter sinkCounter;
+ private String topic;
private volatile boolean canSend = false;
-
- /*
- * Control whether the SinkRunner thread can read data from the Channel
- */
private volatile boolean canTake = false;
-
- private static int EVENT_QUEUE_SIZE = 1000;
-
private int threadNum;
-
- /*
- * send thread pool
- */
private Thread[] sinkThreadPool;
- private LinkedBlockingQueue<Event> eventQueue;
- private SinkCounter sinkCounter;
+ private static final int BAD_EVENT_QUEUE_SIZE = 10000;
+ private static final int EVENT_QUEUE_SIZE = 1000;
+ private static final int DEFAULT_LOG_EVERY_N_EVENTS = 100000;
+ private LinkedBlockingQueue<EventStat> resendQueue;
+ private LinkedBlockingQueue<Event> eventQueue;
- private PulsarClientService pulsarClientService;
+ // for log
+ private Integer logEveryNEvents;
+ private long diskIORatePerSec;
+ private RateLimiter diskRateLimiter;
- private static final Long PRINT_INTERVAL = 30L;
+ // properties for stat
+ private static final String LOG_EVERY_N_EVENTS = "log_every_n_events";
+ private static final String DISK_IO_RATE_PER_SEC = "disk_io_rate_per_sec";
+ private static final String SINK_THREAD_NUM = "thread-num";
- private static final PulsarPerformanceTask pulsarPerformanceTask = new
PulsarPerformanceTask();
+ // for stas
+ private AtomicLong currentSuccessSendCnt = new AtomicLong(0);
+ private AtomicLong lastSuccessSendCnt = new AtomicLong(0);
+ private long t1 = System.currentTimeMillis();
+ private long t2 = 0L;
+ private static AtomicLong totalKafkaSuccSendCnt = new AtomicLong(0);
+ private static AtomicLong totalKafkaSuccSendSize = new AtomicLong(0);
- private static ScheduledExecutorService scheduledExecutorService =
Executors
- .newScheduledThreadPool(1, new
HighPriorityThreadFactory("pulsarPerformance-Printer-thread"));
+ private boolean overflow = false;
- private String topic;
+ private String localIp = "127.0.0.1";
static {
- /*
- * stat pulsar performance
- */
- System.out.println("pulsarPerformanceTask!!!!!!");
- scheduledExecutorService.scheduleWithFixedDelay(pulsarPerformanceTask,
0L,
+ // stat kafka performance
+ logger.info("init kafkaPerformanceTask");
+ scheduledExecutorService.scheduleWithFixedDelay(kafkaPerformanceTask,
0L,
PRINT_INTERVAL, TimeUnit.SECONDS);
}
- public PulsarSink() {
+ public KafkaSink() {
super();
- logger.debug("new instance of PulsarSink!");
- }
-
- /**
- * configure
- * @param context
- */
- public void configure(Context context) {
- logger.info("PulsarSink started and context = {}", context.toString());
- /*
- * topic config
- */
- topic = context.getString(TOPIC);
- logEveryNEvents = context.getInteger(LOG_EVERY_N_EVENTS,
DEFAULT_LOG_EVERY_N_EVENTS);
- logger.debug(this.getName() + " " + LOG_EVERY_N_EVENTS + " " +
logEveryNEvents);
- Preconditions.checkArgument(logEveryNEvents > 0, "logEveryNEvents must
be > 0");
-
- resendQueue = new LinkedBlockingQueue<EventStat>(BAD_EVENT_QUEUE_SIZE);
-
- String sinkThreadNum = context.getString(SINK_THREAD_NUM, "4");
- threadNum = Integer.parseInt(sinkThreadNum);
- Preconditions.checkArgument(threadNum > 0, "threadNum must be > 0");
- sinkThreadPool = new Thread[threadNum];
- eventQueue = new LinkedBlockingQueue<Event>(EVENT_QUEUE_SIZE);
-
- diskIORatePerSec = context.getLong(DISK_IO_RATE_PER_SEC, 0L);
- if (diskIORatePerSec != 0) {
- diskRateLimiter = RateLimiter.create(diskIORatePerSec);
- }
- pulsarClientService = new PulsarClientService(context);
-
- if (sinkCounter == null) {
- sinkCounter = new SinkCounter(getName());
- }
- }
-
- private void initTopic() throws Exception {
- long startTime = System.currentTimeMillis();
- if (topic != null) {
- pulsarClientService.initTopicProducer(topic);
- }
- logger.info(getName() + " initTopic cost: "
- + (System.currentTimeMillis() - startTime) + "ms");
+ logger.debug("new instance of KafkaSink!");
}
@Override
- public void start() {
- logger.info("pulsar sink starting...");
- sinkCounter.start();
- pulsarClientService.initCreateConnection(this);
+ public synchronized void start() {
+ logger.info("kafka sink starting");
+ // create connection
+ sinkCounter.start();
super.start();
this.canSend = true;
this.canTake = true;
- try {
- initTopic();
- } catch (Exception e) {
- logger.info("meta sink start publish topic fail.", e);
- }
+
+ // init topic producer
+ initTopicProducer(topic);
for (int i = 0; i < sinkThreadPool.length; i++) {
- sinkThreadPool[i] = new Thread(new SinkTask(), getName()
- + "_pulsar_sink_sender-"
- + i);
+ sinkThreadPool[i] = new Thread(new SinkTask(), getName() +
"_tube_sink_sender-" + i);
sinkThreadPool[i].start();
}
- logger.debug("meta sink started");
+ logger.debug("kafka sink started");
}
@Override
- public void stop() {
- logger.info("pulsar sink stopping");
- pulsarClientService.close();
+ public synchronized void stop() {
+ logger.info("kafka sink stopping");
+ // stop connection
this.canTake = false;
int waitCount = 0;
while (eventQueue.size() != 0 && waitCount++ < 10) {
try {
- Thread.currentThread().sleep(1000);
+ Thread.sleep(1000);
} catch (InterruptedException e) {
logger.info("Stop thread has been interrupt!");
break;
@@ -256,12 +169,12 @@ public class PulsarSink extends AbstractSink
scheduledExecutorService.shutdown();
}
sinkCounter.stop();
- logger.debug("pulsar sink stopped. Metrics:{}", sinkCounter);
+ logger.debug("kafka sink stopped. Metrics:{}", sinkCounter);
}
@Override
- public Status process() throws EventDeliveryException {
- logger.debug("process......");
+ public Status process() {
+ logger.info("kafka sink processing");
if (!this.canTake) {
return Status.BACKOFF;
}
@@ -277,8 +190,8 @@ public class PulsarSink extends AbstractSink
diskRateLimiter.acquire(event.getBody().length);
}
if (!eventQueue.offer(event, 3 * 1000, TimeUnit.MILLISECONDS))
{
- logger.info("[{}] Channel --> Queue(has no enough
space,current code point) "
- + "--> pulsar,Check if pulsar server or network is
ok.(if this situation "
+ logger.info("[{}] Channel --> Queue(not enough space,
current code point) "
+ + "--> Kafka, check if Kafka server or network is
ok. (If this situation "
+ "last long time it will cause memoryChannel full
and fileChannel write.)", getName());
tx.rollback();
} else {
@@ -293,7 +206,7 @@ public class PulsarSink extends AbstractSink
try {
tx.rollback();
} catch (Throwable e) {
- logger.error("Pulsar Sink transaction rollback exception =
{}", e);
+ logger.error("Kafka Sink transaction rollback exception = {}",
e);
}
} finally {
tx.close();
@@ -302,69 +215,117 @@ public class PulsarSink extends AbstractSink
}
@Override
- public void handleCreateClientSuccess(String url) {
- logger.info("createConnection success for url = {}", url);
- sinkCounter.incrementConnectionCreatedCount();
+ public void configure(Context context) {
+ logger.info("KafkaSink started and context = {}", context.toString());
+
+ topic = context.getString(TOPIC);
+ Preconditions.checkState(StringUtils.isNotEmpty(topic), "No topic
specified");
+
+ producerMap = new HashMap<>();
+
+ logEveryNEvents = context.getInteger(LOG_EVERY_N_EVENTS,
DEFAULT_LOG_EVERY_N_EVENTS);
+ logger.debug(this.getName() + " " + LOG_EVERY_N_EVENTS + " " +
logEveryNEvents);
+ Preconditions.checkArgument(logEveryNEvents > 0, "logEveryNEvents must
be > 0");
+
+ resendQueue = new LinkedBlockingQueue<>(BAD_EVENT_QUEUE_SIZE);
+
+ String sinkThreadNum = context.getString(SINK_THREAD_NUM, "4");
+ threadNum = Integer.parseInt(sinkThreadNum);
+ Preconditions.checkArgument(threadNum > 0, "threadNum must be > 0");
+ sinkThreadPool = new Thread[threadNum];
+ eventQueue = new LinkedBlockingQueue<>(EVENT_QUEUE_SIZE);
+
+ diskIORatePerSec = context.getLong(DISK_IO_RATE_PER_SEC, 0L);
+ if (diskIORatePerSec != 0) {
+ diskRateLimiter = RateLimiter.create(diskIORatePerSec);
+ }
+
+ if (sinkCounter == null) {
+ sinkCounter = new SinkCounter(getName());
+ }
+
+ localIp = NetworkUtils.getLocalIp();
+
+ properties = new Properties();
+ properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,
context.getString(BOOTSTRAP_SERVER));
+ properties.put(ProducerConfig.ACKS_CONFIG, defaultAcks);
+ properties.put(ProducerConfig.RETRIES_CONFIG,
context.getString(RETRIES, defaultRetries));
+ properties.put(ProducerConfig.BATCH_SIZE_CONFIG,
context.getString(BATCH_SIZE, defaultBatchSize));
+ properties.put(ProducerConfig.LINGER_MS_CONFIG,
context.getString(LINGER_MS, defaultLingerMs));
+ properties.put(ProducerConfig.BUFFER_MEMORY_CONFIG,
context.getString(BUFFER_MEMORY, defaultBufferMemory));
}
- @Override
- public void handleCreateClientException(String url) {
- logger.error("createConnection has exception for url = {}", url);
- sinkCounter.incrementConnectionFailedCount();
+ private void initTopicProducer(String topic) {
+ if (StringUtils.isEmpty(topic)) {
+ logger.error("topic is empty");
+ }
+
+ if (producer == null) {
+ producer = new KafkaProducer<>(properties, new StringSerializer(),
new ByteArraySerializer());
+ }
+
+ producerMap.put(topic, producer);
+ logger.info(getName() + " success create producer");
}
- @Override
- public void handleMessageSendSuccess(Object result, EventStat eventStat) {
- /*
- * Statistics pulsar performance
- */
- totalPulsarSuccSendCnt.incrementAndGet();
-
totalPulsarSuccSendSize.addAndGet(eventStat.getEvent().getBody().length);
- /*
- * add to sinkCounter
- */
+ private KafkaProducer<String, byte[]> getProducer(String topic) {
+ if (!producerMap.containsKey(topic)) {
+ synchronized (this) {
+ if (!producerMap.containsKey(topic)) {
+ if (producer == null) {
+ producer = new KafkaProducer<>(properties);
+ }
+ producerMap.put(topic, producer);
+ }
+ }
+ }
+ return producerMap.get(topic);
+ }
+
+ static class KafkaPerformanceTask implements Runnable {
+
+ @Override
+ public void run() {
+ try {
+ if (totalKafkaSuccSendSize.get() != 0) {
+ logger.info("Total kafka performance tps: "
+ + totalKafkaSuccSendCnt.get() / PRINT_INTERVAL
+ + "/s, avg msg size: "
+ + totalKafkaSuccSendSize.get() /
totalKafkaSuccSendCnt.get()
+ + ", print every " + PRINT_INTERVAL + " seconds");
+
+ // totalKafkaSuccSendCnt represents the number of packets
+ totalKafkaSuccSendSize.set(0);
+ totalKafkaSuccSendCnt.set(0);
+ }
+
+ } catch (Exception e) {
+ logger.info("tubePerformanceTask error", e);
+ }
+ }
+ }
+
+ public void handleMessageSendSuccess(EventStat es) {
+ // Statistics tube performance
+ totalKafkaSuccSendCnt.incrementAndGet();
+ totalKafkaSuccSendSize.addAndGet(es.getEvent().getBody().length);
+
+ // add to sinkCounter
sinkCounter.incrementEventDrainSuccessCount();
- currentInFlightCount.decrementAndGet();
currentSuccessSendCnt.incrementAndGet();
long nowCnt = currentSuccessSendCnt.get();
long oldCnt = lastSuccessSendCnt.get();
if (nowCnt % logEveryNEvents == 0 && nowCnt !=
lastSuccessSendCnt.get()) {
lastSuccessSendCnt.set(nowCnt);
t2 = System.currentTimeMillis();
- logger.info("metasink {}, succ put {} events to pulsar,"
- + " in the past {} millsec",
- new Object[]{
- getName(), (nowCnt - oldCnt), (t2 - t1)
- });
+ logger.info("KafkaSink {}, succ put {} events to kafka, in the
past {} millisecond",
+ getName(), (nowCnt - oldCnt), (t2 - t1));
t1 = t2;
}
}
- @Override
- public void handleMessageSendException(EventStat eventStat, Object e) {
- if (e instanceof TooLongFrameException) {
- PulsarSink.this.overflow = true;
- } else if (e instanceof ProducerQueueIsFullError) {
- PulsarSink.this.overflow = true;
- } else if (!(e instanceof AlreadyClosedException
- || e instanceof NotConnectedException
- || e instanceof TopicTerminatedException)) {
- logger.error("handle message send exception ,msg will resend
later, e = {}", e);
- }
- eventStat.incRetryCnt();
- resendEvent(eventStat, true);
- }
-
- /**
- * Resend the data and store the data in the memory cache.
- * @param es
- * @param isDecrement
- */
private void resendEvent(EventStat es, boolean isDecrement) {
try {
- if (isDecrement) {
- currentInFlightCount.decrementAndGet();
- }
if (es == null || es.getEvent() == null) {
return;
}
@@ -376,92 +337,43 @@ public class PulsarSink extends AbstractSink
}
}
- static class PulsarPerformanceTask implements Runnable {
-
- @Override
- public void run() {
- try {
- if (totalPulsarSuccSendSize.get() != 0) {
- logger.info("Total pulsar performance tps :"
- + totalPulsarSuccSendCnt.get() / PRINT_INTERVAL
- + "/s, avg msg size:"
- + totalPulsarSuccSendSize.get() /
totalPulsarSuccSendCnt.get()
- + ",print every " + PRINT_INTERVAL + " seconds");
- /*
- * totalpulsarSuccSendCnt represents the number of packets
- */
- totalPulsarSuccSendCnt.set(0);
- totalPulsarSuccSendSize.set(0);
- }
-
- } catch (Exception e) {
- logger.info("pulsarPerformanceTask error", e);
- }
- }
- }
-
class SinkTask implements Runnable {
@Override
public void run() {
logger.info("Sink task {} started.",
Thread.currentThread().getName());
while (canSend) {
- logger.debug("SinkTask process......");
boolean decrementFlag = false;
Event event = null;
EventStat eventStat = null;
try {
- if (PulsarSink.this.overflow) {
- PulsarSink.this.overflow = false;
- Thread.currentThread().sleep(10);
+ if (KafkaSink.this.overflow) {
+ KafkaSink.this.overflow = false;
+ Thread.sleep(10);
}
if (!resendQueue.isEmpty()) {
- /*
- * Send the data in the retry queue first
- */
+ // Send the data in the retry queue first
eventStat = resendQueue.poll();
if (eventStat != null) {
event = eventStat.getEvent();
}
} else {
- if (currentInFlightCount.get() > BATCH_SIZE) {
- /*
- * Under the condition that the number of
unresponsive messages is greater than 1w, the
- * number of unresponsive messages sent to pulsar
will be printed periodically
- */
- logCounter++;
- if (logCounter == 1 || logCounter % 100000 == 0) {
- logger.info(getName()
- + " currentInFlightCount={}
resendQueue"
- + ".size={}",
- currentInFlightCount.get(),
resendQueue.size());
- }
- if (logCounter > Long.MAX_VALUE - 10) {
- logCounter = 0;
- }
- }
event = eventQueue.take();
eventStat = new EventStat(event);
sinkCounter.incrementEventDrainAttemptCount();
}
- logger.debug("Event is {}, topic = {} ", event, topic);
-
- if (event == null) {
- continue;
- }
- if (topic == null || topic.equals("")) {
- logger.warn("no topic specified in event header, just
skip this event");
+ if (event == null || StringUtils.isBlank(topic)) {
+ logger.warn("event is null or no topic specified in
event header, just skip");
continue;
}
final EventStat es = eventStat;
- boolean sendResult =
pulsarClientService.sendMessage(topic, event,
- PulsarSink.this, es);
+ boolean sendResult = sendMessage(event, topic, es);
if (!sendResult) {
continue;
}
- currentInFlightCount.incrementAndGet();
+
decrementFlag = true;
} catch (InterruptedException e) {
logger.info("Thread {} has been interrupted!",
Thread.currentThread().getName());
@@ -485,5 +397,30 @@ public class PulsarSink extends AbstractSink
}
}
}
+
+ private boolean sendMessage(Event event, String topic, EventStat es) {
+ KafkaProducer<String, byte[]> producer = getProducer(topic);
+ if (producer == null) {
+ logger.error("Get producer is null, topic:{}", topic);
+ return false;
+ }
+
+ logger.debug("producer start to send msg...");
+ ProducerRecord<String, byte[]> record = new
ProducerRecord<>(topic, event.getBody());
+ producer.send(record, (recordMetadata, e) -> {
+
+ if (e == null) {
+ handleMessageSendSuccess(es);
+ return;
+ } else {
+ logger.warn("Send message failed, error message: {},
resendQueue size: {}, event:{}",
+ e.getMessage(), resendQueue.size(),
es.getEvent().hashCode());
+ }
+
+ es.incRetryCnt();
+ resendEvent(es, true);
+ });
+ return true;
+ }
}
}
diff --git
a/inlong-audit/audit-proxy/src/main/java/org/apache/inlong/audit/sink/PulsarSink.java
b/inlong-audit/audit-proxy/src/main/java/org/apache/inlong/audit/sink/PulsarSink.java
index c8c120537..e374b5de2 100644
---
a/inlong-audit/audit-proxy/src/main/java/org/apache/inlong/audit/sink/PulsarSink.java
+++
b/inlong-audit/audit-proxy/src/main/java/org/apache/inlong/audit/sink/PulsarSink.java
@@ -20,11 +20,6 @@ package org.apache.inlong.audit.sink;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.RateLimiter;
import io.netty.handler.codec.TooLongFrameException;
-import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
import org.apache.flume.Channel;
import org.apache.flume.Context;
import org.apache.flume.Event;
@@ -46,6 +41,12 @@ import
org.apache.pulsar.client.api.PulsarClientException.TopicTerminatedExcepti
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
/**
* pulsar sink
*
@@ -151,7 +152,7 @@ public class PulsarSink extends AbstractSink
/*
* stat pulsar performance
*/
- System.out.println("pulsarPerformanceTask!!!!!!");
+ logger.info("init pulsarPerformanceTask");
scheduledExecutorService.scheduleWithFixedDelay(pulsarPerformanceTask,
0L,
PRINT_INTERVAL, TimeUnit.SECONDS);
}
@@ -205,7 +206,7 @@ public class PulsarSink extends AbstractSink
@Override
public void start() {
- logger.info("pulsar sink starting...");
+ logger.info("pulsar sink starting");
sinkCounter.start();
pulsarClientService.initCreateConnection(this);
@@ -261,7 +262,7 @@ public class PulsarSink extends AbstractSink
@Override
public Status process() throws EventDeliveryException {
- logger.debug("process......");
+ logger.info("pulsar sink processing");
if (!this.canTake) {
return Status.BACKOFF;
}
@@ -406,7 +407,6 @@ public class PulsarSink extends AbstractSink
public void run() {
logger.info("Sink task {} started.",
Thread.currentThread().getName());
while (canSend) {
- logger.debug("SinkTask process......");
boolean decrementFlag = false;
Event event = null;
EventStat eventStat = null;
diff --git
a/inlong-audit/audit-proxy/src/main/java/org/apache/inlong/audit/sink/TubeSink.java
b/inlong-audit/audit-proxy/src/main/java/org/apache/inlong/audit/sink/TubeSink.java
index 0caf67ef7..b5f22d1e5 100644
---
a/inlong-audit/audit-proxy/src/main/java/org/apache/inlong/audit/sink/TubeSink.java
+++
b/inlong-audit/audit-proxy/src/main/java/org/apache/inlong/audit/sink/TubeSink.java
@@ -100,7 +100,7 @@ public class TubeSink extends AbstractSink implements
Configurable {
/*
* stat tube performance
*/
- logger.info("tubePerformanceTask!!!!!!");
+ logger.info("init tubePerformanceTask");
scheduledExecutorService.scheduleWithFixedDelay(tubePerformanceTask,
0L,
PRINT_INTERVAL, TimeUnit.SECONDS);
}
@@ -144,7 +144,7 @@ public class TubeSink extends AbstractSink implements
Configurable {
@Override
public synchronized void start() {
- logger.info("tube sink starting...");
+ logger.info("tube sink starting");
try {
createConnection();
} catch (FlumeException e) {
@@ -176,7 +176,7 @@ public class TubeSink extends AbstractSink implements
Configurable {
@Override
public synchronized void stop() {
- logger.info("tubesink stopping");
+ logger.info("tube sink stopping");
destroyConnection();
this.canTake = false;
int waitCount = 0;
@@ -209,7 +209,7 @@ public class TubeSink extends AbstractSink implements
Configurable {
@Override
public Status process() throws EventDeliveryException {
- logger.debug("process......");
+ logger.info("tube sink processing");
if (!this.canTake) {
return Status.BACKOFF;
}
diff --git
a/inlong-audit/audit-proxy/src/test/java/org/apache/inlong/audit/sink/KafkaSinkTest.java
b/inlong-audit/audit-proxy/src/test/java/org/apache/inlong/audit/sink/KafkaSinkTest.java
new file mode 100644
index 000000000..eed28a208
--- /dev/null
+++
b/inlong-audit/audit-proxy/src/test/java/org/apache/inlong/audit/sink/KafkaSinkTest.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.inlong.audit.sink;
+
+import com.google.common.base.Charsets;
+import org.apache.flume.Channel;
+import org.apache.flume.Context;
+import org.apache.flume.Event;
+import org.apache.flume.Sink;
+import org.apache.flume.Transaction;
+import org.apache.flume.channel.MemoryChannel;
+import org.apache.flume.conf.Configurables;
+import org.apache.flume.event.EventBuilder;
+import org.apache.flume.lifecycle.LifecycleController;
+import org.apache.flume.lifecycle.LifecycleState;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.powermock.api.mockito.PowerMockito;
+
+public class KafkaSinkTest {
+
+ private KafkaSink kafkaSink;
+ private Channel channel;
+ private Context context;
+
+ @Before
+ public void setUp() throws Exception {
+ kafkaSink = PowerMockito.mock(KafkaSink.class);
+ PowerMockito.doNothing().when(kafkaSink, "start");
+ PowerMockito.when(kafkaSink.process()).thenReturn(Sink.Status.READY);
+
PowerMockito.when(kafkaSink.getLifecycleState()).thenReturn(LifecycleState.ERROR);
+ channel = new MemoryChannel();
+ context = new Context();
+
+ context.put("topic", "inlong-audit");
+ context.put("master-host-port-list", "127.0.0.1:8080");
+
+ kafkaSink.setChannel(channel);
+ Configurables.configure(kafkaSink, context);
+ Configurables.configure(channel, context);
+
+ }
+
+ @Test
+ public void testProcess() throws InterruptedException {
+ Event event = EventBuilder.withBody("test", Charsets.UTF_8);
+ kafkaSink.start();
+ Assert.assertTrue(LifecycleController.waitForOneOf(kafkaSink,
+ LifecycleState.START_OR_ERROR, 5000));
+ Transaction transaction = channel.getTransaction();
+
+ transaction.begin();
+ for (int i = 0; i < 10; i++) {
+ channel.put(event);
+ }
+ transaction.commit();
+ transaction.close();
+
+ for (int i = 0; i < 5; i++) {
+ Sink.Status status = kafkaSink.process();
+ Assert.assertEquals(Sink.Status.READY, status);
+ }
+
+ kafkaSink.stop();
+ Assert.assertTrue(LifecycleController.waitForOneOf(kafkaSink,
+ LifecycleState.STOP_OR_ERROR, 5000));
+ }
+}
diff --git a/inlong-audit/conf/audit-proxy-kafka.conf
b/inlong-audit/conf/audit-proxy-kafka.conf
new file mode 100644
index 000000000..7263b7427
--- /dev/null
+++ b/inlong-audit/conf/audit-proxy-kafka.conf
@@ -0,0 +1,75 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# The configuration file needs to define the sources,
+# the channels and the sinks.
+# Sources, channels and sinks are defined per agent,
+# in this case called 'agent'
+
+agent1.sources = tcp-source
+agent1.channels = ch-msg1
+agent1.sinks = kafka-sink-msg1
+
+agent1.sources.tcp-source.channels = ch-msg1
+agent1.sources.tcp-source.type = org.apache.inlong.audit.source.SimpleTcpSource
+agent1.sources.tcp-source.msg-factory-name =
org.apache.inlong.audit.source.ServerMessageFactory
+agent1.sources.tcp-source.host = 0.0.0.0
+agent1.sources.tcp-source.port = 10081
+agent1.sources.tcp-source.max-msg-length = 524288
+agent1.sources.tcp-source.connections = 30000
+agent1.sources.tcp-source.max-threads = 64
+agent1.sources.tcp-source.receiveBufferSize = 1048576
+agent1.sources.tcp-source.sendBufferSize = 1048576
+agent1.sources.tcp-source.custom-cp = true
+agent1.sources.tcp-source.selector.type =
org.apache.inlong.audit.channel.FailoverChannelSelector
+agent1.sources.tcp-source.selector.master = ch-msg1
+agent1.sources.tcp-source.metric-recovery-path=./data/recovery
+agent1.sources.tcp-source.set=10
+
+agent1.channels.ch-msg1.type = memory
+agent1.channels.ch-msg1.capacity = 10000
+agent1.channels.ch-msg1.keep-alive = 0
+agent1.channels.ch-msg1.transactionCapacity = 200
+
+agent1.channels.ch-msg2.type = file
+agent1.channels.ch-msg2.capacity = 100000000
+agent1.channels.ch-msg2.maxFileSize = 1073741824
+agent1.channels.ch-msg2.minimumRequiredSpace = 1073741824
+agent1.channels.ch-msg2.checkpointDir =./data/file/ch-msg2/check
+agent1.channels.ch-msg2.dataDirs =./data/file/ch-msg2/data
+agent1.channels.ch-msg2.fsyncPerTransaction = false
+agent1.channels.ch-msg2.fsyncInterval = 10
+
+agent1.sinks.kafka-sink-msg1.channel = ch-msg1
+agent1.sinks.kafka-sink-msg1.type = org.apache.inlong.audit.sink.KafkaSink
+agent1.sinks.kafka-sink-msg1.bootstrap_servers = localhost:9092
+agent1.sinks.kafka-sink-msg1.topic = inlong-audit
+agent1.sinks.kafka-sink-msg1.retries = 0
+agent1.sinks.kafka-sink-msg1.batch_size = 16384
+agent1.sinks.kafka-sink-msg1.linger_ms = 0
+agent1.sinks.kafka-sink-msg1.buffer_memory = 33554432
+
+agent1.sinks.kafka-sink-msg2.channel = ch-msg1
+agent1.sinks.kafka-sink-msg2.type = org.apache.inlong.audit.sink.KafkaSink
+agent1.sinks.kafka-sink-msg2.bootstrap_servers = localhost:9092
+agent1.sinks.kafka-sink-msg2.topic = inlong-audit
+agent1.sinks.kafka-sink-msg2.retries = 0
+agent1.sinks.kafka-sink-msg2.batch_size = 16384
+agent1.sinks.kafka-sink-msg2.linger_ms = 0
+agent1.sinks.kafka-sink-msg2.buffer_memory = 33554432