实时分析

实时分析
1.kafka中创建主题

2.storm从kafka中消费数据
storm提供了storm从kafka消费数据的jar包
storm开发包
kafka开发包
storm连接kafka的开发包
其他包
**注意可能要删除重复的log4j相关的包


导入相关jar包 按照文档编写代码即可实现storm从kafka消费数据


方式一:可以自己开发spout利用kafka提供的api消费数据
方式二:利用storm提供的kafka扩展包连接
String topic = "flux";
BrokerHosts hosts = new ZkHosts("hadoop01,hadoop02,hadoop03:2181");
SpoutConfig spoutConfig = new SpoutConfig(hosts,topic, "/" + topic, UUID.randomUUID().toString());
spoutConfig.scheme = new SchemeAsMultiScheme(new StringScheme());
KafkaSpout spout = new KafkaSpout(spoutConfig);


3.处理业务逻辑
数据清洗
"url","urlname","uvid","sid","scount","stime","cip"
pv
用户一次访问就是一个pv 直接将每次访问都记为1个pv即可
uv
独立访客数 - 当前这个uvid 在今天的数据中是否是第一次出现 如果是记为1 否则为0
-应该将每条记录都存入hbase作为uv计算的依据
-每条记录过来时用uvid和数据库中今天的uvid进行比较 如果发现匹配 则uvid为0 匹配不到则记为1


设计hbase表结果:
列族的设计:
设计一个列族名为cf1即可
行键的设计:
"url","urlname","uvid","sid","scount","stime","cip"
time_uvid_cip_rand
1495244059010_45189712356761262218_0:0:0:0:0:0:0:1_xxxxx(5)
^\d+_xxxxx_.*$
^\d+_\d+_xxxx_.*$
^\d+_xxxx_.*$


create 'flux','cf1';


vv
当前访问是否是一个新的会话 - 是 则 vv为1 否则为0

newip
当前的访问是否是一个历史上从未出现过的ip - 是 newip 为1 否则为0

newcust
当前的访问是否是一个历史上从未出现过的uvid - 是 newcust 为1 否则为0


-------------------
br
跳出率 - 一段时间内 跳出的会话总数/所有的会话总数 得到的比率 - 由于不能根据一条日志 立即推断出是否是一个跳出的会话 所以这个参数不适合用实时计算


avgtime
平均在线时长 - 一段时间内 所有的会话在线时长的平均值 - 由于不能根据一条日志 立即推断出是否是一个会话的完结 所以这个参数不适合用实时计算


avgdeep
平均访问深度 - 一段时间内所有的会话访问深度的平均值 - 由于不能根据一条日志 立即推断出是否是一个会话的结束 所以这个参数不适合用实时计算


以上的参数都是需要积累一段时间数据后 基于这一段时间内数据来进行计算的 更适合于通过离线计算来实现
但是其实在现实情况中 如果想要在较短的时间段内进行如上参数的统计 每次都去启动离线分析是 不太效率的做法 甚至可能无法按时完成任务 像这种情况下人们还是期望能够以更类似于实时计算的方式来对数据做处理 虽然是一段时间内的数据的数据的处理 但是由于时间段比较小 数据量也不算太大 更像一个实时分析的场景
那么如何实现以上利用实时分析计算一段时间内数据的需求呢?
可以设计一个特殊的spout 内置一个定时器 每隔指定的时长就向后发送一个tuple表示时间到了 要求后续的bolt们进行计算 后续的bolt收到这个消息后 开始计算这段时间内收集到的数据


===Storm的tick机制--定时触发任务机制======================
storm在0.8以上的版本中提供了tick机制实现定时任务。
它能够让任何bolt的所有task每隔一段时间(精确到秒级,用户可以自定义)收到一个来自_systemd的_tick stream的tick tuple,bolt收到这样的tuple后可以根据业务需求完成相应的处理。
方式一:为某一个特定的bolt指定定时任务
在bolt中覆盖getComponentConfiguration,在其中设置conf的属性TOPOLOGY_TICK_TUPLE_FREQ_SECS设置为指定时间间隔
@Override
public Map<String, Object> getComponentConfiguration() {
Config conf = new Config();
conf.put(conf.TOPOLOGY_TICK_TUPLE_FREQ_SECS, 900);
return conf;
}
这样这个bolt将会在程序启动后每隔指定时长都会收到一个定时发送tuple来触发程序
在execute方法中可以使用如下判断获知是否是定时任务出发的代码:
if (tuple.getSourceComponent().equals(Constants.SYSTEM_COMPONENT_ID)  && tuple.getSourceStreamId().equals(Constants.SYSTEM_TICK_STREAM_ID)){
//是定时tuple触发的
}else{
//是普通tuple触发的
}
方式二:可以为整个topology指定定时任务,这样整个topology中的所有bolt都会定时收到tuple
代码如下
Config conf = new Config();
conf.put(conf.TOPOLOGY_TICK_TUPLE_FREQ_SECS, 7);
如果即设置了全局定时器 又为某个bolt单独制定定时器,则单独启动的起作用。
==================================================


4.结果存储到mysql中
create database fluxdb;
use fluxdb;
create table tongji_2(
stime DateTime,
pv int,
uv int,
vv int,
newip int,
newcust int
);


create table tongji_3(
stime DateTime,
br double,
avgtime double,
avgdeep double
);

猜你喜欢

转载自blog.csdn.net/vitaair/article/details/80220633