这段时间, 断断续续在搞storm及c++实现方案,遇到了不少坑 , 也参考了不少博客, 主要基于Sasa Petrovic 的c++ 封装, 基本上实现了storm multilang协议。现在把过程捋一捋:
storm 中遇到的问题
这里不谈storm和zookeeper的环境安装与配置, 只说下遇到的几个问题, 其中好几个问题的原因是处理storm版本兼容性比较麻烦导致的
maven找不到backtype.storm.包
一般在正式玩storm之前,会跑一下storm自带的sample, 是由java开发的, 环境中依赖maven。编译的时候报错找不到backtype.storm.*包。原因可能是:
1)可能是环境变量classpath出错了,程序找不到库
2)问题可能出在pom文件中的scope上
<dependency>
<groupId>org.apache.storm</groupId>
<artifactId>storm-core</artifactId>
<version>0.10.0-beta1</version>
<scope>provided</scope>
storm 安装的lib路径下已经存在storm-core或storm库,程序又将storm库打包进去,造成storm运行topology时候识别出多个相同库的问题
3) 可能是使用了storm1.0以上版本,backtype.storm对应的包是org.apache.storm, 我对应的就是这种情况, sample的版本是0.x, 我用的1.0jsoncpp: ambiguous overload for ‘operator[]’ (operand types are ‘Json::Value’ and ‘int’)
class SplitSentence : public Bolt
{
public:
...
void Process(Tuple &tuple)
{
std::string s = tuple.GetValues()[0].asString();
...
}
}
原因是当参数是常量值0的时候,0可能被认为是NULL, 无法确定把它当作是 UINT 还是const char*,string来处理, 无法定位重载方法。应该是他使用了一个不同版本的jsoncpp, 不含value 的operator[]重载方法。
class SplitSentence : public Bolt
{
public:
...
void Process(Tuple &tuple)
{
int i = 0;
std::string s = tuple.GetValues()[i].asString();
...
}
}
发布topologies 时,出现不能序列化log4j.Logger 的异常
一般是storm安装的lib库logger库和项目打包依赖的logger库冲突, 凡是遇到这种情况, 都是以storm安装依赖库为准, 删除或替换掉项目中对应的库解决多语言支持打包问题
开始一直无法将c++可执行程序和shell脚本打包进jar包, 后来找到解决方法:- 项目根目录建立multilang/resources子目录
- 将可执行文件放入该目录
- 将脚本目录加入编译目录
eclipse java build path -> add folder -> 勾选multilang - 重新build
- 重新mvn package
可执行程序执行权限问题
成功打包后, 运行topology, 又出错提示/bin/bash 找不到spout。 猜测应该是权限问题, topology提交部署的过程中会拷贝到节点xxx/tmp/目录,没有执行权限。从一篇博文了解到,确实是这个原因:http://blog.csdn.net/jmppok/article/details/16827837, 在shell脚本中执行可执行文件前chmod修改权限解决, 比如spout 对应脚本:
#/bin/bash
chmod a+x spout
./spout
- org.apache.storm.utils.DisruptorQueue.consumeBatchToCursor
而后来发现原因是之前项目中的bolt wordcounter没有删除(kill),和cpp demo的wordcounter冲突
- 之后topology 跑起来了, 搞定, 结果如下:
最后贴上c++源码地址和java 源码
java topology源码:
package com.topology; import org.apache.storm.Config; import org.apache.storm.LocalCluster; import org.apache.storm.StormSubmitter; import org.apache.storm.spout.ShellSpout; import org.apache.storm.task.ShellBolt; import org.apache.storm.topology.IRichBolt; import org.apache.storm.topology.IRichSpout; import org.apache.storm.topology.OutputFieldsDeclarer; import org.apache.storm.topology.TopologyBuilder; import org.apache.storm.tuple.Fields; import java.util.Map; /** * This topology demonstrates Storm's stream groupings and multilang capabilities. */ public class WordCountTopologyCPP { public static class SentenceSpout extends ShellSpout implements IRichSpout{ public SentenceSpout() { super("/bin/bash", "spout.sh"); } @Override public void declareOutputFields(OutputFieldsDeclarer declarer) { // TODO Auto-generated method stub declarer.declare(new Fields("sentence")); } @Override public Map<String, Object> getComponentConfiguration() { // TODO Auto-generated method stub return null; } } public static class SplitSentence extends ShellBolt implements IRichBolt { public SplitSentence() { super("/bin/bash", "bolt.sh"); } @Override public void declareOutputFields(OutputFieldsDeclarer declarer) { declarer.declare(new Fields("word")); } @Override public Map<String, Object> getComponentConfiguration() { return null; } } public static class WordCount extends ShellBolt implements IRichBolt { public WordCount() { super("/bin/bash", "count.sh"); } @Override public void declareOutputFields(OutputFieldsDeclarer declarer) { } @Override public Map<String, Object> getComponentConfiguration() { return null; } } public static void main(String[] args) throws Exception { TopologyBuilder builder = new TopologyBuilder(); builder.setSpout("spout", new SentenceSpout(), 2); builder.setBolt("bolt", new SplitSentence(), 3).shuffleGrouping("spout"); builder.setBolt("count", new WordCount(), 5).fieldsGrouping("bolt", new Fields("word")); Config conf = new Config(); conf.setDebug(true); if (args != null && args.length > 0) { conf.setNumWorkers(3); StormSubmitter.submitTopologyWithProgressBar(args[0], conf, builder.createTopology()); } else { conf.setMaxTaskParallelism(3); LocalCluster cluster = new LocalCluster(); cluster.submitTopology("word-count", conf, builder.createTopology()); Thread.sleep(10*60*1000); cluster.shutdown(); } } }