最近应用升级之后,有个机器上的 worker 总会在启动一段时间后挂掉。worker 日志如下:
2015-06-18T17:19:19.931+0800 o.a.s.c.ConnectionState [ERROR] Connection timed out for connection string (z124:2181,z128:2181,z168:2181/storm) and timeout (15000) / elapsed (16172)
492856 org.apache.storm.curator.CuratorConnectionLossException: KeeperErrorCode = ConnectionLoss
492857 at org.apache.storm.curator.ConnectionState.checkTimeouts(ConnectionState.java:198) [storm-core-0.9.3.jar:0.9.3]
492858 at org.apache.storm.curator.ConnectionState.getZooKeeper(ConnectionState.java:88) [storm-core-0.9.3.jar:0.9.3]
492859 at org.apache.storm.curator.CuratorZookeeperClient.getZooKeeper(CuratorZookeeperClient.java:115) [storm-core-0.9.3.jar:0.9.3]
492860 at org.apache.storm.curator.framework.imps.CuratorFrameworkImpl.getZooKeeper(CuratorFrameworkImpl.java:488) [storm-core-0.9.3.jar:0.9.3]
492861 at org.apache.storm.curator.framework.imps.ExistsBuilderImpl$2.call(ExistsBuilderImpl.java:168) [storm-core-0.9.3.jar:0.9.3]
492862 at org.apache.storm.curator.framework.imps.ExistsBuilderImpl$2.call(ExistsBuilderImpl.java:161) [storm-core-0.9.3.jar:0.9.3]492863 at org.apache.storm.curator.RetryLoop.callWithRetry(RetryLoop.java:107) [storm-core-0.9.3.jar:0.9.3]492864 at org.apache.storm.curator.framework.imps.ExistsBuilderImpl.pathInForeground(ExistsBuilderImpl.java:157) [storm-core-0.9.3.jar:0.9.3]
492865 at org.apache.storm.curator.framework.imps.ExistsBuilderImpl.forPath(ExistsBuilderImpl.java:148) [storm-core-0.9.3.jar:0.9.3]492866 at org.apache.storm.curator.framework.imps.ExistsBuilderImpl.forPath(ExistsBuilderImpl.java:36) [storm-core-0.9.3.jar:0.9.3]
492867 at sun.reflect.GeneratedMethodAccessor38.invoke(Unknown Source) ~[na:na]
492868 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_71]
492869 at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_71]
492870 at clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:93) [clojure-1.5.1.jar:na]
492871 at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:28) [clojure-1.5.1.jar:na]
492872 at backtype.storm.zookeeper$get_version.invoke(zookeeper.clj:156) [storm-core-0.9.3.jar:0.9.3]
492873 at backtype.storm.cluster$mk_distributed_cluster_state$reify__1915.get_version(cluster.clj:111) [storm-core-0.9.3.jar:0.9.3]
492874 at backtype.storm.cluster$mk_storm_cluster_state$reify__2372.assignment_version(cluster.clj:287) [storm-core-0.9.3.jar:0.9.3]
492875 at sun.reflect.GeneratedMethodAccessor43.invoke(Unknown Source) ~[na:na]
492876 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_71]
492877 at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_71]
492878 at clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:93) [clojure-1.5.1.jar:na]
492879 at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:28) [clojure-1.5.1.jar:na]
492880 at backtype.storm.daemon.worker$mk_refresh_connections$this__3690.invoke(worker.clj:255) [storm-core-0.9.3.jar:0.9.3]
492881 at backtype.storm.daemon.worker$mk_refresh_connections$this__3690.invoke(worker.clj:253) [storm-core-0.9.3.jar:0.9.3]
492882 at backtype.storm.timer$schedule_recurring$this__1649.invoke(timer.clj:99) [storm-core-0.9.3.jar:0.9.3]
492883 at backtype.storm.timer$mk_timer$fn__1632$fn__1633.invoke(timer.clj:50) [storm-core-0.9.3.jar:0.9.3]
492884 at backtype.storm.timer$mk_timer$fn__1632.invoke(timer.clj:42) [storm-core-0.9.3.jar:0.9.3]
492885 at clojure.lang.AFn.run(AFn.java:24) [clojure-1.5.1.jar:na]
492886 at java.lang.Thread.run(Thread.java:745) [na:1.7.0_71]
而同一时间的 supervisor 不停地提示 “{id} still hasn't started”
2015-06-18T17:14:56.752+0800 b.s.d.supervisor [INFO] 2376a892-2a8a-401e-9bd6-85059ab57586 still hasn't started
646 2015-06-18T17:14:57.254+0800 b.s.d.supervisor [INFO] 2376a892-2a8a-401e-9bd6-85059ab57586 still hasn't started
647 2015-06-18T17:14:57.756+0800 b.s.d.supervisor [INFO] 2376a892-2a8a-401e-9bd6-85059ab57586 still hasn't started
...(若干条重复的信息)
当然,正常情况下 supervisor 在刚启动 worker 的时候也会报这个信息,只不过会在 worker 正常运行之后恢复正常。但是这里的 supervisor 之后仍然会不停地尝试重连,并且最终在超时后放弃这个 worker,这个就不属于正常情况了。
2015-06-18T17:17:07.880+0800 o.a.s.z.ClientCnxn [INFO] Unable to read additional data from server sessionid 0x804de6f8a15a0000, likely server has closed socket, closing socket connection and attempting reco nnect
668 2015-06-18T17:17:19.491+0800 o.a.s.z.ClientCnxn [INFO] Opening socket connection to server hd124/192.168.91.124:2181. Will not attempt to authenticate using SASL (unknown error)
669 2015-06-18T17:17:19.492+0800 o.a.s.z.ClientCnxn [INFO] Socket connection established to hd124/192.168.91.124:2181, initiating session
670 2015-06-18T17:17:19.495+0800 o.a.s.z.ClientCnxn [INFO] Session establishment complete on server hd124/192.168.91.124:2181, sessionid = 0x804de6f8a15a0000, negotiated timeout = 20000671 2015-06-18T17:17:27.913+0800 o.a.s.c.f.s.ConnectionStateManager [INFO] State change: SUSPENDED
672 2015-06-18T17:17:27.918+0800 b.s.cluster [WARN] Received event :disconnected::none: with disconnected Zookeeper.
673 2015-06-18T17:17:27.918+0800 o.a.s.c.f.s.ConnectionStateManager [INFO] State change: RECONNECTED
...
689 2015-06-18T17:18:21.492+0800 o.a.s.z.ClientCnxn [INFO] Unable to reconnect to ZooKeeper service, session 0x804de6f8a15a0000 has expired, closing socket connection
690 2015-06-18T17:18:21.492+0800 o.a.s.c.f.s.ConnectionStateManager [INFO] State change: LOST
这个问题乍一看是网络问题,而且很多帖子也这么说,比如http://blog.csdn.net/jmppok/article/details/17073397 还有 SO 上面搜到的几篇答案说的都是 hosts 配置问题。不过这里的配置并没有问题,网络也没有问题,Storm 的元数据也正常。
另外也有说是 JVM 配置问题(http://macrochen.iteye.com/blog/1428093),但实际上机器的内存一直很稳定,而且 JVM 的日志记录也正常。由于我是在执行 DRPC 的时候出现问题的,还特意检查/重启了 DRPC 服务器,发现也不是 DRPC 的问题。
这些都没问题,那就有可能是 CPU 的问题了,top 看一下(没有装 sar 和 iostat 就先这么凑合了)
top - 09:36:52 up 17 days, 21:16, 1 user, load average: 20.31, 19.13, 11.12
Tasks: 128 total, 6 running, 122 sleeping, 0 stopped, 0 zombie
Cpu(s): 27.0%us, 73.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 2075036k total, 2021612k used, 53424k free, 131148k buffers
Swap: 4128760k total, 68k used, 4128692k free, 722616k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4950 root 18 0 698m 573m 13m S 99.2 28.3 10:50.45 java
果然,99.2% 的 CPU 占用,系统不能长时间承受这么高的负载,就中断了 worker 进程。这个理由可以解释,因为确实我们在新版本应用里把吞吐量加大了一倍,从 Storm UI 中可以看出,在拓扑刚上线的时候,处理量较大的 bolt 的 capacity 会瞬间飙升到接近 1 的程度,虽然在后面数据流平稳下来之后可以慢慢降低,但是这个过程还是有很大的不确定性。所以,暂时需要先把吞吐量降下来,再考虑慢慢调整。不过,这个问题还没这么简单。因为我发现集群中同配置的另一个机器就没有这个问题,而且即使在这台机器 worker 挂掉,nimbus 将这台机器的 worker 分配到另外那台机器的情况下,那台机器上的 CPU 也只有 80+%。同样配置同样的网络运行同样的进程怎么会有这么大的差异?
对这个问题苦思了半天不得其解,最后想想还是要看看 CPU 设备信息有没有什么问题。然后,就没有然后了,额,不对,说顺口了,然后应该就是出现真相的地方了
[root@s2 /home/storm/apache-storm-0.9.3/logs]$>cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 62
model name : Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz
这里只有一个 CPU。真是让人哭笑不得,我们的服务器都是用的分配的虚拟机,也不知道谁把这台机器只分了个单核的 CPU,数据流压力稍微高点当然会扛不住。但是也没办法,现在服务器资源还紧张,只能这么凑合着用,然后继续等着新服务器的申请什么时候能批下来……
当然,除了硬件方面的问题之外,拓扑本身也还有可以优化的地方。一方面,从 Storm UI 上观察到的某些负载较大的 bolt 也确实需要调整下并发度;另一方面,数据流优先进入的部分 bolt 也需要优化下处理方法。这样双管齐下才能真正地解决好问题。
彩蛋 # get 到的新技能 - 在 worker 没有日志的时候可以手动执行 supervisor 中的启动命令(就是 “java xxx” 那个大长串)来启动 worker
Comments
comments powered by Disqus