|
22 | 22 | import lombok.extern.log4j.Log4j; |
23 | 23 | import org.apache.commons.lang3.StringUtils; |
24 | 24 | import org.apache.curator.framework.CuratorFramework; |
25 | | -import org.apache.kafka.clients.consumer.ConsumerConfig; |
26 | 25 | import org.apache.kafka.clients.consumer.ConsumerRecord; |
27 | 26 | import org.apache.kafka.clients.consumer.ConsumerRecords; |
28 | 27 | import org.apache.kafka.clients.consumer.KafkaConsumer; |
29 | | -import org.apache.kafka.common.KafkaException; |
| 28 | +import org.apache.kafka.clients.producer.KafkaProducer; |
| 29 | +import org.apache.kafka.clients.producer.ProducerRecord; |
| 30 | +import org.apache.kafka.clients.producer.RecordMetadata; |
30 | 31 | import org.apache.kafka.common.Node; |
31 | 32 | import org.apache.kafka.common.PartitionInfo; |
32 | 33 | import org.apache.kafka.common.TopicPartition; |
33 | 34 | import org.apache.kafka.common.errors.ApiException; |
34 | 35 | import org.apache.kafka.common.errors.InvalidTopicException; |
35 | 36 | import org.apache.kafka.common.requests.MetadataResponse; |
36 | | -import org.apache.kafka.common.serialization.StringDeserializer; |
37 | 37 | import org.gnuhpc.bigdata.CollectionConvertor; |
38 | 38 | import org.gnuhpc.bigdata.componet.OffsetStorage; |
39 | | -import org.gnuhpc.bigdata.constant.ConsumerState; |
| 39 | +import org.gnuhpc.bigdata.config.KafkaConfig; |
40 | 40 | import org.gnuhpc.bigdata.constant.ConsumerType; |
41 | 41 | import org.gnuhpc.bigdata.constant.GeneralResponseState; |
42 | 42 | import org.gnuhpc.bigdata.model.*; |
@@ -84,6 +84,9 @@ public class KafkaAdminService { |
84 | 84 | @Autowired |
85 | 85 | private KafkaUtils kafkaUtils; |
86 | 86 |
|
| 87 | + @Autowired |
| 88 | + private KafkaConfig kafkaConfig; |
| 89 | + |
87 | 90 | @Autowired |
88 | 91 | private OffsetStorage storage; |
89 | 92 |
|
@@ -1046,4 +1049,64 @@ private boolean isConsumerGroupActive(String consumerGroup, ConsumerType type) { |
1046 | 1049 | throw new ApiException("Unknown type " + type); |
1047 | 1050 | } |
1048 | 1051 | } |
| 1052 | + |
| 1053 | + public HealthCheckResult healthCheck() { |
| 1054 | + String healthCheckTopic = kafkaConfig.getHealthCheckTopic(); |
| 1055 | + HealthCheckResult healthCheckResult = new HealthCheckResult(); |
| 1056 | + KafkaProducer producer = kafkaUtils.createProducer(); |
| 1057 | + KafkaConsumer consumer = kafkaUtils.createNewConsumerByTopic(healthCheckTopic); |
| 1058 | + |
| 1059 | + boolean healthCheckTopicExist = existTopic(healthCheckTopic); |
| 1060 | + log.info("HealthCheckTopic:" + healthCheckTopic + " existed:" + healthCheckTopicExist); |
| 1061 | + if (!healthCheckTopicExist) { |
| 1062 | + healthCheckResult.setStatus("unknown"); |
| 1063 | + healthCheckResult.setMsg("HealthCheckTopic: " + healthCheckTopic + " Non-Exist. Please create it before doing health check."); |
| 1064 | + return healthCheckResult; |
| 1065 | + } |
| 1066 | + |
| 1067 | + String message = "healthcheck_" + System.currentTimeMillis(); |
| 1068 | + ProducerRecord<String, String> record = new ProducerRecord(healthCheckTopic, null, message); |
| 1069 | + log.info("Generate message:" + message); |
| 1070 | + try { |
| 1071 | + RecordMetadata recordMetadata = (RecordMetadata) producer.send(record).get(); |
| 1072 | + log.info("Message:" + message + " has been sent to Partition:" + recordMetadata.partition()); |
| 1073 | + } catch (Exception e){ |
| 1074 | + healthCheckResult.setStatus("error"); |
| 1075 | + healthCheckResult.setMsg("Health Check: Produce Message Failure. Exception: " + e.getMessage()); |
| 1076 | + log.error("Health Check: Produce Message Failure.", e); |
| 1077 | + return healthCheckResult; |
| 1078 | + } finally { |
| 1079 | + producer.close(); |
| 1080 | + } |
| 1081 | + |
| 1082 | + int retries = 30; |
| 1083 | + int noRecordsCount = 0; |
| 1084 | + while (true) { |
| 1085 | + final ConsumerRecords<Long, String> consumerRecords = |
| 1086 | + consumer.poll(1000); |
| 1087 | + if (consumerRecords.count() == 0) { |
| 1088 | + noRecordsCount++; |
| 1089 | + if (noRecordsCount > retries) break; |
| 1090 | + else continue; |
| 1091 | + } |
| 1092 | + Iterator<ConsumerRecord<Long, String>> iterator = consumerRecords.iterator(); |
| 1093 | + while(iterator.hasNext()) { |
| 1094 | + ConsumerRecord msg = iterator.next(); |
| 1095 | + log.info("Health Check: Fetch Message " + msg.value() + ", offset:" + msg.offset()); |
| 1096 | + if(msg.value().equals(message)) { |
| 1097 | + healthCheckResult.setStatus("ok"); |
| 1098 | + healthCheckResult.setMsg(message); |
| 1099 | + return healthCheckResult; |
| 1100 | + } |
| 1101 | + } |
| 1102 | + consumer.commitAsync(); |
| 1103 | + } |
| 1104 | + consumer.close(); |
| 1105 | + |
| 1106 | + if(healthCheckResult.getStatus() == null) { |
| 1107 | + healthCheckResult.setStatus("error"); |
| 1108 | + healthCheckResult.setMsg("Health Check: Consume Message Failure. Consumer can't fetch the message."); |
| 1109 | + } |
| 1110 | + return healthCheckResult; |
| 1111 | + } |
1049 | 1112 | } |
0 commit comments