storm集群环境部署

一、storm集群环境部署
1、集群环境下storm包部署:
(1)必须将项目依赖的本地lib目录下的jar包放入集群子节点apache-storm-2.0.0 安装目录的lib-worker 和extlib目录下,和主节点的extlib目录下。否则报
ClassNotFoundException: org.springframework.context.ApplicationContext (lib-worker目录下原来就有环境依赖的jar包,所以比extlib下的jar包多)

执行的 storm jar 包放在apache-storm-2.0.0/bin 目录下,和两个子节点的lib-worker下。

2、集群环境启动

cd /home/apache-storm-2.0.0/bin

在主备节点:
storm nimbus >/dev/null 2>&1 &
storm ui >/dev/null &


在子节点和备节点:
storm supervisor >/dev/null 2>&1 &

查看启动状态:
ps -ef | grep daemon.nimbus
使用浏览器在页面上查看拓扑的状态和集群环境运行状态http://xxx.xxx.xxx.xxx:8080/

3、拓扑的提交与停止:

拓扑提交:
storm jar stormtest-0.0.1-SNAPSHOT.jar com.stormtest.SpringbootApplication APP1 111

storm jar stormtest-0.0.1-SNAPSHOT.jar com.stormtest.SpringbootApplication APP1 111 >/home/apache-storm-2.0.0/bin/info.log &


杀掉拓扑:

cd /home/apache-storm-2.0.0/bin
storm kill 拓扑名

后台查看运行的拓扑:
storm list

4、日志查看:

在子节点/home/apache-storm-2.0.0/logs/workers-artifacts 下找到拓扑名称, 去查看里面的worker.log 日志。

 

二、springboot集成storm 集群环境部署的问题与解决方法

1、解决slf4j冲突
java.lang.IllegalStateException: Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on t

log4j-slf4j-impl-2.11.2.jar
slf4j-log4j12-1.7.25.jar

目前是在集群上lib-worker目录下删除了上面两个jar,不删除在工作节点不打印worker.log 日志 。

log4j-slf4j-impl-2.11.1.jar 必须在lib-worker下存在,不存在不打印worker.log 日志 。


lib-worker下如果有虚无境的 kafkastorm的jar包 就会报(LoggerFactory is not a Logback LoggerContext but Logback is on the classpath.)


2、在集群上父pom文件加 <scope>provided</scope> 解决yaml 冲突,在本地运行时要注释掉。

 

3、将lib包 上传到lib-worker 目录下的时候,删除掉 storm开头的6个jar包。负责会报文件冲突(和2一样),要保留lib-worker目录下 自带的两个storm的jar包。

4、 读取不到依赖工程的 配置文件?
必须把要执行的jar包的properties 配置文件放在config目录下。


5、不在log4j2.xml指定目录打印日志
必须在属性文件中指定日志文件所在位置,在bin目录提交任务的时候 不能指定日志输出目录。

6、libworker 下不能有能运行的提交的jar包其他名称的版本,会报类的序列号不一致。

 


7、本地启动的时候不能设置为2个 worker,否则跑一会 没有任何报错进程就断掉了。


8、同时拉起两个worker,
将两个bolt 分发到5.2X4上,5.2X4上要启动springApplication就会打印 consumer.log日志,就报了
javax.management.InstanceAlreadyExistsException: com.alibaba.druid.filter.stat:name=statFilter,type=StatFilter

将两个spout分发到了 4.2X3上,不需要启动springApplication,因此没有打印consumer.log日志。

停了子节点,上面的worker进程依然存在,worker.log一直打印日志,停了worker进程,会立刻在同一节点拉起来。启动的时候没启动成功的时候会重复多次去拉prepare方法。

同一个worker内,spring只被初始化一次。

 

9、

当设置了两个 worker 进程config.setNumWorkers(2) 时, Bolt emit发射的对象不能继承父类,当继承了父类属性后 ,通过this.collector.emit( "common",new Values(Ball)) 发送给下级bolt数据后,下级bolt通过

Bolt  bolt  =(input.getValueByField( "common") 获取Ball对象的时候会导致获取不到 父类的属性 。

原因是 发射后取对象的时候就取不到父类的属性。

10、为了能使用spring上下文环境中的bean,spout的open()方法和bolt的prepare()方法中要加上 springboot的启动语句,ConfigurableApplicationContext mycontext = SpringApplication.run(SpringbootApplication.class);为了防止同一个worker 进程内 同时拉起多个spring环境导致端口暂用冲突,要对全局静态变量 mycontext 做判断,为空并且没有在拉起的时候才启动,有拉起的时候等待。

11、spout 对接kafka的时候,在open方法里要创建kafka消费对象,每个spout都要new 自己的消费对象,否则会报消费者被占用的错误。

private void kafkaInit()

{
 
this.consumer=new KafkaConsumer(msgKafkaConsumerConfig.consumerKafkaConfigs());
String topic = "nihao";
this.consumer.subscribe(Arrays.asList(new String[] { topic }));
 
}

 

三、集群环境下各个节点的分工

nimbus 将客户端提交的topology代码保存到本地目录/nimbus/stormdist/下

nimbus 分配的任务存放在zk节点/storm/assignments下:

进入zk客户端:
cd /zookeeper/bin
./zkCli.sh
get /storm/assignments
ls /storm/assignments

ls /storm/assignments/wn0827-1-1566868207
quit


子节点从nimbus中获取到的内容放在:
/home/apache-storm-2.0.0/storm-local/supervisor/stormdist/test1-6-1565944602

stormjar.jar

 

 四、storm并行理解与运行状态解析

       每个子节点上可以有多个worker进程,每个worker进程只属于一个拓扑,一个worker进程可以启动多个excutor线程,每个excutor线程只能运行一个bolt或spout的一个或多个实例(默认一个excutor只运行一个task实例),但可以给一个bolt 设置并行度,可以设置2个excutor去执行,这两个excutor可能在一个worker上也可能在两个worker上。可以设置task的并行度,但task的并行度要大于等于excutor,
       拓扑一旦提交后task的数量是不会变得,如果一个bolt的task数量设置为1,后面通过命令修改它的excutor的并行度为2,这个是修改不了的,因为同一个组件的excutor数量一定小于等于task的数量。可以设置task为4,excutor为2,但如果设置了task为1,excutor为2,那个系统也只会给它分配一个excutor线程。

动态改变并行度:
storm rebalance consumer_APP2 -n 2 -e bastionSpout=2

 

Storm UI 运行状态解析:

Version Supervisors Used slots Free slots Total slots Executors Tasks
2.0.0        2                       2               6                8         14              14


两个子节点,使用了两个worker进程, 还有6个进程可以使用, 一共有8个进程, 共启了14个线程, 共有14个task实例再运行。


spout 发射给bolt的数据,bolt如果不取不处理,过了30秒的超时时间,这条消息会faield,可以在storm ui上看到,这时会重新发送,导致恶行循环失败。

 

五、storm 参数调优

参数解析:

1、 supervisor.slots.ports:worker进程的接收线程的监听端口;

2、 topology.receiver.buffer.size:worker接收线程缓存消息的大小,它将该缓存消息发送给executor线程;需要为2的倍数
是worker的 receive thread 一次追加给 executor’s incoming queue 的最大消息数量。设置大了会引起各种问题。

3、 topology.transfer.buffer.size:worker进程中向外发送消息的缓存大小; 32
每个工作进程都有一个发送线程,负责从工作进程的传输队列中读取消息并通过网络将它们发送给下游消费者。

4、 topology.executor.receive.buffer.size:executor线程的接收队列大小;需要为2的倍数 16384 incoming queue

5、 topology.executor.send.buffer.size:executor线程的发送队列大小;需要为2的倍数 outgoing queue

 

数据在storm里的处理流程如下:

每个worker有一个接受线程和一个发送线程,接受线程负责将接受到的消息receive queue(topology.receiver.buffer.size)发送给合适excutor的incoming queue队列(topology.executor.receive.buffer.size)。

每个excutor有一个task线程有一个发送线程,task线程负责将 incoming queue 中的数据处理后放入excutor的 outgoing queue; 发送线程负责将excutor的 outgoing queue中( topology.executor.send.buffer.size)的数据发送到worker进程的 transfer queue中(topology.transfer.buffer.size)。

worker 的发送线程负责将transfer queue中的数据通过网络发送给其他worker ;

只有excutor的outgoing queue中 放的是单个的tuple,其他 queue里每个元素放的都是tuple的list。所以其他queue配置数据偏小。

storm 进程内通讯 参数说明可参考:
http://www.michael-noll.com/blog/2013/06/21/understanding-storm-internal-message-buffers/


拓扑最优参数配置:

conf.put(Config.TOPOLOGY_RECEIVER_BUFFER_SIZE, 8);

conf.put(Config.TOPOLOGY_TRANSFER_BUFFER_SIZE, 32);

conf.put(Config.TOPOLOGY_EXECUTOR_RECEIVE_BUFFER_SIZE, 16384);

conf.put(Config.TOPOLOGY_EXECUTOR_SEND_BUFFER_SIZE, 16384);


posted on 2019-11-15 09:40  luckyna  阅读(772)  评论(0编辑  收藏  举报

导航