Ana içeriğe geç

Kafkaya Giriş#

Kafka açık kaynak kodlu dağıtık event streamig platformudur. Publish/subscribe yapısında bir mesajlaşma sistemidir. Bu sistemlerde mesaj bir topic’e gönderilir ve cosumer’lar bir veya daha fazla topic’e subscribe olarak mesajları alırlar. Burada akıllı olan consumer’dır ve aldığı mesaj ile ilgili ne yapacağını kendisi bilir.

Bütün uygulamalar veri üretir ve bu verileri işleyerek çıkarım yapar. Büyük veri ile ilgili en büyük zorluk bu verileri toplamak ve analiz etmektir. Bunun sorunları çözmek için de bir mesajlaşma sistemine ihtiyaç duyarız.

Neden Kafka Tercih Edebilirim?#

  • Scalability: Multiple producer kullanılabilir. Down time olmadan kolay scale edilebilir.
  • Reliability: Kafka dağıtık olarak, replikasyon yapılarak ve partition’lara bölünerek kullanılabilir. Aynı anda multiple consumer paralel okuma yapabilir.
  • Durability: Kafka distributed commit log kullanır. Disk based retention vardır. veriler mümkün olduğunca hızlı olarak diske yazılır.
  • High Performance

Use Cases#

Kafka projenizden bir çok amaçla kullanılabilir bunlardan bazıları;

  • Messaging
  • Website Activity Tracing
  • Metrics
  • Log Aggregation
  • Stream Processing
  • Event Sourcing
  • Commit Log

Message Queue ve Publish/Subscribe (Pub/Sub) Messaging System Arasındaki Farklar#

Message broker’lar uygulamalar arasında yazıldıkları dil farketmeksizin belirli bir protokol üzerinden haberleşme ve bilgi alışverişi sağlar. Validate eder, yönlendirir ve belirli alıcılara iletir. Mesajı gönderenin alıcının yerini, aktif/pasif olmasını vs. bilmesine gerek kalmaz.

Pub/sub sistemler ise producer’ların her mesajı istedikleri gibi publish etmelerini sağlar . Publisher ve consumer’lar arasında one-to-many ilişki kurar.

RabbitMQ gibi message queue’larda smart broker-dumb consumer iken Kafka’da dumb broker-smart consumer mantığı vardır.

Temel Bileşenler#

Brokers#

Broker Kafka'ya gönderdiğimiz verilerin saklandığı ve işlendiği topic ve partition'ları tutan sunuculardır. Veriler hard disk'te saklanır. Cluster yapılar birden çok birbiri ile koordine çalışan broker’lardan oluşur. Örnek olarak 1 topic'in 3 partition'ı olsun ve 3 broker olsun. Her broker'a 1 partition düşecek şekilde ayarlanır.

  • 2 broker varken, uygulama 2'sini de bilmek zorunda mıdır?

Evet. Tekini bilirse ve bildiği broker çökerse o zaman diğerinden çalışmaya devam edemez. Ancak uygulama ayağa kalkarken bildiği broker çalışıyorsa ve sonradan kapanırsa uygulama hata almadan diğer broker'dan çalışmaya devam eder. Tam cluster olarak çalışması için tüm kafka brokerlarını bilmesi gerekir.

Topic, Partition, Offset#

Broker’lar içinde topic barındırırlar ve topicler de partition’lardan oluşurlar. Veriyi yazdığımız yer aslında partition’dır. Topicler 1 den fazla partion'a sahip olabilir. Her mesaj farklı partionlara yazılacaktır ve her partion yalnızca kendi içerisinde sıra garantisi verir. Her partition'ın kendi offset değeri vardır ve sürekli artarak değer alırlar.

Kendimiz topiclerimizi uygulama ayağa kalkarken oluşturabiliriz. Bunun dışında consumer tarafından dinlenen topicler "spring.kafka.consumer.properties.allow.auto.create.topics: true" olarak ayarlanarak otomatik olarak oluşturulabilir. Otomatik olarak oluşturulan topicler için broker ayarlarından "KAFKA_NUM_PARTITIONS: 3" enviroment'ı verilerek parititon sayısının ayarlanması sağlanabilir.

Çok partition'lı bir topic varsa, aynı sayıda partition'a sahip DLT'si olmalıdır. Aksi durumda hata alındığı zaman DLT'de partition yok diye hata atıyor ve mesajı yazamıyor.

Kafka terminalinden topic paritition güncelleme örnek:

kafka-topics --bootstrap-server localhost:9092 --alter --topic eventLog --partitions 3

Producer & Message Keys#

Topic’lere veriyi yazarlar. Hangi broker ve partitiona yazacağını bilirler, cluster içerisindeki bir broker’a bağlanması yeterlidir. Broker çökse bile otomatik olarak recover olur. Mesaj anahtarı (message key) belirtilmişse, partition’a yazma işlemi anahtar değerine göre yapılır. Aynı anahtar değerine sahip mesajlar, aynı partition’a yazılır. Kafka partition bazında yazma ve okuma işlemini garanti ettiği için, sıranın önemli olduğu durumlarda kullanılabilir. Mesaj anahtarı belirtilmediği durumlarda partition’lara yükü dengelemek için round robin ile yazacaktır.

Consumer & Consumer Groups#

Topic’lerden veriyi okurlar. Hangi broker’dan okuyacağını bilir, broker çökse bile otomatik recover olur. Ayni Partition içerisindeki mesajları sıralı bir şekilde okur. Birden fazla partition’dan okuyabilir. Her bir consumer, bir consumer group’a aittir. Bir partition’ı bir consumer group içerisinde sadece bir consumer okuyabilir. Yani aynı partition'ı sadece farklı consumer grouplardan okumak mümkündür. Consumer eklendikçe Kafka tanır ve otomatik bölüştürür. Ancak fazla olan varsa pasif olarak bekler. Okuyuculardan biri devre dışı kalırsa, bu pasif olan aktif hale geçer. Farklı consumer grubu eklersek bunlar da aynı partition'dan okuyabilir ve isimleri farklı olduğu için birbirlerine karışmazlar.

  • 2 Consumer, 1 Partition, 1 Topic

Mesajlar sadece 1 consumer'a düşer. Diğer consumer mesajları alamaz.

  • 2 Consumer, 2 Partition, 1 Topic

Her consumer 1 partition'a register olur ve kendi partition'ına düşen mesajları alır.

  • 2 Consumer, 3 Partition, 1 Topic

1 consumer 1 paritition'a, diğer consumer 2 partition'a register olur.

  • 2 Ayrı JVM'den 1'er Consumer, 2 Partition, 1 Topic

Her 1 JVM bir partition'a register olur. Eğer JVM'lerden 1'i kapanırsa, diğer JVM'deki consumer 2 partition'ı da otomatik olarak dinlemeye başlar.

  • Concurreny hem yml'dan hem de KafkaListener üzerinden verilirse KafkaListener'dan verilen geçerli olacaktır.

Neden Partition Oluşturuyoruz?#

  • Producer'ların verilerinin belirli özelliklere göre toplanması (aggregate)
  • Verilerin sıralı bir şekilde toplanması (sorting-event sourcing)
  • Daha hızlı okumak (parallelism)
  • Verileri daha verimli saklamak (efficiency)

Consumer Offsets#

Kafka, consumer offset bilgilerini "__consumeroffsets" topic içerisinde tutar. Consumer, Kafka topic’ten mesajı okur, mesajı işler ve mesajın offset değerini “\_consumeroffsets” topic’ine yazar. Offset bilgilerininin topic’e yazılma işlemi consumer tarafından otomatik yapılır yada programlanabilir. Bir consumer kaybedilse bile, tekrar ayağa kalktığında \_consumer_offsets” içerisinde en son hangi mesajı okuduğu kayıtlı olduğu için kaldığı yerden devam edebilir. Offset bilgilerinin tutulduğu topic ayarları broker tarafından aşağıdaki environment'lar verilerek yapılabilir.

KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 3

KAFKA_OFFSETS_TOPIC_NUM_PARTITIONS: 3

Kafka Broker Discovery#

İlk bölümde, producer ve comsumer’lar için cluster içerisindeki hangi broker’a yazacağını veya hangi broker’dan okuyucağını bildiklerini belirtmiştik. Cluster içerisindeki her Kafka broker aslında bir “Bootstrap Server” dır. Diğer broker, topic ve partition bilgilerini bilir ve bir consumer veya producer kendisine bağlandığında bu bilgileri paylaşır. Bu bilgiler metadata olarak adlandırılır. Yani, bir Kafka broker’a bağlanmak tüm Kafka cluster’ına bağlanmak anlamına gelir.

Zookeeper#

Kafka broker’larını yönetir. Topic partition’ları için broker lider seçiminine yardımcı olur. Yeni bir broker ayağa kalktığında veya düştüğünde, topic oluşturulduğunda veya silindiğinde, Zookeeper Kafka broker’lara bildirim gönderir. Kafka, ayağa kalkmak için Zookeeper’a ihtiyaç duyar. Bu nedenle önce Zookeeper, sonra Kafka broker ayağa kaldırılır. Kural olarak cluster içerisindeki Zookeeper sayısı tek sayı olmalıdır. Bir lider ve takipçileri vardır. Kafka, cluster içerisindeki herhangi bir Zookeeper’a bağlanması yeterlidir. Kafka 2.8.0 versiyonundan sonra kullanım zorunluluğu kalkmıştır.