gRPC/REST proxy for Kafka
Kafka-Pixy is a dual API (gRPC and REST) proxy for Kafka with automatic consumer group control. It is designed to hide the complexity of the Kafka client protocol and provide a stupid simple API that is trivial to implement in any language.
Kafka-Pixy is tested against Kafka versions 1.1.1 and 2.3.0, but is likely to work with any version starting from 0.8.2.2. It uses the Kafka Offset Commit/Fetch API to keep track of consumer offsets. However Group Membership API is not yet implemented, therefore it needs to talk to Zookeeper directly to manage consumer group membership.
Warning: Kafka-Pixy does not support wildcard subscriptions and therefore cannot coexist in a consumer group with clients using them. It should be possible to use other clients in the same consumer group as kafka-pixy instance if they subscribe to topics by their full names, but that has never been tested so do that at your own risk.
If you are anxious to get started then install Kafka-Pixy and proceed with a quick start guide for your weapon of choice: Curl, Python, or Golang. If you want to use some other language, then you still can use either of the guides for inspiration, but you would need to generate gRPC client stubs from kafkapixy.proto yourself (please refer to gRPC documentation for details).
gRPC is an open source framework that is using Protocol Buffers as interface definition language and HTTP/2 as transport protocol. Kafka-Pixy API is defined in kafkapixy.proto. Client stubs for Golang and Python are generated and provided in this repository, but you can easily generate stubs for a bunch of other languages. Please refer to the gRPC documentation for information on the language of your choice.
It is highly recommended to use the gRPC API for production/consumption. The HTTP API is only provided for quick tests and operational purposes.
Each API endpoint has two variants which differ by /clusters/
prefix. The one with the proxy prefix is to be used when multiple
clusters are configured. The one without the prefix operates on the
default cluster (the one that is mentioned first in the YAML
configuration file).
POST /topics//messages
POST /clusters//topics//messagesWrites a message to a topic on a particular cluster. If the request content
type is either text/plain or application/json then a message should be sent as
the body of a request. If content type is x-www-form-urlencoded then a
message should be passed as the msg form parameter.
If Kafka-Pixy is configured to use a version of the Kafka protocol (via the
kafka.version proxy setting) that is 0.11.0.0 or later, it is also possible to
add record
headers
to a message by adding HTTP headers to your message. Any HTTP header with the
prefix "X-Kafka-" will have that prefix stripped and the header will be used as
a record header. Since the values of Kafka headers can be arbitrary byte
strings, the value of the HTTP header must be Base 64-encoded.
| Parameter | Opt | Description |
|---|---|---|
| cluster | yes | The name of a cluster to operate on. By default the cluster mentioned first in the proxies section of the config file is used. |
| topic | The name of a topic to produce to | |
| key | yes | A string whose hash is used to determine a partition to produce to. By default a random partition is selected. |
| msg | * | Used only if the request content type is x-www-form-urlencoded. In other cases the request body is the message. |
| sync | yes | A flag (value is ignored) that makes Kafka-Pixy wait for all ISR to confirm write before sending a response back. By default a response is sent immediatelly after the request is received. |
By default the message is written to Kafka asynchronously, that is the HTTP request completes as soon as Kafka-Pixy reads the request from the wire, and production to Kafka is performed in the background. Therefore it is not guaranteed that the message will ever get into Kafka.
If you need a guarantee that a message is written to Kafka, then pass the sync
flag with your request. In that case when Kafka-Pixy returns a response is
governed by producer.required_acks parameter in the YAML config. It can be one
of:
E.g. if a Kafka-Pixy process has been started with the --tcpAddr=0.0.0.0:8080
argument, then you can test it using curl as follows:
curl -X POST localhost:8080/topics/foo/messages?key=bar&sync \
-H 'Content-Type: text/plain' \
-d 'Good news everyone!'If the message is submitted asynchronously then the response will be an
empty json object {}.
If the message is submitted synchronously then in case of success (HTTP status 200) the response will be like:
{
"partition": ,
"offset":
}In case of failure (HTTP statuses 404 and 500) the response will be:
{
"error":
}GET /topics//messages
GET /clusters//topics//messagesConsumes a message from a topic of a particular cluster as a member of a particular consumer group. A message previously consumed from the same topic can be optionally acknowledged.
| Parameter | Opt | Description |
|---|---|---|
| cluster | yes | The name of a cluster to operate on. By default the cluster mentioned first in the proxies section of the config file is used. |
| topic | The name of a topic to consume from. | |
| group | The name of a consumer group. | |
| noAck | yes | A flag (value is ignored) that no message should be acknowledged. For default behaviour read below. |
| ackPartition | yes | A partition number that the acknowledged message was consumed from. For default behaviour read below. |
| ackOffset | yes | An offset of the acknowledged message. For default behaviour read below. |
If noAck is defined in a request then no message is acknowledged
by the request. If a request defines both ackPartition and
ackOffset parameters then a message previously consumed from the
same topic from the specified partition with the specified offset is
acknowledged by the request. If none of the ack related parameters is
specified then the request will acknowledge the message consumed in this
requests if any. It is called auto-ack mode.
When a message is consumed as a member of a consume group for the first time, Kafka-Pixy joins the consumer group and subscribes to the topic. All Kafka-Pixy instances that are currently members of that group and subscribed to that topic distribute partitions between themselves, so that each Kafka-Pixy instance gets a subset of partitions for exclusive consumption (Read more about Kafka consumer groups here).
If a Kafka-Pixy instance has not received consume requests for a topic for the duration of the subscription timeout, then it unsubscribes from the topic, and the topic partitions are redistributed among Kafka-Pixy instances that are still consuming from it.
If there are no unread messages in the topic the request will block waiting for the duration of the long polling timeout. If there are no messages produced during this long poll waiting then the request will return 408 Request Timeout error, otherwise the response will be a JSON document of the following structure:
{
"key": ,
"value": ,
"partition": ,
"offset": ,
"headers": [
{
"key": ,
"value":
}
]
}e.g.:
{
"key": "0JzQsNGA0YPRgdGP",
"value": "0JzQvtGPINC70Y7QsdC40LzQsNGPINC00L7Rh9C10L3RjNC60LA=",
"partition": 0,
"offset": 13,
"headers": [
{
"key": "foo",
"value": "YmFy"
}
]
}Note that headers are only supported if the Kafka protocol version (set via the
kafka.version configuration flag) is set to 0.11.0.0 or later.
POST /topics//acks
POST /clusters//topics//acksAcknowledges a previously consumed message.
| Parameter | Opt | Description |
|---|---|---|
| cluster | yes | The name of a cluster to operate on. By default the cluster mentioned first in the proxies section of the config file is used. |
| topic | The name of a topic to produce to. | |
| group | The name of a consumer group. | |
| partition | A partition number that the acknowledged message was consumed from. | |
| offset | An offset of the ac |
No open issues yet, or sync has not completed.