مقدمة: لماذا TypeScript في الخدمات المصغرة؟
أصبحت بنية الخدمات المصغرة المعيار لبناء تطبيقات قابلة للتوسع ومتحملة للأخطاء. ومع ذلك، يمكن أن يؤثر اختيار لغة البرمجة بشكل كبير على سرعة التطوير وجودة الكود. TypeScript — وهي مجموعة شاملة ومكتوبة بشكل صارم من JavaScript — تقدم توازناً مثالياً بين المرونة والموثوقية. بفضل الكتابة الثابتة (Static Typing)، والواجهات (Interfaces)، ونظام الوحدات القوي، يتيح TypeScript اكتشاف الأخطاء في مرحلة التجميع (Compilation) بدلاً من وقت التشغيل (Runtime)، وهو أمر بالغ الأهمية للأنظمة الموزعة.
في هذه المقالة، سنقوم بتحليل المبادئ الأساسية لبناء الخدمات المصغرة باستخدام TypeScript، وسنستعرض الأطر الشائعة (NestJS، Fastify)، وإعداد التفاعل بين الخدمات عبر RabbitMQ، بالإضافة إلى الحاويات باستخدام Docker. سيتم تقديم جميع أمثلة الكود بلغة TypeScript حتى تتمكن من تطبيقها فوراً في مشاريعك.
1. اختيار الإطار: NestJS مقابل Fastify
لإنشاء خدمات مصغرة باستخدام TypeScript، هناك عدة أطر. الأكثر شيوعاً هما NestJS و Fastify. دعنا نستعرض خصائصهما.
NestJS — "Angular للواجهة الخلفية"
يقدم NestJS بنية معيارية (Modular Architecture)، مستوحاة من Angular. يأتي مع طبقة نقل جاهزة للخدمات المصغرة (TCP، Redis، RabbitMQ، Kafka). هذا هو الخيار المثالي للمشاريع الكبيرة حيث تكون الهيكلة ودعم فريق المطورين أمراً مهماً.
// مثال لخدمة مصغرة أساسية على NestJSimport { NestFactory } from '@nestjs/core';import { Transport, MicroserviceOptions } from '@nestjs/microservices';import { AppModule } from './app.module';
async function bootstrap() { const app = await NestFactory.createMicroservice<MicroserviceOptions>( AppModule, { transport: Transport.RMQ, options: { urls: ['amqp://localhost:5672'], queue: 'orders_queue', queueOptions: { durable: false }, }, }, ); await app.listen();}bootstrap();Fastify — الأداء والبساطة
Fastify هو إطار HTTP فائق السرعة لـ Node.js. لا يوفر دعماً مدمجاً للخدمات المصغرة، ولكنه يتكامل بسهولة مع RabbitMQ أو NATS من خلال حزم منفصلة. إنه مناسب للحالات التي يكون فيها الأداء أمراً بالغ الأهمية، وتكون البنية محددة بالفعل.
// مثال لخادم على Fastify + TypeScriptimport fastify from 'fastify';
const server = fastify({ logger: true });
server.get('/health', async (request, reply) => { return { status: 'OK', service: 'payment-service' };});
const start = async () => { try { await server.listen({ port: 3000 }); } catch (err) { server.log.error(err); process.exit(1); }};start();الخلاصة: للمبتدئين والمشاريع الجماعية، اختر NestJS. للأنظمة عالية التحميل ذات البنية المدروسة جيداً، اختر Fastify.
2. التفاعل بين الخدمات: RabbitMQ و Redis
في بنية الخدمات المصغرة، تتواصل الخدمات مع بعضها البعض عبر وسطاء الرسائل (Message Brokers) أو طلبات HTTP المباشرة. دعنا نستعرض طريقتين شائعتين.
RabbitMQ — قائمة انتظار رسائل موثوقة
يوفر RabbitMQ نقل الرسائل غير المتزامن (Asynchronous) مع ضمان التسليم. في TypeScript، للعمل مع RabbitMQ، غالباً ما يتم استخدام مكتبة amqplib أو الوحدات المدمجة في NestJS.
// نشر رسالة في RabbitMQ (TypeScript)import * as amqp from 'amqplib';
async function publishOrder(order: any) { const connection = await amqp.connect('amqp://localhost'); const channel = await connection.createChannel(); const queue = 'orders';
await channel.assertQueue(queue, { durable: true }); channel.sendToQueue(queue, Buffer.from(JSON.stringify(order)), { persistent: true, });
console.log(`Order sent: ${order.id}`); setTimeout(() => connection.close(), 500);}