kafka與zookeeper的關系
kafka集群只得就是Broker集群,producer和consumer 對kafka來說都是客戶端。
zk在kafka中的作用:
zk只管理broker、consumer,他們在zk上都真實的存了具體數據;Producer端直接連接broker,不在zk上存任何數據,只注冊監聽,監聽broker和topic信息。
只有在zk的節點上存了數據才算被zk管理,只注冊監聽不算被zk管理。
1)Producer端直接連接broker.list列表,從列表中返回TopicMetadataResponse,該Metadata包含Topic下每個partition leader建立socket連接並發送消息.
2)Broker端使用zookeeper用來注冊broker和topic信息,以及監控partition leader存活性.
3)Consumer端使用zookeeper用來注冊consumer信息,其中包括consumer消費的partition列表、消費者的offset等,同時也用來監聽 broker列表,並和partition leader建立socket連接,並獲取消息。
Zookeeper作用:管理broker、consumer
創建Broker后,向zookeeper注冊新的broker信息,實現在服務器正常運行下的水平拓展。具體的,通過注冊watcher,獲取partition的信息。
Topic的注冊,zookeeper會維護topic與broker的關系,通/brokers/topics/topic.name節點來記錄。
Producer向zookeeper中注冊watcher,了解topic的partition的消息,以動態了解運行情況,實現負載均衡。Zookeepr不管理producer,只是能夠提供當前broker的相關信息。
Consumer可以使用group形式消費kafka中的數據。所有的group將以輪詢的方式消費broker中的數據,具體的按照啟動的順序。Zookeeper會給每個consumer group一個ID,即同一份數據可以被不同的用戶ID多次消費。因此這就是單播與多播的實現。以單個消費者還是以組別的方式去消費數據,由用戶自己去定義。Zookeeper管理consumer的offset跟蹤當前消費的offset。
kafka使用ZooKeeper用於管理、協調代理。每個Kafka代理通過Zookeeper協調其他Kafka代理。
當Kafka系統中新增了代理或某個代理失效時,Zookeeper服務將通知生產者和消費者。生產者與消費者據此開始與其他代理協調工作。
Zookeeper在Kakfa中扮演的角色:Kafka將元數據信息保存在Zookeeper中,但是發送給Topic本身的數據是不會發到Zk上的
kafka使用zookeeper來實現動態的集群擴展,不需要更改客戶端(producer和consumer)的配置。broker會在zookeeper注冊並保持相關的元數據(topic,partition信息等)更新。
而客戶端會在zookeeper上注冊相關的watcher。一旦zookeeper發生變化,客戶端能及時感知並作出相應調整。這樣就保證了添加或去除broker時,各broker間仍能自動實現負載均衡。這里的客戶端指的是Kafka的消息生產端(Producer)和消息消費端(Consumer)
Broker端使用zookeeper來注冊broker信息,以及監測partitionleader存活性.
Consumer端使用zookeeper用來注冊consumer信息,其中包括consumer消費的partition列表等,同時也用來發現broker列表,並和partitionleader建立socket連接,並獲取消息.
Zookeer和Producer沒有建立關系,只和Brokers、Consumers建立關系以實現負載均衡,即同一個ConsumerGroup中的Consumers可以實現負載均衡(因為Producer是瞬態的,可以發送后關閉,無需直接等待)
1、Broker注冊
Broker是分布式部署並且相互之間相互獨立,但是需要有一個注冊系統能夠將整個集群中的Broker管理起來,此時就使用到了Zookeeper。在Zookeeper上會有一個專門用來進行Broker服務器列表記錄的節點:
/brokers/ids
每個Broker在啟動時,都會到Zookeeper上進行注冊,即到/brokers/ids下創建屬於自己的節點,如/brokers/ids/[0...N]。
Kafka使用了全局唯一的數字來指代每個Broker服務器,不同的Broker必須使用不同的Broker ID進行注冊,創建完節點后,每個Broker就會將自己的IP地址和端口信息記錄到該節點中去。其中,Broker創建的節點類型是臨時節點,一旦Broker宕機,則對應的臨時節點也會被自動刪除。
2、Topic注冊
在Kafka中,同一個Topic的消息會被分成多個分區並將其分布在多個Broker上,這些分區信息及與Broker的對應關系也都是由Zookeeper在維護,由專門的節點來記錄,如:
/borkers/topics
Kafka中每個Topic都會以/brokers/topics/[topic]的形式被記錄,如/brokers/topics/login和/brokers/topics/search等。Broker服務器啟動后,會到對應Topic節點(/brokers/topics)上注冊自己的Broker ID並寫入針對該Topic的分區總數,如/brokers/topics/login/3->2,這個節點表示Broker ID為3的一個Broker服務器,對於"login"這個Topic的消息,提供了2個分區進行消息存儲,同樣,這個分區節點也是臨時節點。
3、生產者負載均衡
由於同一個Topic消息會被分區並將其分布在多個Broker上,因此,生產者需要將消息合理地發送到這些分布式的Broker上,那么如何實現生產者的負載均衡,Kafka支持傳統的四層負載均衡,也支持Zookeeper方式實現負載均衡。
(1) 四層負載均衡,根據生產者的IP地址和端口來為其確定一個相關聯的Broker。通常,一個生產者只會對應單個Broker,然后該生產者產生的消息都發往該Broker。這種方式邏輯簡單,每個生產者不需要同其他系統建立額外的TCP連接,只需要和Broker維護單個TCP連接即可。但是,其無法做到真正的負載均衡,因為實際系統中的每個生產者產生的消息量及每個Broker的消息存儲量都是不一樣的,如果有些生產者產生的消息遠多於其他生產者的話,那么會導致不同的Broker接收到的消息總數差異巨大,同時,生產者也無法實時感知到Broker的新增和刪除。
(2) 使用Zookeeper進行負載均衡,由於每個Broker啟動時,都會完成Broker注冊過程,生產者會通過該節點的變化來動態地感知到Broker服務器列表的變更,這樣就可以實現動態的負載均衡機制。
4、消費者負載均衡
與生產者類似,Kafka中的消費者同樣需要進行負載均衡來實現多個消費者合理地從對應的Broker服務器上接收消息,每個消費者分組包含若干消費者,每條消息都只會發送給分組中的一個消費者,不同的消費者分組消費自己特定的Topic下面的消息,互不干擾。
5、分區 與 消費者 的關系
消費組 (Consumer Group):
consumer group 下有多個 Consumer(消費者)。
對於每個消費者組 (Consumer Group),Kafka都會為其分配一個全局唯一的Group ID,Group 內部的所有消費者共享該 ID。訂閱的topic下的每個分區只能分配給某個 group 下的一個consumer(當然該分區還可以被分配給其他group)。
同時,Kafka為每個消費者分配一個Consumer ID,通常采用"Hostname:UUID"形式表示。
在Kafka中,規定了每個消息分區 只能被同組的一個消費者進行消費,因此,需要在 Zookeeper 上記錄 消息分區 與 Consumer 之間的關系,每個消費者一旦確定了對一個消息分區的消費權力,需要將其Consumer ID 寫入到 Zookeeper 對應消息分區的臨時節點上,例如:
/consumers/[group_id]/owners/[topic]/[broker_id-partition_id]
其中,[broker_id-partition_id]就是一個 消息分區 的標識,節點內容就是該 消息分區 上 消費者的Consumer ID。
6、消息 消費進度Offset 記錄
在消費者對指定消息分區進行消息消費的過程中,需要定時地將分區消息的消費進度Offset記錄到Zookeeper上,以便在該消費者進行重啟或者其他消費者重新接管該消息分區的消息消費后,能夠從之前的進度開始繼續進行消息消費。Offset在Zookeeper中由一個專門節點進行記錄,其節點路徑為:
/consumers/[group_id]/offsets/[topic]/[broker_id-partition_id]
節點內容就是Offset的值。
7、消費者注冊
消費者服務器在初始化啟動時加入消費者分組的步驟如下
注冊到消費者分組。每個消費者服務器啟動時,都會到Zookeeper的指定節點下創建一個屬於自己的消費者節點,例如/consumers/[group_id]/ids/[consumer_id],完成節點創建后,消費者就會將自己訂閱的Topic信息寫入該臨時節點。
對 消費者分組 中的 消費者 的變化注冊監聽。每個 消費者 都需要關注所屬 消費者分組 中其他消費者服務器的變化情況,即對/consumers/[group_id]/ids節點注冊子節點變化的Watcher監聽,一旦發現消費者新增或減少,就觸發消費者的負載均衡。
對Broker服務器變化注冊監聽。消費者需要對/broker/ids/[0-N]中的節點進行監聽,如果發現Broker服務器列表發生變化,那么就根據具體情況來決定是否需要進行消費者負載均衡。
進行消費者負載均衡。為了讓同一個Topic下不同分區的消息盡量均衡地被多個 消費者 消費而進行 消費者 與 消息 分區分配的過程,通常,對於一個消費者分組,如果組內的消費者服務器發生變更或Broker服務器發生變更,會發出消費者負載均衡。
