diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e026003 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +.idea +.vscode \ No newline at end of file diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 74dba66..0000000 --- a/.gitmodules +++ /dev/null @@ -1,6 +0,0 @@ -[submodule "vendor/github.com/GaryBoone/GoStats"] - path = vendor/github.com/GaryBoone/GoStats - url = git://github.com/GaryBoone/GoStats -[submodule "vendor/github.com/eclipse/paho.mqtt.golang"] - path = vendor/github.com/eclipse/paho.mqtt.golang - url = git://github.com/eclipse/paho.mqtt.golang diff --git a/README.md b/README.md index 4f24515..7008e3d 100644 --- a/README.md +++ b/README.md @@ -12,22 +12,36 @@ go get github.com/krylovsk/mqtt-benchmark The tool supports multiple concurrent clients, configurable message size, etc: ```sh -> mqtt-benchmark --help -Usage of mqtt-benchmark: - -broker="tcp://localhost:1883": MQTT broker endpoint as scheme://host:port - -cert="cert.pem": File path to your client certificate in PEM format - -client-id="mqtt-benchmark": MQTT client id - -clients=10: Number of clients to start - -count=100: Number of messages to send per client - -format="text": Output format: text|json - -key="key.pem": File path to your private key in PEM format - -password="": MQTT password (empty if auth disabled) - -qos=1: QoS for published messages - -quiet=false : Suppress logs while running (except errors and the result) - -size=100: Size of the messages payload (bytes) - -topic="/test": MQTT topic for incoming message - -username="": MQTT username (empty if auth disabled) - -wait="60000": QoS 1 wait timeout in milliseconds (default 60000) +$ ./mqtt-benchmark -h +Usage of ./mqtt-benchmark: + -broker string + MQTT broker endpoint as scheme://host:port (default "tcp://localhost:1883") + -client-cert string + Path to client certificate in PEM format + -client-key string + Path to private clientKey in PEM format + -client-prefix string + MQTT client id prefix (suffixed with '-' (default "mqtt-benchmark") + -clients int + Number of clients to start (default 10) + -count int + Number of messages to send per client (default 100) + -format string + Output format: text|json (default "text") + -password string + MQTT client password (empty if auth disabled) + -qos int + QoS for published messages (default 1) + -quiet + Suppress logs while running + -size int + Size of the messages payload (bytes) (default 100) + -topic string + MQTT topic for outgoing messages (default "/test") + -username string + MQTT client username (empty if auth disabled) + -wait int + QoS 1 wait timeout in milliseconds (default 60000) ``` > NOTE: if `count=1` or `clients=1`, the sample standard deviation will be returned as `0` (convention due to the [lack of NaN support in JSON](https://tools.ietf.org/html/rfc4627#section-2.4)) diff --git a/client.go b/client.go index dad518f..fcb2530 100644 --- a/client.go +++ b/client.go @@ -10,6 +10,7 @@ import ( mqtt "github.com/eclipse/paho.mqtt.golang" ) +// Client implements an MQTT client running benchmark test type Client struct { ID int ClientID string @@ -22,9 +23,10 @@ type Client struct { MsgQoS byte Quiet bool WaitTimeout time.Duration - TlsConfig *tls.Config + TLSConfig *tls.Config } +// Run runs benchmark tests and writes results in the provided channel func (c *Client) Run(res chan *RunResults) { newMsgs := make(chan *Message) pubMsgs := make(chan *Message) @@ -137,8 +139,8 @@ func (c *Client) pubMessages(in, out chan *Message, doneGen, donePub chan bool) opts.SetUsername(c.BrokerUser) opts.SetPassword(c.BrokerPass) } - if c.TlsConfig != nil { - opts.SetTLSConfig(c.TlsConfig) + if c.TLSConfig != nil { + opts.SetTLSConfig(c.TLSConfig) } client := mqtt.NewClient(opts) diff --git a/main.go b/main.go index 0d3f884..abf853c 100644 --- a/main.go +++ b/main.go @@ -58,20 +58,20 @@ type JSONResults struct { func main() { var ( - broker = flag.String("broker", "tcp://localhost:1883", "MQTT broker endpoint as scheme://host:port") - topic = flag.String("topic", "/test", "MQTT topic for outgoing messages") - clientID = flag.String("client-id", "mqtt-benchmark", "MQTT client id") - username = flag.String("username", "", "MQTT username (empty if auth disabled)") - password = flag.String("password", "", "MQTT password (empty if auth disabled)") - qos = flag.Int("qos", 1, "QoS for published messages") - wait = flag.Int("wait", 60000, "QoS 1 wait timeout in milliseconds") - size = flag.Int("size", 100, "Size of the messages payload (bytes)") - count = flag.Int("count", 100, "Number of messages to send per client") - clients = flag.Int("clients", 10, "Number of clients to start") - format = flag.String("format", "text", "Output format: text|json") - quiet = flag.Bool("quiet", false, "Suppress logs while running") - cert = flag.String("cert", "", "File path to your client certificate in PEM format") - key = flag.String("key", "", "File path to your private key in PEM format") + broker = flag.String("broker", "tcp://localhost:1883", "MQTT broker endpoint as scheme://host:port") + topic = flag.String("topic", "/test", "MQTT topic for outgoing messages") + username = flag.String("username", "", "MQTT client username (empty if auth disabled)") + password = flag.String("password", "", "MQTT client password (empty if auth disabled)") + qos = flag.Int("qos", 1, "QoS for published messages") + wait = flag.Int("wait", 60000, "QoS 1 wait timeout in milliseconds") + size = flag.Int("size", 100, "Size of the messages payload (bytes)") + count = flag.Int("count", 100, "Number of messages to send per client") + clients = flag.Int("clients", 10, "Number of clients to start") + format = flag.String("format", "text", "Output format: text|json") + quiet = flag.Bool("quiet", false, "Suppress logs while running") + clientPrefix = flag.String("client-prefix", "mqtt-benchmark", "MQTT client id prefix (suffixed with '-'") + clientCert = flag.String("client-cert", "", "Path to client certificate in PEM format") + clientKey = flag.String("client-key", "", "Path to private clientKey in PEM format") ) flag.Parse() @@ -83,17 +83,17 @@ func main() { log.Fatalf("Invalid arguments: messages count should be > 1, given: %v", *count) } - if *cert != "" && *key == "" { - log.Fatal("Invalid arguments: private key path missing") + if *clientCert != "" && *clientKey == "" { + log.Fatal("Invalid arguments: private clientKey path missing") } - if *cert == "" && *key != "" { + if *clientCert == "" && *clientKey != "" { log.Fatalf("Invalid arguments: certificate path missing") } var tlsConfig *tls.Config - if *cert != "" && *key != "" { - tlsConfig = generateTlsConfig(*cert, *key) + if *clientCert != "" && *clientKey != "" { + tlsConfig = generateTLSConfig(*clientCert, *clientKey) } resCh := make(chan *RunResults) @@ -104,7 +104,7 @@ func main() { } c := &Client{ ID: i, - ClientID: *clientID, + ClientID: *clientPrefix, BrokerURL: *broker, BrokerUser: *username, BrokerPass: *password, @@ -114,7 +114,7 @@ func main() { MsgQoS: byte(*qos), Quiet: *quiet, WaitTimeout: time.Duration(*wait) * time.Millisecond, - TlsConfig: tlsConfig, + TLSConfig: tlsConfig, } go c.Run(resCh) } @@ -183,7 +183,7 @@ func printResults(results []*RunResults, totals *TotalResults, format string) { log.Fatalf("Error marshalling results: %v", err) } var out bytes.Buffer - json.Indent(&out, data, "", "\t") + _ = json.Indent(&out, data, "", "\t") fmt.Println(string(out.Bytes())) default: @@ -211,7 +211,7 @@ func printResults(results []*RunResults, totals *TotalResults, format string) { return } -func generateTlsConfig(certFile string, keyFile string) *tls.Config { +func generateTLSConfig(certFile string, keyFile string) *tls.Config { cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { log.Fatalf("Error reading certificate files: %v", err)