هل خرجت خدمات .NET المصغرة عن السيطرة؟ تعرف على Service Mesh
\n\nتخيل: لديك خمس، عشر، أو ربما خمسون خدمة مصغرة بلغة C#. تتواصل مع بعضها البعض عبر HTTP أو gRPC أو RabbitMQ. كل شيء يعمل... حتى لا يعمل. المهلات، إعادة المحاولة، قواطع الدائرة، موازنة التحميل، المصادقة بين الخدمات — كل مطور يكتب نفس الشيء من الصفر. هل هذا مألوف؟
\n\nهذا ما يسمى "مشكلة حديقة الخدمات المصغرة" — عندما تغرق منطق الأعمال في كود البنية التحتية. وهنا يظهر على المسرح Service Mesh — نمط معماري ينقل كل أعمال الشبكات خارج كود C# الخاص بك. في هذه المقالة، سنشرح كيفية ترويض Service Mesh في عالم .NET، وسنكتب كودًا حقيقيًا ونفهم ما إذا كان الأمر يستحق ذلك.
\n\nما هو Service Mesh بكلمات بسيطة (لمطور C#)
\n\nService Mesh هو طبقة بنية تحتية مخصصة لإدارة الاتصال بين الخدمات. تخيل أن كل خدمة C# مصغرة تحصل على "مساعد غير مرئي" — وكيل جانبي (sidecar-proxy) (عادةً Envoy أو Linkerd-proxy). هذا الوكيل يعترض كل حركة المرور الواردة والصادرة للخدمة ويقوم بكل العمل الشاق نيابة عنك:
\n\n- \n
- اكتشاف الخدمات — لا مزيد من عناوين URL المضمنة بشكل ثابت. \n
- موازنة التحميل — توزيع ذكي للطلبات. \n
- إعادة المحاولة والمهلات — محاولات تلقائية عند الفشل. \n
- قاطع الدائرة (Circuit Breaker) — حماية من الأعطال المتتالية. \n
- تشفير mTLS — أمان "خارج الصندوق". \n
- المراقبة (Observability) — المقاييس، التتبع، السجلات. \n
الميزة الرئيسية لـ C#: يبقى كودك نظيفًا. أنت تكتب فقط منطق الأعمال، بينما يتولى Service Mesh كل السحر الشبكي. أشهر التطبيقات: Istio (ثقيل لكنه قوي) وLinkerd (خفيف، سريع، مكتوب بلغة Rust).
\n\nكتابة خدمة C# مصغرة جاهزة لـ Service Mesh
\n\nلفهم السحر، دعنا ننشئ خدمة .NET مصغرة بسيطة بلغة C# ونهيئها للعمل مع Service Mesh. سنستخدم gRPC — البروتوكول المثالي للاتصال الداخلي للخدمات المصغرة.
\n\nالخطوة 1: إنشاء خدمة gRPC بلغة C#
\n\nافتح الطرفية ونفذ:
\n\ndotnet new grpc -n OrderService\ncd OrderService\n\nأضف ملف proto بسيط Protos/orders.proto:
syntax = "proto3";\n\nservice OrderGrpc {\n rpc GetOrder (OrderRequest) returns (OrderResponse);\n}\n\nmessage OrderRequest {\n string order_id = 1;\n}\n\nmessage OrderResponse {\n string order_id = 1;\n string status = 2;\n double total = 3;\n}\n\nنفذ الخدمة في Services/OrderService.cs:
public class OrderService : OrderGrpc.OrderGrpcBase\n{\n private readonly ILogger<OrderService> _logger;\n\n public OrderService(ILogger<OrderService> logger)\n {\n _logger = logger;\n }\n\n public override Task<OrderResponse> GetOrder(OrderRequest request, ServerCallContext context)\n {\n _logger.LogInformation("طلب الطلب {OrderId}", request.OrderId);\n // هنا يمكن أن يكون منطق أعمالك\n return Task.FromResult(new OrderResponse\n {\n OrderId = request.OrderId,\n Status = "Confirmed",\n Total = 99.99\n });\n }\n}\n\nشغل:
\n\ndotnet run\n\nالخدمة تعمل على المنفذ 5001 (الافتراضي لـ gRPC). تخيل الآن أن لديك 20 خدمة من هذا القبيل. كيف تدير اتصالاتها؟ هنا يأتي دور Service Mesh.
\n\nإعداد Istio لخدمات C# المصغرة: خطوة بخطوة
\n\nلنفترض أن مجموعة Kubernetes الخاصة بك قد تم إعدادها بالفعل. قم بتثبيت Istio:
\n\nistioctl install --set profile=demo -y\n\nالآن، قم بتفعيل الحقن التلقائي للـ sidecar في مساحة الأسماء الخاصة بك:
\n\nkubectl label namespace default istio-injection=enabled\n\nأعد نشر خدمة OrderService الخاصة بك (بعد إنشاء Docker image ودفعها):
\n\nkubectl apply -f deployment.yaml\n\nهذا كل شيء! يقوم Istio تلقائيًا بحقن proxy Envoy بجانب حاوية .NET الخاصة بك. الآن، كل حركة المرور بين الخدمات تمر عبر Service Mesh. يمكنك إضافة قواعد التوجيه، المهلات، وإعادة المحاولة دون تغيير سطر واحد من كود C#.