Authored by chunhua.zhang

kafka support

@@ -22,6 +22,7 @@ @@ -22,6 +22,7 @@
22 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 22 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
23 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 23 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
24 <java.version>1.8</java.version> 24 <java.version>1.8</java.version>
  25 + <spring-kafka.version>1.1.2.RELEASE</spring-kafka.version>
25 </properties> 26 </properties>
26 27
27 <dependencies> 28 <dependencies>
@@ -31,6 +32,12 @@ @@ -31,6 +32,12 @@
31 </dependency> 32 </dependency>
32 33
33 <dependency> 34 <dependency>
  35 + <groupId>org.springframework.kafka</groupId>
  36 + <artifactId>spring-kafka</artifactId>
  37 + <version>${spring-kafka.version}</version>
  38 + </dependency>
  39 +
  40 + <dependency>
34 <groupId>org.springframework.boot</groupId> 41 <groupId>org.springframework.boot</groupId>
35 <artifactId>spring-boot-starter-test</artifactId> 42 <artifactId>spring-boot-starter-test</artifactId>
36 <scope>test</scope> 43 <scope>test</scope>
  1 +package com.yoho.ops.kafka;
  2 +
  3 +import java.util.concurrent.CountDownLatch;
  4 +
  5 +import org.slf4j.Logger;
  6 +import org.slf4j.LoggerFactory;
  7 +import org.springframework.kafka.annotation.KafkaListener;
  8 +
  9 +public class Receiver {
  10 +
  11 + private static final Logger LOGGER = LoggerFactory.getLogger(Receiver.class);
  12 +
  13 + private CountDownLatch latch = new CountDownLatch(1);
  14 +
  15 + @KafkaListener(topics = "${kafka.topic.helloworld}")
  16 + public void receive(String message) {
  17 + LOGGER.info("received message='{}'", message);
  18 + latch.countDown();
  19 + }
  20 +
  21 + public CountDownLatch getLatch() {
  22 + return latch;
  23 + }
  24 +}
  1 +package com.yoho.ops.kafka;
  2 +
  3 +import java.util.HashMap;
  4 +import java.util.Map;
  5 +
  6 +import org.apache.kafka.clients.consumer.ConsumerConfig;
  7 +import org.apache.kafka.common.serialization.StringDeserializer;
  8 +import org.springframework.beans.factory.annotation.Value;
  9 +import org.springframework.context.annotation.Bean;
  10 +import org.springframework.context.annotation.Configuration;
  11 +import org.springframework.kafka.annotation.EnableKafka;
  12 +import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
  13 +import org.springframework.kafka.core.ConsumerFactory;
  14 +import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
  15 +
  16 +@Configuration
  17 +@EnableKafka
  18 +public class ReceiverConfig {
  19 +
  20 + @Value("${kafka.servers.bootstrap}")
  21 + private String bootstrapServers;
  22 +
  23 + @Bean
  24 + public Map<String, Object> consumerConfigs() {
  25 + Map<String, Object> props = new HashMap<>();
  26 + // list of host:port pairs used for establishing the initial connections
  27 + // to the Kakfa cluster
  28 + props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
  29 + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
  30 + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
  31 + // consumer groups allow a pool of processes to divide the work of
  32 + // consuming and processing records
  33 + props.put(ConsumerConfig.GROUP_ID_CONFIG, "helloworld");
  34 +
  35 + return props;
  36 + }
  37 +
  38 + @Bean
  39 + public ConsumerFactory<String, String> consumerFactory() {
  40 + return new DefaultKafkaConsumerFactory<>(consumerConfigs());
  41 + }
  42 +
  43 + @Bean
  44 + public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory() {
  45 + ConcurrentKafkaListenerContainerFactory<String, String> factory =
  46 + new ConcurrentKafkaListenerContainerFactory<>();
  47 + factory.setConsumerFactory(consumerFactory());
  48 +
  49 + return factory;
  50 + }
  51 +
  52 + @Bean
  53 + public Receiver receiver() {
  54 + return new Receiver();
  55 + }
  56 +}
  1 +package com.yoho.ops.kafka;
  2 +
  3 +import org.slf4j.Logger;
  4 +import org.slf4j.LoggerFactory;
  5 +import org.springframework.beans.factory.annotation.Autowired;
  6 +import org.springframework.kafka.core.KafkaTemplate;
  7 +import org.springframework.kafka.support.SendResult;
  8 +import org.springframework.util.concurrent.ListenableFuture;
  9 +import org.springframework.util.concurrent.ListenableFutureCallback;
  10 +
  11 +public class Sender {
  12 +
  13 + private static final Logger LOGGER = LoggerFactory.getLogger(Sender.class);
  14 +
  15 + @Autowired
  16 + private KafkaTemplate<String, String> kafkaTemplate;
  17 +
  18 + public void send(String topic, String message) {
  19 + // the KafkaTemplate provides asynchronous send methods returning a
  20 + // Future
  21 + ListenableFuture<SendResult<String, String>> future = kafkaTemplate.send(topic, message);
  22 +
  23 + // you can register a callback with the listener to receive the result
  24 + // of the send asynchronously
  25 + future.addCallback(new ListenableFutureCallback<SendResult<String, String>>() {
  26 +
  27 + @Override
  28 + public void onSuccess(SendResult<String, String> result) {
  29 + LOGGER.info("sent message='{}' with offset={}", message,
  30 + result.getRecordMetadata().offset());
  31 + }
  32 +
  33 + @Override
  34 + public void onFailure(Throwable ex) {
  35 + LOGGER.error("unable to send message='{}'", message, ex);
  36 + }
  37 + });
  38 +
  39 + // alternatively, to block the sending thread, to await the result,
  40 + // invoke the future's get() method
  41 + }
  42 +}
  1 +package com.yoho.ops.kafka;
  2 +
  3 +import java.util.HashMap;
  4 +import java.util.Map;
  5 +
  6 +import org.apache.kafka.clients.producer.ProducerConfig;
  7 +import org.apache.kafka.common.serialization.StringSerializer;
  8 +import org.springframework.beans.factory.annotation.Value;
  9 +import org.springframework.context.annotation.Bean;
  10 +import org.springframework.context.annotation.Configuration;
  11 +import org.springframework.kafka.core.DefaultKafkaProducerFactory;
  12 +import org.springframework.kafka.core.KafkaTemplate;
  13 +import org.springframework.kafka.core.ProducerFactory;
  14 +
  15 +@Configuration
  16 +public class SenderConfig {
  17 +
  18 + @Value("${kafka.servers.bootstrap}")
  19 + private String bootstrapServers;
  20 +
  21 + @Bean
  22 + public Map<String, Object> producerConfigs() {
  23 + Map<String, Object> props = new HashMap<>();
  24 + // list of host:port pairs used for establishing the initial connections
  25 + // to the Kakfa cluster
  26 + props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
  27 + props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
  28 + props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
  29 + // value to block, after which it will throw a TimeoutException
  30 + props.put(ProducerConfig.MAX_BLOCK_MS_CONFIG, 5000);
  31 +
  32 + return props;
  33 + }
  34 +
  35 + @Bean
  36 + public ProducerFactory<String, String> producerFactory() {
  37 + return new DefaultKafkaProducerFactory<>(producerConfigs());
  38 + }
  39 +
  40 + @Bean
  41 + public KafkaTemplate<String, String> kafkaTemplate() {
  42 + return new KafkaTemplate<>(producerFactory());
  43 + }
  44 +
  45 + @Bean
  46 + public Sender sender() {
  47 + return new Sender();
  48 + }
  49 +}
  1 +kafka.servers.bootstrap=192.168.103.30:9092
  2 +kafka.topic.helloworld=helloworld.t
  1 +package com.yoho.ops.kafka;
  2 +
  3 +import static org.assertj.core.api.Assertions.assertThat;
  4 +
  5 +import java.util.concurrent.TimeUnit;
  6 +
  7 +import org.junit.Test;
  8 +import org.junit.runner.RunWith;
  9 +import org.springframework.beans.factory.annotation.Autowired;
  10 +import org.springframework.boot.test.context.SpringBootTest;
  11 +import org.springframework.test.context.junit4.SpringRunner;
  12 +
  13 +@RunWith(SpringRunner.class)
  14 +@SpringBootTest
  15 +public class SpringKafkaApplicationTests {
  16 +
  17 + @Autowired
  18 + private Sender sender;
  19 +
  20 + @Autowired
  21 + private Receiver receiver;
  22 +
  23 + @Test
  24 + public void testReceive() throws Exception {
  25 + sender.send("helloworld.t", "Hello Spring Kafka!");
  26 +
  27 + Thread.sleep(100000);
  28 + }
  29 +}