La motivación para escribir este artículo fue el hecho de que hay un aumento en la aparición de materiales de marketing sobre Apache Kafka en habr.com. Y también el hecho de que los artículos den la impresión de que están escritos por personas que están un poco lejos del uso real es, por supuesto, solo una impresión, pero por alguna razón, la mayoría de los artículos contienen necesariamente una comparación de Apache Kafka con RabbitMQ, y no a favor de este último. Lo más interesante es que al leer estos artículos, los gerentes sin experiencia técnica comienzan a gastar dinero en investigación interna para que los principales desarrolladores y directores técnicos elijan una de las soluciones. Como soy muy codicioso / hogareño, y también como partidario de la tesis "La verdad NO nace en una disputa", le sugiero que se familiarice con un enfoque diferente, casi sin comparar diferentes corredores.
No hay comparación en ninguna parte
En general, de la manera correcta, debería haber hecho un artículo en un formato Kafka+RabbitMQ+Nats+ActiveMQ+Mosquito+etc
, pero me parece que para ustedes, queridos lectores, será exagerado, aunque generalmente todos los servicios anteriores (y no solo) están presentes en mis soluciones arquitectónicas. Y todavía no estoy hablando de esto sobre AzureServiceBus / AmazonServiceBus, que también participan en "híbridos" en programas de proyectos grandes. Por lo tanto, por ahora, detengámonos en el paquete Kafka + RabbitMQ, y luego comprenderá por qué: por analogía, puede conectar cualquier servicio con su protocolo. Porque:
comparando Apache Kafka y RabbitMQ, está comparando 2 (dos) marcas, o más bien 2 empresas comerciales: Confluent y vmWare, y una pequeña Apache Software Foundation (pero esta no es una empresa)
es decir, formalmente, al comparar, debemos comparar los modelos de negocio de las empresas que son los principales impulsores del desarrollo de nuestros sujetos experimentales de hoy. Dado que Habr todavía no es un portal para la investigación económica, para empezar, debemos recordar no las marcas, sino las descripciones que están detrás de estas marcas (la forma en que nuestros participantes actuales se llaman a sí mismos).
- RabbitMQ es un agente de mensajes extensible y multiprotocolo
- Apache Kafka es una plataforma de transmisión de eventos distribuida
- Plataforma Confluent : una plataforma de transmisión de eventos con la capacidad de crear canales de datos de alto rendimiento para análisis e integración en escenarios comerciales
Confluent — Apache Kafka Confluent Apache Kafka. SchemeRegistry
, RestProxy
, kSQL
, , Kafka-Connect
.
— , RabbitMQ "", Kafka - ( ).
— , .
- RabbitMQ — . ( Erlang)
- Kafka — ( Scala/Java)
- RabbitMQ . , .
- Kafka , .
,
: , , - , , —
,
->
->
— . 14 , , "" ( ), .
- ODBC
- AMQP
- MSMQ
- XMPP
- IP over Avian Carriers
(python, C#, java) 1 — One-S-Connectors
(https://code.google.com/archive/p/one-c-connectors/source/default/source). ( 1 1 " 1-" — ).
( 2006 ) , / -. . ODBC Kafka/NATs/ModBus.
— ( )
, — 1-, .
- Kombu ( Python) — https://docs.celeryproject.org/projects/kombu/en/stable/introduction.html#transport-comparison
- CAP .NetCore — https://github.com/dotnetcore/CAP
Kombu — , Apache Kafka https://github.com/celery/kombu/issues/301 - " ", Python https://github.com/confluentinc/confluent-kafka-python
— , : Java, GoLang, RUST, etc. NATs ActiveMQ JMS — : Java ,
- https://github.com/rabbitmq/rabbitmq-server/tree/master/deps/
- https://docs.confluent.io/current/connect/kafka-connect-rabbitmq/index.html
- https://github.com/84codes/kafka-connect-rabbitmq/blob/master/docker-compose.yml
? , , " " — RabbitMQ ( /deps
) RabbitMQ, Confluent Apache Kafka .
PostgreSQL —CREATE EXTENSION hypopg
, Pivotal/vmWare
— " " — 84Codes
https://github.com/84codes. — 84Codes , / CloudAMQP CloudKarafka.
, , 2 :
- vmWare , RabbitMQ — . , GitHub.
- Confuent Enterprise Enterprise-Kafka-Connect, GUI .
- https://github.com/jcustenborder/kafka-connect-rabbitmq, , Java Maven Archetype https://github.com/jcustenborder/kafka-connect-archtype — , Confluent , Kafka .
Kafka
, Java, Enterprise . RabbitMQ
, (Erlang ), 84Codes
. Erlang — , OpenStack.
—
. , , ITILv4, 3
- ProtocolLock VendorLock — , , - — : .
- , — .
- —
3
—TDD, BDD, CICD, ScallableAgile DevOps (DocOps, DevSecOps)
— . TimeToMarket.
, , Docker-Compose. — () — , . — Kafka+RabbitMQ 84Codes
( — https://www.84codes.com/).
, . , , , Apache Kafka exactly-ones
. — , ->
Kafka ( Topic
) — Offsets
.
exactly-ones — " 1", Exactly once — , .
. :
- Zookeper
- KafkaBroker
- RabbitMQ
- KafkaConnect
- Python AMQP 0.9
- # AMQP 1.0
- C# Kafka
: Apache Kafka — ( ) Java, , librdkafka — C++ - ,. Kafka , " ": , https://github.com/edenhill/librdkafka/pulse/monthly, wmWare https://github.com/rabbitmq
:
RabbitMQ-Kafka-Sinc-Connector
— Confluent Github.
2 — - -.
RabbitMQ Kafka
—
docker-compose -f dockers/infra.yml up -d
, , , Kafka-UI RabbitMQ-Sinc, Kafka RabbitMQ
image: provectuslabs/kafka-ui:latest ports: - 8080:8080 depends_on: - kafka-broker - zookeeper environment: KAFKA_CLUSTERS_0_NAME: local KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: broker:29092 KAFKA_CLUSTERS_0_ZOOKEEPER: zookeeper:2181 KAFKA_CLUSTERS_0_JMXPORT: 9101
Java
<parent>
<groupId>com.github.jcustenborder.kafka.connect</groupId>
<artifactId>kafka-connect-parent</artifactId>
<version>1.0.0</version>
</parent>
pom.xml — , https://github.com/jcustenborder/kafka-connect-parent, Java-Kafka-Adapter
c RMQ Java — https://www.rabbitmq.com/java-client.html
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>${rabbitmq.version}</version>
— , , :
- java —
-1-build-connect-jar.bat
- —
00-build-connect-image.sh
- —
01-start-infra.sh
— Docker PWD Windows Linux — . — sh

RabbitMQ :
:
- 9092 — Kafka
- 8080 — Apache Kafka UI
- 5672 — AMQP 0.9 AMQP 1.0
- 15672 — RabbitMQ
- 28082 —
curl
RabbitMQ Docker:
- —
enabled-rmq-plugins
[ rabbitmq_management, rabbitmq_amqp1_0, rabbitmq_mqtt, rabbitmq_federation, rabbitmq_federation_management, rabbitmq_shovel, rabbitmq_shovel_management, rabbitmq_prometheus ].
- , —
rmq_definitions.json
"bindings":[
{
"source":"orders-send",
"vhost":"/",
"destination":"orders-amqp-10-consumer",
"destination_type":"queue",
"routing_key":"",
"arguments":{
docker-compose -f dockers/infra.yml restart protocol-connect-sync docker-compose -f applications.yml build docker-compose -f applications.yml up

:
- -
2
producer = conn.Producer(serializer='json') producer.publish({'client': '', 'count': 10, 'good': ''}, exchange=order_exchange, declare=[kafka_queue, amqp10_queue]) time.sleep(2)
RUN python -m pip install \ kombu \ librabbitmq
AMQP 0.9 — librabbitmq https://github.com/alanxz/rabbitmq-c
- AMQP 1.0 — , . .
Attach recvAttach = new Attach()
{
Source = new Source()
{
Address = "orders-amqp-10-consumer",
Durable = 1,
},
ReceiverLink receiver =
new ReceiverLink(session,"netcore_amqp_10_consumer", recvAttach, null);
Console.WriteLine("Receiver connected to broker.");
while (true) {
Message message = receiver.Receive();
if (message == null)
{
Console.WriteLine("Client exiting.");
break;
}
Console.WriteLine("Received "
+ System.Text.Encoding.UTF8.GetString((byte[])message.Body)
<ItemGroup> <PackageReference Include="AMQPNetLite.Core" Version="2.4.1" /> </ItemGroup>
https://github.com/Azure/amqpnetlite Microsoft . AMQP 1.0 https://docs.microsoft.com/ru-ru/azure/service-bus-messaging/service-bus-amqp-overview
- Kafka — . Exactly once.
AutoOffsetReset = AutoOffsetReset.Earliest
c.Subscribe("orders-from-amqp");
while (true)
{
try
{
var cr = c.Consume(cts.Token);
:
- 5

- 3

- Kafka-Ui

- RabbitMQ

Java ?
— , , Kafka-Connect-Base
[submodule "dockers/rabbitmq-kafka-sink"] path = dockers/rabbitmq-kafka-sink url = https://github.com/aliczin/kafka-connect-rabbitmq
, Kafka-Connect — .
:
public class RabbitMQSourceTask extends SourceTask {
this.channel.basicConsume(queue, this.consumer);
log.info("Setting channel.basicQos({}, {});", this.config.prefetchCount, this.config.prefetchGlobal);
this.channel.basicQos(this.config.prefetchCount, this.config.prefetchGlobal);
- .
@Override
public List<SourceRecord> poll() throws InterruptedException {
List<SourceRecord> batch = new ArrayList<>(4096);
while (!this.records.drain(batch)) {
AMQP 0.9 . Java . J2EE.
private static final Logger log = LoggerFactory.getLogger(MessageConverter.class);
static final String FIELD_ENVELOPE_DELIVERYTAG = "deliveryTag";
static final String FIELD_ENVELOPE_ISREDELIVER = "isRedeliver";
static final String FIELD_ENVELOPE_EXCHANGE = "exchange";
static final String FIELD_ENVELOPE_ROUTINGKEY = "routingKey";
static final Schema SCHEMA_ENVELOPE = SchemaBuilder.struct()
.name("com.github.jcustenborder.kafka.connect.rabbitmq.Envelope")
.doc("Encapsulates a group of parameters used for AMQP's Basic methods. See " +
"`Envelope <https://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Envelope.html>`_")
.field(FIELD_ENVELOPE_DELIVERYTAG, SchemaBuilder.int64().doc("The delivery tag included in this parameter envelope. See `Envelope.getDeliveryTag() <https://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Envelope.html#getDeliveryTag-->`_").build())
.field(FIELD_ENVELOPE_ISREDELIVER, SchemaBuilder.bool().doc("The redelivery flag included in this parameter envelope. See `Envelope.isRedeliver() <https://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Envelope.html#isRedeliver-->`_").build())
.field(FIELD_ENVELOPE_EXCHANGE, SchemaBuilder.string().optional().doc("The name of the exchange included in this parameter envelope. See `Envelope.getExchange() <https://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Envelope.html#getExchange-->`_"))
.field(FIELD_ENVELOPE_ROUTINGKEY, SchemaBuilder.string().optional().doc("The routing key included in this parameter envelope. See `Envelope.getRoutingKey() <https://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Envelope.html#getRoutingKey-->`_").build())
.build();
… , — . .
Github.
— https://github.com/aliczin/hybrid-eventing. Creative Commons Attribution 4.0 International.
— DevOps . , — , .
" " () —
orderEventsApp->Amqp09: send order Amqp09->Amqp10: fanout\n copy event Amqp09->KafkaQ: fanout\n copy event KafkaQ->KafkaConnect: consume\n on message KafkaConnect->KafkaConnect: transform\n message KafkaConnect->Kafka: publish to topic

—
Amqp10->orderEventSubApp: subcribe\n for event orderJournalApp->Kafka: read kafka journal

Apache Kafka Java , librdkafka —
KafkaAPI
. Java .
, RabbitMQ/Kafka/Nats/ActiveMQ — -.
Docker, .
:
Mosquito — SCADA ModBus/OPC-UA. — " " — https://github.com/mainflux/mainflux
ActiveMQ — Java , Erlang, —
RabbitMQ AMQP 1.0 -> ActiveMQ
RabbitMQ, JMS.
NATs —
OpenFaaS
, " "Amazon Lambda
. — : https://github.com/nats-io/nats-kafka — OpenFaaS 1- — 2.5 https://youtu.be/8sF-oGGVa9M
(/ — : ) /, - , , . " "
: Produser/Consumer : vmWare Stream RabbitMQ vmWare RabbitMQ : 1- ActiveMQ 1 1 Kafka API ActivemeMQ2Kafka 1 etc
, — — : https://github.com/fclairamb/ftpserver/pull/34 — FTP , S3.
— : : .
- . DevOps k8s, OpenShift, etc — , - .
- — PRODUCTION-READY .
( ) , - :
HTTP, AMQP 0.9, AMQP 1.0, Apache Kafka 23, MQTT, WebSockets, <SOAP>
. 1 — . Google 1+RabbitMQ 1+Kafka 1+OpenFaas
— RabbitMQ Kafka " 1" . 1 — , . Java/C#/Python/C++/Rust/etc.
https://shd101wyy.github.io/markdown-preview-enhanced Visual Studio Code — .
Bueno, como punto final, me gustaría señalar que la elección del ecosistema JDK Cunfluent Inc
como plataforma de desarrollo Kafka-Connect
parece igualmente extraña. No me sorprendería que sus competidores hicieran lo mismo, pero en GoLang, NodeJS (algo así como Kafka-Beats-Hub
)

Hago imágenes bonitas en formato GraphViz utilizando el inteligente proyecto Docker2GraphViz: ayuda a mantener actualizados el esquema y la documentación técnica en formato Markdown
set CURPATH=%~dp0 set DOCKER_DIR=%CURPATH%\dockers docker run --rm -it --name dcv -v %DOCKER_DIR%\:/input pmsipilot/docker-compose-viz render -m image --force --output-file=infra-topology.png infra.yml docker run --rm -it --name dcv -v %CURPATH%\:/input pmsipilot/docker-compose-viz render -m image --force --output-file=apps-topology.png applications.yml copy /b/v/y dockers\infra-topology.png content\assets\infra-topology.png copy /b/v/y apps-topology.png content\assets\apps-topology.png