skroutz / rafka

Kafka proxy with a simple API, speaking the Redis protocol
https://engineering.skroutz.gr/blog/kafka-rails-integration/
GNU General Public License v3.0
8 stars 0 forks source link
kafka kafka-client kafka-consumer kafka-producer librdkafka

rafka

Build Status Go report License: GPL v3

Table of Contents

rafka is a gateway service that exposes Kafka using simple semantics.

It implements a small subset of the Redis protocol, so that it can be used by leveraging existing Redis client libraries.

Rationale

Using Kafka with languages that lack a reliable, solid client library can be a problem for mission-critical applications.

Using rafka we can:

Refer to "Introducing Kafka to a Rails application" for more background and how rafka is used in a production environment.

Requirements

Getting Started

  1. Install librdkafka:
# debian
$ sudo apt-get install librdkafka-dev

# macOS
$ brew install librdkafka
  1. Install rafka:
$ go get -u github.com/skroutz/rafka
  1. Run it:
$ rafka -c librdkafka.json.sample
[rafka] 2017/06/26 11:07:23 Spawning Consumer Manager (librdkafka 0.11.0)...
[server] 2017/06/26 11:07:23 Listening on 0.0.0.0:6380

Design

Protocol

rafka exposes a subset of the Redis protocol and tries to keep Redis semantics where possible.

We also try to design the protocol in a way that rafka can be replaced by a plain Redis instance so that it's easier to test client code and libraries.

Consumer

In Kafka, each consumer represents a worker processing messages. That worker sends heartbeats and is de-pooled from its group when it misbehaves.

Those semantics are preserved in rafka by using stateful connections. In rafka, each connection is tied with a set of Kafka consumers. Consumers are not shared between connections and once the connection closes, the respective consumers are gracefully shut down too.

Each consumer must identify itself upon connection, by using client setname <group.id>:<name>. Then it can begin processing messages by issuing blpop calls on the desired topics. Each message should be explicitly acknowledged so it can be committed to Kafka. Acks are rpushed to the special acks key.

For more info refer to API - Consumer.

Caveats

rafka periodically calls Consumer.StoreOffsets() under the hood. This means consumers must be configured accordingly:

For more info see https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md.

Producer

For more info refer to API - Producer.

Caveats

There is currently is an upper message limit of 32MB to the messages that may be produced. It is controlled by go-redisproto.MaxBulkSize.

API

Producer

Example using redis-cli:

127.0.0.1:6380> rpushx topics:greetings "hello there!"
"OK"

Consumer

Example using redis-cli:

127.0.0.1:6380> client setname myapp:a-consumer
"OK"
127.0.0.1:6380> blpop topics:greetings 1000
1) "topic"
2) "greetings"
3) "partition"
4) (integer) 2
5) "offset"
6) (integer) 10
7) "value"
8) "hello there!"
# ... do some work with the greeting...
127.0.0.1:6380> rpush acks greetings:2:10
"OK"

Generic

Client libraries

Development

If this is your first time setting up development on rafka, ensure that you have all the build dependencies via dep:

$ dep ensure

To run all the tests (Go + end-to-end) do:

$ DIST=buster RDKAFKA_VERSION=v1.2.1 make test

License

rafka is released under the GNU General Public License version 3. See COPYING.