storm是java还是python_阿里jstorm和storm区别

最简单的JStorm例子分为4个步骤:

生成Topology

Map conf = new HashMp();//topology所有自定义的配置均放入这个MapTopologyBuilder builder = new TopologyBuilder();//创建topology的生成器int spoutParal = get("spout.parallel", 1);//获取spout的并发设置SpoutDeclarer spout = builder.setSpout(SequenceTopologyDef.SEQUENCE_SPOUT_NAME

,

new SequenceSpout(), spoutParal);//创建Spout, 其中new SequenceSpout() 为真正spout对象,SequenceTopologyDef.SEQUENCE_SPOUT_NAME 为spout的名字,注意名字中不要含有空格int boltParal = get("bolt.parallel", 1);//获取bolt的并发设置BoltDeclarer totalBolt = builder.setBolt(SequenceTopologyDef.TOTAL_BOLT_NAME, new TotalCount(),

boltParal)

.shuffleGrouping(SequenceTopologyDef.SEQUENCE_SPOUT_NAME);//创建bolt, SequenceTopologyDef.TOTAL_BOLT_NAME 为bolt名字,TotalCount 为bolt对象,boltParal为bolt并发数,//shuffleGrouping(SequenceTopologyDef.SEQUENCE_SPOUT_NAME), //表示接收SequenceTopologyDef.SEQUENCE_SPOUT_NAME的数据,并且以shuffle方式,//即每个spout随机轮询发送tuple到下一级bolt中int ackerParal = get("acker.parallel", 1);Config.setNumAckers(conf, ackerParal);//设置表示acker的并发数int workerNum = get("worker.num", 10);

conf.put(Config.TOPOLOGY_WORKERS, workerNum);//表示整个topology将使用几个worker

conf.put(Config.STORM_CLUSTER_MODE, "distributed");//设置topolog模式为分布式,这样topology就可以放到JStorm集群上运行StormSubmitter.submitTopology(streamName, conf,

builder.createTopology());//提交topology

IRichSpout

IRichSpout 为最简单的Spout接口

IRichSpout

{

@Override public void open(Map conf, TopologyContext context, SpoutOutputCollector

collector) {

}

@Override public void

close() {

}

@Override public void

activate() {

}

@Override public void

deactivate() {

}

@Override public void

nextTuple() {

}

@Override public void ack(Object

msgId) {

}

@Override public void fail(Object

msgId) {

}

@Override public void declareOutputFields(OutputFieldsDeclarer

declarer) {

}

@Override public Map

getComponentConfiguration() {

return null;

}

其中注意:

spout对象必须是继承Serializable, 因此要求spout内所有数据结构必须是可序列化的

spout可以有构造函数,但构造函数只执行一次,是在提交任务时,创建spout对象,因此在task分配到具体worker之前的初始化工作可以在此处完成,一旦完成,初始化的内容将携带到每一个task内(因为提交任务时将spout序列化到文件中去,在worker起来时再将spout从文件中反序列化出来)。

open是当task起来后执行的初始化动作

close是当task被shutdown后执行的动作

activate 是当task被激活时,触发的动作

deactivate 是task被deactive时,触发的动作

nextTuple 是spout实现核心, nextuple完成自己的逻辑,即每一次取消息后,用collector 将消息emit出去。

ack, 当spout收到一条ack消息时,触发的动作,详情可以参考 ack机制

fail, 当spout收到一条fail消息时,触发的动作,详情可以参考 ack机制

declareOutputFields, 定义spout发送数据,每个字段的含义

getComponentConfiguration 获取本spout的component 配置

Bolt

IRichBolt

{

@Override public void prepare(Map stormConf, TopologyContext context, OutputCollector

collector) {

}

@Override public void execute(Tuple

input) {

}

@Override public void

cleanup() {

}

@Override public void declareOutputFields(OutputFieldsDeclarer

declarer) {

}

@Override public Map

getComponentConfiguration() {

return null;

}

}

其中注意:

bolt对象必须是继承Serializable, 因此要求spout内所有数据结构必须是可序列化的

bolt可以有构造函数,但构造函数只执行一次,是在提交任务时,创建bolt对象,因此在task分配到具体worker之前的初始化工作可以在此处完成,一旦完成,初始化的内容将携带到每一个task内(因为提交任务时将bolt序列化到文件中去,在worker起来时再将bolt从文件中反序列化出来)。

prepare是当task起来后执行的初始化动作

cleanup是当task被shutdown后执行的动作

execute是bolt实现核心, 完成自己的逻辑,即接受每一次取消息后,处理完,有可能用collector 将产生的新消息emit出去。 ** 在executor中,当程序处理一条消息时,需要执行collector.ack, 详情可以参考 ack机制 ** 在executor中,当程序无法处理一条消息时或出错时,需要执行collector.fail ,详情可以参考 ack机制

declareOutputFields, 定义bolt发送数据,每个字段的含义

getComponentConfiguration 获取本bolt的component 配置

编译

在Maven中配置

com.alibaba.jstorm

jstorm-client

0.9.3.1

provided

com.alibaba.jstorm

jstorm-client-extension

0.9.3.1

provided

如果找不到jstorm-client和jstorm-client-extension包,可以自己下载jstorm源码进行编译,请参考 源码编译

打包时,需要将所有依赖打入到一个包中

maven-assembly-plugin

jar-with-dependencies

storm.starter.SequenceTopology

make-assembly

package

single

org.apache.maven.plugins

maven-compiler-plugin

1.6

1.6

提交jar

JStorm vs Storm vs flume vs S4 选型

jstorm jar xxxxxx.jar com.alibaba.xxxx.xx parameter

xxxx.jar 为打包后的jar

com.alibaba.xxxx.xx 为入口类,即提交任务的类

parameter即为提交参数

JStorm 比Storm更稳定,更强大,更快, storm上跑的程序,一行代码不变可以运行在jstorm上。

Flume 是一个成熟的系统,主要focus在管道上,将数据从一个数据源传输到另外一个数据源, 系统提供大量现成的插件做管道作用。当然也可以做一些计算和分析,但插件的开发没有Jstorm便捷和迅速。

S4 就是一个半成品,健壮性还可以,但数据准确性较糟糕,无法保证数据不丢失,这个特性让S4 大受限制,也导致了S4开源很多年,但发展一直不是很迅速。

AKKA 是一个actor模型,也是一个不错的系统,在这个actor模型基本上,你想做任何事情都没有问题,但问题是你需要做更多的工作,topology怎么生成,怎么序列化。数据怎么流(随机,还是group by)等等。

Spark 是一个轻量的内存MR, 更偏重批量数据处理

0.9.0 性能测试

JStorm 0.9.0 性能非常的好, 使用netty时单worker 发送最大速度为11万QPS, 使用zeromq时,最大速度为12万QPS.

结论

JStorm 0.9.0 在使用Netty的情况下,比Storm 0.9.0 使用netty情况下,快10%, 并且JStorm netty是稳定的而Storm 的Netty是不稳定的

在使用ZeroMQ的情况下, JStorm 0.9.0 比Storm 0.9.0 快30%

原因

Zeromq 减少一次内存拷贝

增加反序列化线程

重写采样代码,大幅减少采样影响

优化ack代码

优化缓冲map性能

Java 比clojure更底层

测试

测试样例

测试环境

5 台 16核, 98G 物理机

uname -a :

Linux dwcache1 2.6.32-220.23.1.tb735.el5.x86_64 #1 SMP Tue Aug 14 16:03:04 CST 2012 x86_64 x86_64 x86_64 GNU/Linux

测试结果

JStorm with netty, Spout 发送QPS 为 11万

storm with netty, Spout 应用发送QPS 为 10万 (截图为上层应用的QPS, 没有包括发送到ack的QPS, Spout发送QPS 正好为上层应用QPS的2倍)

JStorm with zeromq, Spout 发送QPS 为12万

Storm with zeromq, Spout 发送QPS 为9万(截图为上层应用的QPS, 没有包括发送到ack的QPS, Spout发送QPS 正好为上层应用QPS的2倍)

资源硬隔离

cgroups是control groups的缩写,是Linux内核提供的一种可以限制, 记录, 隔离进程组(process groups)所使用的物理资源(如:cpu,memory,IO 等等)的机制。

在Jstorm中,我们使用cgroup进行cpu硬件资源的管理。使用前,需要做如下检查和配置。

检查/etc/passwd 文件中当前用户的uid和gid, 假设当前用户是admin, 则看/etc/passwd文件中admin的uid和gid是多少

cgroup功能在当前系统的内核版本是否支持

检查/etc/cgconfig.conf是否存在。如果不存在, 请“yum install libcgroup”,如果存在,设置cpu子系统的挂载目录位置, 以及修改该配置文件中相应的uid/gid为启动jstorm用户的uid/gid, 本例子中以500为例, 注意是根据第一步来进行设置的。

mount {

cpu = /cgroup/cpu;

}

group jstorm {

perm {

task {

uid = 500;

gid = 500;

}

admin {

uid = 500;

gid = 500;

}

}

cpu {

}

}

然后启动cgroup服务

service cgconfig restart

chkconfig --level 23456 cgconfig on

Note: cgconfig.conf只能在root模式下修改。

或者直接执行命令

这是一个cgconfig.conf配置文件例子。比如jstorm的启动用户为admin,admin在当前 系统的uid/gid为500(查看/etc/passwd 可以查看到uid和gid),那么相对应cpu子系统的jstorm目录uid/gid也需要设置为相同的值。 以便jstorm有相应权限可以在这个目录下为jstorm的每个需要进行资源隔离的进程创建对应 的目录和进行相关设置。

mkdir /cgroup/cpu

mount  -t cgroup -o cpu none /cgroup/cpu

mkdir /cgroup/cpu/jstorm

chown admin:admin /cgroup/cpu/jstorm

. 在jstorm配置文件中打开cgroup, 配置storm.yaml

supervisor.enable.cgroup: true

常见问题

性能问题

参考性能优化

资源不够

当报告 ”No supervisor resource is enough for component “, 则意味着资源不够 如果是仅仅是测试环境,可以将supervisor的cpu 和memory slot设置大,

在jstorm中, 一个task默认会消耗一个cpu slot和一个memory slot, 而一台机器上默认的cpu slot是(cpu 核数 -1), memory slot数(物理内存大小 * 75%/1g), 如果一个worker上运行task比较多时,需要将memory slot size设小(默认是1G), 比如512M, memory.slot.per.size: 535298048

#if it is null, then it will be detect by system

supervisor.cpu.slot.num: null

#if it is null, then it will be detect by system

supervisor.mem.slot.num: null

# support disk slot

# if it is null, it will use $(storm.local.dir)/worker_shared_data

supervisor.disk.slot: null

序列化问题

所有spout,bolt,configuration, 发送的消息(Tuple)都必须实现Serializable, 否则就会出现序列化错误.

如果是spout或bolt的成员变量没有实现Serializable时,但又必须使用时, 可以对该变量申明时,增加transient 修饰符, 然后在open或prepare时,进行实例化

Log4j 冲突

0.9.0 开始,JStorm依旧使用Log4J,但storm使用Logbak,因此应用程序如果有依赖log4j-over-slf4j.jar, 则需要exclude 所有log4j-over-slf4j.jar依赖,下个版本将自定义classloader,就不用担心这个问题。

SLF4J: Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the class path, preempting StackOverflowError.

SLF4J: See also

http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.

Exception in thread "main" java.lang.ExceptionInInitializerError

at org.apache.log4j.Logger.getLogger(Logger.java:39)

at org.apache.log4j.Logger.getLogger(Logger.java:43)

at com.alibaba.jstorm.daemon.worker.Worker.(Worker.java:32)

Caused by: java.lang.IllegalStateException: Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the class path, preempting StackOverflowError. See also

http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.

at org.apache.log4j.Log4jLoggerFactory.(Log4jLoggerFactory.java:49)

... 3 more

Could not find the main class: com.alibaba.jstorm.daemon.worker.Worker.  Program will exit.

类冲突

如果应用程序使用和JStorm相同的jar 但版本不一样时,建议打开classloader, 修改配置文件

topology.enable.classloader: true

或者

ConfigExtension.setEnableTopologyClassLoader(conf, true);

JStorm默认是关掉classloader,因此JStorm会强制使用JStorm依赖的jar

提交任务后,等待几分钟后,web ui始终没有显示对应的task

有3种情况:

用户程序初始化太慢

如果有用户程序的日志输出,则表明是用户的初始化太慢或者出错,查看日志即可。 另外对于MetaQ 1.x的应用程序,Spout会recover ~/.meta_recover/目录下文件,可以直接删除这些消费失败的问题,加速启动。

通常是用户jar冲突或初始化发生问题

打开supervisor 日志,找出启动worker命令,单独执行,然后检查是否有问题。类似下图:

检查是不是storm和jstorm使用相同的本地目录

检查配置项 ”storm.local.dir“, 是不是storm和jstorm使用相同的本地目录,如果相同,则将二者分开

提示端口被绑定

有2种情况:

多个worker抢占一个端口

假设是6800 端口被占, 可以执行命令 “ps -ef|grep 6800” 检查是否有多个进程, 如果有多个进程,则手动杀死他们

系统打开太多的connection

Linux对外连接端口数限制,TCP client对外发起连接数达到28000左右时,就开始大量抛异常,需要

# echo "10000 65535" > /proc/sys/net/ipv4/ip_local_port_range

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值