Architecture
Inside the RabbitMQ (AMQP 0-9-1) connector — the everything-is-a-Queue model, virtual exchange routing, the channel mapping, and cross-protocol interop.
The KubeMQ RabbitMQ (AMQP 0-9-1) connector is an embedded, wire-protocol bridge inside
kubemq-server that speaks the RabbitMQ dialect on plain port 5672 and TLS/AMQPS port
5671. The connector is opt-in (disabled by default) — enable it with
CONNECTORS_AMQP_ENABLE=true (Docker) or spec.amqp.enabled: true (Kubernetes). Any
standard AMQP 0-9-1 client connects to it with only a connection-string change — no code
changes, no library swap, no KubeMQ SDK.
Unlike the AMQP 1.0 connector (which can touch all five KubeMQ patterns), the RabbitMQ connector bridges the AMQP 0-9-1 wire protocol onto exactly one KubeMQ primitive: the Queue. This single fact drives the entire mental model.
Everything is a Queue. Every AMQP queue maps to exactly one KubeMQ Queue channel
named amqp.{vhost}.{queue}. Exchanges and bindings are virtual — connector-side
routing metadata resolved at publish time, not data stores. AMQP only ever touches the
KubeMQ Queue primitive; there is no exchange "storage."
How AMQP 0-9-1 maps to KubeMQ
A publish always resolves to one or more KubeMQ Queue channels. The connector resolves the
exchange routing (default / direct / fanout / topic / headers) into a deduplicated set of
target queues at publish time, then writes the message to each queue's KubeMQ channel
amqp.{vhost}.{queue} through the message broker.
A publish resolves through virtual exchange routing into a deduplicated set of target queues; each maps to a KubeMQ Queue channel amqp.{vhost}.{queue} and is written through the message broker.
The exchange types resolve as in RabbitMQ, but the result is always a set of KubeMQ Queue channels:
| Exchange type | Routing rule |
|---|---|
default ("") | The routing key is the queue name (implicit binding). |
| direct | Exact routing-key match against the bindings. |
| fanout | All bound queues (routing key ignored). |
| topic | Trie match (* = one word, # = zero-or-more words). |
| headers | x-match against the header bindings. |
Matched queues are deduplicated — a message matching multiple bindings to the same queue
is delivered exactly once. If the routed set is empty, the publish returns
basic.return (312 NO_ROUTE) when mandatory=true, otherwise it is silently dropped.
Channel mapping
The channel name is amqp.{vhost}.{queue}. AMQP vhost / maps to the configured
DefaultVhost segment (literal "default"):
| AMQP queue | Vhost | KubeMQ channel |
|---|---|---|
orders | / (default) | amqp.default.orders |
hello | / | amqp.default.hello |
jobs | workers | amqp.workers.jobs |
The full channel name (prefix + vhost + queue) is capped at 255 chars, and queue/vhost
names must not contain ;, :, *, >, whitespace, or end with .. See
Channel mapping for the grammar and
the property/header mapping.
The connector stack
The connector terminates the AMQP 0-9-1 wire protocol and translates it onto KubeMQ Queue
operations. A single amqpmux front door classifies each connection by its 8-byte AMQP
protocol header and dispatches AMQP 0-9-1 traffic to this engine (and AMQP 1.0 traffic to
the AMQP 1.0 engine), so the two dialects coexist on ports 5672/5671.
The connector authenticates over SASL PLAIN, resolves virtual exchange routing, authorizes each target queue, and batch-writes to the KubeMQ Queue channel backed by the message broker's durable store.
- SASL PLAIN only. On a secured broker the username is cosmetic and the password carries
a KubeMQ JWT; identity is
claims.ClientID. Because the JWT travels in the SASL PLAIN password in cleartext at the AMQP layer, production deployments must use the TLS listener (5671). See Authentication. - Native RPC. Request/reply uses RabbitMQ's
amq.rabbitmq.reply-to(direct reply-to); there is no gRPC responder anywhere in the connector. See RPC.
Cross-protocol interop
Because every AMQP queue is a normal KubeMQ Queue channel, AMQP and gRPC/REST clients interoperate on the same channel.
The same KubeMQ Queue channel backs both sides, so an AMQP 0-9-1 client and a gRPC/REST client interoperate transparently.
Header and metadata translation differs by direction:
| Direction | What the consumer sees |
|---|---|
| AMQP → AMQP | Routing context is native: a delivery shows exchange, routing-key, and the original AMQP headers. |
| AMQP → gRPC/REST | AMQP headers are wrapped as Metadata = {"amqp_headers":{...}} (always set, even when empty). E.g. header trace=abc-123 → {"amqp_headers":{"trace":"abc-123"}}. |
| gRPC/REST → AMQP | Native (non-enveloped) gRPC metadata surfaces as the AMQP header x-kubemq-metadata. E.g. gRPC metadata="native-metadata" → AMQP header x-kubemq-metadata: native-metadata. |
The {"amqp_headers":{...}} envelope is an interop concern, not a default-path surprise:
a pure AMQP→AMQP round-trip surfaces headers natively. See
Channel mapping for the full
property/header ⇄ Tag/Metadata table.
Related
Channel mapping
The amqp.{vhost}.{queue} grammar, name constraints, and the property/header mapping.
Exchanges and routing
How default, direct, fanout, topic, and headers exchanges resolve to queues at publish time.
Work queues
Competing consumers and fair dispatch over a single KubeMQ Queue channel.
RPC
Request/reply over the native amq.rabbitmq.reply-to direct reply-to mechanism.
Was this page helpful?