Implement review remarks

This commit is contained in:
Emanuel Zienecker 2019-06-03 14:04:34 +02:00
parent f28cfaaa66
commit c55e5dbed2
3 changed files with 16 additions and 59 deletions

View File

@ -2,9 +2,8 @@ package com.deviceinsight.kafka.health;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import com.deviceinsight.kafka.health.cache.CacheService; import com.github.benmanes.caffeine.cache.Cache;
import com.deviceinsight.kafka.health.cache.CaffeineCacheServiceImpl; import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import org.apache.kafka.clients.consumer.Consumer; import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.clients.consumer.ConsumerConfig;
@ -35,6 +34,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
@ -44,8 +44,7 @@ import javax.annotation.PreDestroy;
public class KafkaConsumingHealthIndicator extends AbstractHealthIndicator { public class KafkaConsumingHealthIndicator extends AbstractHealthIndicator {
private static final Logger logger = LoggerFactory.getLogger( private static final Logger logger = LoggerFactory.getLogger(KafkaConsumingHealthIndicator.class);
com.deviceinsight.kafka.health.KafkaConsumingHealthIndicator.class);
private static final String CONSUMER_GROUP_PREFIX = "health-check-"; private static final String CONSUMER_GROUP_PREFIX = "health-check-";
private final Consumer<String, String> consumer; private final Consumer<String, String> consumer;
@ -59,7 +58,7 @@ public class KafkaConsumingHealthIndicator extends AbstractHealthIndicator {
private final ExecutorService executor; private final ExecutorService executor;
private final AtomicBoolean running; private final AtomicBoolean running;
private final CacheService<String> cacheService; private final Cache<String, String> cache;
private KafkaCommunicationResult kafkaCommunicationResult; private KafkaCommunicationResult kafkaCommunicationResult;
@ -83,9 +82,13 @@ public class KafkaConsumingHealthIndicator extends AbstractHealthIndicator {
this.executor = Executors.newFixedThreadPool(2); this.executor = Executors.newFixedThreadPool(2);
this.running = new AtomicBoolean(true); this.running = new AtomicBoolean(true);
this.cacheService = new CaffeineCacheServiceImpl(calculateCacheExpiration(sendReceiveTimeoutMs)); this.cache = Caffeine.newBuilder()
.expireAfterWrite(calculateCacheExpiration(sendReceiveTimeoutMs), TimeUnit.MILLISECONDS)
.recordStats()
.build();
this.kafkaCommunicationResult = KafkaCommunicationResult.failure(topic, new RejectedExecutionException("Kafka Health Check is starting.")); this.kafkaCommunicationResult = KafkaCommunicationResult.failure(topic,
new RejectedExecutionException("Kafka Health Check is starting."));
} }
@PostConstruct @PostConstruct
@ -102,7 +105,7 @@ public class KafkaConsumingHealthIndicator extends AbstractHealthIndicator {
while (running.get()) { while (running.get()) {
if (messageNotReceived()) { if (messageNotReceived()) {
this.kafkaCommunicationResult = KafkaCommunicationResult.failure(topic, this.kafkaCommunicationResult = KafkaCommunicationResult.failure(topic,
new RejectedExecutionException("Ignore health check, already running...")); new RejectedExecutionException("No message received."));
} else { } else {
this.kafkaCommunicationResult = KafkaCommunicationResult.success(topic); this.kafkaCommunicationResult = KafkaCommunicationResult.success(topic);
} }
@ -161,31 +164,21 @@ public class KafkaConsumingHealthIndicator extends AbstractHealthIndicator {
private void sendMessage() { private void sendMessage() {
Future<Void> sendReceiveTask = null;
try { try {
sendKafkaMessage();
sendReceiveTask = executor.submit(() -> {
sendKafkaMessage();
return null;
});
sendReceiveTask.get(sendReceiveTimeoutMs, MILLISECONDS);
this.kafkaCommunicationResult = KafkaCommunicationResult.success(topic);
} catch (ExecutionException e) { } catch (ExecutionException e) {
logger.warn("Kafka health check execution failed.", e); logger.warn("Kafka health check execution failed.", e);
this.kafkaCommunicationResult = KafkaCommunicationResult.failure(topic, e); this.kafkaCommunicationResult = KafkaCommunicationResult.failure(topic, e);
} catch (TimeoutException | InterruptedException e) { } catch (TimeoutException | InterruptedException e) {
logger.warn("Kafka health check timed out.", e); logger.warn("Kafka health check timed out.", e);
sendReceiveTask.cancel(true);
this.kafkaCommunicationResult = KafkaCommunicationResult.failure(topic, e); this.kafkaCommunicationResult = KafkaCommunicationResult.failure(topic, e);
} catch (RejectedExecutionException e) { } catch (RejectedExecutionException e) {
logger.debug("Ignore health check, already running..."); logger.debug("Ignore health check, already running...");
} }
} }
private void sendKafkaMessage() throws Exception { private void sendKafkaMessage() throws InterruptedException, ExecutionException, TimeoutException {
String message = UUID.randomUUID().toString(); String message = UUID.randomUUID().toString();
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
@ -193,7 +186,7 @@ public class KafkaConsumingHealthIndicator extends AbstractHealthIndicator {
logger.debug("Send health check message = {}", message); logger.debug("Send health check message = {}", message);
producer.send(new ProducerRecord<>(topic, message, message)).get(sendReceiveTimeoutMs, MILLISECONDS); producer.send(new ProducerRecord<>(topic, message, message)).get(sendReceiveTimeoutMs, MILLISECONDS);
cacheService.write(message); cache.put(message, message);
logger.debug("Kafka health check succeeded. took= {} msec", System.currentTimeMillis() - startTime); logger.debug("Kafka health check succeeded. took= {} msec", System.currentTimeMillis() - startTime);
} }
@ -201,7 +194,7 @@ public class KafkaConsumingHealthIndicator extends AbstractHealthIndicator {
private boolean messageNotReceived() { private boolean messageNotReceived() {
return StreamSupport.stream(consumer.poll(Duration.ofMillis(pollTimeoutMs)).spliterator(), false) return StreamSupport.stream(consumer.poll(Duration.ofMillis(pollTimeoutMs)).spliterator(), false)
.noneMatch(msg -> cacheService.get(msg.key()) == null); .noneMatch(msg -> cache.getIfPresent(msg.key()) == null);
} }

View File

@ -1,8 +0,0 @@
package com.deviceinsight.kafka.health.cache;
public interface CacheService<T> {
void write(T entry);
T get(T entry);
}

View File

@ -1,28 +0,0 @@
package com.deviceinsight.kafka.health.cache;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import java.util.concurrent.TimeUnit;
public class CaffeineCacheServiceImpl implements CacheService<String> {
private final Cache<String, String> cache;
public CaffeineCacheServiceImpl(long expireAfterWrite) {
this.cache = Caffeine.newBuilder()
.expireAfterWrite(expireAfterWrite, TimeUnit.MILLISECONDS)
.recordStats()
.build();
}
@Override
public void write(String entry) {
this.cache.put(entry, entry);
}
@Override
public String get(String entry) {
return this.cache.getIfPresent(entry);
}
}