之前總結了 jmeter 分布式測試的過程,在部署過程中提到,要在 system.properties
中配置自己的 IP。
至於為什么要這么做,源於這一次 debug 的過程。
運行環境
mint, ubuntu 兩台主機作為 master 節點,一台 win server 作為 slave 節點,采用分布式的方式,
對 target 進行測試。
問題
問題很奇怪,以 mint 系統作為 master,調度分布式測試沒有問題,
$ jmeter -n -t ./test.jmx -R 10.27.2.210 -l test.jtl -e -o report_test
Creating summariser <summary>
Created the tree successfully using ./888.jmx
Configuring remote engine: 10.27.2.210
Starting remote engines
Starting the test @ Wed May 16 10:09:24 CST 2018 (1526436564379)
Remote engines have been started
Waiting for possible Shutdown/StopTestNow/Heapdump message on port 4445
summary = 1 in 00:00:00 = 3.5/s Avg: 20 Min: 20 Max: 20 Err: 0 (0.00%)
Tidying up remote @ Wed May 16 10:09:26 CST 2018 (1526436566910)
... end of run
而使用另一台 ubuntu 主機作為 master,調度測試,則卡在 waiting 這一行,
$ jmeter -n -t ./test.jmx -R 10.27.2.210 -l test.jtl -e -o report_test
Creating summariser <summary>
Created the tree successfully using ./888.jmx
Configuring remote engine: 10.27.2.210
Starting remote engines
Starting the test @ Wed May 16 10:09:24 CST 2018 (1526436564379)
Remote engines have been started
Waiting for possible Shutdown/StopTestNow/Heapdump message on port 4445
嘗試1:防火牆干擾
第一種猜測,應該是 ubuntu 系統的防火牆干擾,阻止了 4445 端口的數據。
先關閉防火牆
$ sudo service ufw stop
再次運行測試,依舊卡在 waiting 那一行,看來問題沒有那么簡單。
嘗試2:關閉監聽功能
以 Waiting for possible Shutdown/StopTestNow/Heapdump message on port 4445
信息在網上查找,有人建議修改 jmeter 設置,不監聽 shutdown 信息,相應的也就不會開啟 4445 端口,
理論上就不會卡在 waiting 那里,而是直接跳過。
在 ubuntu 主機,修改 jmeter.properties 文件,
#jmeterengine.nongui.maxport=4455 修改為
jmeterengine.nongui.maxport=0
但是依舊不能工作。
嘗試3:端口沒有開啟
在 mint 作為 master,成功調度分布式測試的過程中,mint 主機自身打開了 4445 udp 端口,
用 netstat 可以查看的到。
但是,在 ubuntu 調度的時候,用 netstat 也可以查看到 4445 udp 端口已經打開。
而且用 netcat 測試 udp 端口也是可用的。
$ nc -vz -u 10.27.2.13 4445
Connection to 10.27.2.13 4445 port [udp/*] succeeded!
看來也不是端口未開放的問題。
嘗試4:信息被阻塞
猜測是不是在哪個環節,shutdown message 被阻攔,導致收不過消息,而一直卡在那里。
於是在 mint 主機運行測試的時候,用 wireshark 監聽所有發送與 4445 udp 的信息,然而!什么都沒有!
這樣看來,之前對問題的判斷是不准確的。一直以為和 shutdown message 有關,其實正常運行一次測試,根本不必要有 shutdown message。
嘗試5:在日志中尋找
之前一直被表面現象迷惑,認為是 master 的問題,直到進入 slave 節點查看日志 jmeter-server.log
。
發現這樣的錯誤輸出,
2018-05-14 18:29:56,240 ERROR o.a.j.s.BatchSampleSender: testEnded(host)
java.rmi.ConnectException: Connection refused to host: 127.0.1.1; nested exception is:
java.net.ConnectException: Connection refused: connect
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(Unknown Source) ~[?:1.8.0_162]
at sun.rmi.transport.tcp.TCPChannel.createConnection(Unknown Source) ~[?:1.8.0_162]
at sun.rmi.transport.tcp.TCPChannel.newConnection(Unknown Source) ~[?:1.8.0_162]
at sun.rmi.server.UnicastRef.invoke(Unknown Source) ~[?:1.8.0_162]
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unknown Source) ~[?:1.8.0_162]
at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source) ~[?:1.8.0_162]
at com.sun.proxy.$Proxy20.testEnded(Unknown Source) ~[?:?]
at org.apache.jmeter.samplers.BatchSampleSender.testEnded(BatchSampleSender.java:127) [ApacheJMeter_core.jar:4.0 r1823414]
at org.apache.jmeter.samplers.DataStrippingSampleSender.testEnded(DataStrippingSampleSender.java:86) [ApacheJMeter_core.jar:4.0 r1823414]
at org.apache.jmeter.samplers.RemoteListenerWrapper.testEnded(RemoteListenerWrapper.java:90) [ApacheJMeter_core.jar:4.0 r1823414]
at org.apache.jmeter.engine.StandardJMeterEngine.notifyTestListenersOfEnd(StandardJMeterEngine.java:229) [ApacheJMeter_core.jar:4.0 r1823414]
at org.apache.jmeter.engine.StandardJMeterEngine.run(StandardJMeterEngine.java:495) [ApacheJMeter_core.jar:4.0 r1823414]
at java.lang.Thread.run(Unknown Source) [?:1.8.0_162]
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method) ~[?:1.8.0_162]
at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source) ~[?:1.8.0_162]
at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source) ~[?:1.8.0_162]
at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source) ~[?:1.8.0_162]
at java.net.AbstractPlainSocketImpl.connect(Unknown Source) ~[?:1.8.0_162]
at java.net.PlainSocketImpl.connect(Unknown Source) ~[?:1.8.0_162]
at java.net.SocksSocketImpl.connect(Unknown Source) ~[?:1.8.0_162]
at java.net.Socket.connect(Unknown Source) ~[?:1.8.0_162]
at java.net.Socket.connect(Unknown Source) ~[?:1.8.0_162]
at java.net.Socket.<init>(Unknown Source) ~[?:1.8.0_162]
at java.net.Socket.<init>(Unknown Source) ~[?:1.8.0_162]
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(Unknown Source) ~[?:1.8.0_162]
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(Unknown Source) ~[?:1.8.0_162]
... 13 more
為什么地址是 127.0.1.1 ?為什么要向這個地址通信?
根據對 jmeter master/slave 通信機制的理解,不僅 master 主動向 slave 通信, slave 也向 master 主動通信,自然要知道彼此的地址。
由此聯想到,在 slave 節點多網卡的時候,一般都設置 hostname,猜測 master 也需要進行同樣的設置,告知 slave 自己的通信地址。
於是在 ubuntu master 主機的 system.properties 最后一行添加,
java.rmi.server.hostname=10.27.2.13
測試終於正常運行了。
寫在最后
推而廣之,在 jmeter 的所有節點,無論 master/slave,都顯示設置自己的 IP 地址。
system.properties 最后一行添加
java.rmi.server.hostname=<IP addr>