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

Introducing_FastKafka.pdf

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →

 Introducing_FastKafka.pdf

Avatar for Tvrtko Sternak

Tvrtko Sternak

April 17, 2023

Other Decks in Programming

Transcript

  1. app = FastApi() @app.get() async def on_input_data(msg: InputData) -> Prediction:

    prediction = model.predict(msg) return prediction decodes input using InputData.parse_raw() encodes output using Prediction.json() handles message routing
  2. app = some_kafka_framework.Application() @app.consume() async def on_input_data(msg: InputData): p =

    model.predict(msg) to_prediction(p) @app.produce() async def to_prediction(p: int) -> Prediction: return Prediction(p=p)
  3. What we need • Easy to write code • Testable

    • Automatic documentation generation • High performance • Well maintained
  4. app = fastkafka.FastKafka() @app.consume() async def on_input_data(msg: InputData): # some

    processing decodes consumed message using InputData.parse_raw() consumes messages from input_data topic
  5. @kafka_app.produces() def to_predictions(score: float) -> KafkaEvent[Prediction]: p = Prediction(score=score) return

    KafkaEvent(p, key=b”my_key”) encapsulates Prediction class in order to use key or partition de fi nes key of the produced message
  6. from fastkafka.testing import Tester async with Tester(kafka_app) as tester: await

    tester.to_input_data(msg) await tester.awaited_mocks.on_predictions.assert_awaited_with( Prediction(p=0.97) )
  7. from fastkafka.testing import Tester async with Tester(kafka_app) as tester: await

    tester.to_input_data(msg) await tester.awaited_mocks.on_predictions.assert_awaited_with( Prediction(p=0.97) ) Tester(kafka_app) creates mirrors of consumers and producers: kafka_app.on_input_data → tester.to_input_data kafka_app.to_predictions → tester.on_predictions
  8. from fastkafka.testing import Tester async with Tester(kafka_app) as tester: await

    tester.to_input_data(msg) await tester.awaited_mocks.on_predictions.assert_awaited_with( Prediction(p=0.97) ) Tester(kafka_app) creates mockups for assertions: kafka_app.on_input_data → tester.awaited_mocks.on_input_data kafka_app.to_predictions → tester.awaited_mocks.on_predictions
  9. from fastkafka.testing import Tester async with Tester(kafka_app) as tester: await

    tester.to_input_data(msg) await tester.awaited_mocks.on_predictions.assert_awaited_with( Prediction(p=0.97) ) Tester(kafka_app) runs an Instance of Kafka in background!
  10. Tester runs with in-memory Kafka broker by default • Fully-functional

    Kafka broker running in memory • Fast setup & teardown needed for unit-testing • No side e ff ects
  11. from fastkafka.testing import Tester async with Tester(kafka_app) as tester: await

    tester.to_input_data(msg) await tester.awaited_mocks.on_predictions.assert_awaited_with( Prediction(p=0.97) ) Tester(kafka_app) runs an Instance of Kafka in background Tester(kafka_app) runs an Instance of in memory Kafka mockup
  12. async with Tester(kafka_app).using_local_redpanda() as tester: await tester.to_input_data(msg) await tester.awaited_mocks.on_predictions.assert_awaited_with( Prediction(p=0.97)

    ) async with Tester(kafka_app).using_local_kafka() as tester: await tester.to_input_data(msg) await tester.awaited_mocks.on_predictions.assert_awaited_with( Prediction(p=0.97) )
  13. $ fastkafka run application:kafka_app Symbol kafka_app of type FastKafka to

    import Python module application (or local fi le application.py) with fast_kafka symbol de fi ned
  14. Performance penalty No computation apart from a simple JSON encoding/decoding

    • Worst case performance penalty: ~30% msg/s FastKafka AIOKafka Consuming ~147.000 ~212.000 Producing ~47.000 ~66.000
  15. What we plan to implement • Add transactional logic: @app.process()

    • Add support for other messaging protocols (RabbitMQ…) • Add support for other libraries (Con fl uent…) • Performance improvements • Possibly rewrite (parts of) in Rust • Last but not least, community feedback