官方网页
下载地址:Apache Kafka
执行脚本目录 /bin
windows 在其单独的目录
下载并且解压kafka压缩包
运行服务
以Windows为例,首先打开cmd:
1. 启动zookeeper:
bin\windows\zookeeper-server-start.bat config\zookeeper.properties
2. 启动kafka:
bin\windows\kafka-server-start.bat config\server.properties
bin\windows\kafka-topics.bat --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic cloud
cloud
\bin\windows>kafka-console-producer.bat --broker-list localhost:9092 --topic cloud
>hello
\bin\windows>kafka-console-consumer.bat --bootstrap-server localhost:9092 --topic cloud --from-beginning
hello
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;
import org.apache.kafka.common.serialization.StringSerializer;
public class TestKafka {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Properties properties = new Properties();
properties.setProperty("bootstrap.servers", "localhost:9092");
properties.setProperty("key.serializer", StringSerializer.class.getName());
properties.setProperty("value.serializer", StringSerializer.class.getName());
// 创建 Kafka Producer
KafkaProducer<String, String> kafkaProducer = new KafkaProducer(properties);
// 创建Kafka消息 = ProducerRecord
String topic = "cloud";
Integer partition = 0;
Long timestamp = System.currentTimeMillis();
String key = "message-key";
String value = "how are you!";
ProducerRecord<String, String> record = new ProducerRecord<String, String>(topic, partition, timestamp, key, value);
// 发送kafka消息
Future<RecordMetadata> metadataFuture = kafkaProducer.send(record);
// 强制执行
metadataFuture.get();
}
}
Spring社区对data(Spring-data)操作,有一个基本的模式,Template模式:
XXXTemplate一定实现XXXOpeations
KafkaTemplate implements KafkaOpeations
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
其中KafkaTemplate会被自动装配:
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.kafka.KafkaProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.core.ProducerFactory;
import org.springframework.kafka.support.ProducerListener;
@Configuration
public class KafkaAutoConfiguration {
private final KafkaProperties properties;
public KafkaAutoConfiguration(KafkaProperties properties) {
this.properties = properties;
}
@Bean
@ConditionalOnMissingBean(KafkaTemplate.class)
public KafkaTemplate<?,?> kafkaTemplate(ProducerFactory<Object,Object> kafkaProducerFactory,
ProducerListener<Object,Object> kafkaProducerListener){
KafkaTemplate<Object,Object> kafkaTemplate = new KafkaTemplate<Object,Object>(kafkaProducerFactory);
kafkaTemplate.setProducerListener(kafkaProducerListener);
kafkaTemplate.setDefaultTopic(this.properties.getTemplate().getDefaultTopic());
return kafkaTemplate;
}
}
增加生产者配置
application.properties
全局配置:
### Kafka生产者配置
spring.kafka.producer.bootstrapServers = localhost:9092
### Kafka生产者配置
# spring.kafka.producer.bootstrapServers = localhost:9092
spring.kafka.producer.keySerializer = org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.valueSerializer = org.apache.kafka.common.serialization.StringSerializer
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class KafkaProducerController {
private final KafkaTemplate<String, String> kafkaTemplate;
private final String topic;
@Autowired
public KafkaProducerController(KafkaTemplate<String, String> kafkaTemplate, @Value("${kafka.topic}") String topic) {
this.kafkaTemplate = kafkaTemplate;
this.topic = topic;
}
@PostMapping("/message/send")
public Boolean sendMessage(@RequestParam(required=false)String message) {
kafkaTemplate.send(topic, message);
return true;
}
}
增加消费者配置
### Kafka消费者配置
spring.kafka.consumer.groupId = cloud-1
spring.kafka.consumer.keyDeserializer = org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.valueDeserializer = org.apache.kafka.common.serialization.StringDeserializer
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
@Component
public class KafkaConsumerListener {
@KafkaListener(topics = "${kafka.topic}")
public void onMessage(String message) {
System.out.print("kafka 消费者监听器,接收到消息:" + message);
}
}
基本概念
Reactive Streams:
@Component
@EnableBinding(Source.class)
public class MessageProducerBean {
@Autowired
@Qualifier(Source.OUTPUT)
private MessageChannel messageChannel;
@Autowired
private Source source;
public void send(String message) {
messageChannel.send(MessageBuilder.withPayload(message).build());
source.output().send(MessageBuilder.withPayload(message).build());
}
}
@RestController
public class KafkaProducerController {
private final KafkaTemplate<String, String> kafkaTemplate;
private final MessageProducerBean messageProducerBean;
private final String topic;
@Autowired
public KafkaProducerController(KafkaTemplate<String, String> kafkaTemplate,
@Value("${kafka.topic}") String topic,
MessageProducerBean messageProducerBean) {
this.kafkaTemplate = kafkaTemplate;
this.messageProducerBean = messageProducerBean;
this.topic = topic;
}
@PostMapping("/message/send")
public Boolean sendMessage(@RequestParam(required=false)String message) {
kafkaTemplate.send(topic, message);
return true;
}
@GetMapping("/message/output/send")
public Boolean outputSend(@RequestParam String message) {
messageProducerBean.send(message);
return true;
}
}
@Component
@EnableBinding(Sink.class)
public class MessageConsumerBean {
@Autowired
@Qualifier(Sink.INPUT)
private SubscribableChannel subscribableChannel;
@Autowired
private Sink sink;
@PostConstruct
public void init() {
subscribableChannel.subscribe(new MessageHandler() {
@Override
public void handleMessage(Message<?> message) throws MessagingException {
System.out.println("init: "+message.getPayload());
}
});
}
@ServiceActivator(inputChannel = Sink.INPUT)
public void serviceActivator(Object message) {
System.out.println("serviceActivator: "+message);
}
@StreamListener(Sink.INPUT)
public void streamListener(String message) {
System.out.println("streamListener: "+message);
}
}
public interface MySource {
String MYOUTPUT = "myoutput";
@Output(MySource.MYOUTPUT)
MessageChannel myoutput();
}
@Component
@EnableBinding(MySource.class)
public class MyMessageProducerBean {
@Autowired
@Qualifier(MySource.MYOUTPUT)
private MessageChannel messageChannel;
@Autowired
private MySource mySource;
public void send(String message) {
messageChannel.send(MessageBuilder.withPayload(message).build());
mySource.myoutput().send(MessageBuilder.withPayload(message).build());
}
}
public interface MySink {
String MYINPUT = "myinput";
@Input(MySink.MYINPUT)
SubscribableChannel input();
}
@Component
@EnableBinding(MySink.class)
public class MyMessageConsumerBean {
@Autowired
@Qualifier(MySink.MYINPUT)
private SubscribableChannel subscribableChannel;
@Autowired
private MySink mySink;
@PostConstruct
public void init() {
subscribableChannel.subscribe(new MessageHandler() {
@Override
public void handleMessage(Message<?> message) throws MessagingException {
System.out.println("my - Sink: "+message.getPayload());
}
});
}
@ServiceActivator(inputChannel = MySink.MYINPUT)
public void serviceActivator(Object message) {
System.out.println("my - serviceActivator: "+message);
}
@StreamListener(MySink.MYINPUT)
public void streamListener(String message) {
System.out.println("my - streamListener: "+message);
}
}
kafka.topic.my = mytopic
spring.cloud.stream.bindings.myoutput.destination=${kafka.topic.my}
spring.cloud.stream.bindings.myinput.destination=${kafka.topic.my}
重构Kafka工程,删除强依赖
Stream-kafka实现源码:https://pan.baidu.com/s/1RX5W2wMj4h_SKDkjlPQHkA 提取码:lwak
Stream-rabbit实现源码:https://pan.baidu.com/s/1AX6asvmATN9-dYrhIIfS7w 提取码:dsc5