Professional Documents
Culture Documents
1
Brief Introduction
2
What We’ll Cover
3
Sample Streams Application
...
stream = streamBuilder.stream(Arrays.asList(“A”, “B”))
stream.groupByKey()
.count(Materialized.as(“count-store”))
.toStream()
.to(“output-topic”,
Produced.with(Serdes.String(), Serdes.Long()))
4
View the Topology
topology.describe().toString()
5
View the Topology
Topologies:
Sub-topology: 0
Source: KSTREAM-SOURCE-0000000000 (topics: [A, B])
--> KSTREAM-AGGREGATE-0000000001
Processor: KSTREAM-AGGREGATE-0000000001 (stores: [count-store])
--> KTABLE-TOSTREAM-0000000002
<-- KSTREAM-SOURCE-0000000000
Processor: KTABLE-TOSTREAM-0000000002 (stores: [])
--> KSTREAM-SINK-0000000003
<-- KSTREAM-AGGREGATE-0000000001
Sink: KSTREAM-SINK-0000000003 (topic: output-topic)
<-- KTABLE-TOSTREAM-0000000002
6
View Graphic Topology
https://github.com/zz85/kafka-streams-viz
7
View the Topology
stream.groupByKey()
.count(Materialized.as(“count-store”))
.toStream()
.to(“output-topic”,
Produced.with(Serdes.String(), Serdes.Long()));
8
View the Topology
stream.groupByKey()
.count(Materialized.as(“count-store”))
.toStream()
.to(“output-topic”,
Produced.with(Serdes.String(), Serdes.Long()));
9
View the Topology
stream.groupByKey()
.count(Materialized.as(“count-store”))
.toStream()
.to(“output-topic”,
Produced.with(Serdes.String(), Serdes.Long()));
10
View the Topology
stream.groupByKey()
.count(Materialized.as(“count-store”))
.toStream()
.to(“output-topic”,
Produced.with(Serdes.String(), Serdes.Long()));
11
Kafka Streams Tasks
12
Updated Sample Streams Application
stream = streamBuilder.stream(“A”);
secondStream = streamBuilder.stream("B");
stream.groupByKey()
.count(Materialized.as(“count-store”))
.toStream()
.to(“output-topic”,
Produced.with(Serdes.String(), Serdes.Long()));
13
Updated streams Example Topology
14
Kafka Streams Task Assignments
15
Tasks and Threads
16
Tasks and Threads
17
Tasks and Threads
18
Tasks and Threads
19
Tasks and Threads
20
So what does this mean?
22
Task Migration with State
Standby Tasks
24
Standby Tasks
25
Standby Task Deployment Considerations
26
Standby Task Pros & Cons
27
View Task Assignments
28
The General Problem Areas
• Deserialization
• Producing
• Processing
29
Error Handling - Deserializing
props.put(StreamsConfig.DEFAULT_DESERIALIZATION_EXCEPTION_HANDLER_CLASS_CONFIG,
LogAndFailExceptionHandler.class.getName());
props.put(StreamsConfig.DEFAULT_DESERIALIZATION_EXCEPTION_HANDLER_CLASS_CONFIG,
LogAndContinueExceptionHandler.class.getName());
30
Error Handling - Producing
props.put(StreamsConfig.DEFAULT_PRODUCTION_EXCEPTION_HANDLER_CLASS_CONFIG,
DefaultProductionExceptionHandler.class.getName());
31
Processing Exceptions DSL
ValueMapper<String, ValueContainer> errorProneMapper = v -> {
ValueContainer valueContainer = new ValueContainer();
try {
valueContainer.addValue(v.substring(0, 5));
} catch (Exception e) {
valueContainer.setException(e);
}
return valueContainer;
};
32
Processing Exceptions DSL
Predicate<String, ValueContainer> errorPredicate =
(k, v) -> v.exception() != null;
int errorIndex = 0;
int successIndex = 1;
branched[errorIndex].to(errorReportTopic);
branched[successIndex].mapValues(ValueContainer::formatValue).to(outputTopic);
33
Processing Exceptions DSL
Predicate<String, ValueContainer> errorPredicate = (k, v) -> v.exception() != null;
Predicate<String, ValueContainer> successPredicate = (k,v) ->!errorPredicate.test(k,v);
int errorIndex = 0;
int successIndex = 1;
branched[errorIndex].to(errorReportTopic);
branched[successIndex].mapValues(v -> ValueContainer::formatValue).to(outputTopic);
34
Processing Exceptions DSL
Predicate<String, ValueContainer> errorPredicate = (k, v) -> v.exception() != null;
Predicate<String, ValueContainer> successPredicate = (k,v) ->!errorPredicate.test(k,v);
int errorIndex = 0;
int successIndex = 1;
branched[errorIndex].to(errorReportTopic);
branched[successIndex].mapValues(ValueContainer::formatValue)
.to(outputTopic);
35
Processing Exceptions PAPI
class ErrorProneProcessor extends AbstractProcessor<String, String> {
@Override
public void process(String key, String value) {
ValueContainer valueContainer = new ValueContainer();
try {
valueContainer.addValue(value.substring(0, 5));
context().forward(key,
valueContainer,
To.child(successProcessor));
} catch (Exception e) {
context().forward(key,
e.getMessage(),
To.child(errorSink)
}
}
}
36
Processing Exceptions PAPI
Topology topology = new Topology();
topology.addSource(sourceTopicNode, sourceTopic);
topology.addProcessor(errorProneProcessor,
ErrorProneProcessor::new,
sourceTopicNode);
topology.addProcessor(successProcessor,
SuccessProcessor::new,
errorProneProcessor);
topology.addSink(errorSink,
errorReportTopic,
errorProneProcessor);
37
Uncaught Exceptions
kafkaStreams.setUncaughtExceptionHandler(
(thread, exception) -> {
LOG.info(”It ran on my box fine!");
});
38
StateRestoreListener
kafkaStreams.setGlobalStateRestoreListener(new StateRestoreListener() {
@Override
public void onRestoreStart(TopicPartition topicPartition, String storeName, long
startingOffset, long endingOffset) {
@Override
public void onBatchRestored(TopicPartition topicPartition, String storeName, long
batchEndOffset, long numRestored) {
@Override
public void onRestoreEnd(TopicPartition topicPartition, String storeName, long
totalRestored) {
}
});
39
Kafka Streams StateListener
kafkaStreams.setStateListener((newState, oldState) -> {
if( newState == State.RUNNING &&
oldState == State.REBALANCING ) {
// Do something here
40
Wrapping Up
41
Wrapping Up
42
Thanks!
Kafka Streams in Action book signing @4:15 at the Confluent
booth.
Stay in Touch!
• https://slackpass.io/confluentcommunity
• https://www.confluent.io/blog/
43