1.概要
1.1簡介
Apache kafka 是一個分佈式的基於push-subscribe的消息系統,它具備快速、可擴展、可持久化的特點。它現在是Apache旗下的一個開源系統,作爲hadoop生態系統的一部分,被各種商業公司廣泛應用。它的最大的特性就是可以實時的處理大量數據以滿足各種需求場景:比如基於hadoop的批處理系統、低延遲的實時系統、storm/spark流式處理引擎。
1.2特性
高吞吐量、低延遲:kafka每秒可以處理幾十萬條消息,它的延遲最低只有幾毫秒
可擴展性:kafka集羣支持熱擴展
持久性、可靠性:消息被持久化到本地磁盤,並且支持數據備份防止數據丟失
容錯性:允許集羣中節點失敗(若副本數量爲n,則允許n-1個節點失敗)
高併發:支持數千個客戶端同時讀寫
1.3應用場景
1.日誌收集:一個公司可以用Kafka可以收集各種服務的log,通過kafka以統一接口服務的方式開放給各種consumer,例如hadoop、Hbase、Solr等。
2.消息系統:解耦和生產者和消費者、緩存消息等。
3.用戶活動跟蹤:Kafka經常被用來記錄web用戶或者app用戶的各種活動,如瀏覽網頁、搜索、點擊等活動,這些活動信息被各個服務器發佈到kafka的topic中,然後訂閱者通過
4.訂閱這些topic來做實時的監控分析,或者裝載到hadoop、數據倉庫中做離線分析和挖掘。
5.運營指標:Kafka也經常用來記錄運營監控數據。包括收集各種分佈式應用的數據,生產各種操作的集中反饋,比如報警和報告。
6.流式處理:比如spark streaming和storm
7.事件源
2.安裝環境搭建
2.1 zookeeper
kafka的運行依賴於zoopeeker,可以從官網http://www.apache.org/dyn/closer.cgi/zookeeper/下載zoopeeker,筆者當前使用的是zookeeper-3.4.8,下載下來後如下圖所示:
進入config文件夾,看一下有沒有zoo.cfg文件,如果沒有的話,複製一份zoo_sample.cfg重命名爲zoo.cfg,打開將zoo.cfg文件的dataDir的值改成“\zookeeper-3.4.8\data”。
添加系統變量ZOOKEEPER_HOME:K:\Tools\JAVA\zookeeper\zookeeper-3.4.8(指向你zookeeper的安裝目錄下),然後再將";%ZOOKEEPER_HOME%\bin;"添加到Path變量中去。
進入CMD:輸入zkserver運行。
2.2 kafka
下載kafka資源包,官網http://kafka.apache.org/downloads.html,筆者當前使用的是kafka_2.11-0.8.2.2。
進入config文件夾修改server.properties文件,將log.dirs的值改成 “G:\Tools\JAVA\Kafka\kafka_2.11-0.8.2.2\kafka_2.11-0.8.2.2\kafka-logs”(指向你的安裝目錄下)。
然後打開cmd,進入安裝目錄的文件夾下:cd K:\Tools\JAVA\Kafka\kafka_2.11-0.8.2.2\kafka_2.11-0.8.2.2 回車
運行:.\bin\windows\kafka-server-start.bat .\config\server.properties。
如果在你運行時發現以下異常:
Unrecognized VM option 'UseCompressedOops'
Did you mean '(+/-)CheckCompressedOops'?
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
原因可能:你電腦的window是32位
解決辦法:進入bin/windows目錄下,然後打開kafka-run-class.bat文件,找到 -XX:+UseCompressedOops,去掉即可。
2.3 測試
1.開啓zookeeper服務器
zkserver
2.開啓kafaka服務器
.\bin\windows\kafka-server-start.bat .\config\server.properties
3.創建topics
kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test
4.創建Producer:
kafka-console-producer.bat --broker-list localhost:9092 --topic test
5.創建Consumer:
kafka-console-consumer.bat --zookeeper localhost:2181 --topic test
發送者示意圖:
接受者示意圖:
如果你能正常執行得到以上結果,證明環境已經沒問題了.
3.java api
使用java代碼來實現消息分發:首先啓動zookeeper和kafka服務器,並且創建好topics(我這裏創建了一個yzrtopic).然後編寫以下代碼:
發送端:
package yzr;
import java.util.Properties;
import kafka.javaapi.producer.Producer;
import kafka.producer.KeyedMessage;
import kafka.producer.ProducerConfig;
public class porducer {
private final Producer<String, String> producer;
public final static String TOPIC = "yzrtopic";
public porducer(){
Properties props = new Properties();
props.put("metadata.broker.list", "localhost:9092");
//配置value的序列化類
props.put("serializer.class", "kafka.serializer.StringEncoder");
//配置key的序列化類
props.put("key.serializer.class", "kafka.serializer.StringEncoder");
props.put("request.required.acks","-1");
producer = new Producer<String, String>(new ProducerConfig(props));
}
void produce() {
int messageNo = 1;
final int COUNT = 101;
int messageCount = 0;
while (messageNo < COUNT) {
String messgaekey = String.valueOf(messageNo);
String messageData = "Hello kafka message :" + messgaekey;
producer.send(new KeyedMessage<String, String>(TOPIC, messgaekey ,messageData));
System.out.println(messageData);
messageNo ++;
messageCount++;
}
System.out.println("Producer端全部產生了" + messageCount + "條消息!");
}
public static void main(String[] args){
new porducer().produce();
}
}
接收端:
package yzr;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import kafka.consumer.ConsumerConfig;
import kafka.consumer.ConsumerIterator;
import kafka.consumer.KafkaStream;
import kafka.javaapi.consumer.ConsumerConnector;
import kafka.serializer.StringDecoder;
import kafka.utils.VerifiableProperties;
public class Consumer {
private final ConsumerConnector consumer;
public final static String TOPIC = "yzrtopic";
private Consumer() {
Properties props = new Properties();
// zookeeper 配置
props.put("zookeeper.connect", "localhost:2181");
// 消費者所在組
props.put("group.id", "testgroup");
props.put("consumer.id", "c.nick");
ConsumerConfig config = new ConsumerConfig(props);
consumer = kafka.consumer.Consumer.createJavaConsumerConnector(config);
}
void consume() {
Map<String, Integer> topicCountMap = new HashMap<String, Integer>();
topicCountMap.put(TOPIC, new Integer(1));
StringDecoder keyDecoder = new StringDecoder(new VerifiableProperties());
StringDecoder valueDecoder = new StringDecoder(new VerifiableProperties());
Map<String, List<KafkaStream<String, String>>> consumerMap = consumer.createMessageStreams(topicCountMap,keyDecoder,valueDecoder);
KafkaStream<String, String> streams = consumerMap.get(TOPIC).get(0);
ConsumerIterator<String, String> it = streams.iterator();
int messageCount = 0;
while (it.hasNext()){
System.out.println(it.next().message());
messageCount++;
if(messageCount == 100){
System.out.println("Consumer端一共消費了" + messageCount + "條消息!");
}
}
}
public static void main(String[] args) {
new Consumer().consume();
}
}
如果你在執行時發現錯誤,檢查一下是否缺少了jar包.就像手機一樣,當你想關掉一些進程又不知道怎麼關的時候,就重啓吧,在這裏把全部都導入,肯定就不會報錯.(不喜勿噴)
測試結果:先把接收端啓動起來,然後執行發送端發送數據,看一下接收端是否能夠自動接受到發送端發送的所有消息:
接受端:
參考鏈接:http://blog.csdn.net/lipeng_bigdata/article/details/51036099
本文源代碼下載:下載案列代碼