مقدمة في بنية الخدمات المصغرة باستخدام Java
تطوير البرمجيات الحديث يتجه بشكل متزايد بعيدًا عن الحلول المتجانسة نحو بنية الخدمات المصغرة. Java، بفضل نضجها، ومجتمعها الضخم، وأطر العمل القوية (Spring Boot, Micronaut, Quarkus)، هي واحدة من أفضل اللغات لبناء الخدمات المصغرة. في هذه المقالة، سنقوم بتحليل بنية الخدمات المصغرة باستخدام Java من الأسس النظرية إلى التنفيذ العملي مع أمثلة على الكود.
الخدمات المصغرة هي نهج يتم فيه بناء التطبيق كمجموعة من الخدمات الصغيرة والمستقلة القابلة للنشر. كل خدمة تنفذ وظيفة عمل واحدة، ولها مخزن بيانات خاص بها، وتتفاعل مع الخدمات الأخرى عبر بروتوكولات خفيفة (عادةً HTTP/REST أو الرسائل).
المبادئ الأساسية لبنية الخدمات المصغرة
1. المسؤولية الواحدة (Single Responsibility)
كل خدمة مصغرة مسؤولة عن فرصة عمل واحدة بالضبط. على سبيل المثال، خدمة الطلبات لا ينبغي أن تعرف شيئًا عن التسعير - فهناك خدمة منفصلة لذلك.
2. النشر المستقل
يجب أن تكون قادرًا على تحديث خدمة واحدة دون إيقاف التطبيق بأكمله. يتم تحقيق ذلك من خلال إصدار API والحاويات.
3. إدارة البيانات اللامركزية
كل خدمة تمتلك قاعدة البيانات الخاصة بها. هذا يمنع الارتباطات الصلبة بين الوحدات ويسمح باختيار نظام إدارة قواعد البيانات (DBMS) الأنسب لكل مهمة (على سبيل المثال، PostgreSQL للطلبات و MongoDB لدليل المنتجات).
4. تحمل الأعطال
يجب ألا يؤدي فشل خدمة واحدة إلى انهيار النظام بأكمله. استخدم أنماط Circuit Breaker و Retry و Bulkhead.
التنفيذ العملي: مجموعة تقنيات Java
لإنشاء خدمات مصغرة باستخدام Java، سنستخدم مجموعة تقنيات شائعة:
- Spring Boot 3.x — الأساس لإنشاء خدمات REST بسرعة
- Spring Cloud — لاكتشاف الخدمات (Eureka)، والتكوين (Config Server)، وبوابات API (Gateway)
- Docker — لحاويات كل خدمة
- RabbitMQ / Kafka — للتواصل غير المتزامن
- PostgreSQL / MongoDB — قواعد البيانات حسب الاختيار
مثال: خدمة مصغرة بسيطة باستخدام Spring Boot
لنقم بإنشاء خدمة مصغرة أساسية لإدارة المستخدمين:
// UserServiceApplication.javapackage com.example.userservice;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication@EnableDiscoveryClientpublic class UserServiceApplication { public static void main(String[] args) { SpringApplication.run(UserServiceApplication.class, args); }}
// UserController.java@RestController@RequestMapping("/api/users")public class UserController {
@Autowired private UserService userService;
@GetMapping("/{id}") public ResponseEntity<User> getUser(@PathVariable Long id) { return userService.findById(id) .map(ResponseEntity::ok) .orElse(ResponseEntity.notFound().build()); }
@PostMapping public ResponseEntity<User> createUser(@RequestBody User user) { User saved = userService.save(user); return ResponseEntity.status(HttpStatus.CREATED).body(saved); }}
// UserService.java@Servicepublic class UserService { @Autowired private UserRepository repository;
public Optional<User> findById(Long id) { return repository.findById(id); }
public User save(User user) { return repository.save(user); }}التواصل بين الخدمات: REST والرسائل غير المتزامنة
تتواصل الخدمات المصغرة بطريقتين رئيسيتين