Skip to content

Commit a2a1b33

Browse files
authored
Merge pull request #31 from dist-sys/refactor_v0.8.4
Refactor v0.8.4
2 parents f6d022c + 8ead40e commit a2a1b33

File tree

11 files changed

+72
-37
lines changed

11 files changed

+72
-37
lines changed

build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ plugins {
44
}
55

66
wrapper {
7-
gradleVersion = '7.3.3'
7+
gradleVersion = '7.6'
88
}
99

1010
mainClassName = 'mqttloader.Loader'

doc/usage_en.md

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# MQTTLoader usage (v0.8.4)
1+
# MQTTLoader usage (v0.8.5)
22
MQTTLoader is a load testing tool (client tool) for MQTT.
33
It supports both MQTT v5.0 and v3.1.1.
44
From v0.8.0, it supports TLS authentication.
@@ -13,7 +13,7 @@ Download the archive file (zip or tar) from: https://github.com/dist-sys/mqttloa
1313
Below is an example of downloading by using curl command.
1414

1515
```
16-
$ curl -OL https://github.com/dist-sys/mqttloader/releases/download/v0.8.4/mqttloader-0.8.4.zip
16+
$ curl -OL https://github.com/dist-sys/mqttloader/releases/download/v0.8.5/mqttloader-0.8.5.zip
1717
```
1818

1919
By extracting it, you can get the following files.
@@ -70,7 +70,7 @@ The following table shows the parameters which can be set in *mqttloader.conf*.
7070
|:-----------|:------------:|:------------|:------------|
7171
| broker | Yes | (none) | Broker's IP address or FQDN. <br>Ex. `broker = 127.0.0.1` |
7272
| broker_port | No | 1883 (non-TLS)<br>8883 (TLS) | Broker's port number. <br>Ex. `broker_port = 1883` |
73-
| mqtt_version | No | 5 | MQTT version. `3` for MQTT v3.1.1, and `5` for MQTT v5.0. |
73+
| mqtt_version | No | 5 | MQTT version. 3 for MQTT v3.1.1, and 5 for MQTT v5.0. |
7474
| num_publishers | No | 1 | The number of publishers. All publishers send messages to a same topic. |
7575
| num_subscribers | No | 1 | The number of subscribers. All subscribers are subscribe to a same topic. |
7676
| qos_publisher | No | 0 | QoS level of publishers. <br>Valid values are 0/1/2. |
@@ -82,10 +82,10 @@ The following table shows the parameters which can be set in *mqttloader.conf*.
8282
| num_messages | No | 100 | The number of messages sent by **each** publisher. |
8383
| ramp_up | No | 0 | Ramp-up time in seconds. <br>See **4. How to read the results** for details. |
8484
| ramp_down | No | 0 | Ramp-down time in seconds. <br>See **4. How to read the results** for details. |
85-
| interval | No | 0 | Publish interval in microseconds. |
85+
| interval | No | 0 | Publish interval in microseconds.<br>Regardless of num_publishers, each publisher sends messages at this interval. In addition, the gap between multiple publishers' sending is adjusted to be interval/num_publishers as far as possible. |
8686
| subscriber_timeout | No | 5 | Timeout for receiving messages by subscribers in seconds. |
8787
| exec_time | No | 60 | Maximum execution time for measurement in seconds. |
88-
| log_level | No | INFO | Log level. <br>Valid values are `SEVERE`/`WARNING`/`INFO`/`ALL`. |
88+
| log_level | No | INFO | Log level. <br>Valid values are SEVERE/WARNING/INFO/ALL. |
8989
| ntp | No | (none) | NTP server's IP address or FQDN. By setting this, throughput and latency are calculated based on the NTP server's time.<br>It should be set when running multiple MQTTLoader on different machines.<br>Ex. `ntp = ntp.nict.jp` |
9090
| output <sup>**\*1 \*2**</sup> | No | (none) | Directory path to write out measurement record. If not set, MQTTLoader runs by in-memory mode. <br>Ex. `output = /home/testuser` |
9191
| user_name | No | (none) | User name. Required if the broker has the configuration of password authentication. |
@@ -213,7 +213,7 @@ If QoS level is set to 1 or 2, counting is done when receiving PUBACK or PUBCOMP
213213
After completion, MQTTLoader calculates the maximum throughput, the average throughput, and the number of published messages.
214214
`Per second throughput [msg/s]` is the time series of throughputs per second.
215215

216-
By using the parameterse `ramp_up` and `ramp_down`, you can exclude the beginning and trailing data.
216+
By using the parameters `ramp_up` and `ramp_down`, you can exclude the beginning and trailing data.
217217
If you set the following parameter settings for example, the beginning one second and the trailing one second are excluded.
218218

219219
```
@@ -239,6 +239,7 @@ Note that if the specified directory doesn't exist, it is newly created.
239239
The file `mqttloader_xxxxxxxx-xxxxxx.csv` has records like the following:
240240

241241
```
242+
1599643916401359,,,
242243
1599643916416823,ml-EeiE-p-00001,S,
243244
1599643916416882,ml-EeiE-p-00000,S,
244245
1599643916419123,ml-EeiE-s-00000,R,3165
@@ -248,6 +249,7 @@ The file `mqttloader_xxxxxxxx-xxxxxx.csv` has records like the following:
248249
```
249250

250251
Each line, consists of comma-separeted values, indicates the following data.
252+
The first line indicates the measurement start time.
251253
In the case that the event type is `R`, latency data follows.
252254

253255
```
@@ -256,6 +258,7 @@ timestamp (Unix time in microseconds), client ID, event type (S: send, R: receiv
256258

257259
Although MQTTLoader outputs the measurement result to the console, you can use the above .csv file for further analysis.
258260
Note that the latency in the above file is in microseconds, whereas that in the console is in milliseconds with three digits after the decimal point.
261+
the parameters `ramp_up` and `ramp_down` do not affect this file.
259262

260263
---
261264
---

doc/usage_jp.md

+12-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# MQTTLoader 利用方法 (v0.8.4)
1+
# MQTTLoader 利用方法 (v0.8.5)
22
MQTTLoaderは、MQTT v5.0とv3.1.1に対応した負荷テストツール(クライアントツール)です。
33
v0.8.0から、ブローカとのTLS接続にも対応しました。
44

@@ -14,7 +14,7 @@ https://github.com/dist-sys/mqttloader/releases
1414
以下は、Curlコマンドを使ってダウンロードする場合の例です。
1515

1616
```
17-
$ curl -OL https://github.com/dist-sys/mqttloader/releases/download/v0.8.4/mqttloader-0.8.4.zip
17+
$ curl -OL https://github.com/dist-sys/mqttloader/releases/download/v0.8.5/mqttloader-0.8.5.zip
1818
```
1919

2020
ダウンロードしたファイルを解凍すると、以下のディレクトリ構造が得られます。
@@ -70,27 +70,27 @@ broker_port = 1883
7070
|:-----------|:------------:|:------------|:------------|
7171
| broker || (無し) | ブローカのIPアドレスまたはFQDN。 <br>例: `broker = 127.0.0.1` |
7272
| broker_port | × | 1883 (non-TLS)<br>8883 (TLS) | ブローカのポート番号。 <br>例: `broker_port = 1883` |
73-
| mqtt_version | × | 5 | MQTTバージョン。 `3` を指定するとMQTT v3.1.1、`5` を指定するとMQTT v5.0。 |
73+
| mqtt_version | × | 5 | MQTTバージョン。 3 を指定するとMQTT v3.1.1、5 を指定するとMQTT v5.0。 |
7474
| num_publishers | × | 1 | publisher数。全publisherは同じトピックにメッセージを送信。 |
7575
| num_subscribers | × | 1 | subscriber数。全subscriberは同じトピックをsubscribe。 |
7676
| qos_publisher | × | 0 | publisherのQoSレベル。<br>設定可能な値:0/1/2 |
7777
| qos_subscriber | × | 0 | subscriberのQoSレベル。<br>設定可能な値:0/1/2 |
78-
| shared_subscription | × | false | Shared subscriptionの有効/無効を指定するフラグ。指定可能な値は `true` / `false` 。MQTT v5.0でのみ設定可。<br>有効にすると、各メッセージは全subscriberのうちいずれかひとつに届く。<br>例: `shared_subscription = true` |
79-
| retain | × | false | Retainの有効/無効を指定するフラグ。指定可能な値は `true` / `false`|
78+
| shared_subscription | × | false | Shared subscriptionの有効/無効を指定するフラグ。指定可能な値は true/false 。MQTT v5.0でのみ設定可。<br>有効にすると、各メッセージは全subscriberのうちいずれかひとつに届く。<br>例: `shared_subscription = true` |
79+
| retain | × | false | Retainの有効/無効を指定するフラグ。指定可能な値は true/false 。 |
8080
| topic | × | mqttloader-test-topic | 測定で用いられるトピック名。 |
8181
| payload | × | 20 | publisherが送信するメッセージのペイロードサイズ。単位はbyte。設定可能な最小値は8。 |
8282
| num_messages | × | 100 | ****publisherによって送信されるメッセージの数。 |
8383
| ramp_up | × | 0 | ランプアップ時間。単位は秒。<br>詳細は **4. 測定結果の見方** を参照。 |
8484
| ramp_down | × | 0 | ランプダウン時間。単位は秒。<br>詳細は **4. 測定結果の見方** を参照。 |
85-
| interval | × | 0 | 各publisherがメッセージを送信する間隔。単位はマイクロ秒。 |
85+
| interval | × | 0 | 各publisherがメッセージを送信する間隔。単位はマイクロ秒。<br>num_publishersの値とは関係なく、各publisherはそれぞれがintervalおきに送信する。また、複数publisher同士の送信タイミングは、可能な範囲でinterval/num_publishersだけずれるように調整される。 |
8686
| subscriber_timeout | × | 5 | subscriberの受信タイムアウト。単位は秒。 |
8787
| exec_time | × | 60 | 測定の実行時間上限。単位は秒。 |
88-
| log_level | × | INFO | ログレベル。<br>設定可能な値:`SEVERE`/`WARNING`/`INFO`/`ALL` |
88+
| log_level | × | INFO | ログレベル。<br>設定可能な値:SEVERE/WARNING/INFO/ALL |
8989
| ntp | × | (無し) | NTPサーバのIPアドレスまたはFQDN。設定すると、スループットやレイテンシの計算がNTPサーバ時刻を基準として行われる。<br>複数のMQTTLoaderを異なるマシン上で実行する場合には設定することが望ましい。<br>例:`ntp = ntp.nict.jp` |
9090
| output <sup>**※1※2**</sup> | × | (無し) | 測定レコードを書き出すディレクトリのパス。未指定の場合、MQTTLoaderはメモリ上でのみ動作。 <br>例: `output = /home/testuser` |
9191
| user_name | × | (無し) | ユーザ名(ブローカにてパスワード認証が設定されている場合に指定)。 |
9292
| password | × | (無し) | パスワード(ブローカにてパスワード認証が設定されている場合に指定)。 |
93-
| tls | × | false | TLS認証の有効/無効を指定するフラグ。指定可能な値は `true` / `false`|
93+
| tls | × | false | TLS認証の有効/無効を指定するフラグ。指定可能な値は true/false 。 |
9494
| tls_rootca_cert <sup>**※1**</sup> | × | (無し) | TLSサーバ認証用のルートCA証明書(PEM形式)のパス。Java実行環境が参照する信頼済み証明書ストア(通常、Javaインストールディレクトリの `cacerts` ファイル)に登録済みのルートCAであれば、指定不要。<br>例: `tls_rootca_cert = /home/testuser/rootca.crt` |
9595
| tls_client_key <sup>**※1**</sup> | × | (無し) | TLSクライアント認証用の秘密鍵(PEM形式)のパス。このパラメータを指定することで、TLSクライアント認証が有効になる。<br>例: `tls_client_key = /home/testuser/client.key` |
9696
| tls_client_cert_chain <sup>**※1**</sup> | × | (無し) | TLSクライアント認証用のクライアント証明書(PEM形式)のパス。中間CA証明書(PEM形式)のパスもセミコロン区切りで記載する。クライアント証明書、中間CA証明書、の順序で記載すること。ルートCA証明書は不要。(ファイル名・フォルダ名にセミコロンが含まれていると利用不可)<br>例: `tls_client_cert_chain = /home/testuser/client.crt;/home/testuser/ica.crt` |
@@ -240,6 +240,7 @@ subscriberに関しても、上記と同様にして、受信メッセージの
240240
このcsvファイルには、以下のようなデータが記録されます。
241241

242242
```
243+
1599643916401359,,,
243244
1599643916416823,ml-EeiE-p-00001,S,
244245
1599643916416882,ml-EeiE-p-00000,S,
245246
1599643916419123,ml-EeiE-s-00000,R,3165
@@ -249,14 +250,16 @@ subscriberに関しても、上記と同様にして、受信メッセージの
249250
```
250251

251252
各行は、カンマ区切りで、以下の内容となっています。
252-
送受信種別が `R` の場合のみ、レイテンシも記載されます。
253+
先頭行には測定開始時刻のみが記載されます。
254+
また、送受信種別が `R` の場合のみ、レイテンシも記載されます。
253255

254256
```
255257
タイムスタンプ(マイクロ秒単位Unix時間), クライアントID, 送受信種別(S: 送信, R: 受信), レイテンシ(マイクロ秒単位)
256258
```
257259

258260
MQTTLoaderは、測定結果のサマリをコンソールに出力しますが、追加の集計・分析を行いたい場合には上記のファイルを使ってください。
259261
なお、コンソールに出力されるレイテンシはミリ秒単位(小数点以下3桁まで)であるのに対し、上記ファイルのレイテンシはマイクロ秒単位である点に注意してください。
262+
また、パラメータ`ramp_up``ramp_down`はこのファイルには影響しません(すべての送受信記録が出力されます)。
260263

261264
---
262265
---

gradle/wrapper/gradle-wrapper.jar

1.99 KB
Binary file not shown.
+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
4+
networkTimeout=10000
45
zipStoreBase=GRADLE_USER_HOME
56
zipStorePath=wrapper/dists

gradlew

+19-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/bin/sh
22

33
#
4-
# Copyright ? 2015-2021 the original authors.
4+
# Copyright © 2015-2021 the original authors.
55
#
66
# Licensed under the Apache License, Version 2.0 (the "License");
77
# you may not use this file except in compliance with the License.
@@ -32,10 +32,10 @@
3232
# Busybox and similar reduced shells will NOT work, because this script
3333
# requires all of these POSIX shell features:
3434
# * functions;
35-
# * expansions á$varâ, á${var}â, á${var:-default}â, á${var+SET}â,
36-
# á${var#prefix}â, á${var%suffix}â, and á$( cmd )â;
37-
# * compound commands having a testable exit status, especially ácaseâ;
38-
# * various built-in commands including ácommandâ, ásetâ, and áulimitâ.
35+
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36+
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37+
# * compound commands having a testable exit status, especially «case»;
38+
# * various built-in commands including «command», «set», and «ulimit».
3939
#
4040
# Important for patching:
4141
#
@@ -55,7 +55,7 @@
5555
# Darwin, MinGW, and NonStop.
5656
#
5757
# (3) This script is generated from the Groovy template
58-
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
58+
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
5959
# within the Gradle project.
6060
#
6161
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -80,10 +80,10 @@ do
8080
esac
8181
done
8282

83-
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
84-
85-
APP_NAME="Gradle"
83+
# This is normally unused
84+
# shellcheck disable=SC2034
8685
APP_BASE_NAME=${0##*/}
86+
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
8787

8888
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
8989
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
@@ -143,12 +143,16 @@ fi
143143
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144144
case $MAX_FD in #(
145145
max*)
146+
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
147+
# shellcheck disable=SC3045
146148
MAX_FD=$( ulimit -H -n ) ||
147149
warn "Could not query maximum file descriptor limit"
148150
esac
149151
case $MAX_FD in #(
150152
'' | soft) :;; #(
151153
*)
154+
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
155+
# shellcheck disable=SC3045
152156
ulimit -n "$MAX_FD" ||
153157
warn "Could not set maximum file descriptor limit to $MAX_FD"
154158
esac
@@ -205,6 +209,12 @@ set -- \
205209
org.gradle.wrapper.GradleWrapperMain \
206210
"$@"
207211

212+
# Stop when "xargs" is not available.
213+
if ! command -v xargs >/dev/null 2>&1
214+
then
215+
die "xargs is not available"
216+
fi
217+
208218
# Use "xargs" to parse quoted args.
209219
#
210220
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.

gradlew.bat

+9-6
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
@rem limitations under the License.
1515
@rem
1616

17-
@if "%DEBUG%" == "" @echo off
17+
@if "%DEBUG%"=="" @echo off
1818
@rem ##########################################################################
1919
@rem
2020
@rem Gradle startup script for Windows
@@ -25,7 +25,8 @@
2525
if "%OS%"=="Windows_NT" setlocal
2626

2727
set DIRNAME=%~dp0
28-
if "%DIRNAME%" == "" set DIRNAME=.
28+
if "%DIRNAME%"=="" set DIRNAME=.
29+
@rem This is normally unused
2930
set APP_BASE_NAME=%~n0
3031
set APP_HOME=%DIRNAME%
3132

@@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
4041

4142
set JAVA_EXE=java.exe
4243
%JAVA_EXE% -version >NUL 2>&1
43-
if "%ERRORLEVEL%" == "0" goto execute
44+
if %ERRORLEVEL% equ 0 goto execute
4445

4546
echo.
4647
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
7576

7677
:end
7778
@rem End local scope for the variables with windows NT shell
78-
if "%ERRORLEVEL%"=="0" goto mainEnd
79+
if %ERRORLEVEL% equ 0 goto mainEnd
7980

8081
:fail
8182
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
8283
rem the _cmd.exe /c_ return code!
83-
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84-
exit /b 1
84+
set EXIT_CODE=%ERRORLEVEL%
85+
if %EXIT_CODE% equ 0 set EXIT_CODE=1
86+
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
87+
exit /b %EXIT_CODE%
8588

8689
:mainEnd
8790
if "%OS%"=="Windows_NT" endlocal

src/main/java/mqttloader/Constants.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import java.text.SimpleDateFormat;
2020

2121
public class Constants {
22-
public static final String VERSION = "0.8.4";
22+
public static final String VERSION = "0.8.5";
2323
public static final String BROKER_PREFIX_TCP = "tcp://";
2424
public static final String BROKER_PREFIX_TLS = "ssl://";
2525
public static final String BROKER_PORT_TCP = "1883";

src/main/java/mqttloader/Loader.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -430,8 +430,11 @@ private void startMeasurement() {
430430
measurementStartTime = Util.getCurrentTimeWithOffset().plusMillis(delay);
431431
lastRecvTime = measurementStartTime;
432432

433-
for(AbstractClient pub: publishers){
434-
((AbstractPublisher)pub).start(delay);
433+
// publish interval in micro seconds.
434+
int interval = Util.getPropValueInt(Prop.INTERVAL);
435+
int numPub = publishers.size();
436+
for(int i=0;i<numPub;i++){
437+
((AbstractPublisher)publishers.get(i)).start(delay*Constants.MILLISECOND_IN_MICRO+interval*i/numPub);
435438
}
436439
}
437440

@@ -498,6 +501,9 @@ private void calcResult() {
498501
while ((str = br.readLine()) != null) {
499502
StringTokenizer st = new StringTokenizer(str, ",");
500503
long timestamp = Long.valueOf(st.nextToken());
504+
if(!st.hasMoreTokens()) {
505+
continue; // skip the first line that only has a timestamp.
506+
}
501507
int elapsedTime = (int)((timestamp - Util.getEpochMicros(Loader.measurementStartTime))/Constants.SECOND_IN_MICRO);
502508
st.nextToken(); //client ID
503509
boolean isSend = st.nextToken().equals("S") ? true : false;

src/main/java/mqttloader/Recorder.java

+9
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ public Recorder(File file, boolean inMemory) {
6161
public void run() {
6262
thread = Thread.currentThread();
6363

64+
if(!inMemory) {
65+
try {
66+
bw.write(Util.getEpochMicros(Loader.measurementStartTime) + ",,,");
67+
bw.newLine();
68+
} catch (IOException e) {
69+
e.printStackTrace();
70+
}
71+
}
72+
6473
Record record = null;
6574
while (true) {
6675
try {

src/main/java/mqttloader/client/AbstractPublisher.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ public AbstractPublisher(int clientNumber, String topic, int payloadSize, int nu
5050
public void start(long delay) {
5151
service = Executors.newSingleThreadScheduledExecutor();
5252
if(pubInterval==0){
53-
future = service.schedule(this, delay, TimeUnit.MILLISECONDS);
53+
future = service.schedule(this, delay, TimeUnit.MICROSECONDS);
5454
}else{
55-
future = service.scheduleAtFixedRate(this, delay*Constants.MILLISECOND_IN_MICRO, pubInterval, TimeUnit.MICROSECONDS);
55+
future = service.scheduleAtFixedRate(this, delay, pubInterval, TimeUnit.MICROSECONDS);
5656
}
5757
}
5858

0 commit comments

Comments
 (0)