Feathers: Microservices: Empfohlene Möglichkeit, eine App durch Aufteilen von Diensten umzugestalten?

Erstellt am 19. Mai 2016  ·  27Kommentare  ·  Quelle: feathersjs/feathers

Ich versuche, einen praktischen / empfohlenen Weg zu finden, um Dienste zu extrahieren und sie nach dem Microservices-Stil in ihre eigenen Instanzen aufzuteilen. In dieser Angelegenheit gibt es eine interessante Aussage auf der Landingpage von Federn:

Serviceorientiert: Federn Bietet Ihnen die Struktur, um vom ersten Tag an serviceorientierte Apps zu erstellen. Wenn Sie Ihre App schließlich in Microservices aufteilen müssen, ist dies ein einfacher Übergang, und Federn können Ihre Apps problemlos skalieren.

Aber ich konnte immer noch keine Informationen darüber finden, wie ich mit diesem Anwendungsfall in Federn umgehen soll.

In der Praxis konzentriere ich mich zunächst auf zwei grundlegende Themen:

  • Kommunikation: Ich denke, dies sollte eine Möglichkeit sein, einen Dienst zu extrahieren und der ursprünglichen Anwendung zu ermöglichen, ohne großen Umschreibeaufwand weiter zu kommunizieren, indem beispielsweise die Aufrufe des Dienstes durch HTTP-Anforderungen ersetzt werden.
  • Authentifizierung: Erläuterungen dazu, wie Federn die Authentifizierung für die Kommunikation zwischen Diensten handhaben, nachdem der Dienst aufgeteilt wurde.

Danke im Voraus!

Documentation Question Scaling

Hilfreichster Kommentar

Sie haben Recht, es gibt noch nicht zu viel Dokumentation und wir haben vor einiger Zeit

Nehmen wir an, wir haben zunächst einen Server mit zwei Diensten, vielleicht so etwas

app.use('/users', memory())
  .use('/todos', memory());

Der Benutzerdienst erhält mehr Datenverkehr, als der eine Server verarbeiten kann. Daher möchten wir ihn auf ein anderes System verschieben, indem wir eine andere App dafür erstellen:

// server1
app.use('/users', memory());
// server2
app.use('/todos', memory());

Damit der /todos -Dienst jetzt mit dem Remote-Dienst kommunizieren kann, können wir Feathers als Client verwenden , um eine Verbindung zu ihm herzustellen (Websockets sind schnell und bidirektional. Warum also nicht für die Server-zu-Server-Kommunikation verwenden?):

// server2
const client = require('feathers/client')
const socketClient = require('feathers-socketio/client');
const io = require('socket.io-client');

const socket = io('http://other-server.com');
const otherApp = client().configure(socketClient(socket));

app.use('/todos', memory())
 .use('/users', otherApp.service('users'));

Dies würde den Benutzerdienst grundsätzlich transparent über eine Websocket-Verbindung an den Remote-Dienst weiterleiten. Alles, was den ursprünglichen /users -Endpunkt verwendet, muss nichts ändern.

Für die Authentifizierung gibt es viele verschiedene Optionen. Im obigen Szenario wäre es für server1 am einfachsten, nur die IP-Adresse der anderen Server auf die Whitelist zu setzen, da server2 immer noch der einzige Kommunikationspunkt für die Clients ist. Schließlich könnte server2 einfach ein Gateway werden, das die Benutzerauthentifizierung verwaltet und dann nur Dienstanrufe an andere Server weiterleitet (die sich nicht um die Authentifizierung kümmern müssen, außer die Ursprungs-IP-Adresse zu überprüfen).

Alle 27 Kommentare

Sie haben Recht, es gibt noch nicht zu viel Dokumentation und wir haben vor einiger Zeit

Nehmen wir an, wir haben zunächst einen Server mit zwei Diensten, vielleicht so etwas

app.use('/users', memory())
  .use('/todos', memory());

Der Benutzerdienst erhält mehr Datenverkehr, als der eine Server verarbeiten kann. Daher möchten wir ihn auf ein anderes System verschieben, indem wir eine andere App dafür erstellen:

// server1
app.use('/users', memory());
// server2
app.use('/todos', memory());

Damit der /todos -Dienst jetzt mit dem Remote-Dienst kommunizieren kann, können wir Feathers als Client verwenden , um eine Verbindung zu ihm herzustellen (Websockets sind schnell und bidirektional. Warum also nicht für die Server-zu-Server-Kommunikation verwenden?):

// server2
const client = require('feathers/client')
const socketClient = require('feathers-socketio/client');
const io = require('socket.io-client');

const socket = io('http://other-server.com');
const otherApp = client().configure(socketClient(socket));

app.use('/todos', memory())
 .use('/users', otherApp.service('users'));

Dies würde den Benutzerdienst grundsätzlich transparent über eine Websocket-Verbindung an den Remote-Dienst weiterleiten. Alles, was den ursprünglichen /users -Endpunkt verwendet, muss nichts ändern.

Für die Authentifizierung gibt es viele verschiedene Optionen. Im obigen Szenario wäre es für server1 am einfachsten, nur die IP-Adresse der anderen Server auf die Whitelist zu setzen, da server2 immer noch der einzige Kommunikationspunkt für die Clients ist. Schließlich könnte server2 einfach ein Gateway werden, das die Benutzerauthentifizierung verwaltet und dann nur Dienstanrufe an andere Server weiterleitet (die sich nicht um die Authentifizierung kümmern müssen, außer die Ursprungs-IP-Adresse zu überprüfen).

Danke für die Antwort! Planen Sie, dieses Thema in offiziellen Dokumenten (möglicherweise einem Unterabschnitt der Leitfäden) zu behandeln? Lassen Sie mich wissen, ob ich dazu beitragen kann.

Bestimmt. Und wir könnten definitiv Hilfe gebrauchen. Vielleicht können wir zuerst zusammenfassen, was wir in einem Handbuch sehen möchten, und dann einige Demo-Anwendungen erstellen.

💯 @daffl ist

@daffl Der von Ihnen erwähnte Ansatz,

Ja, aber warum konnten die anderen interessierten Dienste nicht auch Websockets verwenden? Wir denken darüber nach, andere Anbieter hinzuzufügen (z. B. für andere Messaging-Dienste), aber im Moment scheinen Websockets schnell genug zu sein und es wird nirgendwo geschrieben, dass sie nur im Browser verwendet werden können.

@daffl @ekryski Wenn Federnanwendungen verteilt werden, müssen wir auch Probleme wie mindestens einmalige Zustellung (Acks), Idempotenz, Transaktionen, Gegendruck (Warteschlangen) usw. ansprechen. Haben Sie so etwas wie "Federservice" in Betracht gezogen? Arbeiter? ".. dh. externe Prozesse, die Ereignisse aus einer dauerhaften amqp-Warteschlange (dh rabbitmq) oder Redis (zB kue) verbrauchen?

@daffl Ich glaube, ich habe es vor deiner Antwort nicht gut verstanden. Solange die interessierten Dienste Web-Sockets verwenden, um den Producer-Service zu abonnieren, reicht es aus, die reguläre Ereignis-API zu verwenden, um neue Ereignisse auf dem Produzenten zu veröffentlichen, um dies in Federn zu implementieren, oder?

Ich stimme @justingreenberg zu . Ein weiteres Problem, das

Irgendwelche Fortschritte in diesem Bereich? Ich würde wirklich gerne eine Dokumentation / ein funktionierendes Beispiel sehen. Insbesondere in Bezug auf den Umgang mit der Authentifizierung.

@imns wir arbeiten daran. Ich habe angefangen, an einem Beispiel zu arbeiten und eine App aufzuteilen, und wir haben festgestellt, dass die Einrichtung der Authentifizierung einige Einschränkungen aufweist. Daher überarbeiten wir derzeit die Authentifizierung, um dies besser zu unterstützen. Sollte ungefähr eine Woche dauern, bis das landet.

Oh Mann, ich könnte das jetzt so schlecht gebrauchen: D.

Überarbeiten Sie aus Neugier die Authentifizierung, um auch mit mehreren Frontends zu arbeiten? Ich denke, dass viele größere Apps heutzutage einen Microservice im Backend verwenden, aber auch ihre Front-End-Apps aufteilen.

Wenn Sie ein paar zusätzliche Dollars haben, kann dieses Buch als empfohlene Lektüre angesehen werden: https://www.amazon.com/Building-Microservices-Sam-Newman/dp/1491950358/ref=sr_1_1 ? Ie = UTF8 & qid = 1469071253 & sr = 8-1 & keywords = Microservices

Leute, gibt es Updates dazu? Vielen Dank.

@juanpujol Die neuesten Informationen finden Sie immer in diesem Ticket. Vielen Dank für die Überprüfung.

(Marcfawzi hier)

Ich habe nicht den gesamten Thread gelesen, aber ich gehe davon aus, dass wir eine Datenbank pro Dienst verwenden können (in der Micreoservices-Architektur ist diese Trennung für die Aufrechterhaltung der Abstraktion von entscheidender Bedeutung. Andernfalls, wenn alle Dienste dieselbe Datenbank gemeinsam nutzen, wird verhindert, dass Benutzer verwendet werden von der Definition von Beziehungen zwischen Servicemodellen (eine Verletzung der Microservices-Abstraktion) anstelle der Erstellung von Services mithilfe der einheitlichen Service-API?

Nichts verhindert das wirklich, ich würde sagen, es liegt an Ihnen, das nicht zu tun. Es wird nur dann wirklich ein Problem sein, wenn Sie Ihre Modelle und Beziehungen auf ORM-Ebene definieren. Ich glaube nicht, dass das Herstellen von Beziehungen auf Serviceebene durch Aufrufen anderer Services die Abstraktion des Microservices verletzt.

Ja genau das was ich meinte. Ich neige dazu zu denken, dass die Trennung von Diensten, bei denen jeder Dienst seine eigene Datenbank hat, ein sicherer Weg ist, die Zusammensetzung über die Dienstschnittstelle und nicht auf ORM-Ebene zu erzwingen.

Aber Feathers ist allgemeiner als ein Microservices-Framework, also ist hier alles gut. Danke David! Das sieht immer besser aus, je mehr ich mich damit beschäftige! Rundum tolle Arbeit!

Ich dachte nur, ich würde dies hier erwähnen, da es einige der Probleme löst, die bei der Verwendung von Federn in einer Mikrodienstumgebung auftreten. Es ist nur die erste Implementierung, aber wenn Sie etwas beitragen können, besuchen Sie bitte https://github.com/zapur1/feathers-rabbitmq/issues/1

@ zapur1 das sieht vielversprechend aus ... Ich habe einen Kommentar gepostet, um die Diskussion zu

Sie können auch https://github.com/feathersjs/feathers-sync mit rabbitMQ, Redis oder MongoDB als Nachrichtenbroker zwischen den Diensten verwenden, um sie alle synchron zu halten.

@ekryski feathers-sync löst ein etwas anderes Problem. Was ist, wenn Sie möchten, dass ein Ereignis nur einmal im Bereich eines benannten Dienstes empfangen wird (kein Feathers-Dienst, sondern ein Dienst im Microservices-Stil)? Wenn mehrere Instanzen eines einzelnen Dienstes Ereignisse von einer einzelnen API-App empfangen haben, erhält jeder das Ereignis, das wahrscheinlich die Aktionen dupliziert, die ausgeführt werden, wenn dieses Ereignis über mehrere Instanzen mit genau demselben Code empfangen wird.

@ekryski Ich habe mir gerade das Repo noch einmal angesehen und zapur1 / feders-rabbitmq löst das genaue Problem, das Sie in "Caveats" erwähnt haben.

Wenn ich einen Dienst 1 über socketClient mit Dienst 2 verbinde, wenn mein Dienst 2 mehrere Instanzen hat, wie kann ich dann den Lastausgleich implementieren :(

Wenn ich eine separate serverseitige App erstelle, die über socketClient eine Verbindung herstellt, ist dies der beste Weg, um sich zu authentifizieren, damit alle Dienste verfügbar sind, unabhängig von den eingerichteten Einschränkungen.

Ich addiere meine 2 Cent dazu mit https://github.com/kalisio/feathers-distributed . Es zielt darauf ab, N Feder-Apps bereitzustellen, in denen verschiedene Dienste miteinander kommunizieren, sodass Sie jeden einzeln entwickeln können. Es unterscheidet sich von https://github.com/feathersjs/feathers-sync, das meines Wissens darauf abzielt, N Feathers-Apps bereitzustellen, die dieselben Dienste enthalten. All dies wirft eine Reihe von Fragen auf wie:

  • Authentifizierungsverwaltung
  • API-Gateway und Lastausgleich
  • Remote Hooks Aufruf
  • ...

@daffl In dem Beispiel, das Sie für Server 1 und Server 2 gegeben haben, wie würden Sie den Dienst /users in Server 2 sichern? Wenn wir diesen Dienst in Server 2 definiert hätten, könnten wir Hooks in der spezifischen Service-Hook-Datei verwenden. Da wir jedoch app.use('/users', otherApp.service('users')); , wie würden wir sicherstellen, dass Aufrufe dieses Dienstes von Server 2 nur ausgeführt werden ob sich der Benutzer zuerst authentifiziert hat?

BEARBEITEN:
Nvm, ich glaube ich habe eine Idee: Wir könnten so etwas wie const usersService = app.service('users') und dann usersService.hooks(hooks) wo Hooks die Auth-Hooks haben, die erforderlich sind, um den Endpunkt zu sichern, oder?

Ich habe mehr darüber geschrieben, wie verteilte Authentifizierung unter https://stackoverflow.com/questions/41076627/evaluating-featherjs-authentication-needs/41095638#41095638 durchgeführt werden kann :

Es gibt verschiedene Möglichkeiten, Dienste mit jeweils eigenen Vor- und Nachteilen aufzuteilen. Eine allgemein wichtige Sache für Feathers ist, dass es keine Sitzungen gibt, sondern nur JSON-Web-Token. JWTs sind zustandslos und können von jedem Server gelesen werden, der dasselbe Geheimnis teilt, sodass kein zentraler Sitzungsspeicher vorhanden sein muss. Die zwei Hauptoptionen, die mir einfallen, sind:

  1. Verfügen Sie über eine Hauptanwendung, die die Autorisierung und Verwaltung aller verbundenen Clients übernimmt, aber anstatt über Dienste, die mit der Datenbank kommunizieren, eine Verbindung zu separaten einfachen einzelnen API-Servern im internen Netzwerk herstellen. Dies ist die einfachere Einrichtung und der Vorteil ist, dass die internen API-Server sehr einfach sein können und überhaupt keine Authentifizierung benötigen (da die Hauptanwendung alles tun darf und Abfragen gemäß den Einschränkungen der authentifizierten Benutzer durchführt). Der Nachteil ist, dass die Hauptanwendung immer noch der Engpass ist (jedoch mit einer verringerten Last, da sie im Wesentlichen als Proxy für interne APIs fungiert).

my50m

  1. Jeder Client stellt mithilfe eines JWT eine Verbindung zu jedem API-Server her, den er benötigt. Das JWT wird von einer separaten Authentifizierungs- (oder Benutzer-) API erstellt. Dies ist die skalierbarere Lösung, da der einzige Engpass darin besteht, die aktuellsten Benutzerinformationen von einem allgemeinen Benutzerdienst abzurufen (was möglicherweise nicht immer erforderlich ist). Der Nachteil ist, dass die Verwaltung auf der Clientseite komplexer ist und die Authentifizierung (zumindest für JWT) auf jedem Server konfiguriert werden muss. Aufgrund der Staatenlosigkeit von JWT müssen jedoch keine gemeinsamen Sitzungen stattfinden.

lw1bg

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

codeus-de picture codeus-de  ·  4Kommentare

davigmacode picture davigmacode  ·  3Kommentare

rrubio picture rrubio  ·  4Kommentare

corymsmith picture corymsmith  ·  4Kommentare

Vincz picture Vincz  ·  4Kommentare