Sander Hautvast
Sander Hautvast Developer bij Top Squad

Een kafka producer in Rust

Dit is iets wat je gewoon kunt doen, terwijl je op je pipeline zit te wachten:

  1. kafka starten in een docker container
  2. een kafka consumer op een topic starten in dezelfde container
  3. een rust projectje maken dat een bericht stuurt naar de topic.

Er zijn trouwens meer blogs die hetzelfde doen op andere manieren. Hieronder volgt de eenvoudigste:

kafka in een docker container

Dit kun je vinden in de quickstart van kafka:

docker run -p 9092:9092 apache/kafka:3.8.0

een kafka consumer op een topic in dezelfde container

docker ps

docker ps

Vervang $CONTAINER_ID hieronder door de id die je gevonden hebt.

docker exec -it $CONTAINER_ID /bin/bash

en binnen deze shell:

/opt/kafka/bin/kafka-console-consumer.sh --topic rustonomicon  --bootstrap-server localhost:9092

Dit is de snelste manier om een consumer te starten, die eenvoudigweg op de commandline de binnenkomende berichten logt.

Een kafka producer in Rust

Natuurlijk is er ook een rust client voor Kafka. Het is niet een officieel ondersteunde en je hebt daarom in principe geen garantie dat hij alles goed doet, of blijft doen na een update. Maar ik denk dat het in de praktijk niet zo’n vaart zal lopen. Het project heeft een permissieve MIT licentie, dus daar heb je ook geen hinder van. Het bevat ook een redelijk aantal examples, voorbeeldcode die je met cargo –example kunt draaien. Zie de repo.

Ik heb de console-producer.rs gepakt en uitgekleed tot de bare minimum om duidelijk te laten zien hoe eenvoudig het kan zijn:

use anyhow::Result;
use kafka::client::KafkaClient;
use kafka::producer::{Producer, Record};

fn main() -> Result<()> {
    let mut client = KafkaClient::new(vec!["localhost:9092".into()]);
    client.set_client_id("kafka-rust-console-producer".into());
    client.load_metadata_all()?;

    let mut producer = Producer::from_client(client).create()?;

    let record = Record::from_value("rustonomicon", "Hello from rust");
    producer.send(&record)?;
    println!("Sent: {}", record.value);

    Ok(())
}

Hoe krijg je dit aan de praat?

  1. installeer rust
  2. mkdir hello-kafka && cd hello-kafka
    cargo init
    
  3. zet de libraries die je nodig hebt in Cargo.toml (die nu aangemaakt is):
    [dependencies]
    kafka = "0.10"
    anyhow = "1.0"
    
  4. zet de bovenstaande code in src/main.rs (bestaande code verwijderen).
  5. cargo run cargo run
  6. resultaat in de docker terminal kafka consumer

Het vervolg zou zijn om niet alleen tekst uit te wisselen via kafka, maar objecten, met behulp van apache avro, het serialisatie format dat kafka native ondersteunt. Daar ga ik snel eens naar kijken.