مقدمة في بنية الخدمات المصغرة باستخدام JavaScript
بنية الخدمات المصغرة هي نهج لتطوير البرمجيات حيث يتم بناء التطبيق كمجموعة من الخدمات الصغيرة المستقلة القابلة للنشر بشكل منفصل. كل خدمة تنفذ وظيفة عمل واحدة وتتفاعل مع الخدمات الأخرى عبر بروتوكولات خفيفة (عادةً HTTP/REST أو قوائم انتظار الرسائل). JavaScript، وتحديداً بيئة تشغيل Node.js، مثالية لإنشاء الخدمات المصغرة بفضل نموذج الإدخال/الإخراج غير المتزامن، والنظام البيئي الضخم للحزم (npm)، وسرعة التطوير العالية.
في هذه المقالة، سنستعرض الجوانب الرئيسية لإنشاء الخدمات المصغرة باستخدام JavaScript: من تصميم البنية إلى النشر في الحاويات. ستتعلم كيفية تنظيم تبادل البيانات، وضمان تحمل الأخطاء، واختبار النظام الموزع.
1. تصميم بنية الخدمات المصغرة
الخطوة الأولى هي تفكيك التطبيق المتجانس إلى خدمات. يجب أن تمتلك كل خدمة مصغرة قاعدة بيانات خاصة بها (database per service) وأن تكون مستقلة تماماً. لنأخذ مثالاً لمتجر إلكتروني:
- Service Users — التسجيل، المصادقة، الملفات الشخصية.
- Service Products — كتالوج المنتجات، الأسعار، المخزون.
- Service Orders — إنشاء ومعالجة الطلبات.
- Service Payments — التكامل مع بوابات الدفع.
- Service Notifications — إرسال البريد الإلكتروني/الرسائل النصية.
للتفاعل بين الخدمات، نستخدم نهجين: متزامن (REST/gRPC) للطلبات التي تتطلب رداً فورياً، وغير متزامن (قوائم انتظار الرسائل) للأحداث التي لا تتطلب حظراً.
2. إنشاء خدمة مصغرة على Node.js باستخدام Express
لنبدأ بخدمة مصغرة بسيطة لإدارة المستخدمين. سنقوم بتثبيت Express ومكتبة العمل مع UUID:
npm init -y
npm install express uuid
لننشئ ملف users-service.js:
const express = require('express');
const { v4: uuidv4 } = require('uuid');
const app = express();
app.use(express.json());
const users = [];
// إنشاء مستخدم
app.post('/users', (req, res) => {
const { name, email } = req.body;
const user = { id: uuidv4(), name, email };
users.push(user);
res.status(201).json(user);
});
// الحصول على قائمة المستخدمين
app.get('/users', (req, res) => {
res.json(users);
});
// الحصول على مستخدم بواسطة المعرف
app.get('/users/:id', (req, res) => {
const user = users.find(u => u.id === req.params.id);
if (!user) return res.status(404).json({ error: 'User not found' });
res.json(user);
});
app.listen(3001, () => console.log('Users service running on port 3001'));
قم بتشغيل الخدمة: node users-service.js. الآن لديك خدمة مصغرة عاملة مع REST API. وبالمثل، يتم إنشاء خدمات للمنتجات والطلبات (على المنافذ 3002 و 3003 على التوالي).
3. التفاعل غير المتزامن عبر RabbitMQ
للأحداث مثل "تم إنشاء طلب" أو "تم تسجيل مستخدم"، نستخدم قوائم انتظار الرسائل. سنقوم بتثبيت عميل RabbitMQ:
npm install amqplib
لننشئ أداة لنشر الرسائل (event-bus.js):
const amqp = require('amqplib');
let channel;
async function connect() {
const connection = await amqp.connect('amqp://localhost');
channel = await connection.createChannel();
await channel.assertExchange('order_events', 'topic', { durable: true });
}
async function publishEvent(routingKey, data) {
if (!channel) await connect();
channel.publish('order_events', routingKey, Buffer.from(JSON.stringify(data)));
console.log(`Event published: ${routingKey}`);
}
module.exports = { publishEvent };
الآن في خدمة الطلبات (orders-service.js) عند إنشاء طلب، يتم نشر