خدمات مصغرة بلغة C#: من النظرية إلى التطبيق على .NET
أصبحت بنية الخدمات المصغرة (Microservices) المعيار لبناء تطبيقات قابلة للتوسع وتحمل الأخطاء. توفر منصة .NET (C#) جميع الأدوات اللازمة لإنشاء مثل هذه الأنظمة: من الدعم المدمج للحاويات (Containerization) إلى أطر العمل القوية للتواصل بين الخدمات. في هذه المقالة، سنشرح المبادئ الأساسية لبناء الخدمات المصغرة بلغة C# ونستعرض أمثلة عملية على الكود.
1. أساسيات بنية الخدمات المصغرة على .NET
الخدمات المصغرة هي نهج يتم فيه تقسيم التطبيق إلى خدمات مستقلة ومرتبطة بشكل ضعيف. كل خدمة مسؤولة عن وظيفة أعمالها الخاصة ويمكن تطويرها ونشرها وتوسيع نطاقها بشكل مستقل عن الخدمات الأخرى.
المبادئ الأساسية لمطور .NET:
- المسؤولية الواحدة (Single Responsibility) — كل خدمة مصغرة تحل مشكلة واحدة.
- استقلالية البيانات — كل خدمة لها قاعدة بيانات خاصة بها (Database per Service).
- الارتباط الضعيف (Loose Coupling) — تتواصل الخدمات عبر API، وليس عبر ذاكرة مشتركة.
- الاستقلالية — يمكن تعديل الخدمة وإعادة نشرها دون إيقاف النظام بأكمله.
لإنشاء مشروع خدمة مصغرة جديد بلغة C#، استخدم الأمر:
dotnet new webapi -n UserServicedotnet new webapi -n OrderServicedotnet new webapi -n NotificationServiceيحصل كل مشروع على ملف Program.cs الخاص به، والإعدادات والتبعيات.
2. التواصل بين الخدمات: REST و gRPC
في .NET، هناك نهجان رئيسيان للتواصل بين الخدمات المصغرة: المتزامن (REST/gRPC) وغير المتزامن (عبر وسطاء الرسائل). سنناقش كليهما.
REST API باستخدام HttpClient
أبسط طريقة هي استخدام HttpClientFactory لإنشاء عميل مخصص.
// في ملف Program.cs لخدمة OrderServicebuilder.Services.AddHttpClient<IUserServiceClient, UserServiceClient>(client =>{ client.BaseAddress = new Uri("http://userservice:5000");});
// UserServiceClient.cspublic class UserServiceClient : IUserServiceClient{ private readonly HttpClient _httpClient;
public UserServiceClient(HttpClient httpClient) { _httpClient = httpClient; }
public async Task<UserDto> GetUserAsync(int userId) { var response = await _httpClient.GetAsync($"/api/users/{userId}"); response.EnsureSuccessStatusCode(); return await response.Content.ReadFromJsonAsync<UserDto>(); }}توصية: استخدم Polly (مكتبة لـ .NET) لتنفيذ سياسات إعادة المحاولة و Circuit Breaker.
gRPC للسيناريوهات عالية الأداء
يعمل gRPC عبر HTTP/2 ويستخدم Protocol Buffers للتسلسل. هذا أسرع بكثير من JSON.
// تعريف الخدمة في ملف user.protoservice UserGrpcService { rpc GetUser (GetUserRequest) returns (UserResponse);}
// كود الخادم بلغة C#public class UserGrpcServiceImpl : UserGrpcService.UserGrpcServiceBase{ public override Task<UserResponse> GetUser(GetUserRequest request, ServerCallContext context) { var user = _dbContext.Users.Find(request.UserId); return Task.FromResult(new UserResponse { Id = user.Id, Name = user.Name, Email = user.Email }); }}3. إدارة البيانات والمعاملات
في الخدمات المصغرة، كل قاعدة بيانات تنتمي إلى خدمة واحدة فقط. هذا يمنع استعلامات SQL المباشرة بين الخدمات. للعمل مع البيانات في .NET، المعيار هو Entity Framework Core.
مثال على تكوين DbContext لخدمة مصغرة
public cla