Dieser Service ust en einfacher cloud native Message Service, wie es ja schon so viele gibt. Zunächst einmal ist er als reiner Test für eine Go Implementierung und verschiedene Studien gedacht. Längerfristig soll dieser Service den GAP zwischen den vielen kleinen selbstgestrickten Lösungen und den doch recht umfangreichen und komplexen Servicen wie Kafka, RocketMQ, RabbitMQ... schliessen.
Ein kurzer Vergleich:
Kafka: Mit Abstand der am weitesten vorgeschrittene Service. Die Eierlegende Woll-Milch-Sau. Kafka kann so ziemlich alles, was man braucht und eben noch viel mehr. Leider ist der Betrieb aber auch eher schwergewichtig. Neben dem Kafka CLuster selber, wernden och weitere zahreiche Komponeneten für den Betrieb benötigt, die auch nicht gerade einfach sind. Als ein Beispiel Zookeeper.
RocketMQ: Etwas weniger komplex, aber leider doch mit dem Nameserver und Broker Konzept recht komplex, gerade für kleine Installation für meine Begriffe etwas oversized.
RabbitMQ: Zwar werden mich die Entwickler nun schlagen, aber RabbitMQ ist nicht Cloud Native. Dazu gibt es da viel zu viele Sonderlocken. Das Discovery der Nodes ist eher fragwürdig, vor allem, wenn es um eine Docker/Kubernetes Integration geht.
Am nähesten für einen solchen Service käme für einen solchen "kleinen" Service wäre NSQ.
Bei diesen sind jedoch der Lookup beim Start, und die nicht vorhandene Persistenz eines Nodes zu beanstanden. Vor allem, da die Messages nicht im Cluster verteilt werden, sondern nur auf dem Node, auf dem Sie gesendet wurden gespeichert. Geht der Node hops, sind die Messages weg. Auch schwierig, der Client macht zu allen Nodes eine Verbindung auf und sucht dann in den verschiedenen Shards nach der zu konsumierenden Message. Ein Splitbrain ist da schon vorprogrammiert. Aber NSQ ist ja noch relativ jung. (V 1.2)
Da der Service eher für kleine bis mittlere Installation vorgesehen ist, werden folgende Annahmen/Voraussetzungen gemacht.
# port of the http server
port: 8080
# port of the https server
sslport: 8443
# this is the servicURL from outside
serviceURL: http://127.0.0.1:8080
# this is the registry URL from inside this service for consul as service registry
registryURL:
# this is the system id of this service. services in a cluster mode should have the same system id.
systemID: autorest-srv
#sercret file for storing usernames and passwords
secretfile: /tmp/storage/config/secret.yaml
#where the configuration files of the backends are
backendpath: configs/backends
#allow data saving without a registered backend
allowAnonymousBackend: true
# configuration of the gelf logging server
logging:
gelf-url:
gelf-port:
# healthcheck configuration
healthcheck:
# automatically check the health of this service every ## seconds
period: 30
Als Storage wird derzeit nur MongoDB unterstützt.
Bei der Mongo Storage Implementierung werden die verschiedenen Backends allerdings in einer Datenbank abgelegt. Einzelne Modelle werden in jeweils einer Collection abgelegt. Der Collectionname besteht aus dem Backendnamen "." und dem Modellnamen.
Um eine neue Mongodatenbank anzulegen, müssen folgende Kommandos auf der Mongo Console ausgeführt werden:
#create a new db named backend1
use backend1
#create a db admin on db backend1 with user backend1 with password backend1
db.createUser({ user: "backend1", pwd: "backend1", roles: [ "readWrite", "dbAdmin", { role: "dbOwner", db: "backend1" } ]})
Folgende User mit folgenden Rollen werden automatisch angelegt:
Hier nun folgt die Beschreibung des REST Interfaces. Beispielhafte REST Calls sind als Postman Collection im Ordner test/postman vorhanden.
Beispielhaft werden hier alle Calls als Calls auf den lokalen Server (127.0.0.1) mit dem Port 9443 bereitgestellt. Bei einer anderen Serverinstanz bitte entsprechend ändern.
Security: Ja, Authentifizierung derzeit als BasicAuth. Role: admin
zus. Header:
X-mcs-system: autorest-srv (Konfigurationseinstellung: systemID)
X-mcs-apikey: {uuid} Wird beim Starten des Servers auf der Konsole ausgegeben.
...
2020/04/29 08:43:04 systemid: autorest-srv
2020/04/29 08:43:04 apikey: 5854d123dd25f310395954f7c450171c
2020/04/29 08:43:04 ssl: true
...
Request: GET: https://127.0.0.1:9443/api/v1/admin/backends
Beschreibung: Liefert eine Liste mit allen Backenddefinitioninformationen. D.h. pro Backend werden nur der Name, die Beschreibung und die URL auf die Definition ausgeliefert.
Request: GET: https://127.0.0.1:9443/api/v1/admin/backends
Response:
[
{
"Name": "sensors",
"Description": "sensor model für storing and retrieving sensor data",
"URL": "https://127.0.0.1:9443/api/v1/admin/backends/sensors/"
},
{
"Name": "mybe",
"Description": "",
"URL": "https://127.0.0.1:9443/api/v1/admin/backends/mybe/"
}
]
GET: https://127.0.0.1:9443/api/v1/admin/backends/{backendname}/
Beschreibung: Liefert die Definition eines Backends.
Request: https://127.0.0.1:9443/api/v1/admin/backends/sensors/
Response:
{
"backendname": "sensors",
"description": "sensor model für storing and retrieving sensor data",
"models": [
{
"name": "temperatur",
"description": "",
"fields": [
{
"name": "temperatur",
"type": "float",
"mandatory": false,
"collection": false
},
{
"name": "source",
"type": "string",
"mandatory": false,
"collection": false
}
],
"indexes": null
}
],
"datasources": [
{
"name": "temp_wohnzimmer",
"type": "mqtt",
"destination": "temperatur",
"rule": "tasmota_ds18b20",
"config": {
"broker": "127.0.0.1:1883",
"topic": "stat/temperatur/wohnzimmer",
"payload": "application/json",
"username": "temp",
"password": "temp",
"addTopicAsAttribute": "topic",
"simpleValueAttribute": ""
}
},
{
"name": "temp_kueche",
"type": "mqtt",
"destination": "temperatur",
"rule": "tasmota_ds18b20",
"config": {
"broker": "127.0.0.1:1883",
"topic": "tele/tasmota_63E6F8/SENSOR",
"payload": "application/json",
"username": "temp",
"password": "temp",
"addTopicAsAttribute": "topic",
"simpleValueAttribute": ""
}
}
],
"rules": [
{
"name": "tasmota_ds18b20",
"description": "transforming the tasmota json structure of the DS18B20 into my simple structure",
"transform": [
{
"operation": "shift",
"spec": {
"TempUnit": "TempUnit",
"Temperature": "DS18B20.Temperature"
}
}
]
},
{
"name": "hm_temp_simple",
"description": "handle homematic temperatur rightly",
"transform": [
{
"operation": "shift",
"spec": {
"Datetime": "ts",
"Temperature": "val",
"Timestamp": "ts"
}
},
{
"operation": "default",
"spec": {
"TempUnit": "°C"
}
},
{
"operation": "timestamp",
"spec": {
"Datetime": {
"inputFormat": "$unixext",
"outputFormat": "2006-01-02T15:04:05-0700"
}
}
}
]
}
]
}
POST: https://127.0.0.1:9443/api/v1/admin/backends/
Beschreibung: Liefert die Definition eines Backends.
Request: https://127.0.0.1:9443/api/v1/admin/backends/sensors/
Response: Not implemented Yet
DELETE: https://127.0.0.1:9443/api/v1/admin/backends/
Beschreibung: Löscht alle Daten eines Backends.
Request: https://127.0.0.1:9443/api/v1/admin/backends/sensors/dropdata
Response:
{
"backend": "sensors",
"msg": "backend sensors deleted. All data destroyed."
}
GET: https://127.0.0.1:9443/api/v1/admin/backends/{backendname}/models
Beschreibung: Liefert eine Liste aller Modelle eines Backends.
Request: https://127.0.0.1:9443/api/v1/admin/backends/sensors/models
Response:
[
{
"name": "temperatur",
"description": "",
"fields": [
{
"name": "temperatur",
"type": "float",
"mandatory": false,
"collection": false
},
{
"name": "source",
"type": "string",
"mandatory": false,
"collection": false
}
],
"indexes": null
}
]
GET: https://127.0.0.1:9443/api/v1/admin/backends/{backendname}/datasources
Beschreibung: Liefert eine Liste aller Datenquellen eines Backends.
Request: https://127.0.0.1:9443/api/v1/admin/backends/sensors/datasources
Response:
[
{
"name": "temp_wohnzimmer",
"type": "mqtt",
"destination": "temperatur",
"rule": "tasmota_ds18b20",
"config": {
"broker": "127.0.0.1:1883",
"topic": "stat/temperatur/wohnzimmer",
"payload": "application/json",
"username": "temp",
"password": "temp",
"addTopicAsAttribute": "topic",
"simpleValueAttribute": ""
}
},
{
"name": "temp_kueche",
"type": "mqtt",
"destination": "temperatur",
"rule": "tasmota_ds18b20",
"config": {
"broker": "127.0.0.1:1883",
"topic": "tele/tasmota_63E6F8/SENSOR",
"payload": "application/json",
"username": "temp",
"password": "temp",
"addTopicAsAttribute": "topic",
"simpleValueAttribute": ""
}
}
]
GET: https://127.0.0.1:9443/api/v1/admin/backends/{backendname}/rules
Beschreibung: Liefert eine Liste aller Transformationsregelen eines Backends.
Request: https://127.0.0.1:9443/api/v1/admin/backends/sensors/rules
Response:
[
{
"name": "tasmota_ds18b20",
"description": "transforming the tasmota json structure of the DS18B20 into my simple structure",
"transform": [
{
"operation": "shift",
"spec": {
"TempUnit": "TempUnit",
"Temperature": "DS18B20.Temperature"
}
}
]
},
{
"name": "hm_temp_simple",
"description": "handle homematic temperatur rightly",
"transform": [
{
"operation": "shift",
"spec": {
"Datetime": "ts",
"Temperature": "val",
"Timestamp": "ts"
}
},
{
"operation": "default",
"spec": {
"TempUnit": "°C"
}
},
{
"operation": "timestamp",
"spec": {
"Datetime": {
"inputFormat": "$unixext",
"outputFormat": "2006-01-02T15:04:05-0700"
}
}
}
]
}
]
GET: https://127.0.0.1:9443/api/v1/admin/backends/{backendname}/rules/{rulename}
Beschreibung: Definition einer Transformationsregel eines Backends.
Request: https://127.0.0.1:9443/api/v1/admin/backends/sensors/rules/hm_temp_simple
Response:
{
"name": "hm_temp_simple",
"description": "handle homematic temperatur rightly",
"transform": [
{
"operation": "shift",
"spec": {
"Datetime": "ts",
"Temperature": "val",
"Timestamp": "ts"
}
},
{
"operation": "default",
"spec": {
"TempUnit": "°C"
}
},
{
"operation": "timestamp",
"spec": {
"Datetime": {
"inputFormat": "$unixext",
"outputFormat": "2006-01-02T15:04:05-0700"
}
}
}
]
}
POST: https://127.0.0.1:9443/api/v1/admin/backends/{backendname}/rules/{rulename}/test
Beschreibung: Testen einer Transformationsregel eines Backends.
Request: https://127.0.0.1:9443/api/v1/admin/backends/sensors/rules/hm_temp_simple/test
Payload:
{
"val": 22.8,
"ts": 1588142598973,
"lc": 1588142598973
}
Response:
{
"Timestamp": 1588142598973,
"Datetime": "2020-04-29T08:43:18+0200",
"Temperature": 22.8,
"TempUnit": "°C"
}
Security: Ja
Request**: GET: https://127.0.0.1:9443/api/v1/admin/tasks
Beschreibung: Liste der Service Tasks
Security role: admin
Request: GET: https://127.0.0.1:9443/api/v1/admin/tasks
Response:
{
"count": 1,
"data": [
{
"_id": "5eca0c72cfe02b227085e242",
"tdata": "reporting",
"tfile": "1234456789",
"tstatus": "finished",
"ttype": "report"
}
],
"found": 1,
"limit": 0,
"offset": 0,
"query": ""
}
Request: POST: https://127.0.0.1:9443/api/v1/admin/tasks
Beschreibung: Starten eines Service tasks
Security role: admin
Request: POST: https://127.0.0.1:9443/api/v1/admin/tasks/
Payload:
{
"ttype": "report",
"tdata": "[optional data for the task, if necessary]"
}
Response:
{
"tasksid": "5ea92df4d015d95201f6b4b8"
}
Headers: Location: /api/v1/admin/tasks/5ea92df4d015d95201f6b4b8
Security: Ja
Request: POST: https://127.0.0.1:9443/api/v1/files/{backendname}/
Beschreibung: Upload einer Datei auf den Server. Dateien dürfen nicht größer sein als 10MB.
Security role: edit
Request: POST: https://127.0.0.1:9443/api/v1/files/sensors/
Payload: Http Formbased File Upload. Name des Formfeldes: file
Response:
{
"fileid": "5ea92df4d015d95201f6b4b8",
"filename": "readme.md"
}
Headers: Location: /api/v1/files/sensors/5ea92df4d015d95201f6b4b8
Request: GET: https://127.0.0.1:9443/api/v1/files/{backendname}/{fileid}
Beschreibung: Download einer Datei vom Server.
Security role: read
Request: GET: https://127.0.0.1:9443/api/v1/files/sensors/5ea92df4d015d95201f6b4b8
Response:
Die Datei als Download.