Flume-ng+Kafka+storm的学习笔记
Flume-ng
Flume是一个分布式、可靠、和高可用的海量日志采集、聚合和传输的系统。
Flume的文档可以看http://flume.apache.org/FlumeUserGuide.html 官方的英文文档 介绍的比较全面。
不过这里写写自己的见解
这个是flume的架构图
从上图可以看到几个名词:
Agent: 一个Agent包含Source、Channel、Sink和其他的组件。Flume就是一个或多个Agent构成的。
Source:数据源。简单的说就是agent获取数据的入口 。
Channel:管道。数据流通和存储的通道。一个source必须至少和一个channel关联。
Sink:用来接收channel传输的数据并将之传送到指定的地方。传送成功后数据从channel中删除。
Flume具有高可扩展性 可随意组合:
注意 source是接收源 sink是发送源
上图是一个source将数据发给3个channel 其中的sink2将数据发给JMS ,sink3将数据发给另一个source。
总的来说flume的扩展性非常高 根据需要可随意组合。
现在在说说一个概念叫Event:
Event是flume的数据传输的基本单元。Flume本质上是将数据作为一个event从源头传到结尾。是由可选的Headers和载有数据的一个byte array构成。
代码结构:
- /**
- * Basic representation of a data object inFlume.
- * Provides access to data as it flows throughthe system.
- */
- public interface Event{
- /**
- * Returns a map of name-valuepairs describing the data stored in the body.
- */
- public Map<String, String> getHeaders();
- /**
- * Set the event headers
- * @param headersMap of headers to replace the current headers.
- */
- public void setHeaders(Map<String, String> headers);
- /**
- * Returns the raw byte array of the datacontained in this event.
- */
- public byte[] getBody();
- /**
- * Sets the raw byte array of the datacontained in this event.
- * @param body Thedata.
- */
- public void setBody(byte[] body);
- }
这个是网上找的flume channel ,source,sink的汇总
链接是http://abloz.com/2013/02/26/flume-channel-source-sink-summary.html
|
下面介绍下kafka以及kafka和flume的整合
Kafka:
从这个链接抄了些内容下来http://dongxicheng.org/search-engine/kafka/
Kafka是Linkedin于2010年12月份开源的消息系统,它主要用于处理活跃的流式数据。活跃的流式数据在web网站应用中非常常见,这些数据包括网站的pv、用户访问了什么内容,搜索了什么内容等。 这些数据通常以日志的形式记录下来,然后每隔一段时间进行一次统计处理。
传统的日志分析系统提供了一种离线处理日志信息的可扩展方案,但若要进行实时处理,通常会有较大延迟。而现有的消(队列)系统能够很好的处理实时或者近似实时的应用,但未处理的数据通常不会写到磁盘上,这对于Hadoop之类(一小时或者一天只处理一部分数据)的离线应用而言,可能存在问题。Kafka正是为了解决以上问题而设计的,它能够很好地离线和在线应用。
2、 设计目标
(1)数据在磁盘上存取代价为O(1)。一般数据在磁盘上是使用BTree存储的,存取代价为O(lgn)。
(2)高吞吐率。即使在普通的节点上每秒钟也能处理成百上千的message。
(3)显式分布式,即所有的producer、broker和consumer都会有多个,均为分布式的。
(4)支持数据并行加载到Hadoop中。
3、 KafKa部署结构
kafka是显式分布式架构,producer、broker(Kafka)和consumer都可以有多个。Kafka的作用类似于缓存,即活跃的数据和离线处理系统之间的缓存。几个基本概念:
(1)message(消息)是通信的基本单位,每个producer可以向一个topic(主题)发布一些消息。如果consumer订阅了这个主题,那么新发布的消息就会广播给这些consumer。
(2)Kafka是显式分布式的,多个producer、consumer和broker可以运行在一个大的集群上,作为一个逻辑整体对外提供服务。对于consumer,多个consumer可以组成一个group,这个message只能传输给某个group中的某一个consumer.
数据从producer推送到broker,接着consumer在从broker上拉取数据。Zookeeper是一个分布式服务框架 用来解决分布式应用中的数据管理问题等。
在kafka中 有几个重要概念producer生产者 consumer 消费者 topic 主题。
我们来实际开发一个简单的生产者消费者的例子。
生产者:
- public classProducerTest {
- public static void main(String[] args) {
- Properties props = newProperties();
- props.setProperty("metadata.broker.list","xx.xx.xx.xx:9092");
- props.setProperty("serializer.class","kafka.serializer.StringEncoder");
- props.put("request.required.acks","1");
- ProducerConfigconfig = new ProducerConfig(props);
- Producer<String, String> producer = newProducer<String, String>(config);
- KeyedMessage<String, String> data = newKeyedMessage<String, String>("kafka","test-kafka");
- try {
- producer.send(data);
- } catch (Exception e) {
- e.printStackTrace();
- }
- producer.close();
- }
- }
上面的代码中的xx.xx.xx.xx是kafka server的地址.
上面代码的意思就是向主题 kafka中同步(不配置的话 默认是同步发射)发送了一个信息 是test-kafka.
下面来看看消费者:
- public classConsumerTest extends Thread {
- private finalConsumerConnector consumer;
- private final String topic;
- public static voidmain(String[] args) {
- ConsumerTest consumerThread = newConsumerTest("kafka");
- consumerThread.start();
- }
- publicConsumerTest(String topic) {
- consumer =kafka.consumer.Consumer
- .createJavaConsumerConnector(createConsumerConfig());
- this.topic =topic;
- }
- private staticConsumerConfig createConsumerConfig() {
- Properties props = newProperties();
- props.put("zookeeper.connect","xx.xx.xx.xx:2181");
- props.put("group.id", "0");
- props.put("zookeeper.session.timeout.ms","10000");
- // props.put("zookeeper.sync.time.ms", "200");
- // props.put("auto.commit.interval.ms", "1000");
- return newConsumerConfig(props);
- }
- public void run(){
- Map<String,Integer> topickMap = new HashMap<String, Integer>();
- topickMap.put(topic, 1);
- Map<String, List<KafkaStream<byte[],byte[]>>> streamMap =consumer.createMessageStreams(topickMap);
- KafkaStream<byte[],byte[]>stream = streamMap.get(topic).get(0);
- ConsumerIterator<byte[],byte[]> it =stream.iterator();
- System.out.println("--------------------------");
- while(it.hasNext()){
- //
- System.out.println("(consumer)--> " +new String(it.next().message()));
- }
- }
- }
上面的代码就是负责接收生产者发送过来的消息 测试的时候先开启消费者 然后再运行生产者即可看到效果。
接下来 我们将flume 和kafka进行整合:
在flume的source数据源接收到数据后 通过管道 到达sink,我们需要写一个kafkaSink 来将sink从channel接收的数据作为kafka的生产者 将数据 发送给消费者。
具体代码:
- public class KafkaSink extends AbstractSinkimplementsConfigurable {
- private static final Log logger = LogFactory.getLog(KafkaSink.class);
- private Stringtopic;
- private Producer<String, String>producer;
- @Override
- public Status process()throwsEventDeliveryException {
- Channel channel =getChannel();
- Transaction tx =channel.getTransaction();
- try {
- tx.begin();
- Event e = channel.take();
- if(e ==null) {
- tx.rollback();
- return Status.BACKOFF;
- }
- KeyedMessage<String,String> data = new KeyedMessage<String, String>(topic,newString(e.getBody()));
- producer.send(data);
- logger.info("Message: {}"+new String( e.getBody()));
- tx.commit();
- return Status.READY;
- } catch(Exceptione) {
- logger.error("KafkaSinkException:{}",e);
- tx.rollback();
- return Status.BACKOFF;
- } finally {
- tx.close();
- }
- }
- @Override
- public void configure(Context context) {
- topic = "kafka";
- Properties props = newProperties();
- props.setProperty("metadata.broker.list","xx.xx.xx.xx:9092");
- props.setProperty("serializer.class","kafka.serializer.StringEncoder");
- // props.setProperty("producer.type", "async");
- // props.setProperty("batch.num.messages", "1");
- props.put("request.required.acks","1");
- ProducerConfigconfig = new ProducerConfig(props);
- producer = newProducer<String, String>(config);
- }
- }
将此文件打成jar包 传到flume的lib下面 如果你也用的是maven的话 需要用到assembly 将依赖的jar包一起打包进去。
在flume的配置是如下:
- agent1.sources = source1
- agent1.sinks = sink1
- agent1.channels =channel1
- # Describe/configuresource1
- agent1.sources.source1.type= avro
- agent1.sources.source1.bind= localhost
- agent1.sources.source1.port= 44444
- # Describe sink1
- agent1.sinks.sink1.type= xx.xx.xx.KafkaSink(这是类的路径地址)
- # Use a channel whichbuffers events in memory
- agent1.channels.channel1.type= memory
- agent1.channels.channel1.capacity= 1000
- agent1.channels.channel1.transactionCapactiy= 100
- # Bind the source andsink to the channel
- agent1.sources.source1.channels= channel1
- agent1.sinks.sink1.channel= channel1
测试的话是avro的方式传送数据的 可以这样测试
bin/flume-ng avro-client--conf conf -H localhost -p 44444 -F/data/flumetmp/a
/data/flumetmp/a 这个为文件的地址.
测试的时候在本地 一定要把上面写的消费者程序打开 以便接收数据测试是否成功。
接下来我们介绍下storm然后将kafka的消费者和storm进行整合:
Storm:
Storm是一个分布式的实时消息处理系统。
Storm各个组件之间的关系:
Storm集群主要由一个主节点和一群工作节点(worker node)组成,通过 Zookeeper进行协调。
主节点:主节点通常运行一个后台程序 —— Nimbus,用于响应分布在集群中的节点,分配任务和监测故障。
工作节点: Supervisor,负责接受nimbus分配的任务,启动和停止属于自己管理的worker进程。Nimbus和Supervisor之间的协调由zookeeper完成。
Worker:处理逻辑的进程,在其中运行着多个Task,每个task 是一组spout/blots的组合。
Topology:是storm的实时应用程序,从启动开始一直运行,只要有tuple过来 就会触发执行。拓扑:storm的消息流动很像一个拓扑结构。
2. stream是storm的核心概念,一个stream是一个持续的tuple序列,这些tuple被以分布式并行的方式创建和处理。
3. spouts是一个stream的源头,spouts负责从外部系统读取数据,并组装成tuple发射出去,tuple被发射后就开始再topology中传播。
4. bolt是storm中处理 数据的核心,storm中所有的数据处理都是在bolt中完成的
这里就简单介绍一些概念 具体的可以看些详细的教程。
我们接下来开始整合storm和kafka。
从上面的介绍得知storm的spout是负责从外部读取数据的 所以我们需要开发一个KafkaSpout 来作为kafka的消费者和storm的数据接收源。可以看看这个https://github.com/HolmesNL/kafka-spout。我在下面只写一个简单的可供测试。
具体代码:
- public class KafkaSpout implements IRichSpout {
- private static final Log logger = LogFactory.getLog(KafkaSpout.class);
- /**
- *
- */
- private static final long serialVersionUID = -5569857211173547938L;
- SpoutOutputCollector collector;
- private ConsumerConnectorconsumer;
- private Stringtopic;
- public KafkaSpout(String topic) {
- this.topic = topic;
- }
- @Override
- public void open(Map conf, TopologyContext context,
- SpoutOutputCollector collector) {
- this.collector = collector;
- }
- private static ConsumerConfig createConsumerConfig() {
- Properties props = newProperties();
- props.put("zookeeper.connect","xx.xx.xx.xx:2181");
- props.put("group.id","0");
- props.put("zookeeper.session.timeout.ms","10000");
- //props.put("zookeeper.sync.time.ms", "200");
- //props.put("auto.commit.interval.ms", "1000");
- return new ConsumerConfig(props);
- }
- @Override
- public void close() {
- // TODOAuto-generated method stub
- }
- @Override
- public void activate() {
- this.consumer = Consumer.createJavaConsumerConnector(createConsumerConfig());
- Map<String, Integer> topickMap = newHashMap<String, Integer>();
- topickMap.put(topic,new Integer(1));
- Map<String, List<KafkaStream<byte[],byte[]>>>streamMap =consumer.createMessageStreams(topickMap);
- KafkaStream<byte[],byte[]>stream = streamMap.get(topic).get(0);
- ConsumerIterator<byte[],byte[]> it =stream.iterator();
- while (it.hasNext()) {
- String value = newString(it.next().message());
- System.out.println("(consumer)-->" + value);
- collector.emit(new Values(value), value);
- }
- }
- @Override
- public void deactivate() {
- // TODOAuto-generated method stub
- }
- private boolean isComplete;
- @Override
- public void nextTuple() {
- }
- @Override
- public void ack(Object msgId) {
- // TODOAuto-generated method stub
- }
- @Override
- public void fail(Object msgId) {
- // TODOAuto-generated method stub
- }
- @Override
- public void declareOutputFields(OutputFieldsDeclarer declarer) {
- declarer.declare(new Fields("KafkaSpout"));
- }
- @Override
- public Map<String, Object> getComponentConfiguration() {
- // TODOAuto-generated method stub
- return null;
- }
- }
- public class FileBlots implementsIRichBolt{
- OutputCollector collector;
- public void prepare(Map stormConf, TopologyContext context,
- OutputCollector collector) {
- this.collector = collector;
- }
- public void execute(Tuple input) {
- String line = input.getString(0);
- for(String str : line.split("\\s+")){
- List a = newArrayList();
- a.add(input);
- this.collector.emit(a,newValues(str));
- }
- this.collector.ack(input);
- }
- public void cleanup() {
- }
- public void declareOutputFields(OutputFieldsDeclarer declarer) {
- declarer.declare(new Fields("words"));
- }
- public Map<String, Object> getComponentConfiguration() {
- // TODOAuto-generated method stub
- return null;
- }
- }
- public class WordsCounterBlots implementsIRichBolt{
- OutputCollector collector;
- Map<String, Integer> counter;
- public void prepare(Map stormConf, TopologyContext context,
- OutputCollector collector) {
- this.collector = collector;
- this.counter =new HashMap<String, Integer>();
- }
- public void execute(Tuple input) {
- String word = input.getString(0);
- Integer integer = this.counter.get(word);
- if(integer !=null){
- integer +=1;
- this.counter.put(word, integer);
- }else{
- this.counter.put(word, 1);
- }
- System.out.println("execute");
- Jedis jedis = JedisUtils.getJedis();
- jedis.incrBy(word, 1);
- System.out.println("=============================================");
- this.collector.ack(input);
- }
- public void cleanup() {
- for(Entry<String, Integer> entry :this.counter.entrySet()){
- System.out.println("------:"+entry.getKey()+"=="+entry.getValue());
- }
- }
- public void declareOutputFields(OutputFieldsDeclarer declarer) {
- }
- public Map<String, Object> getComponentConfiguration() {
- // TODOAuto-generated method stub
- return null;
- }
- }
Topology测试:
- public class KafkaTopology {
- public static void main(String[] args) {
- try {
- JedisUtils.initialPool("xx.xx.xx.xx", 6379);
- } catch (Exception e) {
- e.printStackTrace();
- }
- TopologyBuilder builder = newTopologyBuilder(); builder.setSpout("kafka",new KafkaSpout("kafka"));
- builder.setBolt("file-blots",new FileBlots()).shuffleGrouping("kafka");
- builder.setBolt("words-counter",new WordsCounterBlots(),2).fieldsGrouping("file-blots",new Fields("words"));
- Config config = new Config();
- config.setDebug(true);
- LocalCluster local = newLocalCluster();
- local.submitTopology("counter", config, builder.createTopology());
- }
- }
至此flume + kafka+storm的整合就写完了。注意 这个是 初始学习阶段做的测试 不可正式用于线上环境,在写本文之时 已经离测试过去了一段时间 所以可能会有些错误 请见谅。
Flume-ng+Kafka+storm的学习笔记的更多相关文章
- Flume 学习笔记之 Flume NG+Kafka整合
Flume NG集群+Kafka集群整合: 修改Flume配置文件(flume-kafka-server.conf),让Sink连上Kafka hadoop1: #set Agent name a1. ...
- 【Storm】学习笔记
Storm 1 基本概念 1.1 分布式.可扩展.高容错.实时流处理.跨语言 1.2 应用场景 1.2.1 实时分析 1.2.2 在线机器学习 1.2.3 分布式RPC 1.2.4 ETL数据抽取 1 ...
- Andrew Ng Machine Learning Coursera学习笔记
课程记录笔记如下: 1.目前ML的应用 包括:数据挖掘database mining.邮件过滤email anti-spam.机器人autonomous robotics.计算生物学computati ...
- Kafka超详细学习笔记【概念理解,安装配置】
目录 本篇要点 Kafka介绍 作为流处理平台的三种特性 主要应用 四个核心API 基本术语 快速开始 安装配置Zookeeper 下载kafka 配置文件 Windows的命令 启动Zookeepe ...
- Flume、Kafka、Storm结合
Todo: 对Flume的sink进行重构,调用kafka的消费生产者(producer)发送消息; 在Sotrm的spout中继承IRichSpout接口,调用kafka的消息消费者(Consume ...
- Flume 学习笔记之 Flume NG高可用集群搭建
Flume NG高可用集群搭建: 架构总图: 架构分配: 角色 Host 端口 agent1 hadoop3 52020 collector1 hadoop1 52020 collector2 had ...
- Flume 学习笔记之 Flume NG概述及单节点安装
Flume NG概述: Flume NG是一个分布式,高可用,可靠的系统,它能将不同的海量数据收集,移动并存储到一个数据存储系统中.轻量,配置简单,适用于各种日志收集,并支持 Failover和负载均 ...
- Flume+Kafka+Storm+Hbase+HDSF+Poi整合
Flume+Kafka+Storm+Hbase+HDSF+Poi整合 需求: 针对一个网站,我们需要根据用户的行为记录日志信息,分析对我们有用的数据. 举例:这个网站www.hongten.com(当 ...
- Flume+Kafka+storm的连接整合
Flume-ng Flume是一个分布式.可靠.和高可用的海量日志采集.聚合和传输的系统. Flume的文档可以看http://flume.apache.org/FlumeUserGuide.html ...
随机推荐
- 写sql语句连接的时候注意的一个小细节
我在写权限的查询的时候,用到了sql语句的链接写一下出错的时候的代码 $sqlpid="select auth_name from sw_auth where auth_level=0&qu ...
- 几个与时间相关的php的函数
这些函数很常用,但是不用的话,像我这样的初学者放下就记不清了,这时最好的办法就是去查文档,写一下印象会更深一些 1.时间戳函数strtotime():一个就是string to time(我自己这样理 ...
- react-native 学习
官网 https://facebook.github.io/react-native/docs/getting-started.html#content 下载 npm install -g react ...
- 校内OJ 1128 词链(link)(Trie+DFS)
1128: 词链(link) 时间限制: 1 Sec 内存限制: 64 MB 提交: 23 解决: 7 [提交][状态][讨论版] 题目描述 给定一个仅包含小写字母的英文单词表,其中每个单词最多包 ...
- 【转】区别和认识.Net四个判等函数
原文地址:不详 .Net有四个判等函数?不少人看到这个标题,会对此感到怀疑.事实上确是如此,.Net提供了ReferenceEquals.静态Equals,具体类型的Equals以及==操作符这四个判 ...
- Maven问题总结:could not resolve archetype xxxxxxx from any of the configured repositories
错误提示 Eclipse中通过Archetype创建Maven项目时报错:Could not resolve archetype xxxxxxx from any of the configured ...
- Unity 中场景切换
Unity游戏开发中,单个Scene解决所有问题似乎不可能,那么多个Scene之间的切换是必然存在.如果仅仅是切换,似乎什么都好说,但是在场景比较大的时候不想让玩家等待加载或者说场景与场景之间想通过一 ...
- Python操作MySQL以及中文乱码的问题
Python操作MySQL需要安装Python-MySQL可以从网上搜索一下,和一般的Python包一样安装 安装好之后,模块名字叫做MySQLdb ,在Window和Linux环境下都可以使用,试验 ...
- composer autoload
1.引入autoload 文件 include “vendor/autoload.php” 2.自定义的单文件引入 “autoload”:{ "files":["lib/ ...
- fenshijin
#include<stdio.h> int map[6][4]={8,0,18,10, 13,10,15,20, 10,50,13,30, ...