ميكروسيرفيسات جافا: الهندسة والممارسة من الألف إلى الياء
\n\nأصبحت هندسة الميكروسيرفيسات (MSA) المعيار الفعلي لبناء التطبيقات الحديثة القابلة للتوسع. على عكس التطبيق المتجانس (Monolith) حيث تكون كل الشفرة عملية واحدة كبيرة، تقوم الميكروسيرفيسات بتقسيم النظام إلى خدمات صغيرة ومستقلة قابلة للنشر. في هذه المقالة، سنشرح كيفية تصميم وتنفيذ ميكروسيرفيسات جافا باستخدام التقنيات الشائعة: Spring Boot، Docker، Kafka و Spring Cloud. ستحصل على وصفات جاهزة وأمثلة على الكود.
\n\n1. أساسيات هندسة الميكروسيرفيسات في جافا
\n\nقبل كتابة الكود، من المهم فهم المبادئ الأساسية لـ MSA:
\n- \n
- المسؤولية الواحدة (Single Responsibility) — كل خدمة مسؤولة عن وظيفة عمل واحدة (مثل: خدمة الطلبات، خدمة المستخدمين). \n
- النشر المستقل — يمكنك تحديث خدمة واحدة دون إعادة تشغيل النظام بأكمله. \n
- إدارة البيانات اللامركزية — كل خدمة لها قاعدة بيانات خاصة بها (Database per Service). \n
- الترابط الضعيف — تتواصل الخدمات عبر بروتوكولات خفيفة الوزن (REST، gRPC، قوائم الرسائل). \n
بالنسبة لجافا، الإطار الرئيسي هو Spring Boot بالاشتراك مع Spring Cloud (لاكتشاف الخدمات، التكوين، بوابات API). دعنا نلقي نظرة على مثال بسيط لميكروسيرفيس.
\n\nمثال: خدمة REST بسيطة باستخدام Spring Boot
\n// pom.xml (مقطع من التبعيات)\n<dependency>\n <groupId>org.springframework.boot</groupId>\n <artifactId>spring-boot-starter-web</artifactId>\n</dependency>\n\n// UserServiceApplication.java\n@SpringBootApplication\npublic class UserServiceApplication {\n public static void main(String[] args) {\n SpringApplication.run(UserServiceApplication.class, args);\n }\n}\n\n// UserController.java\n@RestController\n@RequestMapping("/api/users")\npublic class UserController {\n\n @GetMapping("/{id}")\n public ResponseEntity<String> getUser(@PathVariable Long id) {\n // في مشروع حقيقي، هنا يتم استدعاء المستودع\n return ResponseEntity.ok("User with id: " + id);\n }\n}\n\nتستمع هذه الميكروسيرفيس على المنفذ 8080 وتستجيب لطلبات GET. لتشغيل خدمة ثانية (مثل: خدمة الطلبات)، ما عليك سوى إنشاء مشروع Spring Boot آخر بمنفذ مختلف (server.port=8081).
\n\n2. الممارسة: Docker، Kafka والتفاعل بين الخدمات
\n\nفي النظام الحقيقي، لا يمكن للميكروسيرفيسات التواصل مباشرة عبر HTTP بدون تنسيق. يتم استخدام طريقتين: متزامنة (REST/Feign) وغير متزامنة (وسيط الرسائل).
\n\n2.1. الحاويات باستخدام Docker
\nيتم تغليف كل ميكروسيرفيس في صورة Docker. مثال على Dockerfile لخدمة جافا:
\nFROM openjdk:17-jdk-slim\nCOPY target/user-service-0.0.1-SNAPSHOT.jar app.jar\nEXPOSE 8080\nENTRYPOINT ["java", "-jar", "/app.jar"]\nثم استخدم docker-compose.yml لتشغيل جميع الخدمات مرة واحدة:
version: '3.8'\nservices:\n user-service:\n build: ./user-service\n ports:\n - "8080:8080"\n order-service:\n build: ./order-service\n ports:\n - "8081:8081"\n postgres:\n image: postgres:15\n environment:\n POSTGRES_DB: mydb\n POSTGRES_USER: user\n POSTGRES_PASSWORD: pass\n\n2.2. التفاعل غير المتزامن عبر Apache Kafka
\nعندما تحتاج الخدمة إلى إخطار خدمات أخرى بحدث (مثل: "تم إنشاء الطلب")، فمن الأفضل استخدام Kafka. هذا يفصل الخدمات ويزيد من تحمل الأخطاء.
\n\nمثال على المنتج (Order Service يرسل الحدث):
\n// KafkaProducerConfig.java\n@Configuration\npublic class KafkaProducerConfig {\n @Bean\n public ProducerFactory<String, String> producerFactory() {\n Map<String, Object> props = new Ha