@KafkaListener(topics=“myTopic”)
public void listen(ConsumerRecord<?,	?>	record)	throws Exception	{
logger.info(record.toString());
//	Do	Something...
}
Stream<Async<T>>
Flux<T>
<dependency>
<groupId>io.projectreactor.kafka</groupId>
<artifactId>reactor-kafka</artifactId>
<version>1.2.0.RELEASE</version>
</dependency>
dependencies	{
compile	group:	‘io.projectreactor.kafka’,	name:	‘reactor-kafka’,	version:	‘1.2.0.RELEASE’
}
public Flux<SendResult<String>>	produce(Publisher<String>	publisher)	{
return KafkaSender.create(SENDER_OPTIONS)
.send(publisher.map(o	->	SenderRecord.create(...)));
}
public Flux<ReceiverRecord<String,	String>>	consume()	{
return KafkaReceiver.create(RECEIVER_OPTIONS)
.receive();
}
Consumer
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<version>2.3.3.RELEASE</version>
</dependency>
dependencies	{
compile	group:	‘org.springframework.kafka’,	name:	‘spring-kafka’,	version:	‘2.3.3.RELEASE’
}
public Flux<SendResult<Void>>	produce(String	topic,	String	message)	{
return	new ReactiveKafkaProducerTemplate<>(SENDER_OPTIONS)
.send(topic,	message);
}
public Flux<ReceiverRecord<String,	String>>	consume()	{
return	new ReactiveKafkaConsumerTemplate<>(RECEIVER_OPTIONS)
.receive();
}
public void process()	{
consume().flatMap(this::recordToEventObject)
.flatMap(this::saveEvent)
.flatMap(this::getReceivers)
.flatMap(this::notify)
.flatMap(this::saveResult)
.subscribe();
}
public void process()	{
consume().flatMap(this::recordToEventObject)
.groupBy(Message::key)
.flatMap(flux	->	flux.sampleFirst(Duration.ofSeconds(30))
.flatMap(this::saveEvent)
.flatMap(this::getReceivers)
.flatMap(this::notify)
.flatMap(this::saveResult)
.subscribe();
}
public void process()	{
consume().flatMap(this::recordToNotifyObject)
.groupBy(Message::key)
.flatMap(flux	->	flux.buffer(Duration.ofSeconds(30))
.flatMap(this::notify)
.flatMap(this::saveResult)
.subscribe();
}
!
subscribe()
onSubscribe()
request(n)
onNext()
onNext()
onNext()
.subscribe(this::doSomething);
.subscribe(this::doSomething);
reactor.core.publisher.Flux :
public final Disposable	subscribe(Consumer<?	super T>	consumer);
public abstract void subscribe(CoreSubscriber<?	super T>	actual);
.subscribe(this::doSomething);
reactor.core.publisher.LambdaSubscriber :
public final void onSubscribe(Subscription	s)	{
...
s.request(Long.MAX_VALUE);
...
}
.subscribe(this::doSomething);
org.reactivestreams.Subscription /	java.util.concurrent.Flow.Subscription :
public interface Subscription	{
public void request(long	n);
}
public class CustomSubscriber extends BaseSubscriber<~>	{
@Override
protected void hookOnSubscribe(Subscription	subscription)	{
request(1);
}
}
public class CustomSubscriber extends BaseSubscriber<~>	{
@Override
protected void hookOnNext(ReceiverRecord<String,	String>	record)	{
Mono.just(record)
.flatMap(/*	Do	Something	*/)
.subscribe(r	->	{
record.receiverOffset().acknowledge();
request(1);
});
}
}
public class CustomSubscriber extends BaseSubscriber<~>	{
@Override
protected void hookOnSubscribe(Subscription	subscription)	{
request(10);
}
}
kafkaManager.consume(topicName)
.subscribe(new CustomSubscriber(this::doSomething));
request(4);
onNext()
onNext()
onNext()
onNext()
request(4);
commit()
commit()
commit()
commit()
request(4);
onNext()
onNext()
onNext()
onNext()
request(4);
commit()
commit()
commit()
commit()
request(4);
onNext()
onNext()
onNext()
onNext()
public class CustomSubscriber extends BaseSubscriber<~>	{
private FluxSink<~>	offsetSink;
@Override
protected void hookOnNext(ReceiverRecord<String,	String>	record)	{
Mono.just(record)
.flatMap(/*	Do	Something	*/)
.subscribe(r	->	{
offsetSink.next(record);
request(1);
});
}
}
public class CustomSubscriber extends BaseSubscriber<~>	{
private FluxSink<~>	offsetSink;
public CustomSubscriber(Function<~>	func)	{
...
Flux.<~>create(sink	->	offsetSink =	sink)
.reduce(-1L,	(last,	r)	->	last	<	r.offset()
?	commit(r)
:	last)
.subscribe();
}
}
@ReactiveKafkaListener(topics=“myTopic”)
public Mono<Void>	listen(ReceiverRecord<?,	?>	record)	{
return Mono.just(record)
.flatMap(/*	Do	Something...	*/)
.then();
}
https://github.com/EleganceLESS/nhn-forward-2019
http://t0a.st/oLTV
[2019] 바르게, 빠르게! Reactive를 품은 Spring Kafka
[2019] 바르게, 빠르게! Reactive를 품은 Spring Kafka

[2019] 바르게, 빠르게! Reactive를 품은 Spring Kafka