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的程式運作日志會寫入自己的日志檔案,便于檢視和排錯,如圖所示: