Apache Kafka etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
Apache Kafka etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

6 Mart 2023 Pazartesi

Kafka OAuth

Giriş
Açıklaması şöyle
KIP-255 introduced OAuth Authentication via SASL/OAUTHBEARER, and KIP-768 added default implementation for Login/Validator Callback Handlers(aka OIDC) that use client_credentials Oauth2.0 grant type.
Burada hem broker hem de client tarafında OAuth kullanmak için bir örnek var

23 Şubat 2023 Perşembe

Apache Kafka Connect JdbcSinkConnector

Giriş
Örneğin MySQL'den okumak için io.debezium.connector.mysql.MySqlConnector kullanılır ama PostgreSQL'e yazmak için io.confluent.connect.jdbc.JdbcSinkConnector kullanılır

1. Connector'a bir isim verilir
2. connector.class her zaman io.confluent.connect.jdbc.JdbcSinkConnector olarak belirtilir.

3. Veri tabanı bağlantısı bilgisi tanımlanır. Bu alanlar şöyle
connection.url
connection.user
connection.password

4. Tüketilecek topicler topics ile belirtilir. Açıklaması şöyle
Topics to subscribe for updates.

5. Eğer hedef veri tabanında tablo yoksa auto.create ile yaratılması istenebilir. Açıklaması şöyle
Auto-create the schema objects if they do not exist e.g. the table will be auto-created during the initial sync.

Örnek
Şöyle yaparız
$ curl -X POST -H "Accept:application/json" -H "Content-Type:application/json"
--data @postgres-sink-btc.json http://localhost:8083/connectors
Dosyanın içi şöyledir
{
  "name": "postgres-sink-btc",
  "config": {
    "connector.class":"io.confluent.connect.jdbc.JdbcSinkConnector",
    "tasks.max":"1",
    "topics": "topic_BTC",
    "key.converter": "org.apache.kafka.connect.storage.StringConverter",
    "value.converter": "org.apache.kafka.connect.json.JsonConverter",
    "connection.url": "jdbc:postgresql://questdb:8812/qdb?useSSL=false",
    "connection.user": "admin",
    "connection.password": "quest",
    "key.converter.schemas.enable": "false",
    "value.converter.schemas.enable": "true",
    "auto.create": "true",
    "insert.mode": "insert",
    "pk.mode": "none"
  }
}
Açıklaması şöyle
topics: Kafka topic to consume and convert into Postgres format.

connection: Using default credentials for QuestDB (admin/quest) on port 8812.

value.converter: This example uses JSON with schema, but you can also use Avro or raw JSON. 
Örnek
Şöyle yaparız
name=test-jdbc-sink
connector.class=io.confluent.connect.jdbc.JdbcSinkConnector
tasks.max=1
connection.url=jdbc:postgresql://postgres-postgresql:5432/test?user=postgres&password=<postgresql-password>
topics=students
dialect.name=PostgreSqlDatabaseDialect
auto.create=true
insert.mode=upsert
pk.fields=id
pk.mode=record_value
transforms=unwrap
transforms.unwrap.type=io.debezium.transforms.UnwrapFromEnvelope
transforms* alanı için açıklama şöyle
This is another SMT provided by Debezium that we are going to use. By default, the structure of debezium is complex and consists of multiple levels of information including event key schema, event key payload, event value schema, event value payload (For details refer to Connector Documentation). Even in the event value payload section, we have multiple structures for values before and after. Of these, we are only interested in the final payload and that is what this SMT provides us with. It unwraps the original message and provides a relevant section. Note that we have applied this SMT after the data is saved in Kafka and before it is inserted in PostgreSQL so that Kafka remains a source of truth and has all the information (if and when required).

21 Şubat 2023 Salı

Apache Kafka Partition Rakamını Hesaplama

Partition Nedir?
Açıklaması şöyle. Topic bölümlendirilir. Her parçaya partition denilir.
Topics are divided into smaller parts called partitions. A partition can be described as a commit log. Messages can be appended to the log and can be read-only in the order from the beginning to the end. Partitions are designed to provide redundancy and scalability. The most important fact is that partitions can be hosted on different servers (brokers), giving a very powerful way to scale topics horizontally.
Partition Yöntemleri
Açıklaması şöyle. Consistent Hashing yazısına bakabilirsiniz.
A common and efficient approach is Consistent Hashing. Although, others such as Hashing and range-based partitioning can still be used.
Global Event Order
Partition ve Message Order yazısına taşıdım

Partition Rakamı Nasıl Belirlenir?
kafka-topics komutu ile topic yaratırken bir de istenilen partition sayısı belirtilebiliyor. Bu sayı nasıl hesaplanır. 

Broker Sayısı
Eğer broker sayısı < 6 ise açıklaması şöyle
Partitions per topic is the million-dollar question and there’s no one answer. If you have a small cluster of fewer than six brokers, create two times the number of brokers you have ( N X 2 if N < 6). The reasoning behind it is that if you have more brokers over time, for example 12 brokers. Well, at least you will have enough partitions to cover that.
Consumer Sayısı
partition değeri ile ilgili açıklama şöyle. Yani consumer sayısı da Partition Rakamını belirlerken bir etken
Remember! Kafka topic partition must be the same or less than the number of concurrent consumer threads
Sonuç
Bu iki sayının en küçüğü alınır




17 Şubat 2023 Cuma

Apache Kafka Zookeeper Yerine Kafka Raft

Neden Gerekiyor ? 
Açıklaması şöyle. Yani Zookeeper ile her şey yavaş kalıyor. Ayrıca Kafka ve Zookeeper iki farklı araç ve birbirlerinden çok farklı oldukları için her ikisini de öğrenmek gerekiyor. Bu da zaman ve enerji kaybı
In a Kafka cluster, the Kafka Controller manages broker, topic, and partition meta-data (the “control plane”) 
...
But how does Kafka know which controller should be active, and where the meta-data is stored in case of broker failures? Traditionally a ZooKeeper Ensemble (cluster) has managed the controller elections and meta-data storage ...

But this introduces a bottleneck between the active Kafka controller and the ZooKeeper leader, and meta-data changes (updates) and failovers are slow (as all communication is between one Kafka broker and one ZooKeeper server, and ZooKeeper is not horizontally write scalable). The new Kafka Raft mode (KRaft for short) replaces ZooKeeper with Kafka topics and the Raft consensus algorithm to make Kafka self-managed,...

The Kafka cluster meta-data is now only stored in the Kafka cluster itself, making meta-data update operations faster and more scalable. The meta-data is also replicated to all the brokers, making failover from failure faster too. Finally, the active Kafka controller is now the Quorum Leader, using Raft for leader election.

The motivation for giving Kafka a “brain transplant” (replacing ZooKeeper with KRaft) was to fix scalability and performance issues, enable more topics and partitions, and eliminate the need to run an Apache ZooKeeper cluster alongside every Kafka cluster.
Zookeeper'ın Kaldırılması
Kafka 2.8.0'dan itibaren KPI-500 ile (yani Kafka Process Improvement - 500) Zookeper'ın kaldırılması için çalışılıyor. Kafka Version 2.8.0 çıktığında bu hala gerçekleşmemişti. Açıklaması şöyle
Kafka Version 2.8.0 introduces an early access to Zookeeper-less Kafka as part of KPI-500 using the Kraft mode. The implementation is partially complete and thus is not to be used in production environments.
Kafka 3.3 ile Zookeeper isteğe bağlı olarak kaldırılabilir. Açıklaması şöyle
The changes have been happening incrementally, starting from Kafka version 2.8 (released April 2021) which had KRaft in early access. In version 3.0 (September 2021) it was in preview. The maturity of KRaft has improved significantly since version 2.8 (3.0 had 20 KRaft improvements and bug fixes, 3.0.1 had 1, 3.1.0 had 5, and 3.1.1 had only 1 minor fix), and on October 3 2022 version 3.3 was marked as production ready (for new clusters).
Zookeeper Yerine KRaft
Açıklaması şöyle
“KRaft” stands for “Kafka Raft”, and is a combination of Kafka topics and the Raft consensus algorithm.
@metadata Topic
Açıklaması şöyle. Internal Quorum'daki controller'lar artık @metadata topic ile haberleşecekler.
When Kafka Raft Metadata mode is enabled, Kafka will store its metadata and configurations into a topic called @metadata. This internal topic is managed by the internal quorum and replicated across the cluster. The nodes of the cluster can now serve as brokers, controllers or both (called combined nodes).

When KRaft mode is enabled, only a few selected servers can serve as controllers and these will compose the internal quorum. The controllers can either be in active or standby mode that will eventually take over if the current active controller server fails or is taken down.
Normalde "Broker Liveliness" bilgisi Zookeeper'da saklanır. Kafka Controller "liveliness" bilgisini sürekli kontrol eder. Bu artık olmayacak.

12 Ocak 2023 Perşembe

Apache Kafka ksqlDB Streams and Tables

Giriş
1. CRATE STREAM ile kafka topic'ten okuyan bir stream yaratılır
2. CREATE TABLE ile stream bir materialized view haline getirilir
Şeklen şöyle. Stream ile aggregation yapılır. Table ile de join'ler yapılır.


CREATE TABLE
Örnek - Primary Key
Şöyle yaparız
CREATE TABLE MyTable ( sensorId VARCHAR PRIMARY KEY, timestamp VARCHAR, value DECIMAL(19,5) ) WITH ( KAFKA_TOPIC = '<x>-telemetry', VALUE_FORMAT = 'JSON' ); SELECT * FROM MyTable; SELECT * FROM MyTable WHERE sensorId = "127";
Örnek - ETL
Debezium source tanımlamak için şöyle yaparız
# Create customers, products ve orders topics CREATE SOURCE CONNECTOR `mysql-connector` WITH( "connector.class"= 'io.debezium.connector.mysql.MySqlConnector', "tasks.max"= '1', "database.hostname"= 'mysql', "database.port"= '3306', "database.user"= 'root', "database.password"= 'debezium', "database.server.id"= '184054', "database.server.name"= 'dbserver1', "database.whitelist"= 'inventory', "table.whitelist"= 'inventory.customers,inventory.products,inventory.orders', "database.history.kafka.bootstrap.servers"= 'kafka:9092', "database.history.kafka.topic"= 'schema-changes.inventory', "transforms"= 'unwrap', "transforms.unwrap.type"= 'io.debezium.transforms.ExtractNewRecordState', "key.converter"= 'org.apache.kafka.connect.json.JsonConverter', "key.converter.schemas.enable"= 'false', "value.converter"= 'org.apache.kafka.connect.json.JsonConverter', "value.converter.schemas.enable"= 'false');
Bu 3 tabloyu birleştirmek için şöyle yaparız
# Join all streams CREATE STREAM S_CUSTOMER (ID INT, FIRST_NAME string, LAST_NAME string, EMAIL string) WITH (KAFKA_TOPIC='dbserver1.inventory.customers', VALUE_FORMAT='json'); CREATE TABLE T_CUSTOMER AS SELECT id, latest_by_offset(first_name) as fist_name, latest_by_offset(last_name) as last_name, latest_by_offset(email) as email FROM s_customer GROUP BY id EMIT CHANGES; CREATE STREAM S_PRODUCT (ID INT, NAME string, description string, weight DOUBLE) WITH (KAFKA_TOPIC='dbserver1.inventory.products', VALUE_FORMAT='json'); CREATE TABLE T_PRODUCT AS SELECT id, latest_by_offset(name) as name, latest_by_offset(description) as description, latest_by_offset(weight) as weight FROM s_product GROUP BY id EMIT CHANGES; CREATE STREAM s_order ( order_number integer, order_date timestamp, purchaser integer, quantity integer, product_id integer) WITH (KAFKA_TOPIC='dbserver1.inventory.orders',VALUE_FORMAT='json'); CREATE STREAM SA_ENRICHED_ORDER WITH (VALUE_FORMAT='AVRO') AS select o.order_number, o.quantity, p.name as product, c.email as customer, p.id as product_id, c.id as customer_id from s_order as o left join t_product as p on o.product_id = p.id left join t_customer as c on o.purchaser = c.id partition by o.order_number emit changes;
Sonucu PostgreSQL'e yazmak için şöyle yaparız
CREATE SINK CONNECTOR `postgres-sink` WITH( "connector.class"= 'io.confluent.connect.jdbc.JdbcSinkConnector', "tasks.max"= '1', "dialect.name"= 'PostgreSqlDatabaseDialect', "table.name.format"= 'ENRICHED_ORDER', "topics"= 'SA_ENRICHED_ORDER', "connection.url"= 'jdbc:postgresql://postgres:5432/inventory?user=postgresuser&password=postgrespw', "auto.create"= 'true', "insert.mode"= 'upsert', "pk.fields"= 'ORDER_NUMBER', "pk.mode"= 'record_key', "key.converter"= 'org.apache.kafka.connect.converters.IntegerConverter', "key.converter.schemas.enable" = 'false', "value.converter"= 'io.confluent.connect.avro.AvroConverter', "value.converter.schemas.enable" = 'true', "value.converter.schema.registry.url"= 'http://schema-registry:8081' );
CREATE SOURCE TABLE
Repartition için kullanılır

Örnek
Şöyle yaparız. Burada her algılayıcı ve timestamp için partition oluşturuluyor
# Step 1 CREATE STREAM MyStream ( sensorId VARCHAR KEY, timestamp VARCHAR, value DECIMAL(19,5) ) WITH ( KAFKA_TOPIC = '<x>-telemetry', VALUE_FORMAT = 'JSON' ); # Step 2 CREATE STREAM MyStreamRepartitioned WITH (key_format='json') AS SELECT STRUCT(sensorId:=sensorId, timestamp:=timestamp) AS myStruct, VALUE from MyStream PARTITION BY STRUCT(sensorId:=sensorId, timestamp:=timestamp); # Step 3 CREATE SOURCE TABLE RepartitionedTable (myStruct struct<sensorId VARCHAR, timestamp VARCHAR> PRIMARY KEY, value VARCHAR ) WITH ( KAFKA_TOPIC='<abc>REPARTITIONED', VALUE_FORMAT='json', KEY_FORMAT='json');
Açıklaması şöyle
Note the <abc>REPARTITIONED topic name. This topic name is dynamically created by KSQL DB for the repartitioned stream in step 2.
It is visible in the list of topics in your Confluent cloud environment, so you can take it from there.

Now you can query according to the timestamp field too. Note that the query extracts the values from the JSON serving as the primary key in our source table:
Şöyle yaparız
SELECT EXTRACTJSONFIELD(myStruct -> sensorId, '$.sensorId') AS sensor, myStruct -> timestamp as time, VALUE as val FROM RepartitionedTable WHERE EXTRACTJSONFIELD(myStruct -> sensorId, '$.sensorId') = '127' AND EXTRACTJSONFIELD(myStruct -> timestamp as time) >= '12:00' EMIT CHANGES;

Docker Compose ve Kafka ksqlDB

Giriş
Image olarak 
confluentinc/ksqldb-server
confluentinc/ksqldb-cli
kullanılır

Örnek
Şöyle yaparız
version: '2'

services:
  zookeeper:
    image: confluentinc/cp-zookeeper:7.0.1
    hostname: zookeeper
    container_name: zookeeper
    ports:
      - "2181:2181"
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000

  broker:
    image: confluentinc/cp-kafka:7.0.1
    hostname: broker
    container_name: broker
    depends_on:
      - zookeeper
    ports:
      - "29092:29092"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181'
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://broker:9092,PLAINTEXT_HOST://localhost:29092
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1

  ksqldb-server:
    image: confluentinc/ksqldb-server:0.25.1
    hostname: ksqldb-server
    container_name: ksqldb-server
    depends_on:
      - broker
    ports:
      - "8088:8088"
    environment:
      KSQL_LISTENERS: http://0.0.0.0:8088
      KSQL_BOOTSTRAP_SERVERS: broker:9092
      KSQL_KSQL_LOGGING_PROCESSING_STREAM_AUTO_CREATE: "true"
      KSQL_KSQL_LOGGING_PROCESSING_TOPIC_AUTO_CREATE: "true"

  ksqldb-cli:
    image: confluentinc/ksqldb-cli:0.25.1
    container_name: ksqldb-cli
    depends_on:
      - broker
      - ksqldb-server
    entrypoint: /bin/sh
    tty: true

9 Ocak 2023 Pazartesi

Apache Kafka kafka-avro-console-producer komutu

Örnek
Şöyle yaparız
kafka-avro-console-producer 
  --broker-list localhost:9092 
  --topic atm-fraud-accounts-topic 
  --property value.schema=$(cat src/main/avro/Account.avsc | tr -d '\040\011\012\015') 
  --property schema.registry.url=http://localhost:8081 
  < test-data/accounts.txt


3 Ocak 2023 Salı

Apache Kafka Connect Developer Guide

Giriş
İki tane kavram var
1. Connector
2. Task
Açıklaması şöyle
To copy data between Kafka and another system, users instantiate Kafka Connectors for the systems they want to pull data from or push data to. Connectors come in two flavors: SourceConnectors, which import data from another system, and SinkConnectors, which export data to another system. For example, JDBCSourceConnector would import a relational database into Kafka, and HDFSSinkConnector would export the contents of a Kafka topic to HDFS files.

Implementations of the Connector class do not perform data copying themselves: their configuration describes the set of data to be copied, and the Connector is responsible for breaking that job into a set of Tasks that can be distributed to Kafka Connect workers. Tasks also come in two corresponding flavors: SourceTask and SinkTask. Optionally, the implementation of the Connector class can monitor the data changes of external systems and request task reconfiguration.

26 Aralık 2022 Pazartesi

Docker Compose ve Confluent Schema Registry

Image olarak şunlar kullanılır
confluentinc/cp-zookeeper:7.2.1
confluentinc/cp-kafka:7.2.1
confluentinc/cp-schema-registry:7.2.1
confluentinc/cp-enterprise-control-center:7.2.1

cp-server veya cp-kafka
Kafka broker

cp-schema-registry
Schema Registry sunucusu

cp-enterprise-control-center
Açıklaması şöyle
Confluent Control Center

The Confluent Control Center is a web based tool for monitoring the health of the cluster and observing the metrics exported from the broker, as well as metrics gathered from the application consumers and producers. 
Bununla schema yaratma ve yönetme işleri görsel olarak yapılabilir.  http://localhost:9021 adresine gitmek gerekir.

Örnek
Şöyle yaparız
version: "3"

services:
  zookeeper:
    image: confluentinc/cp-zookeeper:5.4.0
    hostname: zookeeper
    container_name: zookeeper
    ports:
      - "2181:2181"
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000

  broker:
    image: confluentinc/cp-server:5.4.0
    hostname: broker
    container_name: broker
    depends_on:
      - zookeeper
    ports:
      - "9092:9092"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181"
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://broker:29092,PLAINTEXT_HOST://localhost:9092
      KAFKA_METRIC_REPORTERS: io.confluent.metrics.reporter.ConfluentMetricsReporter
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
      KAFKA_CONFLUENT_LICENSE_TOPIC_REPLICATION_FACTOR: 1
      CONFLUENT_METRICS_REPORTER_BOOTSTRAP_SERVERS: broker:29092
      CONFLUENT_METRICS_REPORTER_ZOOKEEPER_CONNECT: zookeeper:2181
      CONFLUENT_METRICS_REPORTER_TOPIC_REPLICAS: 1
      CONFLUENT_METRICS_ENABLE: "true"
      CONFLUENT_SUPPORT_CUSTOMER_ID: "anonymous"

  kafka-tools:
    image: confluentinc/cp-kafka:5.4.0
    hostname: kafka-tools
    container_name: kafka-tools
    command: ["tail", "-f", "/dev/null"]
    network_mode: "host"

  schema-registry:
    image: confluentinc/cp-schema-registry:5.4.0
    hostname: schema-registry
    container_name: schema-registry
    depends_on:
      - zookeeper
      - broker
    ports:
      - "8081:8081"
    environment:
      SCHEMA_REGISTRY_HOST_NAME: schema-registry
      SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: "zookeeper:2181"

  control-center:
    image: confluentinc/cp-enterprise-control-center:5.4.0
    hostname: control-center
    container_name: control-center
    depends_on:
      - zookeeper
      - broker
      - schema-registry
    ports:
      - "9021:9021"
    environment:
      CONTROL_CENTER_BOOTSTRAP_SERVERS: 'broker:29092'
      CONTROL_CENTER_ZOOKEEPER_CONNECT: 'zookeeper:2181'
      CONTROL_CENTER_SCHEMA_REGISTRY_URL: "http://schema-registry:8081"
      CONTROL_CENTER_REPLICATION_FACTOR: 1
      CONTROL_CENTER_INTERNAL_TOPICS_PARTITIONS: 1
      CONTROL_CENTER_MONITORING_INTERCEPTOR_TOPIC_PARTITIONS: 1
      CONFLUENT_METRICS_TOPIC_REPLICATION: 1
      PORT: 9021
Örnek
Şöyle yaparız
services:
    zookeeper:
        image: confluentinc/cp-zookeeper:7.2.1
        hostname: zookeeper
        container_name: zookeeper
        ports:
            - "2181:2181"
        environment:
            ZOOKEEPER_CLIENT_PORT: 2181
            ZOOKEEPER_TICK_TIME: 2000

    kafka:
        image: confluentinc/cp-kafka:7.2.1
        hostname: kafka
        container_name: kafka
        depends_on:
            - zookeeper
        ports:
            - "9092:9092"
        environment:
            KAFKA_BROKER_ID: 1
            KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181"
            KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
            KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092
            KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
            KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
            KAFKA_CONFLUENT_LICENSE_TOPIC_REPLICATION_FACTOR: 1
            KAFKA_CONFLUENT_BALANCER_TOPIC_REPLICATION_FACTOR: 1
            KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
            KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
            KAFKA_CONFLUENT_SCHEMA_REGISTRY_URL: http://schema-registry:8081

    schema-registry:
        image: confluentinc/cp-schema-registry:7.2.1
        hostname: schema-registry
        container_name: schema-registry
        depends_on:
            - zookeeper
            - kafka
        ports:
            - "8081:8081"
        environment:
            SCHEMA_REGISTRY_HOST_NAME: schema-registry
            SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: 'kafka:29092'
            SCHEMA_REGISTRY_LISTENERS: http://0.0.0.0:8081

    control-center:
        image: confluentinc/cp-enterprise-control-center:7.2.1
        hostname: control-center
        container_name: control-center
        depends_on:
            - kafka
            - schema-registry
        ports:
            - "9021:9021"
        environment:
            CONTROL_CENTER_BOOTSTRAP_SERVERS: 'kafka:29092'
            CONTROL_CENTER_SCHEMA_REGISTRY_URL: "http://schema-registry:8081"
            CONTROL_CENTER_REPLICATION_FACTOR: 1
            CONTROL_CENTER_INTERNAL_TOPICS_PARTITIONS: 1
            CONTROL_CENTER_MONITORING_INTERCEPTOR_TOPIC_PARTITIONS: 1
            CONFLUENT_METRICS_TOPIC_REPLICATION: 1
            PORT: 9021


21 Ekim 2022 Cuma

Apache Kafka Rebalancing Protocol

Rebalance Nedir?
Açıklaması şöyle
But you can ask, what will happen when we add a new consumer to the existing and running group? The process of switching ownership from one consumer to another is called rebalance. It is a small break from receiving messages for the whole group. The idea of choosing which partition goes to which consumer is based on the coordinator election problem.
Rebalance işleminde "stop the world" yaklaşımı benimseniyor. Açıklaması şöyle
There is, however, a drawback of the default rebalancing approach. Each consumer gives up its entire assignment of topic partitions, and no processing takes place until the topic partitions are reassigned — sometimes referred to as a “stop-the-world” rebalance. To compound the issue, depending on the instance of the ConsumerPartitionAssignor used, consumers are simply reassigned the same topic partitions that they owned prior to the rebalance, the net effect being that there is no need to pause work on those partitions. This implementation of the rebalance protocol is called eager rebalancing because it prioritizes the importance of ensuring that no consumers in the same group claim ownership over the same topic partitions. 
Rebalance Sıkıntıları
Açıklaması şöyle
Kafka tries to rebalance partitions every time rolling new code on each machine. Unsurprisingly, this problem is notorious in Kafka / Kafka’s stream applications world. Here is how the protocol works when rolling updates:

- When we roll out new code, let us say on an instance A, which hosts a stream application, it will close the current running stream application. As the consequence, which will send a “leave group” request to the group coordinator.

- After instance A finishes rolling out a new code, instance A joins again the old consumer group by sending a “join group” request.

- Kafka membership protocol will resolve again and divide partitions again for each node. Instance A might receive a different partition, which needs to rebuild again the state store from the changelog topic respected to the assigned partition.

- Even worse, when rebalancing is happening, the whole consumer group will stop-the-world, all operations, including the cluster-internal one, cannot work normally and wait for rebalancing to finish. After that, some consumers will stop and restore the original state from the changelog topics. If changelog topics are huge, the service could be slowed down/unresponsive for a long time before coming back to the normal state.
Çözümler şöyle
1. Optimize consumer configurations
2. Optimize state store configurations
3. Change to Static Membership
4. Maintain active and inactive clusters
5. Incremental Cooperative Rebalancing
6. Moving from stateful consumers to stateless consumers
7. Upgrading to Kafka’s stream 2.6
8. Accept downtime

1. Optimize consumer configurations
Burada bir yazı var
Burada bir yazı daha var
session.timeout.ms alanı kullanılarak consumer için timeout atanabiliyor. Açıklaması şöyle. Yani yeni sürüm çalışmaya başlarken heartbeat süresini artırdığımız için Kafka farkına varmıyor
Default value: 3000 (3 seconds)

Timeout for the heartbeat thread. Prevent unnecessary rebalancing due to network issues or the application doing a GC that causes heartbeats not to be sent to the broker coordinator.

It’s also good to understand the differences between session timeout and polling timeout. See https://stackoverflow.com/questions/39730126/difference-between-session-timeout-ms-and-max-poll-interval-ms-for-kafka-0-10

5. Incremental Cooperative Rebalancing Nedir?
Açıklaması şöyle. "stop the world" yaklaşımı yerine group leader'in değişen consumer'ları yayınlaması bekleniyor. Böylece consumer durmak zorunda kalmıyor.
First introduced to Kafka Connect in Apache Kafka 2.3, incremental cooperative rebalancing has now been implemented for the consumer group protocol too. With the cooperative approach, consumers don’t automatically give up ownership of all topic partitions at the start of the rebalance. Instead, all members encode their current assignment and forward the information to the group leader. The group leader then determines which partitions need to change ownership — instead of producing an entirely new assignment from scratch. Now a second rebalance is issued, but this time, only the topic partitions that need to change ownership are involved. It could be revoking topic partitions that are no longer assigned or adding new topic partitions. For the topic partitions that are in both the new and old assignment, nothing has to change, which means continued processing for topic partitions that aren’t moving. The bottom line is that eliminating the "stop-the-world" approach to rebalancing and only stopping the topic partitions involved means less costly rebalances, thus reducing the total time to complete the rebalance. Even long rebalances are less painful now that processing can continue throughout them. 

This positive change in rebalancing is made possible by using the CooperativeStickyAssignor. The CooperativeStickyAssignor makes the trade-off of having a second rebalance but with the benefit of a faster return to normal operations. To enable this new rebalance protocol, you need to set the partition.assignment.strategy to use the new CooperativeStickyAssignor. Also, note that this change is entirely on the client-side. To take advantage of the new rebalance protocol, you only need to update your client version. If you’re a Kafka Streams user, there is even better news. Kafka Streams enables the cooperative rebalance protocol by default, so there is nothing else to do.

26 Aralık 2021 Pazar

Kafka Producer API

Giriş
Açıklaması şöyle.
The Producer API allows an application to publish a stream of records to one or more Kafka topics.
Java örneklerini Kafka Producer API yazısına taşıdım

Idempotent Producer Configuration
Açıklaması şöyle
By configuring the Producer to be idempotent, each Producer is assigned a unique Id (PID) and each message is given a monotonically increasing sequence number. The broker tracks the PID + sequence number combination for each partition, rejecting any duplicate write requests it receives.
enable.idempotence Alanı
Açıklaması şöyle. Yani bu alana ilave olarak acks = all olmalı 
enable.idempotence determines whether the producer may write duplicates of a retried message to the topic partition when a retryable error is thrown. Examples of such transient errors include leader not available and not enough replicas exceptions. It only applies if the retries configuration is greater than 0 (which it is by default).

To ensure the idempotent behaviour then the Producer configuration acks must also be set to all. The leader will wait until at least the minimum required number of in-sync replica partitions have acknowledged receipt of the message before itself acknowledging the message. The minimum number is based on the configuration parameter min.insync.replicas.

By configuring acks equal to all it favours durability and deduplicating messages over performance. The performance hit is usually considered insignificant.
enable.idempotence İçin Timeout
Açıklaması şöyle
The recommendation is to leave the retries as the default (the maximum integer value) and limit retries by time, using the Producer configuration delivery.timeout.ms (defaulted to 2 minutes).
Yani önerilen ayarlar şekle şöyle



KafkaProducer Sınıfı Açısından acks Nedir?
Açıklaması şöyle
For data durability, the KafkaProducer has the configuration setting acks. The acks configuration specifies how many acknowledgments the producer receives to consider a record delivered to the broker. The options to choose from are:

- none: The producer considers the records successfully delivered once it sends the records to the broker. This is basically “fire and forget.”
- one: The producer waits for the lead broker to acknowledge that it has written the record to its log.
- all: The producer waits for an acknowledgment from the lead broker and from the following brokers that they have successfully written the record to their logs.

As you can see, there is a trade-off to make here — and that’s by design because different applications have different requirements. You can opt for higher throughput with a chance for data loss, or you may prefer a very high data durability guarantee at the expense of lower throughput. 
acks=all Durumu
Açıklaması şöyle. min.insync.replicas değerini de atamak gerekir. Bundan sonra NotEnoughReplicasException, NotEnoughReplicasAfterAppendException gibi exception'lar alınabilir.
If you produce records with acks set to all to a cluster of three Kafka brokers, it means that, under ideal conditions, Kafka contains three replicas of your data; one for the lead broker and one each for two followers. When the logs of each of these replicas all have the same record offsets, they are considered to be in sync. In other words, these in-sync replicas have the same content for a given topic partition. 

But there’s some subtlety to using the acks=all configuration. What it doesn’t specify is how many replicas need to be in sync. The lead broker will always be in sync with itself. But, you could have a situation where the two following brokers can’t keep up due to network partitions, record load, etc. So, when a producer has a successful send, the actual number of acknowledgments could have come from only one broker! If the two followers are not in sync, the producer still receives the required number of acks, but it’s only the leader in this case.

By setting acks=all, you are placing a premium on the durability of your data. So, if the replicas aren’t keeping up, it stands to reason that you want to raise an exception for new records until the replicas are caught up. In a nutshell, having only one in sync replica follows the "letter of the law" but not the "spirit of the law." What we need is a guarantee when using the acks=all setting. A successful send involves at least a majority of the available in sync brokers. There just so happens to be one such configuration: min.insync.replicas. The min.insync.replicas configuration enforces the number of replicas that must be in sync for the write to proceed. Note that the min.insync.replicas configuration is set at the broker or topic level and is not a producer configuration. The default value for min.insync.replicas is one. So, to avoid the scenario described above, in a three-broker cluster, you’d want to increase the value to two. 

ProducerRecord Sınıfı
Açıklaması şöyle. Sticky Partitioner kullanma imkanı var. Örnek ver
Kafka uses partitions to increase throughput and spread a load of messages to all brokers in a cluster. Kafka records are in a key/value format, where the keys can be null. Kafka producers don’t immediately send records, instead, they place them into partition-specific batches to be sent later. Batches are an effective means of increasing network utilization. There are three ways the partitioner determines into which partition the records should be written. The partition can be explicitly provided in the ProducerRecord object via the overloaded ProducerRecord constructor. In this case, the producer always uses this partition. If no partition is provided, and the ProducerRecord has a key, the producer takes the hash of the key modulo as the number of partitions. The resulting number from that calculation is the partition that the producer will use. Previously, if there was no key and no partition present in the ProducerRecord, Kafka would use a round-robin approach to assign messages across partitions. The producer would assign the first record in the batch to partition zero, the second to partition one, and so on, until the end of the partitions. The producer would then start over with partition zero and repeat the entire process for all remaining records. 

The round-robin approach works well for even distribution of records across partitions. But there’s one drawback. Due to this "fair" round-robin approach, you can end up sending multiple sparsely populated batches. It’s more efficient to send fewer batches with more records in each batch. Fewer batches mean less queuing of produce requests, hence less load on the brokers.

24 Ekim 2021 Pazar

Apache Kafka Partition ve Global Event Order/Message Order

1. Global Event Order/Message Order
Normalde Kafka ile Global Event Order/Message Order korunamıyor.

Tek Consumer Olsaydı
Eğer tek bir consumer olsaydı mesajların sırası kaybolmazdı, ancak genellikle mesajlar partition şeklinde dağıtıldığı ve bunları işlemek için bir "Consumer Group" kullanıldığı için mesajların sırası kaybolabilir. Şeklen şöyle



Yani Topic dağıtıldığı için "Global Event Order" kaybedilir. Ancak partition 'lar kendi içinde sıralamayı korurlar. Açıklaması şöyle. 
A partition is an actual storage unit of Kafka messages which can be assumed as a Kafka message queue. The number of partitions per topic are configurable while creating it. Messages in a partition are segregated into multiple segments to ease finding a message by its offset. The default size of a segment is very high, i.e. 1GB, which can be configured.
Çözüm
1. Tek bir iş ile alakalı mesajlar aynı partition 'a konulur. Partition içinde sıralama korunduğu için sorun olmaz. Şeklen şöyle

2. Message Priority
Normalde Kafka ile Message Priority sağlanamıyor.

Çözüm
1. Her öncelik için kuyruk oluşturmak
Açıklaması burada

2. The Resequencer Pattern:
Açıklaması burada

3. The Bucket Priority Pattern
Açıklaması burada





3 Mart 2021 Çarşamba

Apache Kafka Streams API

Giriş 
Açıklaması şöyle
Kafka Streams is a client library that uses Kafka topics as sources and sinks for the data processing pipeline.
Bir başka açıklama şöyle
Kafka Streams is a simple Java library that enables streaming application development within the Kafka framework.
Açıklaması şöyle
Kafka Streams is a JVM based library for performing streaming transformations on data sourced from Kafka. It is a very good default choice for data processing backed by Kafka due to its simple deployment model, horizontal scalability, resilience to failures and straightforward well documented public API.

The API lets you read data from Kafka then perform a number of transformations on the data including filtering, mapping, aggregation and joining data from multiple topics. The API supports both stateless and stateful transformations. Stateful transformations back up their state into changelog topics in Kafka and cache values local to the processing nodes, typically using RocksDB.
Streams API kullanmak için iki yöntem var. Bunlar şöyle
There are two approaches to writing a Kafka Streams application:
- The high level DSL,
- And the low level Processor API.
Java örneklerini Kafka Streams API yazısına taşıdım

Exactly once semantic support
Açıklaması şöyle
Exactly once semantic support was added to Kafka Streams in the 0.11.0 Kafka release. Enabling exactly once is a simple configuration change setting the streaming configuration parameter processing.guaranteeto exactly_once(the default is at_least_once).

A typical workload for a Kafka Streams application is to read data from one or more partitions, perform some transformations on the data, update a state store (such as a count), then write the result to an output topic. When exactly once semantics is enabled, Kafka Streams atomically updates consumer offsets, local state stores, state store changelog topics and production to output topics all together. If any one of these steps fail, all of the changes are rolled back.

Side effects
The Kafka Streams API lets you perform any action when processing input data, for instance you can write the data directly to a database, or fire off an email. These “side effect” operations are explicitly not covered by the exactly once guarantee. If a stream job fails after processing data, but just prior to writing it back to Kafka, it will be reprocessed the next time the Kafka Streams worker is restarted re-running any side-effect operations such as emailing a customer.

It is best to keep your Kafka Streams transform “pure” with no side effects beyond updating state stores and writing back to Kafka. This way your application will be more resilient (it won’t fail if it can’t contact the email server) and will shorten the length of transactions.

Side effects can then be performed via Kafka Connect Sink connectors or custom consumers.
Enterprise Messaging vs Event Streaming
Enterprise Messaging ve Event Streaming şu açılardan farklıdır
1. Message processing style
2. Message consumption style
3. Access to message history
4. Fine-grained subscription to messages
5. Message delivery guarantees
1. Message Processing Style
Enterprise Messaging uygulamaları her mesajı bireysel olarak el alır. Streaming uygulamaları mesajları bütünsel olarak ele alabilir.

Örnek
Farkları gösteren bir örnek şöyle
For example, if the reading is less than 20, the thermostat turns on the heater. It repeats the same logic the next time a message comes. Even though this is unnecessary, that is how the messaging works.

For example, the thermostat can calculate the average reading over the last minute and decides whether to turn on the heater. The average seems a realistic measure here.
2. Message consumption style
Enterprise Messaging uygulamaları mesajları siler, Streaming uygulamaları mesajları silmez. 

3. Access to message history
Message consumption style maddesinin sonucu olarak mesaj tarihçesi de oluşur veya oluşmaz

4. Fine-grained subscription to messages
Enterprise Messaging uygulamaları mesajlara filtreler koyabilir, Streaming uygulamaları bir partitiondaki tüm mesajları alır ve  kendisi filtreler.

5. Message delivery guarantees
Bazı seviyeler şöyle
- At least once delivery
-Exactly once delivery
- Transactionally coordinated delivery
Açıklaması şöyle
Messaging systems are good at handling exactly once and transactionally coordinated delivery use cases while streaming is good at handling at least once delivery scenarios.
Stream Analytics
Aslında tüm bu farkların söylemeye çalıştığı şey Stream Analytics. Açıklaması şöyle
But, capturing the data streams is only one part of the challenge. Some data processing has to be performed simultaneously with the incoming data to be able to use the results promptly for decision-making. For example, a selection of products in a shopping cart system can be the trigger for a recommendation system to be executed in parallel. This type of requirement creates another building block in the streaming architecture – called Stream Analytics.

Sometimes a single event from the data stream is enough to trigger a predefined business logic. However, it is often necessary to be able to recognize connections between different events in order to run a high-level business process generating real business value. Such a connection can be established between time-shifted similar events by accumulating them over a given period of time. For example, short-term increased demand for a certain product in an online shop system could trigger the start of an additional production line. In other cases, it may be necessary to correlate certain events of different types and merge the data to trigger the corresponding business process. These methods are also known as Windowing and  Joining.
Stream Analytics için iki temel yöntem var. Windowing ve Joining. Şeklen şöyle


Kafka Streams ve CQRS
Kafka Stream'lerini Event Source olarak kullanmak mümkün.

11 Şubat 2021 Perşembe

Apache Kafka ksqlDB

Pull Queries
Açıklaması şöyle. Pull Queries normal SQL cümlesi gibidir tek seferlik sonuç döndürür.
A pull query is a form of query issued by a client that retrieves a result as of “now”, like a query against a traditional RDBMS. Pull queries enable you to fetch the current state of a materialized view. Because materialized views are incrementally updated as new events arrive.
kSQL ile Kafka Topic'ten farklı olarak update işlemi yapılabilir. Açıklaması şöyle
Kafka does not allow the events to be updated, so we cannot mark the top event as failed or associate any metadata with it.
Removing the event and queueing it back (at the end) doesn’t work either, as this will break the ordering constraints — event #3 will end up before event #1,...
kSQL ile işlem yapmak kodla çalışmaktan daha kolay. 

kSQL CLI

WINDOW TUMBLING - Aggregation
Örnek
Şöyle yaparız
CREATE TABLE anomaly_detection AS
  SELECT temperature_spike_id, COUNT(*) AS total_spikes,
  AVG(temperature) AS avg_temperature
  FROM sensor_data
  WINDOW TUMBLING (SIZE 1 HOUR)
  GROUP BY temperature_spike_id
  EMIT CHANGES;
Açıklaması şöyle
A one-hour sliding window continuously aggregates the temperature spikes from sensors.
Örnek
Şöyle yaparız
SELECT symbol, SUM(shares) FROM stock_txn_stream
WINDOW TUMBLING(SIZE 10 SECONDS)
GROUP BY symboll;
Bunu kodla yapsak şöyle olur
KStream<String,StockTransaction> stream = ...;

Aggregator<String,StockTransaction,Integer> aggregator =
 (k,v,i) -> v.getShares() + i;

stream.groupByKey()
  .windowedBy(TimeWindows.of(10_000))
  .aggregate(()->0,aggregator,
           Materialized.<String,Integer,WindowStore<Bytes,byte[]>> as("SharesPerPeriod")
           .withKeySerde(stringSerde)
           .withValueSerde(Serdes.Integer()))
  .toStream()
  .peek((k,v) -> ...);
PRINT
Şöyle yaparız
PRINT 'pg_dev.public.mini_ticker' FROM BEGINNING;
SHOW QUERIES
Örnek
Şöyle yaparız
ksql> SHOW QUERIES;

 Query ID              | Query Type | Status    | Sink Name      | Sink Kafka Topic | Query String
--------------------------------------------------------------------------------------------------------------------------
 CSAS_SHIPPED_ORDERS_0 | PERSISTENT | RUNNING:1 | SHIPPED_ORDERS | SHIPPED_ORDERS   | CREATE STREAM SHIPPED_ORDERS WITH 
 ...
Şöyle yaparız
ksql> EXPLAIN CSAS_SHIPPED_ORDERS_0;
SHOW TOPICS
Örnek
Şöyle yaparız
ksql> show topics;
Kafka Topic                   | Partitions | Partition Replicas
-----------------------------------------------------------------
dbserver1                     | 1          | 1
dbserver1.inventory.customers | 1          | 1
dbserver1.inventory.orders    | 1          | 1
dbserver1.inventory.products  | 1          | 1
default_ksql_processing_log   | 1          | 1
my_connect_configs            | 1          | 1
my_connect_offsets            | 25         | 1
my_connect_statuses           | 5          | 1
schema-changes.inventory      | 1          | 1
-----------------------------------------------------------------
Örnek
Şöyle yaparız
> docker exec -it ksqldb ksql http://localhost:8088


> show topics;
Kafka Topic                    | Partitions | Partition Replicas
------------------------------------------------------------------
crypto-ksqlksql_processing_log | 1          | 1
docker-connect-configs         | 1          | 1
docker-connect-offsets         | 25         | 1
docker-connect-status          | 5          | 1
------------------------------------------------------------------