storm高并发PV统计,利用zookeeper锁输出汇总值

汇总型方案:
1、shuffleGrouping下,pv(单线程结果) * Executer并发数
一个Executer默认一个task,如果设置Task数大于1,公式应该是:
pv(单线程结果) * Task 数 ,
同一个Executer下task的线程ID相同,taskId不同

优点:简单、计算量小
缺点:稍有误差,但绝大多数场景能接受

优化:
案例PVBolt中每个Task都会输出一个汇总值,实际只需要一个Task输出汇总值,
利用Zookeeper锁来做到只一个Task输出汇总值,而且每5S输出一次


[size=large]1、pom.xml增加zk[/size]
[quote]pom.xml中增加ZK:
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.10</version>
</dependency>
[/quote]
[quote]
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>StormMavenProject</artifactId>
<packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>StormMavenProject</name>
<url>http://maven.apache.org</url>
<dependencies>

<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>5.0.3</version>
</dependency>
<dependency>
<groupId>org.clojure</groupId>
<artifactId>clojure</artifactId>
<version>1.7.0</version>
</dependency>
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.8</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.6.6</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.8</version>
</dependency>
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>minlog</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.objenesis</groupId>
<artifactId>objenesis</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>reflectasm</artifactId>
<version>1.10.1</version>
</dependency>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.apache.storm</groupId>
<artifactId>storm-core</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.storm</groupId>
<artifactId>storm-rename-hack</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>ring-cors</groupId>
<artifactId>ring-cors</artifactId>
<version>0.1.5</version>
</dependency>


<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.10</version>
</dependency>



</dependencies>
<build>
<finalName>StormMavenProject</finalName>
</build>
</project>
[/quote]

2、创建队列数据源


public class SourceSpout implements IRichSpout{

/**
* 数据源Spout
*/
private static final long serialVersionUID = 1L;

Queue<String> queue = new ConcurrentLinkedQueue<String>();

SpoutOutputCollector collector = null;

String str = null;

public void nextTuple() {
if (queue.size() >= 0) {
collector.emit(new Values(queue.poll()));
}
try {
Thread.sleep(500) ;
} catch (InterruptedException e) {
e.printStackTrace();
}

}

public void open(Map conf, TopologyContext context,
SpoutOutputCollector collector) {
try {
this.collector = collector;

Random random = new Random();
String[] hosts = { "www.taobao.com" };
String[] session_id = { "ABYH6Y4V4SCVXTG6DPB4VH9U123", "XXYH6YCGFJYERTT834R52FDXV9U34", "BBYH61456FGHHJ7JL89RG5VV9UYU7",
"CYYH6Y2345GHI899OFG4V9U567", "VVVYH6Y4V4SFXZ56JIPDPB4V678" };
String[] time = { "2014-01-07 08:40:50", "2014-01-07 08:40:51", "2014-01-07 08:40:52", "2014-01-07 08:40:53",
"2014-01-07 09:40:49", "2014-01-07 10:40:49", "2014-01-07 11:40:49", "2014-01-07 12:40:49" };

for (int i = 0; i < 20; i++) {
queue.add(hosts[0]+"\t"+session_id[random.nextInt(5)]+"\t"+time[random.nextInt(8)]);
}

} catch (Exception e) {
e.printStackTrace();
}
}

public void close() {
// TODO Auto-generated method stub
}

public void declareOutputFields(OutputFieldsDeclarer declarer) {
// TODO Auto-generated method stub
declarer.declare(new Fields("log"));
}


public Map<String, Object> getComponentConfiguration() {
// TODO Auto-generated method stub
return null;
}

public void ack(Object msgId) {
// TODO Auto-generated method stub
System.out.println("spout ack:"+msgId.toString());
}


public void activate() {
// TODO Auto-generated method stub

}



public void deactivate() {
// TODO Auto-generated method stub

}


public void fail(Object msgId) {
// TODO Auto-generated method stub
System.out.println("spout fail:"+msgId.toString());
}

}


[size=large]3、编写bolt[/size]


public class PVBolt implements IRichBolt{

/**
* zookeeper写入某个线程的id到zookeeper目录,bolt在输出pv时,通过对比线程id确定是否输出。
*/
private static final long serialVersionUID = 1L;

public static final String zk_path = "/lock/storm/pv";


public void cleanup() {
try {
zKeeper.close();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String logString = null;
String lockData = null;
String session_id = null;
ZooKeeper zKeeper = null;

long Pv = 0;
long beginTime = System.currentTimeMillis() ;
long endTime = 0;


public void execute(Tuple input) {
try {
endTime = System.currentTimeMillis() ;
logString = input.getString(0);
if (logString != null) {
session_id = logString.split("\t")[1];
if (session_id != null) {
Pv ++ ;
}
}
//5秒钟输出一次
if (endTime - beginTime >= 5 * 1000) {
System.err.println(lockData+" ======================== ");
if (lockData.equals(new String(zKeeper.getData(zk_path, false, null)))) {
System.err.println("pv ======================== "+ Pv * 4);
}
beginTime = System.currentTimeMillis() ;
}
} catch (Exception e) {
e.printStackTrace();
}

}


public void prepare(Map stormConf, TopologyContext context,
OutputCollector collector) {
try {
//创建zookeeper对象,三个参数:zookeper节点,超时,监听
zKeeper = new ZooKeeper("192.168.1.201:2181,192.168.1.202:2181",3000,new Watcher(){

public void process(WatchedEvent event) {
System.out.println("event:"+event.getType());
}
});

//判断zookeeper是否连上,如果没连上,进入sleep状态
while (zKeeper.getState() != ZooKeeper.States.CONNECTED) {
Thread.sleep(1000);
}

InetAddress address = InetAddress.getLocalHost();
lockData = address.getHostAddress() + ":" +context.getThisTaskId() ;
System.err.println(lockData+"++++++++++++++++++++++++++++");
//将线程ID写入zookeeper临时目录。
if(zKeeper.exists(zk_path, false) == null)
{
zKeeper.create(zk_path, lockData.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
}

} catch (Exception e) {
try {
zKeeper.close();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}

}


public void declareOutputFields(OutputFieldsDeclarer declarer) {
// TODO Auto-generated method stub

}


public Map<String, Object> getComponentConfiguration() {
// TODO Auto-generated method stub
return null;
}

}


[size=large]
4、编写topoloy类[/size]


public class PvTopo {

public static void main(String[] args) {

TopologyBuilder builder = new TopologyBuilder();

builder.setSpout("spout", new SourceSpout(), 1);

builder.setBolt("bolt", new PVBolt(),4).shuffleGrouping("spout");

Map conf = new HashMap();
conf.put(Config.TOPOLOGY_WORKERS, 4);

if (args.length > 0) {
try {
StormSubmitter.submitTopology(args[0], conf, builder.createTopology());
} catch (AlreadyAliveException e) {
e.printStackTrace();
} catch (InvalidTopologyException e) {
e.printStackTrace();
}catch (AuthorizationException e) {
e.printStackTrace();
}
}else {
LocalCluster localCluster = new LocalCluster();
localCluster.submitTopology("mytopology", conf, builder.createTopology());
}

}

}


[size=large]5、启动zookeeper、storm,master(superviser)主机上创建zookeeper临时路径[/size]
[quote]
进入zk目录
zkCli.sh -server localhost:2181
创建文件夹
create /lock "“
create /lock/storm “”
ls /lock
get /lock/storm/pv
[/quote]
[img]http://dl2.iteye.com/upload/attachment/0124/8335/03e2d714-3bbe-3bab-93e8-b21485ce6531.jpg[/img]

[size=large]6、运行PvTopo结果[/size]
[img]http://dl2.iteye.com/upload/attachment/0124/8337/37a92a73-6ffb-384f-9cb1-997492a65f1b.jpg[/img]
Storm项目实战 之案例优化引入Zookeeper锁控制线程操作 Storm项目实战 之案例优化引入Zookeeper锁控制线程操作,出自Storm流计算从入门到精通之技术篇,Storm入门视频教程用到技术:Storm集群、Zookeeper集群等,涉及项目:网站PV、UV案例实战、其他案例 学习此课程需要具有: Java基础、Linux基础 学习Storm视频教程可以提升的技能(Storm除外):Zookeeper、Java、Linux 立即下载

相关推荐

cartographer基于3d地图的纯定位模式

关于纯定位模式呢,本人试过2d和3d,怎么说呢,有条件的话,建议直接上3d,因为博主当初在做定位时针对室内和室外都尝试过,2d只在室内环境下效果会很棒,但是在室外就呵呵啦!所以这里直接讲解3d室外定位(建图篇请自己查看我之前的博客:[3d建图](https://blog.youkuaiyun.com/qq_40216084/article/details/105531983) 看了我之前的博客大概知道配置文件和源文件路径了,我这里就不把路径写出来了,挺麻烦的。直接讲怎么做把,有不懂的留言,看到了我一定知无不言。 **首

qq_40216084的博客 5552

storm引入zookeeper锁控制线程操作

storm两类统计逻辑 汇总型:如网站pv,销售额,订单数等 去重:网站UV,顾客数,销售商品数等 汇总型方案: 1,shuffleGrouping下,pv(单线程结果)*executor并发数 一个executor默认一个task,如果设置task数大于1,公式应该是: pv(单线程结果)*task数 同一个executor下task的线程id相同,但是taskid不同

1454

实战指南:将MediaPipe封装为Windows DLL,实现C++/C#高效调用

在计算机视觉和多媒体处理领域,跨平台框架为开发者提供了强大的算法模型和计算能力。其核心原理在于通过预训练的机器学习模型和优化的计算图,实现对图像、视频流中特定目标(如人脸、手势、姿态)的实时检测与分析。这项技术的价值在于能够将复杂的AI能力模块化,降低应用开发门槛。在实际工程实践中,为了突破特定语言生态的限制并优化部署流程,开发者常需将核心功能封装成独立的库。例如,将Google的MediaPipe框架封装为Windows动态链接库(DLL),就是一个典型的工程实践。此举能有效解决语言壁垒和部署简化问题,使

weixin_28691741的博客 360

PV 并发量的计算

PV与并发之间换算的算法换算公式 并发连接数 = PV / 统计时间 * 页面衍生连接次数 * http响应时间 * 因数 / web服务器数量 PV = 并发连接数 * 统计时间 * web服务器数量/ 页面衍生连接次数 / http响应时间 / 因数 解释:统计时间 : pv统计的总时间,单位秒,要计算一天的pv就是86400秒页面衍生连接次数: 一个HTML页面可能会请求好几次htt...

记录点滴 473

Win10系统内存占用异常飙升?三步排查法快速定位问题根源

本文针对Win10系统内存占用异常飙升问题,提供了一套三步排查法。首先利用任务管理器和资源监视器进行深度系统体检,定位隐形内存消耗者;其次通过干净启动和禁用非必要后台服务,揪出导致内存泄漏的第三方软件或驱动;最后进行终极深度清理,包括检查内存完整性、调整虚拟内存设置以及更新关键驱动程序,帮助用户快速恢复系统流畅运行。

weixin_29251567的博客 196

POWER(十一)charge pump原理

电荷泵是一种基于电容充放电原理的DC-DC转换电路,通过开关控制实现电压转换,包括升压、降压和负压输出。其核心是利用电荷守恒原理,通过电容存储和转移电荷来改变输出电压。典型拓扑结构包括倍压电路和多阶升压电路,具有结构简单、体积小等优势。关键参数包括转换效率、输出电流能力和开关频率,适用于芯片供电、显示屏驱动等低功耗场景。LVDS部分补充说明了自举电路在驱动电路中的应用及其自同步特性。

zhlwsh的博客 2824

014-案例开发.Storm计算网站PV

高并发多线程下采用storm统计网站的pv数据

艾文 3829

Pspice安装教程:Windows系统完整指南(含环境变量设置)

详细讲解在Windows系统中完成Pspice安装的全过程,涵盖安装步骤与关键的环境变量设置,帮助用户顺利运行仿真工具。适合初学者快速上手pspice安装教程中的核心环节。

weixin_42230607的博客 1179

storm高并发PV统计

[b][size=medium]一、PV统计思考[/size][/b] 方案需要考虑分析多线程下,注意线程安全问题。 线程安全:多线程处理的结果和单线程一致 如下是否可行? 不可行方案: 定义static long pv, Synchronized 控制累计操作。Synchronized 和 Lock在单个JVM下有效,但在多JVM下无效。 可行方案两个方案: 1...

futureofstar的博客 315

Starlink第三代终端与第二代终端的差异分析

SpaceX星链第三代终端实现显著升级,硬件售价维持599美元不变但性能全面提升。相比第二代产品,第三代终端取消自动调节电机改为手动定向,防水防尘等级提升至IP67,天线面积扩大46%,支持235台设备连接(提升87%),下载速度可达1Gbps(提升4倍),延迟降至20ms以下。新增3个千兆接口和WiFi6支持,同时推出199美元单独路由器选项。这些改进使第三代终端在保持价格优势的同时,更好地满足户外、移动和商业场景需求,标志着SpaceX卫星互联网服务从亏损销售转向盈利模式的重要转折。

通信行业老兵、物联网从业者,做一个有趣的普通人。 3031

基于STM32L4XX、HAL库的E180-ZG120B ZigBee模块驱动程序设计

/ 频率: 470MHz, SF7, BW125kHz, CR4/5, 功率14dBm。// 检查是否收到完整响应(根据实际情况调整)// 每5秒发送一次。PB0 <---> AUX (可选,用于状态检测)// 实际发送命令可能需要根据模块AT指令集调整。PC13 <---> RESET (可选)// 处理接收到的数据。// 缓冲区满,从头开始。// 其他必要的HAL库初始化代码...// 初始化E180模块。// 启动UART接收。// 如果需要等待响应。// 配置LoRa参数。

zhusl6688的博客 381

【Storm】Spout的storm-starter及Grouping策略、并发度讲解、网站浏览量和用户数统计

maven先安装好。 以下讲storm-starter的使用。 1、从github下载官方的storm-starter例子包,是maven工程, 地址https://github.com/nathanmarz/storm-starter 2、把文件解压复制到workspace目录下,用cmd命令行,在该文件目录下运行mvn eclipse:eclipse,生成eclipse所...

晚风中的自由 763

docker安装部署openclaw详细教程(安装、卸载、问题处理)

摘要: 本文详细介绍了使用Docker部署OpenClaw本地AI智能体框架的全流程,包括代码下载、容器化安装、交互式配置及Token设置。Docker方案解决了环境配置复杂、依赖冲突等痛点,提供开箱即用的隔离环境。教程涵盖常见错误(如EACCES权限问题、网关启动失败、设备配对需求)的解决方案,并提供了完整的卸载指南。通过Docker部署,用户可快速构建安全、一致的AI智能体开发环境,实现大模型与本地工具的高效连接。

少说,多做 4004

storm项目实战开发 Storm视频教程下载

学习Storm视频教程需要具有:Java基础、Linux基础;学习Storm视频教程可以提升的技能(Storm除外):Zookeeper、Java、Linux 用到技术:Storm集群、Zookeeper集群等 涉及项目:网站PV、UV案例实战、其他案例 Storm视频教程 Storm入门教程-Storm流计算从入门到精通-技术篇,Storm视频教程全面、系统、深入讲解Storm,采用最新的稳定版本Storm 0.9.0.1 ;注重实践,对较抽象难懂的技术点如Grouping策略、并发度及线程安全、批

北风网IT 6543

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

storm

storm和hadoop的区别 storm用于实时计算;hadoop用于离线计算 storm处理的数据保存在内存中,源源不断;hadoop保存在文件系统中,一批一批处理 storm的数据通过网络传输进来;hadoop的数据保存在磁盘中 storm与hadoop的编程模型相似 ...

qq_37612412的博客 241

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Storm——分布式实时流式计算框架

Storm 第一章 是什么一 介绍二 拓扑流程流式处理实时处理三 性能对比Storm 与MapReduce的关系Storm 与 Spark Streaming 的关系四 计算模型第二章 Storm编程案例一 WordSum ( 数据累加 )SpoutBoltTest二 WordCountSpoutBoltTest第三章 Storm Grouping1. Shuffle Grouping2. F...

时间静止 4045

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Storm整理(上)

Storm整理(上) 一,Storm认识 Storm是个实时的,分布式以及具备高容错的计算框架。 主要有两个特点:Storm进程常驻内存,Storm数据不经过磁盘,在内存中处理。 应用: 双十一实时更新成交额: QQ实时在线人数统计: Storm架构简单介绍,后面有详细解释 架构: Nimbus Supervisor Worker 编程模型: DAG(Topology...

lemon 377

storm知识点学习总结(一)

storm --流式处理框架 storm是个实时的、分布式以及具备高容错的计算系统 - storm 进程常驻内存 - storm 数据不经过磁盘,在内存中处理 Twitter开源的分布式实时大数据处理框架,最早开源于github storm 架构 -Nimbus -Supervisor -Worker 编程模型: - DAG -S...

baiwacuan6352的博客 537

storm学习1

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34311757的博客 101

Storm搭建和笔记 flume

Storm Storm 简介 相当于右边的电梯,实时处理数据,不是一批一批的处理数据 Storm特征 Storm是个实时的、分布式以及具备高容错的计算系统 Storm进程常驻内存 Storm数据不经过磁盘,在内存中处理 Twitter开源的分布式实时大数据处理框架,最早开源于github 2013年,Storm进入Apache社区进行孵化 2014年9月,晋级成为了Apache顶级项目 官网 http://storm.apache.org/ 国内外各大网站使用,例如雅虎、阿里、百度 架构 Nim

hjs19981227的博客 460

storm 架构与原理

storm 架构与原理 1 storm简介 1.1 storm是什么 如果只用一句话来描述 storm 是什么的话:分布式 &amp;&amp; 实时 计算系统。按照作者 Nathan Marz 的说法,storm对于实时计算的意义类似于hadoop对于批处理的意义。 Hadoop(大数据分析领域无可争辩的王者)专注于批处理。这种模型对许多情形(比如为网页建立索引)已经足够,但...

jason_xiaojie_liu的博客 494

11 kafka 用户日志上报

11 kafka 用户日志上报更多干货分布式实战(干货)spring cloud 实战(干货)mybatis 实战(干货)spring boot 实战(干货)React 入门实战(干货)构建中小型互联网企业架构(干货)python 学习持续更新ElasticSearch 笔记kafka storm 实战 (干货)一、概述对网站产生的用户访问日志进行处理并分析出该网站在某天的PV、UV等数据,其走的...

架构师的成长之路的博客 2090

Flume+Kafka+storm的连接整合

Flume-ng Flume是一个分布式、可靠、和高可用的海量日志采集、聚合和传输的系统。 Flume的文档可以看http://flume.apache.org/FlumeUserGuide.html官方的英文文档 介绍的比较全面。 不过这里写写自己的见解 这个是flume的架构图 从上图可以看到几个名词: Agent: 一个Agent包含S...

weixin_30561425的博客 124

网站流量统计分析系统-02

0.将埋点收到的数据通过flume导入到kafka中a.配置flume的配置文件配置文件有两种:第一种是需要导入插件的,第二种是使用flume原生的。以下配置是第二种#agent a1.sources = r1 a1.sinks = k1 a1.channels = c1 #Source a1.sources.r1.type = avro a1.sources.r1.bind...

tansuoliming的博客 605

网站流量统计分析系统-05

定时任务计算:br、avgTime、avgDeepbr编写两个topologypackage com.liming.flux; import java.util.UUID; import backtype.storm.Config; import backtype.storm.LocalCluster; import backtype.storm.generated.StormTopology...

tansuoliming的博客 389

101电商平台高频实时访问架构

对于一个大型网站的电商平台来说,随着业务不断增长,用户规模不断增加。面对大流量、高并发的访问,网站性能问题就成了一个瓶颈,那么如何分析一个网站处理的能力,需要我们通过多方面的指标来分析处理。这些指标一般包括: 首页平均响应时长、搜索商品处理能力、登录鉴权能力、下单处理能力等。通过实时分析各个指标的能力可以为网站的建设者提供优化方案。接下来通过模拟下单生成日志,来实时分析下单处理能力。这些方案具有很强的通用性,只要掌握处理方案的方法,就可以做到应对一切变化.

艾文 1548
上一篇: storm高并发PV统计
下一篇: storm高并发UV统计
futureofstar
博客等级 码龄17年 0粉丝 89原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值