jstorm是由alibaba开源的实时计算系统,它使用java重写了apache storm(使用clojure+java混编),而且在原来的基础上做了很多改进的地方。使用java重写,对于使用java的开发人员来说,可以通过阅读源码来了解jstorm内部的原理和实现,而且可以根据运行错误日志来排查错误。
下面通过安装配置,以及简单使用的验证,来说明jstorm宏观上与apache storm的不同之处。
安装配置jstorm server
首先,要保证jdk成功安装配置,然后在一个节点上下载、安装、配置jstorm。例如,我在hadoop1节点上,下载并解压缩:
<code>1</code>
<code>2</code>
<code>unzip jstorm-0.9.6.2.zip</code>
<code>3</code>
<code>cd</code> <code>jstorm-0.9.6.2</code>
修改配置文件conf/storm.yaml,内容修改如下:
<code>01</code>
<code>########### these must be filled in for a storm configuration</code>
<code>02</code>
<code></code><code>storm.zookeeper.servers:</code>
<code>03</code>
<code></code><code>- "10.10.4.128"</code>
<code>04</code>
<code></code><code>- "10.10.4.129"</code>
<code>05</code>
<code></code><code>- "10.10.4.130"</code>
<code>06</code>
<code>07</code>
<code></code><code>storm.zookeeper.root: "/jstorm"</code>
<code>08</code>
<code>09</code>
<code># %jstorm_home% is the jstorm home directory</code>
<code>10</code>
<code></code><code>storm.local.dir: "/tmp/jstorm/data"</code>
<code>11</code>
<code>12</code>
<code></code><code>java.library.path: "/usr/local/lib:/opt/local/lib:/usr/lib"</code>
<code>13</code>
<code>14</code>
<code></code><code>supervisor.slots.ports:</code>
<code>15</code>
<code></code><code>- 6800</code>
<code>16</code>
<code></code><code>- 6801</code>
<code>17</code>
<code></code><code>- 6802</code>
<code>18</code>
<code></code><code>- 6803</code>
要保证zookeeper集群已经成功启动,并在zookeeper中创建/jstorm,执行如下命令:
<code>ssh</code> <code>[email protected]</code>
<code>/usr/</code><code>local</code><code>/zookeeper/bin/zkcli.sh</code>
然后创建/jstorm,执行如下命令:
<code>create /jstorm</code><code>""</code>
配置环境变量jstorm_home,修改~/.bashrc文件,增加如下内容:
<code>export</code> <code>jstorm_home=/home/kaolatj/jstorm-0.9.6.2</code>
<code>export</code> <code>path=$path:$jstorm_home/bin</code>
使环境变量生效:
<code>source</code> <code>~/.bashrc</code>
配置完上面内容后,需要创建~/.jstorm目录,并将配置好的storm.yaml文件拷贝到该目录下:
<code>mkdir</code> <code>~/.jstorm</code>
<code>cp</code> <code>-f $jstorm_home/conf/storm.yaml ~/.jstorm</code>
最好在每个节点都执行上述配置,尤其是在提交topology的时候,如果没有这个就会报错的。
最后,要将jstorm安装文件拷贝到集群其他从节点上,我这里有2个从节点hadoop2和hadoop3,执行如下命令:
<code>scp</code> <code>-r /home/kaolatj/jstorm-0.9.6.2 kaolatj@hadoop2:~/</code>
<code>scp</code> <code>-r /home/kaolatj/jstorm-0.9.6.2 kaolatj@hadoop3:~/</code>
同样,在从节点上配置好环境变量jstorm_home。
安装jstorm ui
安装jstorm ui,可以安装在任何一个节点上,只要保证jstorm ui的安装包(war文件)的配置文件和jstorm集群相同即可。jstorm ui运行在web容器之中,可以使用tomcat。我这里,直接在nimbus节点上安装jstorm ui。
首先,安装tomcat web容器:
<code>unzip apache-tomcat-7.0.57.zip</code>
<code>cd</code> <code>apache-tomcat-7.0.57</code>
<code>4</code>
<code>chmod</code> <code>+x bin/*.sh</code>
然后,将jstorm-ui-0.9.6.2.war软件包拷贝到tomcat的webapps目录下,jstorm-ui-0.9.6.2.war直接在解压缩的jstorm-0.9.6.2.zip包中,拷贝即可:
<code>cp</code> <code>~/jstorm-0.9.6.2/jstorm-ui-0.9.6.2.war webapps/</code>
<code>mv</code> <code>root root.old</code>
<code>ln</code> <code>-s jstorm-ui-0.9.6.2 root</code>
在启动tomcat之前,要保证配置文件$jstorm_home/conf/storm.yaml拷贝到目录~/.jstorm下面。
最后,启动tomcat,并查看日志:
<code>bin/catalina.sh start</code>
<code>tail</code> <code>-100f logs/catalina.out</code>
jstorm ui安装完成后,可以通过访问http://10.10.4.125:8080即可看到web ui界面。
另外,可以直接通过源码进行构建,将对应的配置配好的文件$jstorm_home/conf/storm.yaml直接打包到war文件里面,然后就可以直接发布到web容器中(如tomcat),这样可以不用将$jstorm_home/conf/storm.yaml拷贝到目录~/.jstorm下面。
验证jstorm
我这里写了一个相对比较复杂的jstorm程序,原来是基于apache-storm-0.9.2-incubating构建的应用,现在迁移到jstorm计算平台,保留了apache storm中一些工具包,像storm-kafka,同时还用到kafka,在storm ui上dag图如下所示:

参考maven依赖配置如下:
<code><</code><code>properties</code><code>></code>
<code></code><code><</code><code>project.build.sourceencoding</code><code>>utf-8</</code><code>project.build.sourceencoding</code><code>></code>
<code></code><code><</code><code>jstorm.version</code><code>>0.9.6.2-snapshot</</code><code>jstorm.version</code><code>></code>
<code></</code><code>properties</code><code>></code>
<code><</code><code>dependencies</code><code>></code>
<code></code><code><</code><code>dependency</code><code>></code>
<code></code><code><</code><code>groupid</code><code>>com.alibaba.jstorm</</code><code>groupid</code><code>></code>
<code></code><code><</code><code>artifactid</code><code>>jstorm-server</</code><code>artifactid</code><code>></code>
<code></code><code><</code><code>version</code><code>>${jstorm.version}</</code><code>version</code><code>></code>
<code></code><code><</code><code>scope</code><code>>provided</</code><code>scope</code><code>></code>
<code></code><code></</code><code>dependency</code><code>></code>
<code></code><code><</code><code>artifactid</code><code>>jstorm-client</</code><code>artifactid</code><code>></code>
<code>19</code>
<code>20</code>
<code>21</code>
<code></code><code><</code><code>artifactid</code><code>>jstorm-client-extension</</code><code>artifactid</code><code>></code>
<code>22</code>
<code>23</code>
<code>24</code>
<code>25</code>
<code></code>
<code>26</code>
<code>27</code>
<code></code><code><</code><code>groupid</code><code>>org.apache.storm</</code><code>groupid</code><code>></code>
<code>28</code>
<code></code><code><</code><code>artifactid</code><code>>storm-kafka</</code><code>artifactid</code><code>></code>
<code>29</code>
<code></code><code><</code><code>version</code><code>>0.9.3-rc1</</code><code>version</code><code>></code>
<code>30</code>
<code></code><code><</code><code>exclusions</code><code>></code>
<code>31</code>
<code></code><code><</code><code>exclusion</code><code>></code>
<code>32</code>
<code></code><code><</code><code>groupid</code><code>>log4j</</code><code>groupid</code><code>></code>
<code>33</code>
<code></code><code><</code><code>artifactid</code><code>>log4j</</code><code>artifactid</code><code>></code>
<code>34</code>
<code></code><code></</code><code>exclusion</code><code>></code>
<code>35</code>
<code></code><code></</code><code>exclusions</code><code>></code>
<code>36</code>
<code>37</code>
<code>38</code>
<code></code><code><</code><code>groupid</code><code>>org.apache.kafka</</code><code>groupid</code><code>></code>
<code>39</code>
<code></code><code><</code><code>artifactid</code><code>>kafka_2.9.2</</code><code>artifactid</code><code>></code>
<code>40</code>
<code></code><code><</code><code>version</code><code>>0.8.1.1</</code><code>version</code><code>></code>
<code>41</code>
<code>42</code>
<code>43</code>
<code></code><code><</code><code>groupid</code><code>>org.apache.zookeeper</</code><code>groupid</code><code>></code>
<code>44</code>
<code></code><code><</code><code>artifactid</code><code>>zookeeper</</code><code>artifactid</code><code>></code>
<code>45</code>
<code>46</code>
<code>47</code>
<code>48</code>
<code>49</code>
<code>50</code>
<code>51</code>
<code>52</code>
<code>53</code>
<code>54</code>
<code></code><code><</code><code>groupid</code><code>>org.apache.hadoop</</code><code>groupid</code><code>></code>
<code>55</code>
<code></code><code><</code><code>artifactid</code><code>>hadoop-client</</code><code>artifactid</code><code>></code>
<code>56</code>
<code></code><code><</code><code>version</code><code>>2.2.0</</code><code>version</code><code>></code>
<code>57</code>
<code>58</code>
<code>59</code>
<code></code><code><</code><code>groupid</code><code>>org.slf4j</</code><code>groupid</code><code>></code>
<code>60</code>
<code></code><code><</code><code>artifactid</code><code>>slf4j-log4j12</</code><code>artifactid</code><code>></code>
<code>61</code>
<code>62</code>
<code>63</code>
<code>64</code>
<code>65</code>
<code>66</code>
<code></code><code><</code><code>artifactid</code><code>>hadoop-hdfs</</code><code>artifactid</code><code>></code>
<code>67</code>
<code>68</code>
<code>69</code>
<code>70</code>
<code>71</code>
<code>72</code>
<code>73</code>
<code>74</code>
<code>75</code>
<code>76</code>
<code></code><code><</code><code>groupid</code><code>>com.github.ptgoetz</</code><code>groupid</code><code>></code>
<code>77</code>
<code></code><code><</code><code>artifactid</code><code>>storm-hdfs</</code><code>artifactid</code><code>></code>
<code>78</code>
<code></code><code><</code><code>version</code><code>>0.1.3-snapshot</</code><code>version</code><code>></code>
<code>79</code>
<code>80</code>
<code>81</code>
<code></code><code><</code><code>groupid</code><code>>commons-configuration</</code><code>groupid</code><code>></code>
<code>82</code>
<code></code><code><</code><code>artifactid</code><code>>commons-configuration</</code><code>artifactid</code><code>></code>
<code>83</code>
<code></code><code><</code><code>version</code><code>>1.10</</code><code>version</code><code>></code>
<code>84</code>
<code>85</code>
<code>86</code>
<code>87</code>
<code></code><code><</code><code>artifactid</code><code>>slf4j-api</</code><code>artifactid</code><code>></code>
<code>88</code>
<code></code><code><</code><code>version</code><code>>1.7.5</</code><code>version</code><code>></code>
<code>89</code>
<code>90</code>
<code>91</code>
<code>92</code>
<code></</code><code>dependencies</code><code>></code>
提交topology程序包到jstorm集群,执行如下命令:
<code>bin/jstorm jar ~/jstorm-msg-process-0.0.1-snapshot.jar org.shirdrn.storm.msg.msgprocesstopology msgprocesstopology</code>
然后,我们可以通过命令行来查看topology列表:
<code>bin/jstorm list</code>
结果示例如下所示:
<code>clustersummary(supervisors:[supervisorsummary(host:hadoop2, supervisor_id:43bb2701-4a3c-4941-8605-68000c66eea5, uptime_secs:89864, num_workers:4, num_used_workers:2), supervisorsummary(host:hadoop3, supervisor_id:0e72bc94-52d2-4695-8c29-8fbf57d89c9c, uptime_secs:96051, num_workers:4, num_used_workers:3)], nimbus_uptime_secs:226520, topologies:[topologysummary(id:wordcounttopology-1-1420369616, name:wordcounttopology, status:active, uptime_secs:237166, num_tasks:5, num_workers:3, error_info:y), topologysummary(id:msgprocesstopology-3-1420447738, name:msgprocesstopology, status:active, uptime_secs:159044, num_tasks:23, num_workers:2, error_info:)], version:0.9.6.2)</code>
接着再看一下jstorm ui首页的效果图,如图所示:
运行在jstorm集群上的msgprocesstopology,点击上图中的topology name中的链接,就可以看到topology的效果图,如下所示:
在jstorm ui首页上,点击supervisor节点链接,可以查看各个节点上运行的topology及其task的消息情况,示例如图所示:
点击task list中的链接,还可以查看某个task的明细信息,不再累述。
问题总结
如果原来基于apache storm开发的程序,理论上可以无需改动便可以运行在jstorm集群上,只不过在编译打包的时候,指定jstorm依赖:
<code><</code><code>dependency</code><code>></code>
<code></</code><code>dependency</code><code>></code>
启动nimbus和supervisor进程的时候,一定要在后台启动,否则可能会出现进程无缘无故挂掉的问题,可以执行命令:
<code>nohup</code> <code>jstorm nimbus >/dev/null 2>&1 &</code>
<code>nohup</code> <code>jstorm supervisor >/dev/null 2>&1 &</code>
如果忘记配置cp -f $jstorm_home/conf/storm.yaml ~/.jstorm,在提交topology到jstorm集群时,会出现如下错误:
<code>[info 2015-01-04 17:34:50 curatorframeworkimpl:238 main] starting</code>
<code>[warn 2015-01-04 17:34:50 clientcnxn:1102 main-sendthread(localhost:2181)] session 0x0 for server null, unexpected error, closing socket connection and attempting reconnect</code>
<code>java.net.connectexception: connection refused</code>
<code></code><code>at sun.nio.ch.socketchannelimpl.checkconnect(native method)</code>
<code>5</code>
<code></code><code>at sun.nio.ch.socketchannelimpl.finishconnect(socketchannelimpl.java:708)</code>
<code>6</code>
<code></code><code>at org.apache.zookeeper.clientcnxnsocketnio.dotransport(clientcnxnsocketnio.java:361)</code>
<code>7</code>
<code></code><code>at org.apache.zookeeper.clientcnxn$sendthread.run(clientcnxn.java:1081)</code>
<code>8</code>
<code>[warn 2015-01-04 17:34:51 clientcnxn:1102 main-sendthread(localhost:2181)] session 0x0 for server null, unexpected error, closing socket connection and attempting reconnect</code>
<code>9</code>
目前,在哪个节点上提交topology,必须配置将 $jstorm_home/conf/storm.yaml拷贝到~/.jstorm目录下,否则就会报错。
这个配置,我觉得以后jstorm可以做个优化,只要宿主机安装了jstorm程序,实际上就应该根据环境变量$jstorm_home自动找到对应的配置文件$jstorm_home/conf/storm.yaml。
在使用jstorm maven依赖的时候,你可以无法在网上找到public repository,这时,你需要下载指定版本的jstorm源码,然后在你的开发主机上安装到本地maven repository,执行如下命令:
<code>cd</code> <code>~/jstorm-0.9.6.2</code>
<code>mvn</code><code>install</code> <code>-dskiptests</code>
查看jstorm运行日志,每个topology的程序运行日志会写入自己的日志文件,便于查看和排错,如图所示: