Einleitung: Warum Mikroservices in JavaScript?
\nDie moderne Webentwicklung entfernt sich zunehmend von monolithischen Anwendungen und wendet sich der Mikroservice-Architektur zu. JavaScript, genauer gesagt seine serverseitige Umgebung Node.js, eignet sich aufgrund seiner Asynchronität, ereignisorientierten Modell und riesigen Ökosystem-Community ideal für die Erstellung von Mikroservices. In diesem Artikel werden wir uns ansehen, wie man Mikroservices in JavaScript entwirft, entwickelt und bereitstellt – von der Theorie bis zu praktischen Codebeispielen.
\n\n1. Grundlagen der Mikroservice-Architektur
\nDie Mikroservice-Architektur ist ein Ansatz, bei dem eine Anwendung in kleine, unabhängige Dienste aufgeteilt wird. Jeder Dienst ist für seine eigene Geschäftslogik verantwortlich, verfügt über einen eigenen Datenspeicher und kann separat bereitgestellt, skaliert und aktualisiert werden.
\nVorteile von Mikroservices mit Node.js
\n- \n
- Skalierbarkeit: Node.js verarbeitet dank nicht-blockierender Ein-/Ausgabe problemlos tausende gleichzeitige Verbindungen. \n
- Schnelles Prototyping: npm-Pakete und Frameworks (Express, Fastify, NestJS) ermöglichen die schnelle Erstellung von REST/GraphQL-APIs. \n
- Fehlerisolierung: Ein Ausfall in einem Dienst legt nicht die gesamte Anwendung lahm. \n
- Technologische Flexibilität: Verschiedene Dienste können unterschiedliche Node.js-Versionen oder sogar verschiedene Sprachen verwenden. \n
Schlüsselkomponenten
\n- \n
- API Gateway – ein zentraler Einstiegspunkt, der Anfragen an die entsprechenden Dienste weiterleitet. \n
- Message Broker (RabbitMQ, Redis, Kafka) – für den asynchronen Datenaustausch. \n
- Service Registry (Consul, etcd) – zur Dienstfindung. \n
- Containerisierung (Docker, Kubernetes) – zur Standardisierung der Umgebung. \n
2. Praxis: Zwei Mikroservices erstellen
\nBetrachten wir ein Beispiel für ein Bestellsystem. Wir werden zwei Mikroservices haben: user-service (Benutzerverwaltung) und order-service (Bestellverwaltung). Sie kommunizieren über eine REST-API und asynchron über RabbitMQ.
2.1. Basisdienst mit Express
\nBeginnen wir mit dem user-service. Installieren Sie die Abhängigkeiten:
npm init -y\nnpm install express body-parser\nErstellen Sie die Datei index.js:
const express = require('express');\nconst bodyParser = require('body-parser');\nconst app = express();\nconst PORT = process.env.PORT || 3001;\n\napp.use(bodyParser.json());\n\nconst users = [];\n\napp.post('/users', (req, res) => {\n const { name, email } = req.body;\n const user = { id: users.length + 1, name, email };\n users.push(user);\n res.status(201).json(user);\n});\n\napp.get('/users/:id', (req, res) => {\n const user = users.find(u => u.id === parseInt(req.params.id));\n if (!user) return res.status(404).json({ error: 'User not found' });\n res.json(user);\n});\n\napp.listen(PORT, () => {\n console.log(`User service running on port ${PORT}`);\n});\nErstellen Sie analog den order-service auf Port 3002. Er enthält ein Array von Bestellungen und zwei Endpunkte: POST /orders und GET /orders/:id.
2.2. API Gateway
\nErstellen wir ein einfaches Gateway auf Port 3000, das Anfragen basierend auf dem Pfad weiterleitet:
\nconst express = require('express');\nconst httpProxy = require('http-proxy-middleware');\nconst app = express();\n\napp.use('/users', httpProxy.createProxyMiddleware({ target: 'http://localhost:3001', changeOrigin: true }));\napp.use('/orders', httpProxy.createProxyMiddleware({ target: 'http://localhost:3002', changeOrigin: true }));\n\napp.listen(3000, () => console.log('API Gateway on port 3000'));\nJetzt gehen alle Anfragen an /users zum user-service und an /orders zum order-service.
2.3. Asynchrone Kommunikation mit RabbitMQ
\nAngenommen, bei der Erstellung einer B