مقدمة: لماذا TypeScript مثالي للخدمات المصغرة
أصبحت بنية الخدمات المصغرة المعيار لبناء تطبيقات معقدة وقابلة للتوسع ومتسامحة مع الأخطاء. TypeScript، بفضل كتابته الصارمة، ونظامه البيئي الغني، ودعمه لعدم التزامن، هي واحدة من أفضل اللغات لتنفيذ الخدمات المصغرة. فهو يسمح بكتابة كود يسهل إعادة هيكلته واختباره وتوثيقه، وهو أمر بالغ الأهمية عند تقسيم النظام إلى عشرات الخدمات المستقلة.
في هذه المقالة، سنقوم بتحليل المبادئ المعمارية، وبناء خدمة مصغرة بسيطة باستخدام NestJS، وإعداد التفاعل بين الخدمات عبر RabbitMQ، وتغليف كل شيء في Docker Compose. ستحصل على أساس عملي جاهز للبدء.
بنية الخدمات المصغرة في TypeScript
الهندسة الصحيحة هي مفتاح النجاح. بالنسبة للخدمات المصغرة في TypeScript، يتم تمييز ثلاث طبقات رئيسية:
- طبقة النقل — مسؤولة عن استقبال وإرسال الطلبات (HTTP, gRPC, قوائم الرسائل).
- منطق الأعمال — دوال وخدمات نقية، لا تعتمد على الإطار البرمجي.
- طبقة البيانات — المستودعات و ORM (TypeORM, Prisma).
يجب أن تكون كل خدمة مصغرة مستقلة: لها قاعدة بياناتها الخاصة، و CI/CD، ومنطق النشر الخاص بها. عادةً ما يتم الاتصال بين الخدمات عبر قوائم انتظار غير متزامنة (RabbitMQ, Kafka) أو استدعاءات متزامنة (gRPC).
تطبيق عملي: إنشاء خدمة مصغرة على NestJS
الخطوة 1: تهيئة المشروع
قم بتثبيت واجهة سطر الأوامر لـ NestJS وأنشئ مشروعًا جديدًا:
npm i -g @nestjs/clinest new user-service --package-manager npmcd user-serviceالخطوة 2: إضافة دعم الخدمات المصغرة
يحتوي NestJS على دعم مدمج لناقلات الخدمات المصغرة. سنقوم بتثبيت RabbitMQ:
npm install @nestjs/microservices amqplib amqp-connection-managerلنقم بإنشاء main.ts، الذي يقوم بتشغيل الخدمة كخدمة مصغرة:
import { NestFactory } from '@nestjs/core';import { MicroserviceOptions, Transport } 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: 'user_queue', queueOptions: { durable: false }, }, }, ); await app.listen();}bootstrap();الخطوة 3: تنفيذ المتحكم
لنقم بإنشاء متحكم بسيط يعالج الرسائل من قائمة الانتظار:
import { Controller } from '@nestjs/common';import { MessagePattern, Payload } from '@nestjs/microservices';
@Controller()export class UserController { @MessagePattern('user.create') createUser(@Payload() data: { name: string; email: string }): string { // هنا يجب أن يكون منطق الأعمال لإنشاء المستخدم return `تم إنشاء المستخدم ${data.name}`; }}الآن يمكن لأي خدمة إرسال رسالة إلى قائمة الانتظار user_queue بنمط user.create والحصول على رد.
التفاعل بين الخدمات: متزامن وغير متزامن
المتزامن: gRPC
للأنظمة عالية التحميل التي تتطلب كتابة صارمة وزمن وصول منخفض، استخدم gRPC. قم بتثبيت الحزمة:
npm install @nestjs/microservices @grpc/grpc-js @grpc/proto-loaderقم بتعريف ملف .proto:
syntax = "proto3";package user;service UserService { rpc GetUser (UserId) returns (User);}message UserId { int32 id = 1; }message User { string name = 1; string email = 2; }في المتحكم، استخدم المُزَيِّن @GrpcMethod لمعالجة الطلب.