-
Notifications
You must be signed in to change notification settings - Fork 230
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Mochi
committed
Feb 9, 2020
1 parent
e96ef01
commit 073d825
Showing
5 changed files
with
127 additions
and
120 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,128 +1,117 @@ | ||
mqtt | ||
# Mochi MQTT | ||
### A High-performance MQTT server in Go (v3.0 | v3.1.1) | ||
|
||
Mochi MQTT is an embeddable high-performance MQTT broker server written in Go, and compliant with the MQTT v3.0 and v3.1.1 specification for the development of IoT and smarthome projects. The server can be used either as a standalone binary or embedded as a library in your own projects. | ||
|
||
## Benchmarks | ||
#### What is MQTT? | ||
MQTT stands for MQ Telemetry Transport. It is a publish/subscribe, extremely simple and lightweight messaging protocol, designed for constrained devices and low-bandwidth, high-latency or unreliable networks. [Learn more](https://mqtt.org/faq) | ||
|
||
#### Mochi MQTT Features | ||
- Paho MQTT 3.0 / 3.1.1 compatible. | ||
- Full MQTT Feature-set (QoS, Retained, $SYS) | ||
- Trie-based Subscription model. | ||
- Ring Buffer packet codec. | ||
- TCP, Websocket, (including SSL/TLS) and Dashboard listeners. | ||
- Interfaces for Client Authentication and Topic access control. | ||
- Bolt-backed persistence and storage interfaces. | ||
|
||
#### Roadmap | ||
- Inline Pub-sub (without client) and event hooks | ||
- Docker Image | ||
- MQTT v5 Compatibility | ||
|
||
#### Performance | ||
... | ||
|
||
``` | ||
BenchmarkNewClients-4 145755818 7.92 ns/op 0 B/op 0 allocs/op | ||
BenchmarkClientsAdd-4 24870105 55.9 ns/op 0 B/op 0 allocs/op | ||
BenchmarkClientsGet-4 55802703 23.2 ns/op 0 B/op 0 allocs/op | ||
BenchmarkClientsLen-4 70591254 16.4 ns/op 0 B/op 0 allocs/op | ||
BenchmarkClientsDelete-4 33240973 37.5 ns/op 0 B/op 0 allocs/op | ||
BenchmarkNewClient-4 2598082 461 ns/op 448 B/op 6 allocs/op | ||
BenchmarkNextPacketID-4 100000000 11.6 ns/op 0 B/op 0 allocs/op | ||
BenchmarkClientNoteSubscription-4 24480771 46.5 ns/op 0 B/op 0 allocs/op | ||
BenchmarkClientForgetSubscription-4 12960447 95.5 ns/op 0 B/op 0 allocs/op | ||
BenchmarkInflightSet-4 17793058 67.1 ns/op 0 B/op 0 allocs/op | ||
BenchmarkInflightGet-4 25092826 46.4 ns/op 0 B/op 0 allocs/op | ||
BenchmarkNew-4 22918302 44.3 ns/op 0 B/op 0 allocs/op | ||
BenchmarkServerAddListener-4 7614312 160 ns/op 0 B/op 0 allocs/op | ||
BenchmarkServerServe-4 405841 4993 ns/op 556 B/op 4 allocs/op | ||
BenchmarkServerClose-4 781466 1814 ns/op 192 B/op 3 allocs/op | ||
BenchmarkServerProcessPacket-4 345994209 7.46 ns/op 0 B/op 0 allocs/op | ||
BenchmarkServerProcessConnect-4 230116939 5.22 ns/op 0 B/op 0 allocs/op | ||
BenchmarkServerProcessDisconnect-4 214293916 5.11 ns/op 0 B/op 0 allocs/op | ||
BenchmarkServerProcessPingreq-4 796363 2678 ns/op 459 B/op 7 allocs/op | ||
BenchmarkServerProcessPublish-4 8610757 237 ns/op 48 B/op 1 allocs/op | ||
BenchmarkServerProcessPubrec-4 44983093 24.2 ns/op 0 B/op 0 allocs/op | ||
BenchmarkServerProcessPubrel-4 48499730 25.6 ns/op 0 B/op 0 allocs/op | ||
BenchmarkServerProcessPubcomp-4 46276398 22.8 ns/op 0 B/op 0 allocs/op | ||
BenchmarkServerProcessSubscribe-4 590350 3744 ns/op 728 B/op 9 allocs/op | ||
BenchmarkServerProcessUnsubscribe-4 508149 2687 ns/op 475 B/op 7 allocs/op | ||
``` | ||
|
||
#### Using the Broker | ||
Mochi MQTT can be used as a standalone broker. Simply checkout this repository and run the `main.go` entrypoint in the `cmd` folder which will expose tcp (:1883), websocket (:1882), and dashboard (:8080) listeners. | ||
|
||
``` | ||
BenchmarkNewListeners-4 100000000 10.0 ns/op 0 B/op 0 allocs/op | ||
BenchmarkAddListener-4 18383103 64.2 ns/op 0 B/op 0 allocs/op | ||
BenchmarkGetListener-4 54720651 21.9 ns/op 0 B/op 0 allocs/op | ||
BenchmarkLenListener-4 70944740 16.3 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDeleteListener-4 33414661 36.4 ns/op 0 B/op 0 allocs/op | ||
BenchmarkServeListener-4 578126 3569 ns/op 529 B/op 2 allocs/op | ||
BenchmarkServeAllListeners-4 266442 24929 ns/op 1592 B/op 7 allocs/op | ||
BenchmarkCloseListener-4 5804686 211 ns/op 96 B/op 1 allocs/op | ||
BenchmarkCloseAllListeners-4 8264860 392 ns/op 96 B/op 1 allocs/op | ||
BenchmarkNewTCP-4 31808517 247 ns/op 96 B/op 1 allocs/op | ||
BenchmarkTCPSetConfig-4 16300988 134 ns/op 32 B/op 1 allocs/op | ||
BenchmarkTCPID-4 74531133 16.3 ns/op 0 B/op 0 allocs/op | ||
cd cmd | ||
go build -o mqtt && ./mqtt | ||
``` | ||
|
||
#### Quick Start | ||
|
||
``` go | ||
import ( | ||
mqtt "github.com/mochi-co/mqtt/server" | ||
) | ||
|
||
func main() { | ||
// Create the new MQTT Server. | ||
server := mqtt.New() | ||
|
||
// Create a TCP listener on a standard port. | ||
tcp := listeners.NewTCP("t1", ":1883") | ||
|
||
// Add the listener to the server with default options (nil). | ||
err := server.AddListener(tcp, nil) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
// Start the broker. Serve() is blocking - see examples folder | ||
// for usage ideas. | ||
err = server.Serve() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
} | ||
``` | ||
BenchmarkAllowAuth-4 1000000000 0.335 ns/op 0 B/op 0 allocs/op | ||
BenchmarkAllowACL-4 1000000000 0.351 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDisallowAuth-4 1000000000 0.340 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDisallowACL-4 1000000000 0.345 ns/op 0 B/op 0 allocs/op | ||
``` | ||
|
||
Examples of running the broker with various configurations can be found in the `examples` folder. | ||
|
||
#### Network Listeners | ||
The server comes with a variety of pre-packaged network listeners which allow the broker to accept connections on different protocols. The current listeners are: | ||
- `listeners.NewTCP(id, address string)` - A TCP Listener, taking a unique ID and a network address to bind. | ||
- `listeners.NewWebsocket(id, address string)` A Websocket Listener | ||
- `listeners.NewHTTPStats()` An HTTP $SYS info dashboard | ||
|
||
##### Configuring Network Listeners | ||
When a listener is added to the server using `server.AddListener`, a `*listeners.Config` may be passed as the second argument. | ||
|
||
##### Authentication and ACL | ||
Authentication and ACL may be configured on a per-listener basis by providing an Auth Controller to the listener configuration. Custom Auth Controllers should satisfy the `auth.Controller` interface found in `listeners/auth`. Two default controllers are provided, `auth.Allow`, which allows all traffic, and `auth.Disallow`, which denies all traffic. | ||
|
||
```go | ||
err := server.AddListener(tcp, &listeners.Config{ | ||
Auth: new(auth.Allow), | ||
}) | ||
``` | ||
BenchmarkNew-4 43395020 25.3 ns/op 0 B/op 0 allocs/op | ||
BenchmarkPoperate-4 4947649 246 ns/op 0 B/op 0 allocs/op | ||
BenchmarkSubscribe-4 4079262 301 ns/op 0 B/op 0 allocs/op | ||
BenchmarkUnsubscribe-4 2971792 406 ns/op 0 B/op 0 allocs/op | ||
BenchmarkSubscribers-4 2497588 462 ns/op 0 B/op 0 allocs/op | ||
BenchmarkIsolateParticle-4 22714515 48.3 ns/op 0 B/op 0 allocs/op | ||
BenchmarkRetainMessage-4 4361300 285 ns/op 0 B/op 0 allocs/op | ||
BenchmarkMessages-4 3255422 359 ns/op 0 B/op 0 allocs/op | ||
|
||
> If no auth controller is provided in the listener configuration, the server will default to _Disallowing_ all traffic to prevent unintentional security issues. | ||
##### SSL | ||
SSL may be configured on both the TCP and Websocket listeners by providing a public-private PEM key pair to the listener configuration as `[]byte` slices. | ||
```go | ||
err := server.AddListener(tcp, &listeners.Config{ | ||
Auth: new(auth.Allow), | ||
TLS: &listeners.TLS{ | ||
Certificate: publicCertificate, | ||
PrivateKey: privateKey, | ||
}, | ||
}) | ||
``` | ||
> Note the mandatory inclusion of the Auth Controller! | ||
``` | ||
BenchmarkDecodeString-4 78840612 23.0 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDecodeBytes-4 100000000 13.7 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDecodeByte-4 1000000000 0.978 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDecodeUint16-4 1000000000 0.756 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDecodeByteBool-4 1000000000 0.900 ns/op 0 B/op 0 allocs/op | ||
BenchmarkEncodeBool-4 1000000000 0.585 ns/op 0 B/op 0 allocs/op | ||
BenchmarkEncodeBytes-4 1000000000 0.441 ns/op 0 B/op 0 allocs/op | ||
BenchmarkEncodeUint16-4 1000000000 0.529 ns/op 0 B/op 0 allocs/op | ||
BenchmarkEncodeString-4 87987272 21.2 ns/op 0 B/op 0 allocs/op | ||
BenchmarkConnackEncode-4 36861868 38.0 ns/op 14 B/op 0 allocs/op | ||
BenchmarkConnackDecode-4 39480138 34.4 ns/op 0 B/op 0 allocs/op | ||
BenchmarkConnackValidate-4 1000000000 0.374 ns/op 0 B/op 0 allocs/op | ||
BenchmarkConnectEncode-4 7838436 136 ns/op 38 B/op 0 allocs/op | ||
BenchmarkConnectDecode-4 14495463 74.0 ns/op 0 B/op 0 allocs/op | ||
BenchmarkConnectValidate-4 335426919 3.51 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDisconnectEncode-4 70712485 18.8 ns/op 7 B/op 0 allocs/op | ||
BenchmarkDisconnectDecode-4 44808872 29.1 ns/op 0 B/op 0 allocs/op | ||
BenchmarkDisconnectValidate-4 1000000000 0.348 ns/op 0 B/op 0 allocs/op | ||
BenchmarkFixedHeaderEncode-4 78281166 32.3 ns/op 6 B/op 0 allocs/op | ||
BenchmarkFixedHeaderDecode-4 100000000 12.0 ns/op 0 B/op 0 allocs/op | ||
BenchmarkEncodeLength-4 100000000 15.1 ns/op 2 B/op 0 allocs/op | ||
BenchmarkNewParser-4 1000000000 0.960 ns/op 0 B/op 0 allocs/op | ||
BenchmarkRefreshDeadline-4 9184636 131 ns/op 0 B/op 0 allocs/op | ||
BenchmarkReadFixedHeader-4 18477132 61.0 ns/op 0 B/op 0 allocs/op | ||
BenchmarkRead-4 5692833 204 ns/op 96 B/op 2 allocs/op | ||
BenchmarkPingreqEncode-4 82176246 15.7 ns/op 6 B/op 0 allocs/op | ||
BenchmarkPingreqDecode-4 44557917 31.3 ns/op 0 B/op 0 allocs/op | ||
BenchmarkPingreqValidate-4 1000000000 0.338 ns/op 0 B/op 0 allocs/op | ||
BenchmarkPingrespEncode-4 79194856 16.4 ns/op 6 B/op 0 allocs/op | ||
BenchmarkPingrespDecode-4 48515474 43.4 ns/op 0 B/op 0 allocs/op | ||
BenchmarkPingrespValidate-4 1000000000 0.449 ns/op 0 B/op 0 allocs/op | ||
BenchmarkPubackEncode-4 29720542 46.3 ns/op 9 B/op 0 allocs/op | ||
BenchmarkPubackDecode-4 23842455 107 ns/op 0 B/op 0 allocs/op | ||
BenchmarkPubackValidate-4 1000000000 0.373 ns/op 0 B/op 0 allocs/op | ||
BenchmarkPubcompEncode-4 39364371 34.0 ns/op 13 B/op 0 allocs/op | ||
BenchmarkPubcompDecode-4 35092684 31.5 ns/op 0 B/op 0 allocs/op | ||
BenchmarkPubcompValidate-4 1000000000 0.335 ns/op 0 B/op 0 allocs/op | ||
BenchmarkPublishEncode-4 15284678 66.6 ns/op 18 B/op 0 allocs/op | ||
BenchmarkPublishDecode-4 23294798 53.3 ns/op 0 B/op 0 allocs/op | ||
BenchmarkPublishCopy-4 1000000000 0.376 ns/op 0 B/op 0 allocs/op | ||
BenchmarkPublishValidate-4 779486254 1.44 ns/op 0 B/op 0 allocs/op | ||
BenchmarkPubrecEncode-4 40375525 34.6 ns/op 13 B/op 0 allocs/op | ||
BenchmarkPubrecDecode-4 37656330 28.6 ns/op 0 B/op 0 allocs/op | ||
BenchmarkPubrecValidate-4 1000000000 0.378 ns/op 0 B/op 0 allocs/op | ||
BenchmarkPubrelEncode-4 36370036 32.8 ns/op 15 B/op 0 allocs/op | ||
BenchmarkPubrelDecode-4 38191740 29.9 ns/op 0 B/op 0 allocs/op | ||
BenchmarkPubrelValidate-4 1000000000 0.394 ns/op 0 B/op 0 allocs/op | ||
BenchmarkSubackEncode-4 19691620 59.6 ns/op 27 B/op 0 allocs/op | ||
BenchmarkSubackDecode-4 26178052 40.6 ns/op 0 B/op 0 allocs/op | ||
BenchmarkSubackValidate-4 1000000000 0.366 ns/op 0 B/op 0 allocs/op | ||
BenchmarkSubscribeEncode-4 6134076 187 ns/op 90 B/op 0 allocs/op | ||
BenchmarkSubscribeDecode-4 2296219 472 ns/op 303 B/op 0 allocs/op | ||
BenchmarkSubscribeValidate-4 1000000000 0.585 ns/op 0 B/op 0 allocs/op | ||
BenchmarkUnsubackEncode-4 39235142 32.8 ns/op 13 B/op 0 allocs/op | ||
BenchmarkUnsubackDecode-4 34655808 42.6 ns/op 0 B/op 0 allocs/op | ||
BenchmarkUnsubackValidate-4 1000000000 0.458 ns/op 0 B/op 0 allocs/op | ||
BenchmarkUnsubscribeEncode-4 7313114 171 ns/op 83 B/op 0 allocs/op | ||
BenchmarkUnsubscribeDecode-4 3187930 372 ns/op 259 B/op 0 allocs/op | ||
BenchmarkUnsubscribeValidate-4 1000000000 0.544 ns/op 0 B/op 0 allocs/op | ||
#### Data Persistence | ||
Mochi MQTT provides a `persistence.Store` interface for developing and attaching persistent stores to the broker. The default persistence mechanism packaged with the broker is backed by [Bolt](https://github.com/etcd-io/bbolt) and can be enabled by assigning a `*bolt.Store` to the server. | ||
```go | ||
// import "github.com/mochi-co/mqtt/server/persistence/bolt" | ||
err = server.AddStore(bolt.New("mochi.db", nil)) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
``` | ||
> Persistence is on-demand (not flushed) and will potentially reduce throughput when compared to the standard in-memory store. Only use it if you need to maintain state through restarts. | ||
#### Paho Interoperability Test | ||
You can check the broker against the [Paho Interoperability Test](https://github.com/eclipse/paho.mqtt.testing/tree/master/interoperability) by starting the broker using `examples/paho/main.go`, and then running the test with `python3 client_test.py` from the _interoperability_ folder. | ||
|
||
## Contributions | ||
Contributions and feedback are both welcomed and encouraged! Open an [issue](https://github.com/mochi-co/mqtt/issues) to report a bug, ask a question, or make a feature request. | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.