Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Making sense of Event-Driven Systems

Jorge Quilcate
September 19, 2019

Making sense of Event-Driven Systems

Oracle Code One 2019 - San Francisco

Jorge Quilcate

September 19, 2019
Tweet

More Decks by Jorge Quilcate

Other Decks in Technology

Transcript

  1. Making sense of event-driven systems Distributed tracing for Apache Ka

    a®-based applications with Zipkin @jeqo89 | #codeone
  2. @jeqo89 | #codeone “Complexity symptoms: - Change amplification - Cognitive

    load - Unknown unknowns” John Ousterhout, “A Philosophy of Software Design”
  3. @jeqo89 | #codeone “Complexity is caused by two things: dependencies

    and obscurity” John Ousterhout, “A Philosophy of Software Design”
  4. @jeqo89 | #codeone Jorge Esteban Quilcate Otoya twitter: @jeqo89 |

    github: jeqo Peruvian in Oslo, Norway Integration team at SYSCO AS Unclogging Data pipelines by day Contributing to Apache Kafka and OpenZipkin communities by night
  5. @jeqo89 | #codeone Talk: “Making sense of your event-driven systems”

    37 min Q&A Why? What’s distributed tracing? How to instrument Kafka apps? Demo What’s next? Demo time depth sync/async causal relation
  6. @jeqo89 | #codeone “Demystifying” Kafka client configurations Kafka producers Kafka

    Streams Kafka Consumer github.com/jeqo/tracing-kafka-apps
  7. @jeqo89 | #codeone github.com/jeqo/tracing-kafka-apps Batched send var producerConfig = new

    Properties(); // ... producerConfig.put(ProducerConfig.LINGER_MS_CONFIG, 1_000); producerConfig.put(ProducerConfig.BATCH_SIZE_CONFIG, 100_000);
  8. @jeqo89 | #codeone github.com/jeqo/tracing-kafka-apps commit per record var records =

    consumer.poll(TIMEOUT); records.forEach(record -> { doSomething(record); consumer.commitSync(Map.of(new TopicPartition(...), new OffsetAndMetadata(...))); });
  9. @jeqo89 | #codeone /** Annotation-based approach **/ ScopedSpan span =

    tracer.startScopedSpan("process"); try { // The span is in "scope" doProcess(); } catch (RuntimeException | Error e) { span.error(e); // mark as error throw e; } finally { span.finish(); // always finish }
  10. @jeqo89 | #codeone /** Annotation-based approach **/ ScopedSpan span =

    tracer.startScopedSpan("process"); try { // The span is in "scope" doProcess(); } catch (RuntimeException | Error e) { span.error(e); // mark as error throw e; } finally { span.finish(); // always finish }
  11. @jeqo89 | #codeone /** Annotation-based approach **/ ScopedSpan span =

    tracer.startScopedSpan("process"); try { // The span is in "scope" doProcess(); } catch (RuntimeException | Error e) { span.error(e); // mark as error throw e; } finally { span.finish(); // always finish }
  12. @jeqo89 | #codeone CLIENT SERVER TraceContext=abc Black-box agent agent TRACES

    linkerd.io/2019/08/09/service-mesh-distributed-tracing-myths/
  13. @jeqo89 | #codeone CLIENT SERVER TraceContext=abc mixed agent agent TRACES

    tracer tracer linkerd.io/2019/08/09/service-mesh-distributed-tracing-myths/
  14. @jeqo89 | #codeone “The more accurately you try to measure

    the position of a particle, the less accurately you can measure its speed” Heisenberg's uncertainty principle
  15. @jeqo89 | #codeone Streaming Messaging Kafka Clients REST Proxy KSQL

    Kafka Source Connector Kafka Streams Kafka Sink Connector
  16. @jeqo89 | #codeone /** Instrumentation for Kafka Clients **/ Producer<K,

    V> producer = new KafkaProducer<>(settings); Producer<K, V> tracedProducer = kafkaTracing.producer(producer); producer.send( new ProducerRecord<>( "my-topic", key, value ));
  17. @jeqo89 | #codeone /** Instrumentation for Kafka Clients **/ Producer<K,

    V> producer = new KafkaProducer<>(settings); Producer<K, V> tracedProducer = kafkaTracing.producer(producer); // wrap tracedProducer.send( new ProducerRecord<>( "my-topic", key, value ));
  18. @jeqo89 | #codeone /** Instrumentation for Kafka Clients **/ Consumer<K,

    V> consumer = new KafkaConsumer<>(settings); Consumer<K, V> tracedConsumer = kafkaTracing.consumer(consumer); while (running) { var records = consumer.poll(1000); records.forEach(this::process); }
  19. @jeqo89 | #codeone /** Instrumentation for Kafka Clients **/ Consumer<K,

    V> consumer = new KafkaConsumer<>(settings); Consumer<K, V> tracedConsumer = kafkaTracing.consumer(consumer); // wrap while (running) { var records = tracedConsumer.poll(1000); records.forEach(this::process); }
  20. @jeqo89 | #codeone /** Instrumentation for Kafka Clients **/ void

    process(ConsumerRecord<K, V> record){ // extract span from record headers Span span = kafkaTracing.nextSpan(record) .name("process") .start(); try (var ws = tracer.withSpanInScope(span)) { doProcess(record); } catch (RuntimeException | Error e) { span.error(e); throw e; } finally { span.finish(); } }
  21. @jeqo89 | #codeone /** Instrumentation for Kafka Streams **/ var

    b = new StreamsBuilder(); b.stream("input-topic") .map(this::prepare)) .join(table, this::tableJoiner) .transformValues(this::transform)) .to("output-topic"); var topology = b.build(); KafkaStreams kafkaStreams = new KafkaStreams(topology, config); kafkaStreams.start();
  22. @jeqo89 | #codeone /** Instrumentation for Kafka Streams **/ var

    b = new StreamsBuilder(); b.stream("input-topic") .map(this::prepare)) .join(table, this::tableJoiner) .transformValues(this::transform)) .to("output-topic"); var topology = b.build(); KafkaStreams kafkaStreams = // wrap ksTracing.kafkaStreams(topology, config); kafkaStreams.start();
  23. @jeqo89 | #codeone /** Instrumentation for Kafka Streams **/ var

    b = new StreamsBuilder(); b.stream("input-topic") .map(this::prepare)) .join(table, this::tableJoiner) .transformValues(this::transform)) .to("output-topic"); var topology = b.build();
  24. @jeqo89 | #codeone /** Instrumentation for Kafka Streams **/ var

    b = new StreamsBuilder(); b.stream("input-topic") .transform(ksTracing.map(“preparing”, () -> this::prepare)) .join(table, this::tableJoiner) .transformValues(ksTracing.transformValues( “transforming”, () -> this::transform))) .to("output-topic");
  25. @jeqo89 | #codeone Distributed Tracing is a Stream Processing Problem

    Span Collected partitioned-spans Traces Store github.com/openzipkin-contrib/zipkin-storage-kafka
  26. @jeqo89 | #codeone Distributed Tracing is a Stream Processing Problem

    Span Collected Trace Aggregation partitioned-spans traces-completed Traces Store github.com/openzipkin-contrib/zipkin-storage-kafka
  27. @jeqo89 | #codeone var b = new StreamsBuilder(); b.stream(spansTopic, ...).groupByKey()

    // how long to wait for another span .windowedBy(SessionWindows.with(timeout)...) .aggregate(ArrayList::new, aggregateSpans(), joinAggregates(), ...) // hold until a new record tells that a window is closed and we can process it further .suppress(untilWindowCloses(unbounded())) .toStream()
  28. @jeqo89 | #codeone Distributed Tracing is a Stream Processing Problem

    Span Collected Trace Aggregation partitioned-spans traces-completed dependencies Traces Store github.com/openzipkin-contrib/zipkin-storage-kafka
  29. @jeqo89 | #codeone var b = new StreamsBuilder(); b.stream(spansTopic, ...).groupByKey()

    ... // session windows and suppression .toStream() // traceStream .flatMapValues(spansToDependencyLinks()) .selectKey((key, value) -> linkKey(value)) .to(dependencyTopic, ...));
  30. @jeqo89 | #codeone Distributed Tracing is a Stream Processing Problem

    Span Collected Trace Aggregation Traces Store partitioned-spans traces-completed Dependencies Store dependencies github.com/openzipkin-contrib/zipkin-storage-kafka
  31. @jeqo89 | #codeone Distributed Tracing is a Stream Processing Problem

    Span Collected Trace Aggregation Traces Store partitioned-spans traces-completed Dependencies Store Custom processors dependencies github.com/openzipkin-contrib/zipkin-storage-kafka
  32. @jeqo89 | #codeone Distributed Tracing is a Stream Processing Problem

    partitioned-spans traces-completed error-traces dependencies github.com/jeqo/zipkin-storage-kafka-experiments github.com/openzipkin/openzipkin.github.io/wiki/2018-07-18-Aggregation-and-Analysis-at-Netflix Long-term Error Trace Store path-aggregate
  33. @jeqo89 | #codeone Haystack: tracing and analysis platform Tracing Trends

    and Metrics Anomaly Detection Remediation Alerting services expediadotcom.github.io/haystack/
  34. @jeqo89 | #codeone Wrapping up: Consider Distributed Tracing as better

    data source to deal with system collaboration complexity Distributed Tracing pipeline is an Event Streaming pipeline Focus on aggregation, model extraction and signals (!)
  35. @jeqo89 | #codeone * Demos, source code: github.com/jeqo/tracing-kafka-apps github.com/jeqo/talk-kafka-zipkin *

    Blog post: confluent.io/blog/importance-of-distributed-tracing-for-apache-kafka-based-applications * Zipkin Kafka Backend: github.com/openzipkin-contrib/zipkin-storage-kafka * Kafka Interceptor for Zipkin: github.com/sysco-middleware/kafka-interceptor-zipkin * Sites using Zipkin: github.com/openzipkin/openzipkin.github.io/wiki/Sites * Haystack: github.com/ExpediaDotCom/haystack, gitter.im/expedia-haystack * Martin Kleppmann et al. 2019. Online Event Processing. https://dl.acm.org/citation.cfm?id=3321612 * John Ousterhout. A Philosophy of Software Design. amazon.com/Philosophy-Software-Design-John-Ousterhout/dp/1732102201 * Jonathan Kaldor et al.2017. Canopy: An End-to-End Performance Tracing And Analysis System.SOSP’17(2017). doi.org/10.1145/3132747.3132749 * Peter Alvaro et al.2016. Automating Failure Testing Research at Internet Scale.SoCC ’16. dx.doi.org/10.1145/2987550.2987555 * Mark Burgess 2019. From Observability to Significance in Distributed Information Systems. https://arxiv.org/abs/1907.05636 Resources