Flume+Kafka+Storm整合

1. 需求:

有一个客户端Client可以产生日志信息,我们需要通过Flume获取日志信息,再把该日志信息放入到Kafka的一个Topic:flume-to-kafka

再由Storm读取该topic:flume-to-kafka,进行日志分析处理(这里我们做的逻辑处理为filter,即过滤日志信息),处理完日志信息后,再由Storm把处理好的日志信息放入到Kafka的另一个topic:storm-to-kafka

2.组件分布情况

我总共搭建了3个节点node1,node2,node3

Zookeeper安装在node1,node2,nod3

Flume安装在node2

Kafka安装在node1,node2,node3

Storm安装在node1,node2,node3

3.JDK安装

--在node1, node2, node3上面安装jdk
--install JDK -- http://blog.51cto.com/vvxyz/1642258(LInux安装jdk的三种方法)
--解压安装
rpm -ivh your-package.rpm --修改环境变量
vi /etc/profile JAVA_HOME=/usr/java/jdk1.7.0_67
JRE_HOME=/usr/java/jdk1.7.0_67/jre
CLASS_PATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
export JAVA_HOME JRE_HOME CLASS_PATH PATH :wq --使配置有效
source /etc/profile

4.Zookeeper的安装

---============================
--解压zookeeper压缩包并安装
tar -zxvf zookeeper-3.4.6.tar.gz --创建zookeeper的软链
ln -sf /root/zookeeper-3.4.6 /home/zk --配置zookeeper
cd /home/zk/conf/ --把下面的zoo_sample.cfg文件重新命名
cp zoo_sample.cfg zoo.cfg --修改zoo.cfg配置文件
vi zoo.cfg --设置zookeeper的文件存放目录
--找到dataDir=/tmp/zookeeper,并设置为下面值
dataDir=/opt/zookeeper --设置zookeeper集群
server.1=node1:2888:3888
server.2=node2:2888:3888
server.3=node3:2888:3888 :wq --创建/opt/zookeeper目录
mkdir /opt/zookeeper --进入/opt/zookeeper目录
cd /opt/zookeeper --创建一个文件myid
vi myid --输入1
1
:wq
--以此类推,在node2,node3,值分别是2, 3 --拷贝zookeeper目录到node2, node3的/opt/目录下面
cd ..
scp -r zookeeper/ root@node2:/opt/
scp -r zookeeper/ root@node3:/opt/ --分别进入到node2, node3里面,修改/opt/zookeeper/myid,值分别是2, 3 --作为以上配置,把node1里面的zookeeper拷贝到node2, node3上面。
scp -r zookeeper-3.4.6 root@node2:~/
scp -r zookeeper-3.4.6 root@node3:~/ --分别进入到node2, node3里面,创建软链
ln -sf /root/zookeeper-3.4.6/ /home/zk --配置zookeeper环境变量
cd /home/zk/bin --修改/etc/profile文件,把zookeeper的bin目录路径添加进去
vi /etc/profile
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin:/home/zk/bin --让配置文件生效
source /etc/profile --分别进入到node2, node3里面,修改/etc/profile文件,把zookeeper的bin目录路径添加进去 --作为环境变量配置,就可以启动zookeeper了。
--分别在node1, node2, node3上面启动zookeeper
zkServer.sh start --测试是否启动成功
jps
--观察是否有QuorumPeerMain进程

5.Flume的安装

---------------------------------------------------
--安装Flume
--把安装包上传到node2上面
cd
tar -zxvf apache-flume-1.6.0-bin.tar.gz --创建软链
ln -s /root/apache-flume-1.6.0-bin /home/flume --配置flume
cd /root/apache-flume-1.6.0-bin/conf cp flume-env.sh.template flume-env.sh vi flume-env.sh --配置JDK
export JAVA_HOME=/usr/java/jdk1.7.0_67 :wq --加入系统变量
vi /etc/profile export FLUME_HOME=/root/apache-flume-1.6.0-bin
export PATH=$PATH:$FLUME_HOME/bin :wq source /etc/profile --验证是否安装成功
flume-ng version flume-ng version
Flume 1.6.0
Source code repository: https://git-wip-us.apache.org/repos/asf/flume.git
Revision: 2561a23240a71ba20bf288c7c2cda88f443c2080
Compiled by hshreedharan on Mon May 11 11:15:44 PDT 2015
From source with checksum b29e416802ce9ece3269d34233baf43f

6.Kafka的安装

---------------------------------------------------
--kafka安装
--在node1, node2, node3上面搭建kafka
--先进入node1
mkdir /root/kafka --解压
tar -zxvf kafka_2.10-0.8.2.2.tgz --创建软链
ln -s /root/kafka/kafka_2.10-0.8.2.2 /home/kafka-2.10 --配置
cd /root/kafka/kafka_2.10-0.8.2.2/config vi server.properties --node1=0, node2=1,node2=2
broker.id=0
log.dirs=/opt/kafka-log
zookeeper.connect=node1:2181,node2:2181,node3:2181 :wq --为了启动方便
cd /root/kafka/kafka_2.10-0.8.2.2
vi start-kafka.sh nohup bin/kafka-server-start.sh config/server.properties > kafka.log 2>&1 & :wq chmod 755 start-kafka.sh --配置好以后
--分发到node2,node3
cd /root/kafka/
scp -r kafka_2.10-0.8.2.2/ root@node2:/root/kafka
scp -r kafka_2.10-0.8.2.2/ root@node3:/root/kafka --进入到node2
cd /root/kafka/kafka_2.10-0.8.2.2/config vi server.properties --node1=0, node2=1,node2=2
broker.id=1 :wq --进入到node3
cd /root/kafka/kafka_2.10-0.8.2.2/config vi server.properties --node1=0, node2=1,node2=2
broker.id=2 :wq --启动kafka
./zkServer.sh start --分别进入node1,node2,node3
cd /root/kafka/kafka_2.10-0.8.2.2
./start-kafka.sh --检查是否启动
jps
查看是否有Kafka进程

7.Storm的安装

------------
--Storm分布式安装
--部署到node1,node2,node3节点上
--进入node1
cd /root/apache-storm-0.10.0/conf vi storm.yaml --配置如下
# storm.zookeeper.servers:
- "node1"
- "node2"
- "node3"
#
nimbus.host: "node1"
storm.local.dir: "/opt/storm"
supervisor.slots.ports:
- 6700
- 6701
- 6702
- 6703 :wq --从node1分发到node2,node3
scp -r apache-storm-0.10.0 root@node2:/
scp -r apache-storm-0.10.0 root@node3:/ --分别进入node2,node3创建软链
ln -r /root/apache-storm-0.10.0 /home/storm-0.10 --分别进入node1,node2,node3快捷启动
cd /root/apache-storm-0.10.0 vi start-storm.sh nohup bin/storm nimbus >> logs/numbus.out 2>&1 &
nohup bin/storm supervisor >> logs/supervisor.out 2>&1 & --node1上面配置,node2,node3上面不需要UI
nohup bin/storm ui >> logs/ui.out 2>&1 &
nohup bin/storm drpc >> logs/drpc.out 2>&1 & :wq --分别进入node1,node2,node3快捷stop-storm vi stop-storm.sh --node1上面配置,node2,node3上面不需要UI
kill -9 `jps | grep core | awk '{print $1}'` kill -9 `jps | grep supervisor | awk '{print $1}'`
kill -9 `jps | grep nimbus | awk '{print $1}'`
kill -9 `jps | grep worker | awk '{print $1}'`
kill -9 `jps | grep LogWriter | awk '{print $1}'` :wq chmod 755 start-storm.sh
chmod 755 stop-storm.sh --启动Zookeeper服务
--在node1,node2,node3上面启动
zkServer.sh start --在node1,node2,node3上面启动Storm
cd /root/apache-storm-0.10.0
./start-storm.sh --上传storm_wc.jar 文件
./storm jar /root/storm_wc.jar storm.wordcount.Test wordcount ------------
Storm DRPC 配置
--进入node1
cd /root/apache-storm-0.10.0/conf vi storm.yaml drpc.servers:
- "node1" :wq --从node1,分发到node2,node3
cd /root/apache-storm-0.10.0/conf/
scp -r root@node2:/root/apache-storm-0.10.0/conf
scp -r root@node3:/root/apache-storm-0.10.0/conf --配置完,进入node1,node2,node3
cd /root/apache-storm-0.10.0
./start-storm.sh &

8.Flume+Kafka+Storm整合

8.1.配置Flume

--从node2
cd flumedir vi flume_to_kafka --node2配置如下
a1.sources = r1
a1.sinks = k1
a1.channels = c1 # Describe/configure the source
a1.sources.r1.type = avro
a1.sources.r1.bind = node2
a1.sources.r1.port = 41414 # Describe the sink
a1.sinks.k1.type = org.apache.flume.sink.kafka.KafkaSink
a1.sinks.k1.topic = flume-to-kafka
a1.sinks.k1.brokerList = node1:9092,node2:9092,node3:9092
a1.sinks.k1.requiredAcks = 1
a1.sinks.k1.batchSize = 20 # Use a channel which buffers events in memory
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000000
a1.channels.c1.transactionCapacity = 10000 # Bind the source and sink to the channel
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1 :wq

8.2.启动Zookeeper

--启动Zookeeper,在node1,node2,node3
--关闭防火墙
service iptables stop --启动Zookeeper
zkServer.sh start

8.3.启动Kfaka

--启动kafka
--分别进入node1,node2,node3
cd /root/kafka/kafka_2.10-0.8.2.2
./start-kafka.sh

8.4.启动Flume

--进入node2,启动
cd /root/flumedir flume-ng agent -n a1 -c conf -f flume_to_kafka -Dflume.root.logger=DEBUG,console

8.4.启动客户端Client

启动客户端产生日志信息。

大家可以参考RPC clients - Avro and Thrift的代码

import org.apache.flume.Event;
import org.apache.flume.EventDeliveryException;
import org.apache.flume.api.RpcClient;
import org.apache.flume.api.RpcClientFactory;
import org.apache.flume.event.EventBuilder;
import java.nio.charset.Charset; public class MyApp {
public static void main(String[] args) {
MyRpcClientFacade1 client = new MyRpcClientFacade1();
// Initialize client with the remote Flume agent's host and port
client.init("node2", 41414); // Send 10 events to the remote Flume agent. That agent should be
// configured to listen with an AvroSource.
String sampleData = "Hello ERROR ! ------ Test";
for (int i = 500; i < 505; i++) {
client.sendDataToFlume(sampleData + " " + i);
System.out.println(sampleData + " " + i);
} client.cleanUp();
}
} class MyRpcClientFacade1 {
private RpcClient client;
private String hostname;
private int port; public void init(String hostname, int port) {
// Setup the RPC connection
this.hostname = hostname;
this.port = port;
this.client = RpcClientFactory.getDefaultInstance(hostname, port);
// Use the following method to create a thrift client (instead of the
// above line):
// this.client = RpcClientFactory.getThriftInstance(hostname, port);
} public void sendDataToFlume(String data) {
// Create a Flume Event object that encapsulates the sample data
Event event = EventBuilder.withBody(data, Charset.forName("UTF-8")); // Send the event
try {
client.append(event);
} catch (EventDeliveryException e) {
// clean up and recreate the client
client.close();
client = null;
client = RpcClientFactory.getDefaultInstance(hostname, port);
// Use the following method to create a thrift client (instead of
// the above line):
// this.client = RpcClientFactory.getThriftInstance(hostname, port);
}
} public void cleanUp() {
// Close the RPC connection
client.close();
}
}

在eclipse控制台输出的结果是:

[ WARN ] - [ org.apache.flume.api.NettyAvroRpcClient.configure(NettyAvroRpcClient.java:505) ] Invalid value for batchSize: 0; Using default value.
[ WARN ] - [ org.apache.flume.api.NettyAvroRpcClient.configure(NettyAvroRpcClient.java:634) ] Using default maxIOWorkers
Hello ERROR ! ------ Test 500
Hello ERROR ! ------ Test 501
Hello ERROR ! ------ Test 502
Hello ERROR ! ------ Test 503
Hello ERROR ! ------ Test 504

8.5.查看Kafka的Topic

--进入node3,查看kafka的topic
cd /home/kafka-2.10/bin
./kafka-topics.sh --zookeeper node1,node2,node3 --list

可以看到,由于客户端代码的执行,Kafka里面的topic:flume-to-kafka被自动创建

8.6.启动Kafka Consumer:flume-to-kafka

我们在这里是查看topic: flume-to-kafka的消费信息

--进入node3,启动kafka消费者
cd /home/kafka-2.10/bin
./kafka-console-consumer.sh --zookeeper node1,node2,node3 --from-beginning --topic flume-to-kafka

控制台输出:

Hello ERROR ! ------ Test 500
Hello ERROR ! ------ Test 501
Hello ERROR ! ------ Test 502
Hello ERROR ! ------ Test 503
Hello ERROR ! ------ Test 504

8.7.创建Topic:storm-to-kafka

在Kafka里面创建另一个topic:

--进入node1,创建一个topic:storm-to-kafka
--设置3个partitions
--replication-factor=3
./kafka-topics.sh --zookeeper node1,node2,node3 --create --topic storm-to-kafka --partitions 3 --replication-factor 3

8.8.运行Storm代码

package storm.logfilter;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties; import storm.kafka.KafkaSpout;
import storm.kafka.SpoutConfig;
import storm.kafka.StringScheme;
import storm.kafka.ZkHosts;
import storm.kafka.bolt.KafkaBolt;
import storm.kafka.bolt.mapper.FieldNameBasedTupleToKafkaMapper;
import storm.kafka.bolt.selector.DefaultTopicSelector;
import backtype.storm.Config;
import backtype.storm.LocalCluster;
import backtype.storm.StormSubmitter;
import backtype.storm.spout.SchemeAsMultiScheme;
import backtype.storm.topology.BasicOutputCollector;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.TopologyBuilder;
import backtype.storm.topology.base.BaseBasicBolt;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Tuple;
import backtype.storm.tuple.Values; public class LogFilterTopology { public static class FilterBolt extends BaseBasicBolt {
private static final long serialVersionUID = 1L; @Override
public void execute(Tuple tuple, BasicOutputCollector collector) {
String line = tuple.getString(0);
// 包含ERROR的行留下
if (line.contains("ERROR")) {
System.err.println("Filter: " + line + " ~ filtered.");
collector.emit(new Values(line + " ~ filtered."));
}
} @Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
// 定义message提供给后面FieldNameBasedTupleToKafkaMapper使用
declarer.declare(new Fields("message"));
}
} public static void main(String[] args) throws Exception {
TopologyBuilder builder = new TopologyBuilder(); // https://github.com/apache/storm/tree/master/external/storm-kafka
// config kafka spout,话题
String topic = "flume-to-kafka";
ZkHosts zkHosts = new ZkHosts("node1:2181,node2:2181,node3:2181");
// /MyKafka,偏移量offset的根目录,记录队列取到了哪里
SpoutConfig spoutConfig = new SpoutConfig(zkHosts, topic, "/MyKafka", "MyTrack");
List<String> zkServers = new ArrayList<String>();
for (String host : zkHosts.brokerZkStr.split(",")) {
zkServers.add(host.split(":")[0]);
} spoutConfig.zkServers = zkServers;
spoutConfig.zkPort = 2181;
// 是否从头开始消费
spoutConfig.forceFromStart = true;
spoutConfig.socketTimeoutMs = 60 * 1000;
// StringScheme将字节流转解码成某种编码的字符串
spoutConfig.scheme = new SchemeAsMultiScheme(new StringScheme()); KafkaSpout kafkaSpout = new KafkaSpout(spoutConfig); // set kafka spout
builder.setSpout("kafkaSpout", kafkaSpout, 3); // set bolt
builder.setBolt("filterBolt", new FilterBolt(), 8).shuffleGrouping("kafkaSpout"); // 数据写出
// set kafka bolt
// withTopicSelector使用缺省的选择器指定写入的topic: storm-to-kafka
// withTupleToKafkaMapper tuple==>kafka的key和message
KafkaBolt kafka_bolt = new KafkaBolt().withTopicSelector(new DefaultTopicSelector("storm-to-kafka"))
.withTupleToKafkaMapper(new FieldNameBasedTupleToKafkaMapper()); builder.setBolt("kafkaBolt", kafka_bolt, 2).shuffleGrouping("filterBolt"); Config conf = new Config();
// set producer properties.
Properties props = new Properties();
props.put("metadata.broker.list", "node1:9092,node2:9092,node3:9092");
/**
* Kafka生产者ACK机制 0 : 生产者不等待Kafka broker完成确认,继续发送下一条数据 1 :
* 生产者等待消息在leader接收成功确认之后,继续发送下一条数据 -1 :
* 生产者等待消息在follower副本接收到数据确认之后,继续发送下一条数据
*/
props.put("request.required.acks", "1");
props.put("serializer.class", "kafka.serializer.StringEncoder");
conf.put("kafka.broker.properties", props); conf.put(Config.STORM_ZOOKEEPER_SERVERS, zkServers); if (args == null || args.length == 0) {
// 本地方式运行
LocalCluster localCluster = new LocalCluster();
localCluster.submitTopology("storm-kafka-topology", conf, builder.createTopology());
} else {
// 集群方式运行
conf.setNumWorkers(3);
StormSubmitter.submitTopology(args[0], conf, builder.createTopology());
} }
}

8.9.启动Kafka Consumer:storm-to-kafka

我们在这里是查看topic: storm-to-kafka的消费信息

--进入node1,启动kafka消费者
cd /home/kafka-2.10/bin
./kafka-console-consumer.sh --zookeeper node1,node2,node3 --from-beginning --topic storm-to-kafka

控制台输出:

Hello ERROR ! ------ Test 504 ~ filtered.
Hello ERROR ! ------ Test 500 ~ filtered.
Hello ERROR ! ------ Test 501 ~ filtered.
Hello ERROR ! ------ Test 503 ~ filtered.
Hello ERROR ! ------ Test 502 ~ filtered.

========================================================

More reading,and english is important.

I'm Hongten

大哥哥大姐姐,觉得有用打赏点哦!你的支持是我最大的动力。谢谢。
Hongten博客排名在100名以内。粉丝过千。
Hongten出品,必是精品。

E | hongtenzone@foxmail.com  B | http://www.cnblogs.com/hongten

========================================================

Flume+Kafka+Storm整合的更多相关文章

  1. 大数据处理框架之Strom:Flume+Kafka+Storm整合

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk1.8 storm-0.9 apache-flume-1.6.0 ...

  2. Flume+Kafka+Storm+Hbase+HDSF+Poi整合

    Flume+Kafka+Storm+Hbase+HDSF+Poi整合 需求: 针对一个网站,我们需要根据用户的行为记录日志信息,分析对我们有用的数据. 举例:这个网站www.hongten.com(当 ...

  3. Flume+Kafka+storm的连接整合

    Flume-ng Flume是一个分布式.可靠.和高可用的海量日志采集.聚合和传输的系统. Flume的文档可以看http://flume.apache.org/FlumeUserGuide.html ...

  4. 简单测试flume+kafka+storm的集成

    集成 Flume/kafka/storm 是为了收集日志文件而引入的方法,最终将日志转到storm中进行分析.storm的分析方法见后面文章,这里只讨论集成方法. 以下为具体步骤及测试方法: 1.分别 ...

  5. flume+kafka+storm+mysql架构设计

    前段时间学习了storm,最近刚开blog,就把这些资料放上来供大家参考. 这个框架用的组件基本都是最新稳定版本,flume-ng1.4+kafka0.8+storm0.9+mysql (项目是mav ...

  6. Flume+Kafka+Storm+Redis 大数据在线实时分析

    1.实时处理框架 即从上面的架构中我们可以看出,其由下面的几部分构成: Flume集群 Kafka集群 Storm集群 从构建实时处理系统的角度出发,我们需要做的是,如何让数据在各个不同的集群系统之间 ...

  7. 一次简单的springboot+dubbo+flume+kafka+storm+redis系统

    最近无事学习一下,用springboot+dubbo+flume+kafka+storm+redis做了一个简单的scenic系统 scenicweb:展现层,springboot+dubbo sce ...

  8. flume+kafka+storm

    centos06.6+JDK1.7 flume1.4+kafka2.10+storm0.9.3 zookeeper3.4.6 集群: 192.168.80.133 x01 192.168.80.134 ...

  9. flume+kafka+storm单机部署

    flume-1.6.0 kafka0.9.0.0 storm0.9.6 一.部署flume 1.解压 tar -xzvf apache-flume-1.6.0-bin.tar.gz -C ../app ...

随机推荐

  1. shell 批量远程主机执行命令

    [yunwei@Y24-209 ~]$cat ls.sh #!/bin/bash ip55=`cat ip1` for i in $ip55;do ping -c 1 $i if [ $? -eq 0 ...

  2. 20164305 徐广皓 Exp4 恶意代码分析

    实践目标 1.1是监控你自己系统的运行状态,看有没有可疑的程序在运行. 1.2是分析一个恶意软件,就分析Exp2或Exp3中生成后门软件:分析工具尽量使用原生指令或sysinternals,systr ...

  3. Java基础 -- String,StringBuilder,StringBuffer三者的区别

    结论 1-String,StringBuilder,StringBuffer 之间的区别主要是在两个方面,即运行速度和线程安全这两方面: 首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:St ...

  4. # 20175333曹雅坤《Java程序设计》第四周学习总结

    教材学习内容总结 第五章:子类与继承 5.1子类与父类:关键字extends 5.2子类的继承性:如果子类与父类在一个包中,除了private其他都可以继承:如果不在一个包中,则private和友好都 ...

  5. 笔记,ajax,事件绑定,序列化

    1. Python序列化 字符串 = json.dumps(对象) 对象->字符串 对象 = json.loads(字符串) 字符串->对象 JavaScript: 字符串 = JSON. ...

  6. jqGrid基础写法

    $("#jqGrid").jqGrid({ url: baseURL + 'sys/scheduleLog/list', datatype: "json", c ...

  7. STM32F0使用LL库实现Modbus通讯

    在本次项目中,限于空间要求我们选用了STM32F030F4作为控制芯片.这款MCU不但封装紧凑,而且自带的Flash空间也非常有限,所以我们选择了LL库实现.本篇将说明基于LL实现USART通讯. 1 ...

  8. Java_异常以及处理

    目录 JAVA异常 异常的处理机制 自定义异常 写了一天的bug,来try...catch...finally了解一下.异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的. ...

  9. 可持久化线段树——区间更新hdu4348

    和线段树类似,每个结点也要打lazy标记 但是lazy标记和线段树不一样 具体区别在于可持久化后lazy-tag不用往下传递,而是固定在这个区间并不断累加,变成了这个区间固有的性质(有点像分块的标记了 ...

  10. python3 迭代器(Iterator)和生成器(generator)

    一.迭代器定义: 迭代是访问集合元素的一种方式,迭代器是一个可以记住遍历位置的对象: 集合数据类型如list.dict.str等是Iterable但不是Iterator,不过可以通过iter()函数获 ...