sarama Documentation

Sarama is a Go library for Apache Kafka.

12,501 stars Go Go 1 file ยท ~2,807 tokens #go#kafka#kafka-client
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy sarama on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name sarama -p 29091:29091 --restart always docker.io/library/zookeeper:3.7.2
Configured Services & Ports
โš™๏ธ zookeeper-1
image: docker.io/library/zookeeper:3.7.2
โš™๏ธ zookeeper-2
image: docker.io/library/zookeeper:3.7.2
โš™๏ธ zookeeper-3
image: docker.io/library/zookeeper:3.7.2
โš™๏ธ kafka-1
image: sarama/fv-kafka-${KAFKA_VERSION:-4.3.1}
โš™๏ธ kafka-2
image: sarama/fv-kafka-${KAFKA_VERSION:-4.3.1}
โš™๏ธ kafka-3
image: sarama/fv-kafka-${KAFKA_VERSION:-4.3.1}
โš™๏ธ kafka-4
image: sarama/fv-kafka-${KAFKA_VERSION:-4.3.1}
โš™๏ธ kafka-5
image: sarama/fv-kafka-${KAFKA_VERSION:-4.3.1}
โš™๏ธ toxiproxy
image: ghcr.io/shopify/toxiproxy:2.12.0
๐Ÿ”Œ Ports: 29091:29091, 29092:29092, 29093:29093, 29094:29094, 29095:29095, 8474:8474
docker-compose.yml
yaml (docker-compose.yml)
x-zookeeper-base: &zookeeper-base
  image: 'docker.io/library/zookeeper:3.7.2'
  init: true
  restart: always
  profiles:
    - zookeeper
  environment: &zookeeper-base-env
    ZOO_SERVERS: 'server.1=zookeeper-1:2888:3888 server.2=zookeeper-2:2888:3888 server.3=zookeeper-3:2888:3888'
    ZOO_CFG_EXTRA: 'clientPort=2181 peerPort=2888 leaderPort=3888'
    ZOO_INIT_LIMIT: '10'
    ZOO_SYNC_LIMIT: '5'
    ZOO_MAX_CLIENT_CNXNS: '0'
    ZOO_4LW_COMMANDS_WHITELIST: 'mntr,conf,ruok'

x-kafka-base: &kafka-base
  image: 'sarama/fv-kafka-${KAFKA_VERSION:-4.3.1}'
  init: true
  build:
    context: .
    dockerfile: Dockerfile.kafka
    args:
      KAFKA_VERSION: ${KAFKA_VERSION:-4.3.1}
      SCALA_VERSION: ${SCALA_VERSION:-2.13}
  depends_on:
    - toxiproxy
  restart: always
  environment: &kafka-base-env
    KAFKA_VERSION: ${KAFKA_VERSION:-4.3.1}
    KAFKA_CFG_DEFAULT_REPLICATION_FACTOR: '2'
    KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR: '2'
    KAFKA_CFG_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: '2'
    KAFKA_CFG_ZOOKEEPER_SESSION_TIMEOUT_MS: '6000'
    KAFKA_CFG_ZOOKEEPER_CONNECTION_TIMEOUT_MS: '6000'
    KAFKA_CFG_REPLICA_SELECTOR_CLASS: 'org.apache.kafka.common.replica.RackAwareReplicaSelector'
    KAFKA_CFG_DELETE_TOPIC_ENABLE: 'true'
    KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE: 'false'
    KAFKA_CFG_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
    KAFKA_JVM_PERFORMANCE_OPTS: "-XX:+IgnoreUnrecognizedVMOptions"
    KAFKA_CFG_INTER_BROKER_LISTENER_NAME: 'LISTENER_INTERNAL'
    KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: 'LISTENER_INTERNAL:PLAINTEXT,LISTENER_LOCAL:PLAINTEXT,CONTROLLER:PLAINTEXT'
    # ZooKeeper-specific
    KAFKA_CFG_ZOOKEEPER_CONNECT: 'zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181'
    # KRaft-specific
    KAFKA_CFG_PROCESS_ROLES: 'broker,controller'
    KAFKA_CFG_CONTROLLER_QUORUM_VOTERS: '1@kafka-1:9093,2@kafka-2:9093,3@kafka-3:9093,4@kafka-4:9093,5@kafka-5:9093'
    KAFKA_CFG_CONTROLLER_LISTENER_NAMES: 'CONTROLLER'
    KAFKA_CFG_CLUSTER_ID: 'cDZEekk4T3hTNGVlNzB3LUtUbkxaQQo='

services:
  zookeeper-1:
    <<: *zookeeper-base
    container_name: 'zookeeper-1'
    environment:
      <<: *zookeeper-base-env
      ZOO_MY_ID: '1'

  zookeeper-2:
    <<: *zookeeper-base
    container_name: 'zookeeper-2'
    environment:
      <<: *zookeeper-base-env
      ZOO_MY_ID: '2'

  zookeeper-3:
    <<: *zookeeper-base
    container_name: 'zookeeper-3'
    environment:
      <<: *zookeeper-base-env
      ZOO_MY_ID: '3'

  kafka-1:
    <<: *kafka-base
    container_name: 'kafka-1'
    healthcheck:
      test: ['CMD', '/opt/kafka-${KAFKA_VERSION:-4.3.1}/bin/kafka-broker-api-versions.sh', '--bootstrap-server', 'kafka-1:9091']
      interval: 5s
      timeout: 15s
      retries: 30
      start_period: 360s
    environment:
      <<: *kafka-base-env
      KAFKA_CFG_BROKER_ID: '1'
      KAFKA_CFG_NODE_ID: '1'
      KAFKA_CFG_BROKER_RACK: '1'
      KAFKA_CFG_LISTENERS: 'LISTENER_INTERNAL://:9091,LISTENER_LOCAL://:29091,CONTROLLER://:9093'
      KAFKA_CFG_ADVERTISED_LISTENERS: 'LISTENER_INTERNAL://kafka-1:9091,LISTENER_LOCAL://localhost:29091'

  kafka-2:
    <<: *kafka-base
    container_name: 'kafka-2'
    healthcheck:
      test: ['CMD', '/opt/kafka-${KAFKA_VERSION:-4.3.1}/bin/kafka-broker-api-versions.sh', '--bootstrap-server', 'kafka-2:9091']
      interval: 5s
      timeout: 15s
      retries: 30
      start_period: 360s
    environment:
      <<: *kafka-base-env
      KAFKA_CFG_BROKER_ID: '2'
      KAFKA_CFG_NODE_ID: '2'
      KAFKA_CFG_BROKER_RACK: '2'
      KAFKA_CFG_LISTENERS: 'LISTENER_INTERNAL://:9091,LISTENER_LOCAL://:29092,CONTROLLER://:9093'
      KAFKA_CFG_ADVERTISED_LISTENERS: 'LISTENER_INTERNAL://kafka-2:9091,LISTENER_LOCAL://localhost:29092'

  kafka-3:
    <<: *kafka-base
    container_name: 'kafka-3'
    healthcheck:
      test: ['CMD', '/opt/kafka-${KAFKA_VERSION:-4.3.1}/bin/kafka-broker-api-versions.sh', '--bootstrap-server', 'kafka-3:9091']
      interval: 5s
      timeout: 15s
      retries: 30
      start_period: 360s
    environment:
      <<: *kafka-base-env
      KAFKA_CFG_BROKER_ID: '3'
      KAFKA_CFG_NODE_ID: '3'
      KAFKA_CFG_BROKER_RACK: '3'
      KAFKA_CFG_LISTENERS: 'LISTENER_INTERNAL://:9091,LISTENER_LOCAL://:29093,CONTROLLER://:9093'
      KAFKA_CFG_ADVERTISED_LISTENERS: 'LISTENER_INTERNAL://kafka-3:9091,LISTENER_LOCAL://localhost:29093'

  kafka-4:
    <<: *kafka-base
    container_name: 'kafka-4'
    healthcheck:
      test: ['CMD', '/opt/kafka-${KAFKA_VERSION:-4.3.1}/bin/kafka-broker-api-versions.sh', '--bootstrap-server', 'kafka-4:9091']
      interval: 5s
      timeout: 15s
      retries: 30
      start_period: 360s
    environment:
      <<: *kafka-base-env
      KAFKA_CFG_BROKER_ID: '4'
      KAFKA_CFG_NODE_ID: '4'
      KAFKA_CFG_BROKER_RACK: '4'
      KAFKA_CFG_LISTENERS: 'LISTENER_INTERNAL://:9091,LISTENER_LOCAL://:29094,CONTROLLER://:9093'
      KAFKA_CFG_ADVERTISED_LISTENERS: 'LISTENER_INTERNAL://kafka-4:9091,LISTENER_LOCAL://localhost:29094'

  kafka-5:
    <<: *kafka-base
    container_name: 'kafka-5'
    healthcheck:
      test: ['CMD', '/opt/kafka-${KAFKA_VERSION:-4.3.1}/bin/kafka-broker-api-versions.sh', '--bootstrap-server', 'kafka-5:9091']
      interval: 5s
      timeout: 15s
      retries: 30
      start_period: 360s
    environment:
      <<: *kafka-base-env
      KAFKA_CFG_BROKER_ID: '5'
      KAFKA_CFG_NODE_ID: '5'
      KAFKA_CFG_BROKER_RACK: '5'
      KAFKA_CFG_LISTENERS: 'LISTENER_INTERNAL://:9091,LISTENER_LOCAL://:29095,CONTROLLER://:9093'
      KAFKA_CFG_ADVERTISED_LISTENERS: 'LISTENER_INTERNAL://kafka-5:9091,LISTENER_LOCAL://localhost:29095'

  toxiproxy:
    container_name: 'toxiproxy'
    image: 'ghcr.io/shopify/toxiproxy:2.12.0'
    init: true
    healthcheck:
      test: ['CMD', '/toxiproxy-cli', 'l']
      interval: 15s
      timeout: 15s
      retries: 3
      start_period: 30s
    ports:
      # The tests themselves actually start the proxies on these ports
      - '29091:29091'
      - '29092:29092'
      - '29093:29093'
      - '29094:29094'
      - '29095:29095'

      # This is the toxiproxy API port
      - '8474:8474'

1. Project Overview & Quickstart (IBM/sarama)

File: README.md

sarama



Sarama is an MIT-licensed Go client library for Apache Kafka.

Getting started

  • API documentation and examples are available via pkg.go.dev.
  • Mocks for testing are available in the mocks subpackage.
  • The examples directory contains more elaborate example applications.
  • The tools directory contains command line tools that can be useful for testing, diagnostics, and instrumentation.

You might also want to look at the Frequently Asked Questions.

Compatibility and API stability

Sarama provides a "2 releases + 2 months" compatibility guarantee: we support
the two latest stable releases of Kafka and Go, and we provide a two month
grace period for older releases. However, older releases of Kafka are still likely to work.

Sarama follows semantic versioning and provides API stability via the standard Go
module version numbering scheme.

A changelog is available here.

Contributing


File: examples/interceptors/README.md

Interceptors Example

It creates a Producer interceptor to produce some OpenTelemetry spans and also modifies
the intercepted message to include some headers.

go
conf.Producer.Interceptors = []sarama.ProducerInterceptor{xxx}

Run the example

  • go run main.go trace_interceptor.go.
  • or `go build and pass different parameters.
sh
go build && ./interceptors --h
Usage of ./interceptors:
  -brokers string
        The Kafka brokers to connect to, as a comma separated list (default "localhost:9092")
  -topic string
        The Kafka topic to use (default "default_topic")

App will output OpenTelemetry spans for every intercepted message, i.e:

text
/* Detailed source-code truncated for AI context efficiency. */

Check the produced intercepted messages

Check that messages have some headers added by the interceptor:

sh
kafkacat -Cb localhost:9092 -t default_topic -f '\n- %s\nheaders: %h'
text
headers: trace_id=235b3424775d8b2f9bf21e458496f447,span_id=50da1552c105e712,message_id=50da1552c105e712
- test message 1/2 from kafka-client-go-test at 2020-08-11T11:36:01-07:00
headers: trace_id=2c4210c1d6c2ebe758eb41cbc95a0478,span_id=046bfc6d6db17ed7,message_id=046bfc6d6db17ed7
- test message 2/2 from kafka-client-go-test at 2020-08-11T11:36:01-07:00
% Reached end of topic default_topic [0] at offset 444

File: examples/http_server/README.md

HTTP server example

This HTTP server example shows you how to use the AsyncProducer and SyncProducer, and how to test them using mocks. The server simply sends the data of the HTTP request's query string to Kafka, and send a 200 result if that succeeds. For every request, it will send an access log entry to Kafka as well in the background.

If you need to know whether a message was successfully sent to the Kafka cluster before you can send your HTTP response, using the SyncProducer is probably the simplest way to achieve this. If you don't care, e.g. for the access log, using the AsyncProducer will let you fire and forget. You can send the HTTP response, while the message is being produced in the background.

One important thing to note is that both the SyncProducer and AsyncProducer are thread-safe. Go's http.Server handles requests concurrently in different goroutines, but you can use a single producer safely. This will actually achieve efficiency gains as the producer will be able to batch messages from concurrent requests together.


File: examples/exactly_once/README.md

Exactly-Once example

This example shows you how to use the Sarama transactional producer to ensure exacly-once paradigm with Kafka transaction. The example simply starts consuming the given Kafka topics and produce the consumed message to another topic including current message offset in procuder transaction.

bash
$ go run main.go -brokers="127.0.0.1:9092" -topics="sarama" -destination-topic="destination-sarama" -group="example"

To ensure transactional-id uniqueness it implement some ProducerProvider that build a producer using current message topic-partition.
You can also toggle (pause/resume) the consumption by sending SIGUSR1.


File: examples/consumergroup/README.md

Consumergroup example

This example shows you how to use the Sarama consumer group consumer. The example simply starts consuming the given Kafka topics and logs the consumed messages.

bash
$ go run main.go -brokers="127.0.0.1:9092" -topics="sarama" -group="example"

You can also toggle (pause/resume) the consumption by sending SIGUSR1


File: examples/sasl_scram_client/README.md

Example command line:

./sasl_scram_client -brokers localhost:9094 -username foo -passwd a_password -topic topic_name -tls -algorithm [sha256|sha512]


File: examples/txn_producer/README.md

Transactional producer example

This example shows you how to use the Sarama transactional producer. The example simply starts some goroutine that produce endlesslly on associated topic.

bash
$ go run main.go -brokers="127.0.0.1:9092" -topic "sarama" -producers 10 -records-number 10000

To ensure transactional-id uniqueness it implement some ProducerProvider that build a producer appending an integer that grow when producer is created.
You can also see record-rate each 5s printing on stdout.


File: examples/README.md

Sarama examples

This folder contains example applications to demonstrate the use of Sarama. For code snippet examples on how to use the different types in Sarama, see Sarama's API documentation on pkg.go.dev

HTTP server

http_server is a simple HTTP server uses both the sync producer to produce data as part of the request handling cycle, as well as the async producer to maintain an access log. It also uses the mocks subpackage to test both.

Interceptors

Basic example to use a producer interceptor that produces OpenTelemetry spans and add some headers for each intercepted message.

Transactional Producer

txn_producer Basic example to use a transactional producer that produce on some topic within a Kafka transaction. To ensure transactional-id uniqueness it implement some ProducerProvider that build a producer appending an integer that grow when producer is created.

Exacly-once transactional paradigm

exactly_once Basic example to use a transactional producer that produce consumed message from some topics within a Kafka transaction. To ensure transactional-id uniqueness it implement some ProducerProvider that build a producer using current message topic-partition.

Load-aware sticky consumer

consumer_load_aware demonstrates the SubscriptionUserDataBalanceStrategy interface: a LoadAwareSticky strategy wraps the built-in sticky assignor and injects a fresh load sample (CPU%, in-flight count) into each JoinGroup's subscription metadata.

Alter partition reassignments

alter_partition_reassignments shows how to raise the replication factor of an existing topic with ClusterAdmin.AlterPartitionReassignments, including how to construct the per-partition replica list and how to poll ListPartitionReassignments until the move completes.


File: internal/toxiproxy/README.md

toxiproxy

A minimal client implementation to setup proxies and toxics in toxiproxy as used in the FV suite.
We have our own minimal client implementation to avoid having to pull in the toxiproxy repo which carries a number of transitive dependencies.


File: mocks/README.md

sarama/mocks

The mocks subpackage includes mock implementations that implement the interfaces of the major sarama types.
You can use them to test your sarama applications using dependency injection.

The following mock objects are available:

The mocks allow you to set expectations on them. When you close the mocks, the expectations will be verified,
and the results will be reported to the *testing.T object you provided when creating the mock.

2. Official Technical Reference & Guides (IBM/IBM.github.io)

Portal for IBM @ GitHub

This repository is rendered online at http://ibm.github.io, it contains a listing of repositories that are open source and maintained by IBM teams.

Adding a new repo to the listing

In order to have your repository show up at http://ibm.github.io, a minor change to orgs.js is required.

  • To add a single repository add a new entry to orgs.js, specify the Github organization name and the repository name (separate them with a /), and set the type to repo, an example can be seen below:
text
{
      "name": "RuntimeTools/appmetrics",
      "type": "repo"
  }
  • To add all the repositories in a Github organization add a new entry to orgs.js, specify the Github organization name, and set the type to org, an example can be seen below:
text
{
      "name": "IBMResilient",
      "type": "org"
  }

To test changes locally

From within the top level folder of the cloned repository run:

text
$ python -m http.server {port}

For example: python -m http.server 8000 -> Open the following URL in a browser:

text
http://localhost:8000/

Quick Git tutorial

  1. Clone the repository and checkout a new branch
text
$ git clone https://github.com/IBM/ibm.github.io
$ git checkout -b branch_name
  1. Update the files you'd like to change
  2. Push the changes upstream
text
$ git add file1 file2
$ git commit -m "add your commit message here"
$ git push origin branch_name
  1. View your branch in Github and create a Pull Request