kafka接入学习

什么是kafka?

Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是在现代网络上的许多社会功能的一个关键因素。 这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。 对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。Kafka的目的是通过Hadoop的并行加载机制来统一线上和离线的消息处理,也是为了通过集群机来提供实时的消费。

kafka有哪些优点?

1.它是一种高容错的消息发布订阅系统(因为它的数据是持久化到硬盘,可以重复读取)

2.它是高效率,有很大的吞吐量

3.它的扩展性极高,是用zookeeper集群来管理Consumer和Broker节点的动态加入与退出

4.支持实时流的方式传输数据


怎么样使用kafka?

1.首先要配置一下zookeeper的集群,这里是配置一下Zookeeper.properties

  1. #记录节点的信息已经Kafka节点和Consumer的一些值  
  2. dataDir=/data/zookeeper  
  3. # the port at which the clients will connect  
  4. #占用到的端口  
  5. clientPort=2181  
  6. # disable the per-ip limit on the number of connections since this is a non-production config  
  7. maxClientCnxns=0  
  8. #心跳最长时间确定节点的存活  
  9. tickTime=2000  
  10. syncLimit=2  
  11. #初始尝试最多链接5次  
  12. initLimit=5  
  13. #集群配置  
  14. server.1=192.168.196.138:2888:3888  
  15. server.2=192.168.196.140:2888:3888  
  16. server.3=192.168.196.139:2888:3888  

2.然后在配置kafka的broker的节点,这边是配置Conf里面的Server.properties文件

  1. broker.id=0  #broker的唯一标识,集群中也不能一样  
  2. port=9092 #broker用到的端口  
  3. num.network.threads=2  
  4. num.io.threads=8 #开启多少线程同时在执行IO数据持久化  
  5. socket.send.buffer.bytes=1048576   #数据接受的缓冲大小  
  6. socket.receive.buffer.bytes=1048576  #消费时发出去的缓冲大小  
  7. socket.request.max.bytes=104857600  #一个请求会接受的最大数据量  
  8. log.dirs=/tmp/kafka-logs   #日志的打印目录  
  9. num.partitions=2  #Topic默认的分区数  
  10. log.retention.hours=168   
  11. log.segment.bytes=536870912  
  12. log.retention.check.interval.ms=60000  
  13. log.cleaner.enable=false  
  14. zookeeper.connect=localhost:2181,192.168.196.140:2181,192.168.196.139:2181  #zookeeper集群配置  
  15. zookeeper.connection.timeout.ms=1000000    
  16. host.name=192.168.196.138  #hostname  
  17. delete.topic.enable=true  #配置这个参数删除Topic的时候同时也会删除数据   

3.启动zookeeper集群

  1. ./bin/zookeeper-server-start.sh ./conf/zookeeper.properties  

4.启动kafk的Broker节点

  1. ./bin/kafka-server-start.sh ./conf/server.properties  

5.创建Topic

  1. ./bin/kafka-topics.sh --create --zookeeper Master:2181 --replication-factor 2 --partitions 2 --topic test-topic  

6.可以查看以下kafka集群中存在的Topic

  1. ./bin/kafka-topics.sh --list --zookeeper 192.168.196.138:2181  
  1. ./bin/kafka-topics.sh --describe --zookeeper Master:2181--topic test-topic  #查看某一个分区的具体情况  

7.Flume数据源传输数据到Kafka

KafkaSink的代码:这边还需要把要用到的包引入到Flume底下的lib文件夹,具体的包可以在我的百度云盘下载:点击打开链接这里面解压后又一个lib里面的所有包都拷贝进去。

  1. package org.apache.flume.plugins;  
  2.   
  3. /** 
  4.  * KAFKA Flume Sink (Kafka 0.8 Beta, Flume 1.5). 
  5.  * User: YiYongWu 
  6.  * Date: 2016/03/28 
  7.  * Time: PM 4:32 
  8.  */  
  9.   
  10. import java.util.Properties;  
  11.   
  12. import kafka.javaapi.producer.Producer;  
  13. import kafka.producer.KeyedMessage;  
  14. import kafka.producer.ProducerConfig;  
  15.   
  16. import org.apache.commons.lang.StringUtils;  
  17. import org.apache.flume.*;  
  18. import org.apache.flume.conf.Configurable;  
  19. import org.apache.flume.event.EventHelper;  
  20. import org.apache.flume.sink.AbstractSink;  
  21. import org.slf4j.Logger;  
  22. import org.slf4j.LoggerFactory;  
  23.   
  24. import com.google.common.base.Preconditions;  
  25. import com.google.common.collect.ImmutableMap;  
  26.   
  27. /** 
  28.  * kafka sink. 
  29.  */  
  30. public class KafkaSink extends AbstractSink implements Configurable {  
  31.   
  32.     /** 
  33.      * 日志记录 
  34.      */  
  35.     private static final Logger LOGGER = LoggerFactory.getLogger(KafkaSink.class);  
  36.   
  37.     /** 
  38.      * 参数 
  39.      */  
  40.     private Properties parameters;  
  41.     /** 
  42.      * 生产者 
  43.      */  
  44.     private Producer<String, String> producer;  
  45.     /** 
  46.      * The Context.上下文 
  47.      */  
  48.     private Context context;  
  49.   
  50.     /** 
  51.      * Configure void. 参数设置 
  52.      *  
  53.      * @param context 
  54.      *            the context 
  55.      */  
  56.     @Override  
  57.     public void configure(Context context) {  
  58.         this.context = context;  
  59.         ImmutableMap<String, String> props = context.getParameters();  
  60.   
  61.         parameters = new Properties();  
  62.         for (String key : props.keySet()) {  
  63.             String value = props.get(key);  
  64.             this.parameters.put(key, value);  
  65.         }  
  66.     }  
  67.     /** 
  68.      * Start void. 
  69.      */  
  70.     @Override  
  71.     public synchronized void start() {  
  72.         super.start();  
  73.         ProducerConfig config = new ProducerConfig(this.parameters);  
  74.         this.producer = new Producer<String, String>(config);  
  75.     }  
  76.   
  77.     /** 
  78.      * Process status. 
  79.      *  
  80.      * @return the status 
  81.      * @throws EventDeliveryException 
  82.      *             the event delivery exception 
  83.      */  
  84.     @Override  
  85.     public Status process() throws EventDeliveryException {  
  86.         Status status = null;  
  87.   
  88.         // Start transaction  
  89.         Channel ch = getChannel();  
  90.         Transaction txn = ch.getTransaction();  
  91.         txn.begin();  
  92.         try {  
  93.             // This try clause includes whatever Channel operations you want to do  
  94.             Event event = ch.take();  
  95.   
  96.             String partitionKey = (String) parameters.get(KafkaFlumeConstans.PARTITION_KEY_NAME);  
  97.             String encoding = StringUtils.defaultIfEmpty(  
  98.                     (String) this.parameters.get(KafkaFlumeConstans.ENCODING_KEY_NAME),  
  99.                     KafkaFlumeConstans.DEFAULT_ENCODING);  
  100.             String topic = Preconditions.checkNotNull(  
  101.                     (String) this.parameters.get(KafkaFlumeConstans.CUSTOME_TOPIC_KEY_NAME),  
  102.                     "custom.topic.name is required");  
  103.   
  104.             String eventData = new String(event.getBody(), encoding);  
  105.   
  106.             KeyedMessage<String, String> data;  
  107.   
  108.             // if partition key does'nt exist  
  109.             if (StringUtils.isEmpty(partitionKey)) {  
  110.                 data = new KeyedMessage<String, String>(topic, eventData);  
  111.             } else {  
  112.                 data = new KeyedMessage<String, String>(topic, partitionKey, eventData);  
  113.             }  
  114.   
  115.             if (LOGGER.isInfoEnabled()) {  
  116.                 LOGGER.info("Send Message to Kafka : [" + eventData + "] -- [" + EventHelper.dumpEvent(event) + "]");  
  117.             }  
  118.   
  119.             producer.send(data);  
  120.             txn.commit();  
  121.             status = Status.READY;  
  122.         } catch (Throwable t) {  
  123.             txn.rollback();  
  124.             status = Status.BACKOFF;  
  125.   
  126.             // re-throw all Errors  
  127.             if (t instanceof Error) {  
  128.                 throw (Error) t;  
  129.             }  
  130.         } finally {  
  131.             txn.close();  
  132.         }  
  133.         return status;  
  134.     }  
  135.   
  136.     /** 
  137.      * Stop void. 
  138.      */  
  139.     @Override  
  140.     public void stop() {  
  141.         producer.close();  
  142.     }  
  143. }  


还要写一个分区策略,简单的分区策略SinglePartition
  1. @Override  
  2.    public int partition(Object key, int numPartitions) {  
  3.        try {  
  4.            int partitionNum = Integer.parseInt((String) key);  
  5.            return Math.abs(Integer.parseInt((String) key) % numPartitions);  
  6.        } catch (Exception e) {  
  7.            return Math.abs(key.hashCode() % numPartitions);  
  8.        }  
  9.    }  


8.写kafka消费着去消费集群中所在Topic的数据.

1.Consumer所需要用到的静态配置数据

  1. package com.yiyong.kafka;  
  2.   
  3. /** 
  4.  * Created by root on 16-3-13. 
  5.  */  
  6. public class KafkaProperties {  
  7.     public final static String zkConnect="192.168.196.138:2181,192.168.196.139:2181,192.168.196.140:2181";  
  8.     public final static String groupId="group1";  
  9.     public final static String groupId2="group2";  
  10.     public final static String topic="kafkaToptic";  
  11.     public final static int kafkaProduceBufferSize=64*1024;  
  12.     public final static int connectionTimeOut=20000;  
  13.     public final static int reconnectInterval=10000;  
  14.     public final static String topic2="topic2";  
  15.     public final static String topic3="topic3";  
  16.   
  17.   
  18. }  
2.消费者的具体实现
  1. package com.yiyong.kafka;  
  2.   
  3. import kafka.consumer.ConsumerConfig;  
  4. import kafka.consumer.ConsumerIterator;  
  5. import kafka.consumer.KafkaStream;  
  6. import kafka.javaapi.consumer.ConsumerConnector;  
  7.   
  8. import java.util.HashMap;  
  9. import java.util.List;  
  10. import java.util.Map;  
  11. import java.util.Properties;  
  12.   
  13. /** 
  14.  * Created by root on 16-3-14. 
  15.  */  
  16. public class KafkaConsumer2 extends Thread {  
  17.   
  18.     private final String topic;  
  19.     private final ConsumerConnector consumer;  
  20.     public KafkaConsumer2(String topic){  
  21.         consumer = kafka.consumer.Consumer.createJavaConsumerConnector(createConsumerConfig());  
  22.   
  23.         this.topic = topic;  
  24.     }  
  25.   
  26.     private static ConsumerConfig createConsumerConfig(){  
  27.         Properties props = new Properties();  
  28.         props.put("zookeeper.connect",KafkaProperties.zkConnect);  
  29.         props.put("group.id",KafkaProperties.groupId2);  
  30.         props.put("zookeeper.session.timeout.ms","40000");  
  31.         props.put("zookeeper.sync.time.ms","200");  
  32.         props.put("auto.commit.interval.ms","1000");  
  33.   
  34.         return new ConsumerConfig(props);  
  35.     }  
  36.   
  37.     @Override  
  38.     public void run() {  
  39.         Map<String,Integer> topicCountMap = new HashMap<String,Integer>();  
  40.         topicCountMap.put(topic, new Integer(1));  
  41.         Map<String,List<KafkaStream<byte[],byte[]>>> consumerMap = consumer.createMessageStreams(topicCountMap);  
  42.         KafkaStream<byte[],byte[]> stream = consumerMap.get(topic).get(0);  
  43.         ConsumerIterator<byte[],byte[]> it = stream.iterator();  
  44.         while(it.hasNext()){  
  45.             System.out.println("receiced:"+new String(it.next().message()));  
  46.             try {  
  47.                 sleep(3000);  
  48.             }catch(InterruptedException e){  
  49.                 e.printStackTrace();  
  50.             }  
  51.         }  
  52.   
  53.     }  
  54. }  

这里还需要把用到的Kafka相关的包给引进来,直接用maven引进就可以,下次直接补充。

我的海量日志采集架构

我这边实现一个海量日志采集平台,主要是利用Flume采集服务平台的实时日志,然后对日志进行过滤复制处理,其中正则配置只选择JSON格式的日志,复制两份日志数据,一份存入HDFS,一份传入Kafka转为实时流。其中在HDFS和Kafka两条线都做了负载均衡处理。一张整体框架图还有一张详细的数据路径图






架构实现

该架构的其中一条线已经在Flume的那篇博客讲述过,这边就不在重复,这边只进行Kafka这条线进行实现分析。这里上文已经知道消费者怎么进行消费,所以只需要在Flume端配置联通这个数据传输通道就能将数据稳定传输,Flume客户端启动在Flume那篇博客已经写得很清楚了。这里也不做过多介绍。
接下去写Flume接入Kafka的那个MasterClient2.conf的配置如下:
  1. Flume配置  
  2.   
  3. client2.sources = source1  
  4. client2.sinks  = sink1 sink2  
  5. client2.channels = channel1  
  6.   
  7. #Define a sink group which for Load balancing  
  8. client1.sinkgroups = g1  
  9. client1.sinkgroups.g1.sinks = sink1 sink2  
  10. client1.sinkgroups.g1.processor.type = load_balance  
  11. client1.sinkgroups.g1.processor.backoff = true  
  12. client1.sinkgroups.g1.processor.selector = round_robin  
  13.   
  14. #Describe source  
  15. client2.sources.source1.type = avro  
  16. client2.sources.source1.channels = channel1  
  17. client2.sources.source1.port = 6666  
  18. client2.sources.source1.bind = 0.0.0.0  
  19.   
  20. #Describe sink1  
  21. #client2.sinks.sink1.type = logger  
  22. client2.sinks.sink1.type = org.apache.flume.plugins.KafkaSink  
  23. client2.sinks.sink1.metadata.broker.list=192.168.196.138:9092,192.168.196.139:9092,192.168.196.140:9092  
  24. client2.sinks.sink1.zk.connect=192.168.196.138:2181,192.168.196.139:2181,192.168.196.140:2181  
  25. client2.sinks.sink1.partition.key=0  
  26. client2.sinks.sink1.partitioner.class=org.apache.flume.plugins.SinglePartition  
  27. client2.sinks.sink1.serializer.class=kafka.serializer.StringEncoder  
  28. client2.sinks.sink1.request.required.acks=1  
  29. client2.sinks.sink1.max.message.size=1000000  
  30. client2.sinks.sink1.producer.type=async  
  31. client2.sinks.sink1.custom.encoding=UTF-8  
  32. client2.sinks.sink1.custom.topic.name=kafkaToptic  
  33.   
  34. #Describe sink2  
  35. #client2.sinks.sink2.type = logger  
  36. client2.sinks.sink2.type = org.apache.flume.plugins.KafkaSink  
  37. client2.sinks.sink2.metadata.broker.list=192.168.196.138:9092,192.168.196.139:9092,192.168.196.140:9092  
  38. client2.sinks.sink2.zk.connect=192.168.196.138:2181,192.168.196.139:2181,192.168.196.140:2181  
  39. client2.sinks.sink2.partition.key=0  
  40. client2.sinks.sink2.partitioner.class=org.apache.flume.plugins.SinglePartition  
  41. client2.sinks.sink2.serializer.class=kafka.serializer.StringEncoder  
  42. client2.sinks.sink2.request.required.acks=1  
  43. client2.sinks.sink2.max.message.size=1000000  
  44. client2.sinks.sink2.producer.type=async  
  45. client2.sinks.sink2.custom.encoding=UTF-8  
  46. client2.sinks.sink2.custom.topic.name=kafkaToptic  
  47.   
  48. #Describe channel  
  49. client2.channels.channel1.type = memory  
  50. client2.channels.channel1.capacity = 10000  
  51. client2.channels.channel1.transactionCapacity = 1000  
  52.   
  53. #bind the source/sink with channel  
  54. client2.sinks.sink1.channel = channel1  
  55. client2.sources.source1.channels = channel1  

然后启动三个Flume客户端后在开启日志模拟器,开启消费者程序就可以开始看到日志的传输,在2G内存,20G硬盘,1核处理器的集群单个节点上数据的传输延迟大概是0.8秒。

转载自: http://blog.csdn.net/u014001866/article/details/50971098
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用C++接入Kafka的一个简单示例: ```cpp #include <iostream> #include <librdkafka/rdkafkacpp.h> int main() { std::string brokers = "localhost:9092"; // Kafka brokers地址 std::string topic_name = "test_topic"; // Kafka主题名 // 创建Kafka生产者配置对象 RdKafka::Conf *conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); std::string errstr; // 设置broker地址 if (conf->set("bootstrap.servers", brokers, errstr) != RdKafka::Conf::CONF_OK) { std::cerr << "Failed to set broker address: " << errstr << std::endl; return 1; } // 创建Kafka生产者对象 RdKafka::Producer *producer = RdKafka::Producer::create(conf, errstr); if (!producer) { std::cerr << "Failed to create producer: " << errstr << std::endl; return 1; } // 创建Kafka消息对象 RdKafka::Topic *topic = RdKafka::Topic::create(producer, topic_name, NULL, errstr); if (!topic) { std::cerr << "Failed to create topic: " << errstr << std::endl; return 1; } // 发送消息 std::string message = "Hello, Kafka!"; RdKafka::ErrorCode resp = producer->produce(topic, RdKafka::Topic::PARTITION_UA, RdKafka::Producer::RK_MSG_COPY, const_cast<char *>(message.c_str()), message.size(), NULL, NULL); if (resp != RdKafka::ERR_NO_ERROR) { std::cerr << "Failed to produce message: " << RdKafka::err2str(resp) << std::endl; return 1; } // 关闭资源 delete topic; delete producer; delete conf; return 0; } ``` 注意:该示例仅用于演示C++接入Kafka的基本流程,实际应用中需要根据实际情况进行配置和细节处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值