Stateful Functions의 Kafka 레코드 헤더: 5세 격차 해소

작성자

카테고리:

← 피드로
DEV Community · Oleksandr Kazimirov · 2026-07-24 개발(SW)

Oleksandr Kazimirov

Apache Stateful Functions never let a function see Kafka record headers, and never let it set them. Five years, no headers. StateFun Actors 3.4.0-KZM-3.4 closes that gap.

Read them on the way in, set them on the way out:

// in: the headers of the record that invoked you
String traceId = message.headers().stream()
    .filter(h -> h.key().equals("traceparent"))
    .findFirst()
    .map(MessageHeader::valueAsUtf8String)
    .orElse("no-trace");

// out: headers on the record you produce
context.send(
    KafkaEgressMessage.forEgress(EGRESS)
        .withTopic("orders.done")
        .withUtf8Key(orderId)
        .withValue(receipt)
        .withUtf8Header("traceparent", traceId)
        .withHeader("attempt", 2)     // a real binary int, not "2"
        .build());

Enter fullscreen mode Exit fullscreen mode

Turn it on per topic in module.yaml:

kind: io.statefun.kafka.v1/ingress
spec:
  id: shop/orders-in
  address: kafka:9092
  forwardHeaders: true          # every topic below inherits this
  topics:
    - topic: orders
      valueType: shop/Order
      targets: [shop/order-fn]
    - topic: clickstream
      forwardHeaders: false     # noisy topic opts back out
      valueType: shop/Click
      targets: [shop/click-fn]

Enter fullscreen mode Exit fullscreen mode

The details that matter:

  • Null stays null. Kafka distinguishes a null header value from an empty one, and so do we, through the whole ingress, function, egress round trip.
  • Reads never throw in production. Absent or undecodable values come back as null, not as an exception inside a live invocation.
  • Off by default. Topics that don’t opt in never capture header bytes, so header-free pipelines pay nothing.
  • Additive protocol. Old SDKs and new runtimes interoperate. No lockstep upgrade, no savepoint impact.
  • Tracing works now. A W3C traceparent header can finally ride through a StateFun function graph without living inside your payload schema.

Full guide: Kafka record headers · Design write-up: how it landed with zero flink-core changes

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다