ميكروسيرفيسات TypeScript: الهندسة والممارسة من الألف إلى الياء
\nفي تطوير الويب الحديث، تفسح الهندسة المتجانسة المجال أمام الميكروسيرفيسات المرنة والقابلة للتوسع. أصبحت TypeScript بفضل كتابتها الصارمة وأدواتها القوية اللغة المثالية لبناء مثل هذه الأنظمة. في هذه المقالة، سنشرح كيفية تصميم وتنفيذ ميكروسيرفيسات TypeScript باستخدام الإطار الشهير NestJS، ووسيط الرسائل RabbitMQ، والحاويات Docker.
1. أساسيات بنية الميكروسيرفيسات في TypeScript
\nتفترض بنية الميكروسيرفيسات تقسيم التطبيق إلى خدمات مستقلة ومترابطة بشكل ضعيف. كل خدمة مسؤولة عن منطق أعمالها الخاص (مثل إدارة المستخدمين، معالجة الطلبات، المدفوعات) ويمكن تطويرها ونشرها وتوسيع نطاقها بشكل منفصل.
\n\nلماذا TypeScript؟
\n- \n
- الكتابة: الأخطاء في مرحلة التجميع، وليس في وقت التشغيل. هذا مهم بشكل خاص عند تفاعل العديد من الخدمات عبر الشبكة. \n
- الواجهات والأنواع: تسمح بتحديد عقود API بدقة (مثل DTO للطلبات/الاستجابات). \n
- JavaScript الحديث: يتم تجميع TypeScript إلى JS نقي يعمل على Node.js. \n
لننظر إلى مثال بسيط لـ DTO مكتوب بدقة لخدمة المستخدمين:
\n\n// user.dto.ts\nexport interface CreateUserDto {\n readonly email: string;\n readonly password: string;\n readonly name: string;\n}\n\nexport interface UserResponse {\n id: string;\n email: string;\n name: string;\n createdAt: Date;\n}\n\nعند نقل البيانات بين الخدمات (عبر HTTP أو RabbitMQ)، تضمن TypeScript أن بنية الكائن تتطابق مع المتوقع. هذا يقلل بشكل كبير من عدد الأخطاء.
\n\n2. تنفيذ ميكروسيرفيس باستخدام NestJS
\nNestJS هو إطار تقدمي لـ Node.js يدعم بنية الميكروسيرفيسات بشكل افتراضي. يوفر موصلات لـ TCP و Redis و RabbitMQ و Kafka و gRPC.
\n\nلنقم بإنشاء ميكروسيرفيس أساسي لإدارة المستخدمين باستخدام موصل RabbitMQ.
\n\nالخطوة 1: تثبيت التبعيات
\nnpm install --save @nestjs/core @nestjs/common @nestjs/microservices\nnpm install --save amqplib amqp-connection-manager\n\nالخطوة 2: إنشاء الوحدة الرئيسية ووحدة التحكم
\n// user.controller.ts\nimport { Controller } from '@nestjs/common';\nimport { MessagePattern, Payload } from '@nestjs/microservices';\nimport { CreateUserDto, UserResponse } from './user.dto';\n\n@Controller()\nexport class UserController {\n @MessagePattern('user.create')\n async createUser(@Payload() data: CreateUserDto): Promise<UserResponse> {\n // هنا منطق إنشاء المستخدم في قاعدة البيانات\n console.log('إنشاء مستخدم:', data);\n return {\n id: 'uuid-123',\n email: data.email,\n name: data.name,\n createdAt: new Date(),\n };\n }\n}\n\nالخطوة 3: إعداد الملف الرئيسي للعمل في وضع الميكروسيرفيس
\n// main.ts\nimport { NestFactory } from '@nestjs/core';\nimport { MicroserviceOptions, Transport } from '@nestjs/microservices';\nimport { AppModule } from './app.module';\n\nasync function bootstrap() {\n const app = await NestFactory.createMicroservice<MicroserviceOptions>(\n AppModule,\n {\n transport: Transport.RMQ,\n options: {\n urls: ['amqp://localhost:5672'],\n queue: 'user_queue',\n queueOptions: {\n durable: false,\n },\n },\n },\n );\n await app.listen();\n console.log('تم تشغيل ميكروسيرفيس المستخدمين');\n}\nbootstrap();\n\nبهذه الطريقة، تتصل خدمتنا بـ RabbitMQ وتستمع إلى قائمة الانتظار user_queue. أي خدمة أخرى (مثل خدمة الطلبات)