Mein Blog

InfluxDB Fehler 500 und Timeout

Für meine Diagramme und so nutze ich eine Influx DB + Grafana. Die Daten hatte ich mal über den influxDb History Adapter von ioBroker gemacht, aber da gab´s immer mal Fehler. Also sende ich die Daten jetzt selbst. So wie ich sie brauche und nur die Daten die ich brauche. In den wenigen Tagen wo ich den ioBroker Adapter laufen lies sind auch über 1GB Daten angefallen.. das bedeutet allein schon knapp 50GB pro Jahr – das wäre Wahnsinn.

Jetzt hatte ich aber das Problem, dass die Influx wohl überlastet ist. Es gab immer wieder Error 500 oder Timeout Probleme. Also dachte ich mir, ich reduziere die Anzahl der Requests auf die DB. Bisher habe ich jeden Wert einzeln gesendet und auch gedrosselt gab es Probleme.
Deswegen jetzt ein Subflow: Jetzt fasse ich eine Messeinheit als ein Objekt zusammen und sende das – 1x pro Minute.

Bisher: Also der Messwert kommt, wird per Funktion dem Feld zugeordnet und eventuell konvertiert und dann über eine Drosselung zur InfluxDB geschickt.

Jetzt neu gibt es ein Subflow der die Werte speichert und wenn welche vorhanden sind schickt er diese gebündelt ab. Aus einem Objekt mit einem Messwert wird also ein Objekt mit beliebig vielen Objekten. Das Measurement und die Haltezeit sind einstellbar.

Zum Ablauf: Die Werte kommen rein, werden in einem Javascript Objekt gespeichert. Jede Sekunde wird per Inject geprüft wie lange die letzte Ausgabe her ist und in einer Flow-Variable gespeichert. 300ms später prüft der Switch ob die Differenz größer ist als in den Eigenschaften definiert und wenn ja werden die Werte ausgegeben. Dabei wird auch das Objekt zurück gesetzt. Sprich geleert. Für das Senden hätte man auch das Gate aus dem letzten Beitrag nutzen können 🙂

Hier der Node Red Code für den Subflow:

[{"id":"b1ba376d.4bdd98","type":"subflow","name":"Payload Merge","info":"# Eingang\nmsg.payload muss ein Objekt sein. Alle Felder werden gespeichert und nach der definierten Zeit gesandt. \n\nKommt in der Zeit ein Messwert 2x wird der alte überschrieben!\n\n# Ausgang\nWenn werte eingelaufen sind kommt nach der definierten Zeit ein payload Objekt mit allen Feldern.\n\n# Reset\nwenn das Topic reset lautet wird alles zurück gesetzt - zum testen eher gedacht.","category":"","in":[{"x":40,"y":100,"wires":[{"id":"5dc702f5.f3a23c"}]}],"out":[{"x":880,"y":340,"wires":[{"id":"2014191d.a97366","port":0}]}],"env":[{"name":"SendInterval_in_sek","type":"num","value":"60"},{"name":"measurement","type":"str","value":""}],"color":"#DDAA99","inputLabels":["Messwerte"],"outputLabels":["zusammengefasstes Messwerte Objekt"],"status":{"x":360,"y":180,"wires":[{"id":"5dc702f5.f3a23c","port":1}]}},{"id":"c328ed2e.4af27","type":"function","z":"b1ba376d.4bdd98","name":"Werte speichern","func":"var data = flow.get('data') || \"{}\";\ndata = JSON.parse(data);\n\nvar payload = msg.payload;\n\nif (!(typeof payload === 'object' && payload !== null)){\n    return msg;\n}\n\nvar now =  Math.round((new Date()).getTime() / 1000);\n\nfor(var key in payload){\n   data[key]  = payload[key];\n}\n\n// speichern\nflow.set('data', JSON.stringify(data));\n\nreturn msg;","outputs":1,"noerr":0,"x":400,"y":120,"wires":[[]]},{"id":"99f17cad.7e5c8","type":"inject","z":"b1ba376d.4bdd98","name":"","topic":"","payload":"","payloadType":"date","repeat":"1","crontab":"","once":false,"onceDelay":0.1,"x":130,"y":260,"wires":[["3badf961.3ca726","f556411c.2ce3a"]]},{"id":"2014191d.a97366","type":"function","z":"b1ba376d.4bdd98","name":"werte ausgeben","func":"var data = flow.get('data') || \"{}\";\ndata = JSON.parse(data);\n\n\nvar now =  Math.round((new Date()).getTime() / 1000);\n\nvar anzahl = 0;\nfor(var key2 in data){\n   anzahl++;\n}\n\n\n// speichern\nflow.set('data', \"{}\"); // leeren\nflow.set('lastUpd', now);\n\nmsg.measurement = env.get('measurement')||\"\";\nmsg.payload = data;\n\nif (anzahl == 0) return;\n\nreturn msg;","outputs":1,"noerr":0,"x":700,"y":340,"wires":[[]]},{"id":"5dc702f5.f3a23c","type":"switch","z":"b1ba376d.4bdd98","name":"","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"reset","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":170,"y":100,"wires":[["3b41e132.44415e"],["c328ed2e.4af27"]]},{"id":"3b41e132.44415e","type":"function","z":"b1ba376d.4bdd98","name":"reset","func":"\n\n// speichern\nflow.set('data', \"{}\");\nflow.set('lastUpd', 0);\nnode.warn(\"RESET\");\n\nreturn msg;","outputs":1,"noerr":0,"x":370,"y":60,"wires":[[]]},{"id":"f6973c1a.70a6","type":"switch","z":"b1ba376d.4bdd98","name":"","property":"SendDiff","propertyType":"flow","rules":[{"t":"gt","v":"SendInterval_in_sek","vt":"env"}],"checkall":"true","repair":false,"outputs":1,"x":550,"y":340,"wires":[["2014191d.a97366"]]},{"id":"3badf961.3ca726","type":"function","z":"b1ba376d.4bdd98","name":"berechnet SendInterval_in_sek","func":"var lastUpd = parseInt( flow.get('lastUpd') || 0);\nvar now =  Math.round((new Date()).getTime() / 1000);\n\nvar SendInterval_in_sek = parseInt(env.get('SendInterval_in_sek') || 30);\n\nvar diff  = now - lastUpd;\n//node.warn(\"Diff: \"+ diff);\nflow.set('SendDiff', diff);\n\nreturn msg;","outputs":1,"noerr":0,"x":430,"y":260,"wires":[[]]},{"id":"f556411c.2ce3a","type":"delay","z":"b1ba376d.4bdd98","name":"","pauseType":"delay","timeout":"300","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":360,"y":340,"wires":[["f6973c1a.70a6"]]}]

Die Fehler sind nicht ganz weg – aber schon weniger. Man könnte nun noch die payloads die da kommen in einen Batch zusammen fügen 🙂 – das später.

Die mobile Version verlassen