Ein Node.js-Toolkit für Microservice-Architekturen
Dieses Open-Source-Modul wird von Voxgig gesponsert und unterstützt. |
---|
Seneca ist ein Toolkit zum Schreiben von Microservices und zum Organisieren der Geschäftslogik Ihrer App. Sie können Ihre App in „Dinge, die passieren“ aufteilen, anstatt sich auf Datenmodelle oder die Verwaltung von Abhängigkeiten zu konzentrieren.
Seneca bietet,
Mustervergleich: eine wunderbar flexible Möglichkeit, geschäftliche Anforderungen zu erfüllen
Transportunabhängigkeit: Sie sollten sich keine Gedanken darüber machen, wie Nachrichten zum richtigen Server gelangen
Reife: 8 Jahre in der Produktion (bevor wir es Microservices nannten), wurde aber einmal durch einen Blitz zerstört
Plus: ein tiefes und breites Ökosystem an Plugins
Buch: Ein Leitfaden zum Entwerfen von Microservice-Architekturen: taomicro
Verwenden Sie dieses Modul, um Befehle zu definieren, die funktionieren, indem sie etwas JSON aufnehmen und optional etwas JSON zurückgeben. Der auszuführende Befehl wird durch Mustervergleich im Eingabe-JSON ausgewählt. Es gibt integrierte und optionale Befehlssätze, mit denen Sie Minimum Viable Products erstellen können: Datenspeicherung, Benutzerverwaltung, verteilte Logik, Caching, Protokollierung usw. Und Sie können Ihr eigenes Produkt definieren, indem Sie es in einen Befehlssatz aufteilen – „ Dinge, die passieren". Das ist so ziemlich alles.
Wenn Sie dieses Modul verwenden und Hilfe benötigen, können Sie:
Wenn Sie generell neu bei Seneca sind, werfen Sie bitte einen Blick auf senecajs.org. Wir haben alles von Tutorials bis hin zu Beispiel-Apps, damit Sie schnell loslegen können.
Die Quelle von Seneca kann mit Anmerkungen gelesen werden, indem npm run annotate
ausgeführt wird. Eine kommentierte Version jeder Datei wird in ./docs/
generiert.
Um über npm zu installieren,
npm install seneca
'use strict'
var Seneca = require ( 'seneca' )
// Functionality in seneca is composed into simple
// plugins that can be loaded into seneca instances.
function rejector ( ) {
this . add ( 'cmd:run' , ( msg , done ) => {
return done ( null , { tag : 'rejector' } )
} )
}
function approver ( ) {
this . add ( 'cmd:run' , ( msg , done ) => {
return done ( null , { tag : 'approver' } )
} )
}
function local ( ) {
this . add ( 'cmd:run' , function ( msg , done ) {
this . prior ( msg , ( err , reply ) => {
return done ( null , { tag : reply ? reply . tag : 'local' } )
} )
} )
}
// Services can listen for messages using a variety of
// transports. In process and http are included by default.
Seneca ( )
. use ( approver )
. listen ( { type : 'http' , port : '8260' , pin : 'cmd:*' } )
Seneca ( )
. use ( rejector )
. listen ( 8270 )
// Load order is important, messages can be routed
// to other services or handled locally. Pins are
// basically filters over messages
function handler ( err , reply ) {
console . log ( err , reply )
}
Seneca ( )
. use ( local )
. act ( 'cmd:run' , handler )
Seneca ( )
. client ( { port : 8270 , pin : 'cmd:run' } )
. client ( { port : 8260 , pin : 'cmd:run' } )
. use ( local )
. act ( 'cmd:run' , handler )
Seneca ( )
. client ( { port : 8260 , pin : 'cmd:run' } )
. client ( { port : 8270 , pin : 'cmd:run' } )
. use ( local )
. act ( 'cmd:run' , handler )
// Output
// null { tag: 'local' }
// null { tag: 'approver' }
// null { tag: 'rejector' }
Um normal, beispielsweise in einem Container, zu laufen, verwenden Sie
$ node microservice.js
(wobei microservice.js
eine Skriptdatei ist, die Seneca verwendet). Protokolle werden im JSON-Format ausgegeben, sodass Sie sie an einen Protokollierungsdienst senden können.
Um im Testmodus mit für Menschen lesbaren, vollständigen Debug-Protokollen auszuführen, verwenden Sie:
$ node microservice.js --seneca.test
Damit es keine Rolle spielt,
Solange ein Befehl ein bestimmtes JSON-Dokument verarbeiten kann, ist alles in Ordnung.
Hier ist ein Beispiel:
var seneca = require ( 'seneca' ) ( )
seneca . add ( { cmd : 'salestax' } , function ( msg , done ) {
var rate = 0.23
var total = msg . net * ( 1 + rate )
done ( null , { total : total } )
} )
seneca . act ( { cmd : 'salestax' , net : 100 } , function ( err , result ) {
console . log ( result . total )
} )
Wenn Seneca in diesem Code das Muster {cmd:'salestax'}
sieht, führt es die diesem Muster zugeordnete Funktion aus, die die Umsatzsteuer berechnet. An der Eigenschaft cmd
gibt es nichts Besonderes. Es handelt sich lediglich um die Eigenschaft, die wir als Muster abgleichen möchten. Sie könnten nach foo
für alle Seneca-Sorgen suchen! Yah!
Die seneca.add
-Methode fügt ein neues Muster und die Funktion hinzu, die immer dann ausgeführt wird, wenn dieses Muster auftritt.
Die seneca.act
-Methode akzeptiert ein Objekt und führt gegebenenfalls den passenden Befehl aus.
Woher kommt der Umsatzsteuersatz? Versuchen wir es noch einmal:
seneca . add ( { cmd : 'config' } , function ( msg , done ) {
var config = { rate : 0.23 }
var value = config [ msg . prop ]
done ( null , { value : value } )
} )
seneca . add ( { cmd : 'salestax' } , function ( msg , done ) {
seneca . act ( { cmd : 'config' , prop : 'rate' } , function ( err , result ) {
var rate = parseFloat ( result . value )
var total = msg . net * ( 1 + rate )
done ( null , { total : total } )
} )
} )
seneca . act ( { cmd : 'salestax' , net : 100 } , function ( err , result ) {
console . log ( result . total )
} )
Der Befehl config
liefert Ihnen Ihre Konfiguration. Das ist cool, denn es spielt keine Rolle , woher die Konfiguration kommt – fest codiert, Dateisystem, Datenbank, Netzwerkdienst, was auch immer. Mussten Sie eine Abstraktions-API definieren, damit dies funktioniert? Nein.
Es gibt hier ein wenig, aber zu viel Ausführlichkeit, finden Sie nicht? Lassen Sie uns das beheben:
seneca . act ( 'cmd:salestax,net:100' , function ( err , result ) {
console . log ( result . total )
} )
Anstatt ein Objekt bereitzustellen, können Sie eine Zeichenfolge mithilfe einer Kurzform von JSON bereitstellen. Tatsächlich können Sie beides bereitstellen:
seneca . act ( 'cmd:salestax' , { net : 100 } , function ( err , result ) {
console . log ( result . total )
} )
Dies ist eine sehr praktische Möglichkeit, Muster und Parameterdaten zu kombinieren .
Der Weg, Node.js-Systeme zu erstellen, besteht darin, viele kleine Prozesse zu erstellen. Hier ist ein großartiger Vortrag, der erklärt, warum Sie dies tun sollten: Programmer Anarchy.
Seneca macht das wirklich einfach. Lassen Sie uns die Konfiguration im Netzwerk in einen eigenen Prozess umwandeln:
seneca . add ( { cmd : 'config' } , function ( msg , done ) {
var config = { rate : 0.23 }
var value = config [ msg . prop ]
done ( null , { value : value } )
} )
seneca . listen ( )
Die listen
-Methode startet einen Webserver, der auf JSON-Nachrichten wartet. Wenn diese eintreffen, werden sie an die lokale Seneca-Instanz übermittelt und auf normale Weise als Aktionen ausgeführt. Das Ergebnis wird dann als Antwort auf die HTTP-Anfrage an den Client zurückgegeben. Seneca kann auch über einen Nachrichtenbus auf Aktionen warten.
Ihre Implementierung des Konfigurationscodes bleibt gleich .
Der Client-Code sieht folgendermaßen aus:
seneca . add ( { cmd : 'salestax' } , function ( msg , done ) {
seneca . act ( { cmd : 'config' , prop : 'rate' } , function ( err , result ) {
var rate = parseFloat ( result . value )
var total = msg . net * ( 1 + rate )
done ( null , { total : total } )
} )
} )
seneca . client ( )
seneca . act ( 'cmd:salestax,net:100' , function ( err , result ) {
console . log ( result . total )
} )
Auf der Client-Seite bedeutet der Aufruf von seneca.client()
, dass Seneca alle Aktionen, die es lokal nicht abgleichen kann, über das Netzwerk sendet. In diesem Fall stimmt der Konfigurationsserver mit dem cmd:config
Muster überein und gibt die Konfigurationsdaten zurück.
Beachten Sie auch hier, dass sich Ihr Umsatzsteuercode nicht ändert . Es muss nicht bekannt sein, woher die Konfiguration kommt, wer sie bereitstellt und wie.
Sie können dies mit jedem Befehl tun.
Das Besondere an Geschäftsanforderungen ist, dass sie keinen Respekt vor gesundem Menschenverstand, Logik oder geordneten Strukturen haben. Die reale Welt ist chaotisch.
Nehmen wir in unserem Beispiel an, dass einige Länder einen einheitlichen Umsatzsteuersatz haben und andere einen variablen Satz, der entweder vom Standort oder der Produktkategorie abhängt.
Hier ist der Code. Wir werden den Konfigurationscode für dieses Beispiel herausreißen.
// fixed rate
seneca . add ( { cmd : 'salestax' } , function ( msg , done ) {
var rate = 0.23
var total = msg . net * ( 1 + rate )
done ( null , { total : total } )
} )
// local rates
seneca . add ( { cmd : 'salestax' , country : 'US' } , function ( msg , done ) {
var state = {
'NY' : 0.04 ,
'CA' : 0.0625
// ...
}
var rate = state [ msg . state ]
var total = msg . net * ( 1 + rate )
done ( null , { total : total } )
} )
// categories
seneca . add ( { cmd : 'salestax' , country : 'IE' } , function ( msg , done ) {
var category = {
'top' : 0.23 ,
'reduced' : 0.135
// ...
}
var rate = category [ msg . category ]
var total = msg . net * ( 1 + rate )
done ( null , { total : total } )
} )
seneca . act ( 'cmd:salestax,net:100,country:DE' , function ( err , result ) {
console . log ( 'DE: ' + result . total )
} )
seneca . act ( 'cmd:salestax,net:100,country:US,state:NY' , function ( err , result ) {
console . log ( 'US,NY: ' + result . total )
} )
seneca . act ( 'cmd:salestax,net:100,country:IE,category:reduced' , function ( err , result ) {
console . log ( 'IE: ' + result . total )
} )
In diesem Fall stellen Sie unterschiedliche Implementierungen für unterschiedliche Muster bereit. Dadurch können Sie die Komplexität an genau definierten Stellen isolieren. Es bedeutet auch, dass Sie sich sehr einfach mit Sonderfällen befassen können.
Die Senecajs-Organisation fördert die Teilnahme. Wenn Sie das Gefühl haben, dass Sie in irgendeiner Weise helfen können, sei es durch Fehlerberichte, Dokumentation, Beispiele, zusätzliche Tests oder neue Funktionen, können Sie gerne ein Problem erstellen oder, noch besser, eine Pull-Anfrage einreichen. Weitere Informationen zum Beitragen finden Sie in unserem Beitragsleitfaden.
Um Tests lokal auszuführen,
npm run test
Um einen Abdeckungsbericht zu erhalten,
npm run coverage; open docs/coverage.html
Copyright (c) 2010–2018 Richard Rodger und andere Mitwirkende; Lizenziert unter MIT .