Flume+Kafka+SparkStreaming+Hbase+可视化(二)

分布式消息缓存Kafka
 
1、消息中间件:生产者和消费者 生产者、消费者、数据流(消息)
  • 发布和订阅消息
  • 容错存储消息记录
  • 处理流数据
Kafka架构:
procedure:生产者
consumer:消费者
broker:容错存储
topic:分类主题、标签
consumer group:一个consumer最多消费一个分区的数据 consumer数量=partitions
磁盘顺序读写,省掉寻道时间,提高性能
零字节拷贝:内核空间和用户空间不直接拷贝、SendFile
/opt/bigdata/kafka_2.11-1.0.0/kafka-log2s/logkafka-0/00000000000000000000.index index的序号就是message在日志文件中的相对offset(偏移量)
offsetIndex是稀疏索引,先根据offset找到对应log文件,计算 offset - (log文件第一个offset -1) 得到相对索引,再到index文件找到消息。如果index找不到,则取最近的,再去log文件对应位置向下查找
ack: 0 :不等待broker返回确认消息,无阻塞
1 :partitions 中的leader 保存成功
-1: partitions 中的leader和follower都成功
 
启动ZK:
启动Kafka:kafkaStart.sh
nohup $KAFKA_HOME/bin/kafka-server-start.sh $KAFKA_HOME/config/server0.properties &
nohup $KAFKA_HOME/bin/kafka-server-start.sh $KAFKA_HOME/config/server1.properties &
nohup $KAFKA_HOME/bin/kafka-server-start.sh $KAFKA_HOME/config/server2.properties &
 
创建Topic:
kafka-topics.sh --create --zookeeper bigdata:2181,bigdata:2182,bigdata:2183 --replication-factor 1 --partitions 1 --topic logkafka
--partitions 可以提高消费并发
 
查看Topic:
kafka-topics.sh --list --zookeeper bigdata:2181
kafka-topics.sh --describe --zookeeper bigdata:2181 --topic test (指定Topic,否则查看所有topic的详细信息)
 
发送消息:
kafka-console-producer.sh --broker-list localhost:9092 --topic logkafka
 
接受消息:
kafka-console-consumer.sh --zookeeper bigdata:2181 --topic logkafka --from-beginning (--from-beginning . 是否从头开始消费消息)
 
停止Kafka:kafkaStop.sh
$KAFKA_HOME/bin/kafka-server-stop.sh $KAFKA_HOME/config/server0.properties &
$KAFKA_HOME/bin/kafka-server-stop.sh $KAFKA_HOME/config/server1.properties &
$KAFKA_HOME/bin/kafka-server-stop.sh $KAFKA_HOME/config/server2.properties &
 
两种方式连接Kafka:简单理解为:Receiver方式是通过zookeeper来连接kafka队列,Direct方式是直接连接到kafka的节点上获取数据
Receiver:
1、Kafka中topic的partition与Spark中RDD的partition是没有关系的,因此,在KafkaUtils.createStream()中,提高partition的数量,只会增加Receiver的数量,也就是读取Kafka中topic partition的线程数量,不会增加Spark处理数据的并行度。
2、可以创建多个Kafka输入DStream,使用不同的consumer group和topic,来通过多个receiver并行接收数据。
3、如果基于容错的文件系统,比如HDFS,启用了预写日志机制,接收到的数据都会被复制一份到预写日志中。因此,在KafkaUtils.createStream()中,设置的持久化级别是StorageLevel.MEMORY_AND_DISK_SER。
Direct:
1、简化并行读取:如果要读取多个partition,不需要创建多个输入DStream,然后对它们进行union操作。Spark会创建跟Kafka partition一样多的RDD partition,并且会并行从Kafka中读取数据。所以在Kafka partition和RDD partition之间,有一个一对一的映射关系。
2、高性能:如果要保证零数据丢失,在基于receiver的方式中,需要开启WAL机制。这种方式其实效率低下,因为数据实际上被复制了两份,Kafka自己本身就有高可靠的机制会对数据复制一份,而这里又会复制一份到WAL中。而基于direct的方式,不依赖Receiver,不需要开启WAL机制,只要Kafka中作了数据的复制,那么就可以通过Kafka的副本进行恢复。
3、一次且仅一次的事务机制:基于receiver的方式,是使用Kafka的高阶API来在ZooKeeper中保存消费过的offset的。这是消费Kafka数据的传统方式。这种方式配合着WAL机制可以保证数据零丢失的高可靠性,但是却无法保证数据被处理一次且仅一次,可能会处理两次。因为Spark和ZooKeeper之间可能是不同步的。基于direct的方式,使用kafka的简单api,Spark Streaming自己就负责追踪消费的offset,并保存在checkpoint中。Spark自己一定是同步的,因此可以保证数据是消费一次且仅消费一次。由于数据消费偏移量是保存在checkpoint中,因此,如果后续想使用kafka高级API消费数据,需要手动的更新zookeeper中的偏移量
 
2、API操作
<dependency>  
       <groupId>org.apache.kafka</groupId>  
        <artifactId>kafka_2.11</artifactId>  
        <version>1.0.0</version>     
</dependency>  
 
Scala版 Producer :
package com.kafka
import java.util.HashMap
import org.apache.kafka.clients.producer.{KafkaProducer, ProducerConfig, ProducerRecord}
object producer {
  def main(args: Array[String]): Unit = {
  // 传参
  if (args.length < 4){
  System.err.println("Usage: producer <metadataBrokerList> <topics> <messageSec> <wordsPerMessage>")
  System.exit(1)
  }
  val Array(brokers, topics, messageSec, wordsPerMessage) = args
  // ZK 配置
  val zkProps = new HashMap[String, Object]()
  zkProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, brokers)
  zkProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer")
  zkProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer")
  // Kafka Producer
  val producer = new KafkaProducer[String, String](zkProps)
  var i = 0
  for ( i <- 1 to 10) {
    (1 to messageSec.toInt).foreach { messageNum =>
      val msg = (1 to wordsPerMessage.toInt).map(x => scala.util.Random.nextInt(10).toString).mkString(" ")
      val msgs = new ProducerRecord[String, String](topics, null, msg)
      producer.send(msgs)
    }
    Thread.sleep(100)
   }
  }
}

  

3、整合Flume:
conf1:exec-mem-avro.conf
# Name the components on this agent
a1.sources = exec-source
a1.channels = memory-channel
a1.sinks = avro-sink
 
# configure for sources
a1.sources.exec-source.type = exec
a1.sources.exec-source.command = tail -F /opt/datas/log-collect-system/log_server.log
 
# configure for channels
a1.channels.memory-channel.type = memory
a1.channels.memory-channel.capacity = 1000
a1.channels.memory-channel.transactionCapacity = 100
 
# configure for sinks
a1.sinks.avro-sink.type = avro
a1.sinks.avro-sink.hostname = localhost
a1.sinks.avro-sink.port = 44444
 
# configure
a1.sinks.avro-sink.channel = memory-channel
a1.sources.exec-source.channels = memory-channel

 

Kafka conf:exec-memory-kafka.cnf
# Name the components on this agent
a1.sources = avro-source
a1.channels = memory-channel
a1.sinks = logger-sink
 
# configure for sources
a1.sources.avro-source.type = avro
a1.sources.avro-source.bind = localhost
a1.sources.avro-source.port = 44444
 
# configure for channels
a1.channels.memory-channel.type = memory
a1.channels.memory-channel.capacity = 1000
a1.channels.memory-channel.transactionCapacity = 100
 
# configure for sinks
a1.sinks.kafka-sink.type = org.apache.flume.sink.kafka.KafkaSink
#a1.sinks.kafka-sink.bootstrap.servers = bigdata:9092,bigdata:9093,bigdata:9094
a1.sinks.kafka-sink.brokerList = bigdata:9092,bigdata:9093,bigdata:9094
a1.sinks.kafka-sink.topic = logkafka
 
# configure
a1.sinks.kafka-sink.channel = memory-channel
a1.sources.avro-source.channels = memory-channel

  

posted @ 2018-07-25 22:16  麻辣小虾  阅读(1575)  评论(0编辑  收藏  举报