From f5b3cd52a8758dc049e788dc378ca2d06b6cb4f0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=BD=97=E7=A5=A5?= <1366971433@qq.com>
Date: Tue, 28 May 2019 13:11:44 +0800
Subject: [PATCH] =?UTF-8?q?kafka=E7=94=9F=E4=BA=A7=E8=80=85?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
code/Kafka/kafka-basis/pom.xml | 38 ++++++++
.../heibaiying/producers/ProducerASyn.java | 43 +++++++++
.../com/heibaiying/producers/ProducerSyn.java | 42 +++++++++
.../producers/ProducerWithPartitioner.java | 37 ++++++++
.../heibaiying/producers/SimpleProducer.java | 34 ++++++++
.../producers/utils/CustomPartitioner.java | 29 +++++++
notes/Kafka生产者详解.md | 82 ++++++++++++++++++
pictures/kafka-simple-producer.png | Bin 0 -> 10251 bytes
8 files changed, 305 insertions(+)
create mode 100644 code/Kafka/kafka-basis/pom.xml
create mode 100644 code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/ProducerASyn.java
create mode 100644 code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/ProducerSyn.java
create mode 100644 code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/ProducerWithPartitioner.java
create mode 100644 code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/SimpleProducer.java
create mode 100644 code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/utils/CustomPartitioner.java
create mode 100644 pictures/kafka-simple-producer.png
diff --git a/code/Kafka/kafka-basis/pom.xml b/code/Kafka/kafka-basis/pom.xml
new file mode 100644
index 0000000..d46efa3
--- /dev/null
+++ b/code/Kafka/kafka-basis/pom.xml
@@ -0,0 +1,38 @@
+
+
+ 4.0.0
+
+ com.heibaiying
+ kafka-basis
+ 1.0
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 8
+ 8
+
+
+
+
+
+
+
+
+ org.apache.kafka
+ kafka-clients
+ 2.2.0
+
+
+ org.slf4j
+ slf4j-nop
+ 1.7.25
+
+
+
+
+
\ No newline at end of file
diff --git a/code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/ProducerASyn.java b/code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/ProducerASyn.java
new file mode 100644
index 0000000..0bebb09
--- /dev/null
+++ b/code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/ProducerASyn.java
@@ -0,0 +1,43 @@
+package com.heibaiying.producers;
+
+import org.apache.kafka.clients.producer.*;
+
+import java.util.Properties;
+import java.util.concurrent.ExecutionException;
+
+/*
+ * Kafka生产者示例——异步发送消息
+ */
+public class ProducerASyn {
+
+ public static void main(String[] args) {
+
+ String topicName = "Hello-Kafka";
+
+ Properties props = new Properties();
+ props.put("bootstrap.servers", "192.168.200.226:9092");
+ props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
+ props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
+ /*创建生产者*/
+ Producer producer = new KafkaProducer<>(props);
+
+ for (int i = 0; i < 10; i++) {
+ /*异步发送消息*/
+ ProducerRecord record = new ProducerRecord<>(topicName, "k" + i, "world" + i);
+ producer.send(record, new Callback() {
+ @Override
+ public void onCompletion(RecordMetadata metadata, Exception exception) {
+ if (exception != null) {
+ System.out.println("进行异常处理");
+ } else {
+ System.out.printf("topic=%s, partition=%d, offset=%s \n",
+ metadata.topic(), metadata.partition(), metadata.offset());
+ }
+ }
+ });
+ }
+
+ /*关闭生产者*/
+ producer.close();
+ }
+}
\ No newline at end of file
diff --git a/code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/ProducerSyn.java b/code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/ProducerSyn.java
new file mode 100644
index 0000000..0fa05ad
--- /dev/null
+++ b/code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/ProducerSyn.java
@@ -0,0 +1,42 @@
+package com.heibaiying.producers;
+
+import org.apache.kafka.clients.producer.KafkaProducer;
+import org.apache.kafka.clients.producer.Producer;
+import org.apache.kafka.clients.producer.ProducerRecord;
+import org.apache.kafka.clients.producer.RecordMetadata;
+
+import java.util.Properties;
+import java.util.concurrent.ExecutionException;
+
+/*
+ * Kafka生产者示例——同步发送消息
+ */
+public class ProducerSyn {
+
+ public static void main(String[] args) {
+
+ String topicName = "Hello-Kafka";
+
+ Properties props = new Properties();
+ props.put("bootstrap.servers", "192.168.200.226:9092");
+ props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
+ props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
+ /*创建生产者*/
+ Producer producer = new KafkaProducer<>(props);
+
+ for (int i = 0; i < 10; i++) {
+ /*同步发送消息*/
+ try {
+ ProducerRecord record = new ProducerRecord<>(topicName, "k" + i, "world" + i);
+ RecordMetadata metadata = producer.send(record).get();
+ System.out.printf("topic=%s, partition=%d, offset=%s \n",
+ metadata.topic(), metadata.partition(), metadata.offset());
+ } catch (InterruptedException | ExecutionException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /*关闭生产者*/
+ producer.close();
+ }
+}
\ No newline at end of file
diff --git a/code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/ProducerWithPartitioner.java b/code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/ProducerWithPartitioner.java
new file mode 100644
index 0000000..b707323
--- /dev/null
+++ b/code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/ProducerWithPartitioner.java
@@ -0,0 +1,37 @@
+package com.heibaiying.producers;
+
+import org.apache.kafka.clients.producer.*;
+
+import java.util.Properties;
+
+/*
+ * Kafka生产者示例——异步发送消息
+ */
+public class ProducerWithPartitioner {
+
+ public static void main(String[] args) {
+
+ String topicName = "Kafka-Partitioner-Test";
+
+ Properties props = new Properties();
+ props.put("bootstrap.servers", "192.168.200.226:9092");
+ props.put("key.serializer", "org.apache.kafka.common.serialization.IntegerSerializer");
+ props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
+
+ props.put("partitioner.class", "com.heibaiying.producers.utils.CustomPartitioner");
+ props.put("pass.line", 6);
+
+ Producer producer = new KafkaProducer<>(props);
+
+ for (int i = 0; i <= 10; i++) {
+ /*异步发送消息*/
+ String score = "score:" + i;
+ ProducerRecord record = new ProducerRecord<>(topicName, i, score);
+ producer.send(record, (metadata, exception) ->
+ System.out.printf("%s, partition=%d, \n", score, metadata.partition()));
+ }
+
+ /*关闭生产者*/
+ producer.close();
+ }
+}
\ No newline at end of file
diff --git a/code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/SimpleProducer.java b/code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/SimpleProducer.java
new file mode 100644
index 0000000..e0429ec
--- /dev/null
+++ b/code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/SimpleProducer.java
@@ -0,0 +1,34 @@
+package com.heibaiying.producers;
+
+import org.apache.kafka.clients.producer.KafkaProducer;
+import org.apache.kafka.clients.producer.ProducerRecord;
+
+import java.util.Properties;
+
+/*
+ * Kafka生产者示例
+ */
+
+public class SimpleProducer {
+
+ public static void main(String[] args) {
+
+ String topicName = "Hello-Kafka";
+
+ Properties props = new Properties();
+ props.put("bootstrap.servers", "192.168.200.226:9092");
+ props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
+ props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
+ /*创建生产者*/
+ org.apache.kafka.clients.producer.Producer producer = new KafkaProducer<>(props);
+
+ for (int i = 0; i < 10; i++) {
+ /* 发送消息*/
+ ProducerRecord record = new ProducerRecord<>(topicName, "hello" + i, "world" + i);
+ producer.send(record);
+ }
+
+ /*关闭生产者*/
+ producer.close();
+ }
+}
\ No newline at end of file
diff --git a/code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/utils/CustomPartitioner.java b/code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/utils/CustomPartitioner.java
new file mode 100644
index 0000000..1842406
--- /dev/null
+++ b/code/Kafka/kafka-basis/src/main/java/com/heibaiying/producers/utils/CustomPartitioner.java
@@ -0,0 +1,29 @@
+package com.heibaiying.producers.utils;
+
+import org.apache.kafka.clients.producer.Partitioner;
+import org.apache.kafka.common.Cluster;
+
+import java.util.Map;
+
+
+public class CustomPartitioner implements Partitioner {
+
+ private int passLine;
+
+ @Override
+ public void configure(Map configs) {
+ passLine = (Integer) configs.get("pass.line");
+ }
+
+ @Override
+ public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
+ return (Integer) key >= passLine ? 1 : 0;
+ }
+
+ @Override
+ public void close() {
+ System.out.println("分区器关闭");
+ }
+
+
+}
diff --git a/notes/Kafka生产者详解.md b/notes/Kafka生产者详解.md
index e69de29..f5cfd19 100644
--- a/notes/Kafka生产者详解.md
+++ b/notes/Kafka生产者详解.md
@@ -0,0 +1,82 @@
+#### 1. 启动Kakfa
+
+Kafka的运行依赖于zookeeper,需要预先启动,可以启动Kafka内置的zookeeper,也可以启动自己安装的。
+
+```shell
+# zookeeper启动命令
+bin/zkServer.sh start
+
+# 内置zookeeper启动命令
+bin/zookeeper-server-start.sh config/zookeeper.properties
+```
+
+启动单节点kafka用于测试:
+
+```shell
+# bin/kafka-server-start.sh config/server.properties
+```
+
+#### 2. 创建topic
+
+```shell
+# 创建用于测试主题
+bin/kafka-topics.sh --create \
+ --bootstrap-server hadoop001:9092 \
+ --replication-factor 1 --partitions 1 \
+ --topic Hello-Kafka
+
+# 查看所有主题
+ bin/kafka-topics.sh --list --bootstrap-server hadoop001:9092
+```
+
+#### 3. 启动消费者
+
+ 启动一个控制台消费者用于观察写入情况,启动命令如下:
+
+```shell
+# bin/kafka-console-consumer.sh --bootstrap-server hadoop001:9092 --topic Hello-Kafka --from-beginning
+```
+
+
+
+```shell
+topic=Hello-Kafka, partition=0, offset=40
+topic=Hello-Kafka, partition=0, offset=41
+topic=Hello-Kafka, partition=0, offset=42
+topic=Hello-Kafka, partition=0, offset=43
+topic=Hello-Kafka, partition=0, offset=44
+topic=Hello-Kafka, partition=0, offset=45
+topic=Hello-Kafka, partition=0, offset=46
+topic=Hello-Kafka, partition=0, offset=47
+topic=Hello-Kafka, partition=0, offset=48
+topic=Hello-Kafka, partition=0, offset=49
+```
+
+
+
+
+
+```shell
+ bin/kafka-topics.sh --create \
+ --bootstrap-server hadoop001:9092 \
+ --replication-factor 1 --partitions 2 \
+ --topic Kafka-Partitioner-Test
+```
+
+
+
+```shell
+score:6, partition=1,
+score:7, partition=1,
+score:8, partition=1,
+score:9, partition=1,
+score:10, partition=1,
+score:0, partition=0,
+score:1, partition=0,
+score:2, partition=0,
+score:3, partition=0,
+score:4, partition=0,
+score:5, partition=0,
+分区器关闭
+```
+
diff --git a/pictures/kafka-simple-producer.png b/pictures/kafka-simple-producer.png
new file mode 100644
index 0000000000000000000000000000000000000000..0ff45311c93af0c8e92a6c73fd84ed57c9c937fc
GIT binary patch
literal 10251
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