Spark Streaming实时流处理项目2——分布式消息队列Kafka学习

Kafka架构理解:

Producer:生产者(生产馒头的老妈)

consumer:消费者(吃馒头的你)

broker:篮子(放馒头)

topic:主题,给馒头带上一个标签,topic A是给你吃的,topic B是给你弟弟吃的。

Kafka部署:

单节点单Broker部署

单节点多Broker部署

多节点多Broker部署

本次学习中,我们使用多节点多Broker的方式部署,最大程度上契合实际生产环境。四台虚拟机上都安装了Kafka,主机名分别是hadoop0、hadoop1、hadoop2、hadoop3.

kafak的使用依赖于zookeeper,因此安装kafka之前需要首先安装好zookeeper集群。zookeeper的安装这里不再介绍。

zookeeper启动命令:bin/zkServer.sh start

kafak下载解压之后,修改server.properties配置文件

#broker.id=0  每台服务器的broker.id都不能相同

#hostname
host.name=192.168.25.100

#日志存储的路径修改一下
log.dirs=/soft/kafka/logs

#在log.retention.hours=168 下面新增下面三项
message.max.byte=5242880
default.replication.factor=2
replica.fetch.max.bytes=5242880

#设置zookeeper的连接端口
zookeeper.connect=192.168.25.100:12181,192.168.25.101:12181,192.168.25.107:12181

kafka启动命令:

#从后台启动Kafka集群(3台都需要启动)
cd/opt/kafka/kafka_2.11-0.9.0.1//bin #进入到kafka的bin目录 
./kafka-server-start.sh -daemon ../config/server.properties

Kafka使用:

1、创建Topic(要指定zookeeper)
./kafka-topics.sh --create --zookeeper 192.168.25.128:2181 --replication-factor 2 --partitions 1 --topic shuaige
#解释
--replication-factor 2   #复制两份
--partitions 1 #创建1个分区
--topic #主题为shuaige

2、在一台服务器上创建一个发布者(指定Broker)
./kafka-console-producer.sh --broker-list 192.168.25.128:9092 --topic shuaige

3、在一台服务器上创建一个订阅者(要指定zookeeper)
./kafka-console-consumer.sh --zookeeper localhost:2181 --topic shuaige --from-beginning

4、查看所有已创建的topic
./kafka-topics.sh --list --zookeeper hadoop0:2181

Kafka实际环境有可能会出现Consumer全部宕机,虽然基于Kafka的高可用特性,消费者群组中的消费者可以实现再均衡,所有Consumer不处理数据的情况很少,但是还是有可能会出现,此时就要求Consumer重启的时候能够读取在宕机期间Producer发送的数据。基于消费者订阅模式默认是无法实现的,因为只能订阅最新发送的数据。通过消费者命令行可以实现,只要在命令行中加上--from-beginning即可
查看topic状态:

/kafka-topics.sh --describe --zookeeper localhost:2181 --topic shuaige
#下面是显示信息
Topic:ssports    PartitionCount:1    ReplicationFactor:2    Configs:
    Topic: shuaige    Partition: 0    Leader: 1    Replicas: 0,1    Isr: 1
#分区为为1  复制因子为2   他的  shuaige的分区为0 
#Replicas: 0,1   复制的为0,1

kafka容错性测试:

partitionCount: 1  代表分区数为1          replicationFactor: 3 代表副本数为3      replicas:3 1 2 代表副本存放的brokerid

Isr : 3 1 2 代表活着的是3 1 2                  leader: 3 代表broker编号为3 的是leader

理解kafka的容错性:(容错性测试)

当我们kafka有3个,随意删除其2个都不会影响kafka运行,当只剩下一个时,那么默认这个就是leader,输入jps -m 显示三个kafka 进程

我们删除俩个,kafka依然运行。

Kafka API使用:

IDEA+Maven+Java语言

/**
 * @author YuZhansheng
 * @desc  Kafka常用配置文件
 * @create 2019-02-17 16:05
 */
public class KafkaProperties {

    public static final String ZK = "192.168.25.128:2181";

    public static final String TOPIC = "shuaige";

    public static final String BROKER_LIST = "192.168.25.128:9092,192.168.25.141:9092,192.168.25.142:9092,192.168.25.143:9092";

}
/**
 * @author YuZhansheng
 * @desc  生产者
 * @create 2019-02-17 16:10
 */
public class KafkaProducer extends Thread{

    private String topic;

    private Producer<Integer,String> producer;

    public KafkaProducer(String topic){
        this.topic = topic;

        Properties properties = new Properties();

        properties.put("metadata.broker.list",KafkaProperties.BROKER_LIST);
        properties.put("serializer.class","kafka.serializer.StringEncoder");
        properties.put("request.required.acks","1");

        producer = new Producer<Integer, String>(new ProducerConfig(properties));

    }

    @Override
    public void run() {
        int messageNo = 1;

        while (true){
            String message = "message_" + messageNo;
            producer.send(new KeyedMessage<Integer, String>(topic,message));
            System.out.println("sent: " + message);
            messageNo++;

            try {
                Thread.sleep(2000);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}
/**
 * @author YuZhansheng
 * @desc  Kafka Java API测试
 * @create 2019-02-17 16:32
 */
public class KafkaClientApp {

    public static void main(String[] args) {
        new KafkaProducer(KafkaProperties.TOPIC).start();

        new KafkaConsumer(KafkaProperties.TOPIC).start();
    }
}
/**
 * @author YuZhansheng
 * @desc   消费者
 * @create 2019-02-17 16:39
 */
public class KafkaConsumer extends Thread{

    private String topic;

    public KafkaConsumer(String topic){
        this.topic = topic;
    }

    private ConsumerConnector createConnector(){
        Properties properties = new Properties();
        properties.put("zookeeper.connect",KafkaProperties.ZK);
        properties.put("group.id",KafkaProperties.GROUP_ID);

        return Consumer.createJavaConsumerConnector(new ConsumerConfig(properties));
    }

    @Override
    public void run() {
        ConsumerConnector consumer = createConnector();

        Map<String,Integer> topicCountMap = new HashMap<String, Integer>();
        topicCountMap.put(topic,1);

        //第一个String就是传的topic;List<KafkaStream就是对应的数据流
        Map<String, List<KafkaStream<byte[], byte[]>>> messageStream = consumer.createMessageStreams(topicCountMap);

        //get(0)就是获取每次接收到的数据
        KafkaStream<byte[], byte[]> stream = messageStream.get(topic).get(0);

        ConsumerIterator<byte[], byte[]> iterator = stream.iterator();

        while (iterator.hasNext()){
            String message = new String(iterator.next().message());
            System.out.println("rec: " + message);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_21583077/article/details/87523509