مشاركة عبر


ASP.NET الأساسية في الخدمات الموثوقة لنسيج خدمة Azure

ASP.NET Core هو إطار مفتوح المصدر ومتعدد المنصات. صُمم هذا الإطار لإنشاء تطبيقات قائمة على السحابة ومتصلة بالإنترنت، مثل تطبيقات الويب وتطبيقات إنترنت الأشياء والنهايات الخلفية للجوال.

هذه المقالة هي دليل متعمق لاستضافة ASP.NET الخدمات الأساسية في Service Fabric Reliable Services باستخدام Microsoft.ServiceFabric.AspNetCore. مجموعة من حزم NuGet.

للحصول على برنامج تعليمي تمهيدي حول ASP.NET Core في Service Fabric وإرشادات حول إعداد بيئة التطوير الخاصة بك، راجع البرنامج التعليمي: إنشاء تطبيق ونشره باستخدام خدمة واجهة برمجة تطبيقات الويب الأساسية ASP.NET وخدمة خلفية ذات حالة.

تفترض بقية هذه المقالة أنك تعرف ASP.NET Core فعلاً. إذا لم يكن الأمر كما هو، فالرجاء قراءة أساسيات ASP.NET Core.

ASP.NET الأساسية في بيئة نسيج الخدمة

يمكن تشغيل كل من تطبيقات ASP.NET Core ونسيج الخدمة على .NET Core أو .NET Framework الكامل. يمكنك استخدام ASP.NET Core بطريقتين مختلفتين في نسيج الخدمة:

  • مستضاف كضيف قابل للتنفيذ. تُستخدم هذه الطريقة بشكل أساسي لتشغيل تطبيقات ASP.NET Core الموجودة على نسيج الخدمة دون أي تغييرات في التعليمات البرمجية.
  • تشغيل داخل خدمة موثوق بها. تتيح هذه الطريقة تكاملاً أفضل مع وقت تشغيل نسيج الخدمة وتسمح بخدمات ASP.NET الأساسية الرائعة.

تُبين بقية هذه المقالة كيفية استخدام ASP.NET Core داخل خدمة موثوقة، من خلال مكونات تكامل Core ASP.NET التي تُشحن مع Service Fabric SDK.

استضافة خدمة نسيج الخدمة

في Service Fabric، يتم تشغيل مثيل واحد أو أكثر و/أو نسخ متماثلة من الخدمة في عملية مضيف خدمة: ملف قابل للتنفيذ يقوم بتشغيل التعليمات البرمجية للخدمة. بصفتك مؤلف خدمة، تمتلك عملية مضيف الخدمة، ويقوم نسيج الخدمة بتنشيطها ومراقبتها نيابة عنك.

يقترن ASP.NET التقليدي (حتى MVC 5) بإحكام ب IIS من خلال System.Web.dll. يوفر ASP.NET Core فصلاً بين خادم الويب وتطبيق الويب خاصتك. يسمح هذا الفصل لتطبيقات الويب بأن تكون محمولة بين خوادم الويب المختلفة. كما يسمح باستضافة خوادم الويب ذاتيا. هذا يعني أنه يمكنك بدء تشغيل خادم ويب في العملية خاصتك، بدلاً من العملية التي يملكها برنامج خادم ويب مخصص، مثل IIS.

للجمع بين خدمة Service Fabric ASP.NET، إما كضيف قابل للتنفيذ أو في خدمة موثوقة، يجب أن تكون قادرًا على بدء ASP.NET داخل عملية مضيف الخدمة. تتيح لك ASP.NET Core الاستضافة الذاتية للقيام بذلك.

Hosting ASP.NET الأساسية في خدمة موثوقة

عادة ما تقوم تطبيقات ASP.NET Core المستضافة ذاتيا بإنشاء WebHost في نقطة إدخال التطبيق، مثل static void Main() الأسلوب في Program.cs. في هذه الحالة، ترتبط دورة حياة WebHost بدورة حياة العملية.

استضافة ASP.NET Core في عملية

لكن نقطة إدخال التطبيق ليست المكان المناسب لإنشاء WebHost في خدمة موثوقة. وذلك لأن نقطة إدخال التطبيق تُستخدم فقط لتسجيل نوع خدمة مع وقت تشغيل نسيج الخدمة، بحيث يمكنها إنشاء مثيلات من نوع الخدمة هذه. يجب إنشاء WebHost في خدمة موثوقة نفسها. ضمن عملية مضيف الخدمة، يمكن أن تمر مثيلات الخدمة و/أو النسخ المتماثلة بدورات حياة متعددة.

يتم تمثيل مثيل خدمة موثوق بها بواسطة فئة الخدمة المشتقة من StatelessService أو StatefulService. يتم تضمين مكدس الاتصال لخدمة في ICommunicationListener تنفيذ في فئة الخدمة الخاصة بك. Microsoft.ServiceFabric.AspNetCore.* تحتوي حزم NuGet على تطبيقات ICommunicationListener لبدء وإدارة ASP.NET Core WebHost إما ل Kestrel أو HTTP.sys في خدمة موثوق بها.

رسم تخطيطي لاستضافة ASP.NET Core في خدمة موثوق بها

ASP.NET Core ICommunicationListeners

تطبيقات ICommunicationListener Kestrel و HTTP.sys في Microsoft.ServiceFabric.AspNetCore.* حزم NuGet لها أنماط استخدام مماثلة. لكنهم يقومون بإجراءات مختلفة قليلاً خاصة بكل خادم ويب.

يوفر كل من مستمعي الاتصال منشئًا يأخذ الوسيطات التالية:

  • ServiceContext serviceContext: هذا هو الكائن الذي ServiceContext يحتوي على معلومات حول الخدمة قيد التشغيل.
  • string endpointName: هذا هو اسم Endpoint التكوين في ServiceManifest.xml. إنه في المقام الأول المكان الذي يختلف فيه اثنان من مستمعو التواصل. يتطلب HTTP.sys تكويناEndpoint، بينما لا يتطلب Kestrel ذلك.
  • Func<string, AspNetCoreCommunicationListener, IWebHost> build: هذا lambda الذي تقوم بتنفيذه، حيث تقوم بإنشاء وإرجاع IWebHost. يسمح لك بتكوين IWebHost الطريقة التي تفعلها عادة في تطبيق ASP.NET Core. يوفر lambda عنوان URL الذي تم إنشاؤه لك، اعتمادا على خيارات تكامل Service Fabric التي تستخدمها والتكوين الذي Endpoint توفره. يمكنك بعد ذلك تعديل عنوان URL هذا أو استخدامه لبدء تشغيل خادم الويب.

تكامل نسيج الخدمة الوسيطة

Microsoft.ServiceFabric.AspNetCore تتضمن حزمة NuGet أسلوب الامتداد UseServiceFabricIntegration على IWebHostBuilder الذي يضيف البرنامج الوسيط المدرك ل Service Fabric. يقوم هذا البرنامج الوسيط بتكوين Kestrel أو HTTP.sys ICommunicationListener لتسجيل عنوان URL خدمة فريد مع خدمة تسمية Service Fabric. ثم يتحقق من صحة طلبات العملاء لضمان اتصال العملاء بالخدمة الصحيحة.

هذه الخطوة ضرورية لمنع العملاء من الاتصال عن طريق الخطأ بالخدمة الخطأ. ويرجع ذلك إلى أنه في بيئة مضيف مشترك مثل نسيج الخدمة، يمكن تشغيل تطبيقات ويب متعددة على نفس الجهاز الفعلي أو الظاهري ولكنها لا تستخدم أسماء مضيفين فريدة. يُوصف هذا السيناريو بمزيد من التفصيل في القسم التالي.

حالة من الهوية الخطأ

تستمع النسخ المتماثلة للخدمة، بغض النظر عن البروتوكول، إلى مجموعة IP:port فريدة. بمجرد أن تبدأ نسخة متماثلة من الخدمة في الاستماع إلى نقطة نهاية IP:port، فإنها تُبلغ عن عنوان نقطة النهاية هذا إلى خدمة تسمية نسيج الخدمة. هناك، يمكن للعملاء أو الخدمات الأخرى اكتشافه. إذا كانت الخدمات تستخدم منافذ تطبيق معينة ديناميكيًا، فقد تستخدم نسخة متماثلة من الخدمة نفس نقطة نهاية IP:port لخدمة أخرى كانت موجودة مسبقًا على نفس الجهاز الفعلي أو الظاهري. يمكن أن يتسبب ذلك في اتصال العميل بالخدمة الخطأ عن طريق الخطأ. يمكن أن ينتج هذا السيناريو في حالة حدوث تسلسل الأحداث التالي:

  1. تستمع الخدمة A على 10.0.0.1:30000 عبر HTTP.
  2. يحل العميل الخدمة A ويحصل على العنوان 10.0.0.1:30000.
  3. تنتقل الخدمة A إلى عقدة مختلفة.
  4. تُوضع الخدمة B على 10.0.0.1 وتستخدم بالصدفة نفس المنفذ 30000.
  5. يحاول العميل الاتصال بالخدمة A باستخدام العنوان المخزن مؤقتًا 10.0.0.1:30000.
  6. يتم الآن توصيل العميل بنجاح بالخدمة B، دون إدراك أنه متصل بالخدمة الخطأ.

هذا يمكن أن يسبب أخطاء في أوقات عشوائية يمكن أن يكون من الصعب تشخيصها.

استخدام عناوين URL الفريدة للخدمة

لمنع هذه الأخطاء، يمكن للخدمات نشر نقطة نهاية إلى "خدمة التسمية" باستخدام معرف فريد، ثم التحقق من صحة هذا المعرف الفريد في أثناء طلبات العميل. هذا عمل تعاوني بين الخدمات في بيئة موثوقة غير معادية للمستأجر. لا يوفر مصادقة خدمة آمنة في بيئة مستأجرة معادية.

في بيئة موثوق بها، يقوم البرنامج الوسيط الذي تمت إضافته بواسطة UseServiceFabricIntegration الأسلوب تلقائيا بإلحاق معرف فريد بالعنوان المنشور في خدمة التسمية. ويتحقق من صحة هذا المعرف في كل طلب. إذا لم يتطابق المعرف، فسيقوم البرنامج الوسيط على الفور بإرجاع استجابة HTTP 410 Gone.

يجب أن تستفيد الخدمات التي تستخدم منفذًا معينًا ديناميكيًا من هذه البرامج الوسيطة.

لا تواجه الخدمات التي تستخدم منفذًا فريدًا ثابتًا هذه المشكلة في بيئة تعاونية. عادةً ما يتم استخدام منفذ فريد ثابت للخدمات التي تواجه خارجيًا والتي تحتاج إلى منفذ معروف لتطبيقات العميل للاتصال بها. على سبيل المثال، ستستخدم معظم تطبيقات الويب التي تواجه الإنترنت المنفذ 80 أو 443 لاتصالات مستعرض الويب. في هذه الحالة، لا ينبغي تمكين المعرف الفريد.

يُبين الرسم التخطيطي التالي تدفق الطلب مع تمكين البرامج الوسيطة:

تكامل Service Fabric ASP.NET Core

تستخدم كل من تطبيقات Kestrel و HTTP.sys ICommunicationListener هذه الآلية بنفس الطريقة بالضبط. على الرغم من أن HTTP.sys يمكن أن يميز الطلبات داخليا استنادا إلى مسارات URL الفريدة باستخدام ميزة مشاركة منفذ HTTP.sys الأساسية، إلا أن تنفيذ HTTP.sys ICommunicationListener لا يستخدم هذه الوظيفة. هذا لأنه ينتج عنه رموز حالة خطأ HTTP 503 وHTTP 404 في السيناريو الموضح سابقًا. وهذا بدوره يجعل من الصعب على العملاء تحديد الهدف من الخطأ، حيث يتم استخدام HTTP 503 وHTTP 404 بشكل شائع للإشارة إلى الأخطاء الأخرى.

وبالتالي، فإن كلا من Kestrel وتطبيقات HTTP.sys ICommunicationListener تتوحد على البرامج الوسيطة التي يوفرها أسلوب الامتداد UseServiceFabricIntegration . لذلك، يحتاج العملاء فقط إلى تنفيذ إجراء إعادة حل نقطة نهاية الخدمة على استجابات HTTP 410.

HTTP.sys في خدمات موثوقة

يمكنك استخدام HTTP.sys في خدمات موثوقة عن طريق استيراد حزمة Microsoft.ServiceFabric.AspNetCore.HttpSys NuGet. تحتوي هذه الحزمة على HttpSysCommunicationListener، وتنفيذ .ICommunicationListener HttpSysCommunicationListener يسمح لك بإنشاء ASP.NET Core WebHost داخل خدمة موثوق بها باستخدام HTTP.sys كخادم ويب.

تم إنشاء HTTP.sys على واجهة برمجة تطبيقات Windows HTTP Server. تستخدم واجهة برمجة التطبيقات هذه برنامج تشغيل kernel HTTP.sys لمعالجة طلبات HTTP وتوجيهها إلى العمليات التي تقوم بتشغيل تطبيقات الويب. يسمح ذلك لعمليات متعددة على نفس الجهاز الفعلي أو الظاهري باستضافة تطبيقات الويب على نفس المنفذ، مع إزالة الغموض إما عن طريق مسار عنوان URL فريد أو اسم مضيف. هذه الميزات مفيدة في نسيج الخدمة لاستضافة مواقع ويب متعددة في نفس المجموعة.

إشعار

HTTP.sys التنفيذ يعمل فقط على نظام Windows.

يوضح الرسم التخطيطي التالي كيفية استخدام HTTP.sys برنامج تشغيل HTTP.sys kernel على Windows لمشاركة المنفذ:

رسم تخطيطي HTTP.sys

HTTP.sys في خدمة غير متماثلة

للاستخدام HttpSys في خدمة عديمة الحالة، قم بتجاوز CreateServiceInstanceListeners الأسلوب وإرجاع مثيل HttpSysCommunicationListener :

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    return new ServiceInstanceListener[]
    {
        new ServiceInstanceListener(serviceContext =>
            new HttpSysCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
                new WebHostBuilder()
                    .UseHttpSys()
                    .ConfigureServices(
                        services => services
                            .AddSingleton<StatelessServiceContext>(serviceContext))
                    .UseContentRoot(Directory.GetCurrentDirectory())
                    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                    .UseStartup<Startup>()
                    .UseUrls(url)
                    .Build()))
    };
}

HTTP.sys في خدمة راقية

HttpSysCommunicationListenerغير مصمم حاليا للاستخدام في الخدمات ذات الحالة بسبب المضاعفات مع ميزة مشاركة المنفذ HTTP.sys الأساسية. لمزيد من المعلومات، راجع القسم التالي حول تخصيص المنفذ الديناميكي باستخدام HTTP.sys. بالنسبة إلى الخدمات المتميزة، فإن Kestrel هو خادم الويب المقترح.

تكوين نقطة النهاية

Endpoint التكوين مطلوب لخوادم الويب التي تستخدم واجهة برمجة تطبيقات Windows HTTP Server، بما في ذلك HTTP.sys. يجب أن تحتفظ خوادم الويب التي تستخدم واجهة برمجة تطبيقات Windows HTTP Server أولا بعنوان URL الخاص بها مع HTTP.sys (يتم إنجاز ذلك عادة باستخدام أداة netsh ).

يتطلب هذا الإجراء امتيازات مرتفعة لا تتمتع بها خدماتك افتراضيًا. يتم استخدام خيارات "http" أو "https" لخاصية Protocol Endpoint التكوين في ServiceManifest.xml خصيصا لإرشاد وقت تشغيل Service Fabric لتسجيل عنوان URL مع HTTP.sys نيابة عنك. يقوم بذلك باستخدام بادئة URL لأحرف البدل القوية.

على سبيل المثال، للحجز http://+:80 لخدمة، استخدم التكوين التالي في ServiceManifest.xml:

<ServiceManifest ... >
    ...
    <Resources>
        <Endpoints>
            <Endpoint Name="ServiceEndpoint" Protocol="http" Port="80" />
        </Endpoints>
    </Resources>

</ServiceManifest>

ويجب تمرير اسم نقطة النهاية إلى الدالة HttpSysCommunicationListener الإنشائية:

 new HttpSysCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
 {
     return new WebHostBuilder()
         .UseHttpSys()
         .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
         .UseUrls(url)
         .Build();
 })

استخدام HTTP.sys مع منفذ ثابت

لاستخدام منفذ ثابت مع HTTP.sys، قم بتوفير رقم المنفذ في Endpoint التكوين:

  <Resources>
    <Endpoints>
      <Endpoint Protocol="http" Name="ServiceEndpoint" Port="80" />
    </Endpoints>
  </Resources>

استخدام HTTP.sys مع منفذ ديناميكي

لاستخدام منفذ معين ديناميكيا مع HTTP.sys، احذف الخاصية Port في Endpoint التكوين:

  <Resources>
    <Endpoints>
      <Endpoint Protocol="http" Name="ServiceEndpoint" />
    </Endpoints>
  </Resources>

يوفر المنفذ الديناميكي المخصص بواسطة التكوين منفذا Endpoint واحدا فقط لكل عملية مضيف. يسمح نموذج استضافة نسيج الخدمة الحالي باستضافة مثيلات خدمة متعددة و/أو نُسخ متماثلة في نفس العملية. وهذا يعني أن كل واحد سيشارك نفس المنفذ عند تخصيصه من خلال Endpoint التكوين. يمكن لمثيلات HTTP.sys المتعددة مشاركة منفذ باستخدام ميزة مشاركة منفذ HTTP.sys الأساسية. ولكنه غير مدعوم من قبل HttpSysCommunicationListener بسبب المضاعفات التي يقدمها لطلبات العميل. لاستخدام المنفذ الديناميكي، Kestrel هو خادم الويب المقترح.

Kestrel في خدمات موثوقة

يمكنك استخدام Kestrel في Reliable Services عن طريق استيراد حزمة Microsoft.ServiceFabric.AspNetCore.Kestrel NuGet. تحتوي هذه الحزمة على KestrelCommunicationListener، وتنفيذ .ICommunicationListener KestrelCommunicationListener يسمح لك بإنشاء ASP.NET Core WebHost داخل خدمة موثوق بها باستخدام Kestrel كخادم ويب.

Kestrel هو خادم ويب عبر الأنظمة الأساسية ل ASP.NET Core. على عكس HTTP.sys، لا يستخدم Kestrel مدير نقطة نهاية مركزي. أيضًا على عكس HTTP.sys، لا يدعم Kestrel مشاركة المنفذ بين عمليات متعددة. يجب أن يستخدم كل مثيل من Kestrel منفذًا فريدًا. لمزيد من المعلومات حول Kestrel، راجع تفاصيل التنفيذ.

رسم تخطيطي ل Kestrel

Kestrel في خدمة غير متماثلة

للاستخدام Kestrel في خدمة عديمة الحالة، قم بتجاوز CreateServiceInstanceListeners الأسلوب وإرجاع مثيل KestrelCommunicationListener :

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    return new ServiceInstanceListener[]
    {
        new ServiceInstanceListener(serviceContext =>
            new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
                new WebHostBuilder()
                    .UseKestrel()
                    .ConfigureServices(
                        services => services
                            .AddSingleton<StatelessServiceContext>(serviceContext))
                    .UseContentRoot(Directory.GetCurrentDirectory())
                    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
                    .UseStartup<Startup>()
                    .UseUrls(url)
                    .Build();
            ))
    };
}

Kestrel في خدمة رائعة

للاستخدام Kestrel في خدمة ذات حالة، قم بتجاوز CreateServiceReplicaListeners الأسلوب وإرجاع مثيل KestrelCommunicationListener :

protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
    return new ServiceReplicaListener[]
    {
        new ServiceReplicaListener(serviceContext =>
            new KestrelCommunicationListener(serviceContext, (url, listener) =>
                new WebHostBuilder()
                    .UseKestrel()
                    .ConfigureServices(
                         services => services
                             .AddSingleton<StatefulServiceContext>(serviceContext)
                             .AddSingleton<IReliableStateManager>(this.StateManager))
                    .UseContentRoot(Directory.GetCurrentDirectory())
                    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
                    .UseStartup<Startup>()
                    .UseUrls(url)
                    .Build();
            ))
    };
}

في هذا المثال، يتم توفير مثيل مفرد من IReliableStateManager إلى حاوية حقن تبعية WebHost. هذا ليس ضروريا تماما، ولكنه يسمح لك باستخدام IReliableStateManager مجموعات موثوقة في أساليب إجراء وحدة تحكم MVC.

Endpoint لا يتم توفير اسم تكوين في KestrelCommunicationListener خدمة ذات حالة. يُشرح ذلك بمزيد من التفصيل في القسم التالي.

تكوين Kestrel لاستخدام HTTPS

عند تمكين HTTPS باستخدام Kestrel في خدمتك، ستحتاج إلى تعيين العديد من خيارات الاستماع. ServiceInstanceListener قم بتحديث لاستخدام نقطة نهايةHttps والاستماع إلى منفذ معين (مثل المنفذ 443). عند تكوين مضيف الويب لاستخدام خادم الويب Kestrel، يجب عليك تكوين Kestrel للاستماع إلى عناوين IPv6 على جميع واجهات الشبكة:

new ServiceInstanceListener(
serviceContext =>
    new KestrelCommunicationListener(
        serviceContext,
        "EndpointHttps",
        (url, listener) =>
        {
            ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");

            return new WebHostBuilder()
                .UseKestrel(opt =>
                {
                    int port = serviceContext.CodePackageActivationContext.GetEndpoint("EndpointHttps").Port;
                    opt.Listen(IPAddress.IPv6Any, port, listenOptions =>
                    {
                        listenOptions.UseHttps(GetCertificateFromStore());
                        listenOptions.NoDelay = true;
                    });
                })
                .ConfigureAppConfiguration((builderContext, config) =>
                {
                    config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
                })

                .ConfigureServices(
                    services => services
                        .AddSingleton<HttpClient>(new HttpClient())
                        .AddSingleton<FabricClient>(new FabricClient())
                        .AddSingleton<StatelessServiceContext>(serviceContext))
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseStartup<Startup>()
                .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                .UseUrls(url)
                .Build();
        }))

للحصول على مثال كامل في برنامج تعليمي، راجع تكوين Kestrel لاستخدام HTTPS.

تكوين نقطة النهاية

Endpoint التكوين غير مطلوب لاستخدام Kestrel.

Kestrel هو خادم ويب مستقل بسيط. على عكس HTTP.sys (أو HttpListener)، لا يحتاج إلى Endpoint تكوين في ServiceManifest.xml لأنه لا يتطلب تسجيل عنوان URL قبل البدء.

استخدام Kestrel مع منفذ ثابت

يمكنك تكوين منفذ ثابت في Endpoint تكوين ServiceManifest.xml للاستخدام مع Kestrel. على الرغم من أن هذا ليس ضروريًا للغاية، فإنه يوفر فائدتين محتملتين:

  • إذا لم يقع المنفذ في نطاق منفذ التطبيق، فإنه مفتوح من خلال جدار حماية نظام التشغيل بواسطة نسيج الخدمة.
  • سيستخدم عنوان URL المقدم لك من خلال KestrelCommunicationListener هذا المنفذ.
  <Resources>
    <Endpoints>
      <Endpoint Protocol="http" Name="ServiceEndpoint" Port="80" />
    </Endpoints>
  </Resources>

Endpoint إذا تم تكوين، يجب تمرير اسمه إلى الدالة KestrelCommunicationListener الإنشائية:

new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) => ...

إذا لم يستخدم ServiceManifest.xml تكوينا Endpoint ، فاحذف الاسم في الدالة KestrelCommunicationListener الإنشائية. في هذه الحالة، سيستخدم منفذًا ديناميكيًا. راجع القسم التالي للحصول على مزيد من المعلومات حول هذا.

استخدام Kestrel مع منفذ ديناميكي

لا يمكن ل Kestrel استخدام تعيين المنفذ التلقائي من Endpoint التكوين في ServiceManifest.xml. وذلك لأن تعيين المنفذ التلقائي من Endpoint تكوين يعين منفذا فريدا لكل عملية مضيف، ويمكن أن تحتوي عملية مضيف واحد على مثيلات Kestrel متعددة. هذا لا يعمل مع Kestrel لأنه لا يدعم مشاركة المنفذ. لذلك، يجب فتح كل مثيل Kestrel على منفذ فريد.

لاستخدام تعيين المنفذ الديناميكي مع Kestrel، احذف Endpoint التكوين في ServiceManifest.xml بالكامل، ولا تمرر اسم نقطة نهاية إلى الدالة KestrelCommunicationListener الإنشائية، كما يلي:

new KestrelCommunicationListener(serviceContext, (url, listener) => ...

في هذا التكوين، KestrelCommunicationListener سيتم تحديد منفذ غير مستخدم تلقائيا من نطاق منفذ التطبيق.

بالنسبة إلى HTTPS، يجب أن تحتوي على نقطة النهاية التي كُونت باستخدام بروتوكول HTTPS بدون منفذ محدد في ServiceManifest.xml وتمرير اسم نقطة النهاية إلى منشئ KestrelCommunicationListener.

تكامل IHost ونموذج الحد الأدنى من الاستضافة

بالإضافة إلى IWebHost/IWebHostBuilder، يدعم KestrelCommunicationListener وHttpSysCommunicationListener بناء خدمات ASP.NET Core باستخدام IHost/IHostBuilder. يتوفر هذا بدءًا من الإصدار 5.2.1363 من Microsoft.ServiceFabric.AspNetCore.Kestrel والحزم Microsoft.ServiceFabric.AspNetCore.HttpSys.

// Stateless Service
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    return new ServiceInstanceListener[]
    {
        new ServiceInstanceListener(serviceContext =>
            new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
            {
                return Host.CreateDefaultBuilder()
                        .ConfigureWebHostDefaults(webBuilder =>
                        {
                            webBuilder.UseKestrel()
                                .UseStartup<Startup>()
                                .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                                .UseContentRoot(Directory.GetCurrentDirectory())
                                .UseUrls(url);
                        })
                        .ConfigureServices(services => services.AddSingleton<StatelessServiceContext>(serviceContext))
                        .Build();
            }))
    };
}

// Stateful Service
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
    return new ServiceReplicaListener[]
    {
        new ServiceReplicaListener(serviceContext =>
            new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
            {
                return Host.CreateDefaultBuilder()
                        .ConfigureWebHostDefaults(webBuilder =>
                        {
                            webBuilder.UseKestrel()
                                .UseStartup<Startup>()
                                .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
                                .UseContentRoot(Directory.GetCurrentDirectory())
                                .UseUrls(url);
                        })
                        .ConfigureServices(services =>
                        {
                            services.AddSingleton<StatefulServiceContext>(serviceContext);
                            services.AddSingleton<IReliableStateManager>(this.StateManager);
                        })
                        .Build();
            }))
    };
}

إشعار

نظرًا لأن KestrelCommunicationListener وHttpSysCommunicationListener مخصصان لخدمات الويب، فمن المطلوب تسجيل/تكوين خادم ويب (باستخدام أسلوب ConfigureWebHostDefaults أو ConfigureWebHost) عبر IHost

قدم ASP.NET 6 نموذج الحد الأدنى من الاستضافة وهو طريقة أكثر تبسيطًا لإنشاء تطبيقات الويب. يمكن أيضًا استخدام نموذج الحد الأدنى من الاستضافة مع KestrelCommunicationListener وHttpSysCommunicationListener.

// Stateless Service
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    return new ServiceInstanceListener[]
    {
        new ServiceInstanceListener(serviceContext =>
            new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
            {
                var builder = WebApplication.CreateBuilder();

                builder.Services.AddSingleton<StatelessServiceContext>(serviceContext);
                builder.WebHost
                            .UseKestrel()
                            .UseContentRoot(Directory.GetCurrentDirectory())
                            .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                            .UseUrls(url);

                builder.Services.AddControllersWithViews();

                var app = builder.Build();

                if (!app.Environment.IsDevelopment())
                {
                    app.UseExceptionHandler("/Home/Error");
                }

                app.UseHttpsRedirection();
                app.UseStaticFiles();
                app.UseRouting();
                app.UseAuthorization();
                app.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");

                return app;
            }))
    };
}
// Stateful Service
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
    return new ServiceReplicaListener[]
    {
        new ServiceReplicaListener(serviceContext =>
            new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
            {
                var builder = WebApplication.CreateBuilder();

                builder.Services
                            .AddSingleton<StatefulServiceContext>(serviceContext)
                            .AddSingleton<IReliableStateManager>(this.StateManager);
                builder.WebHost
                            .UseKestrel()
                            .UseContentRoot(Directory.GetCurrentDirectory())
                            .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
                            .UseUrls(url);

                builder.Services.AddControllersWithViews();

                var app = builder.Build();

                if (!app.Environment.IsDevelopment())
                {
                    app.UseExceptionHandler("/Home/Error");
                }
                app.UseStaticFiles();
                app.UseRouting();
                app.UseAuthorization();
                app.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");

                return app;
            }))
    };
}

مزود تكوين نسيج الخدمة

يعتمد تكوين التطبيق في ASP.NET Core على أزواج القيم الرئيسية التي أنشأها موفر التكوين. اقرأ التكوين في ASP.NET Core لفهم المزيد حول دعم تكوين ASP.NET Core العام.

يصف هذا القسم كيفية تكامل موفر تكوين Service Fabric مع تكوين ASP.NET Core عن طريق استيراد حزمة Microsoft.ServiceFabric.AspNetCore.Configuration NuGet.

ملحقات بدء تشغيل AddServiceFabricConfiguration

بعد استيراد حزمة Microsoft.ServiceFabric.AspNetCore.Configuration NuGet، تحتاج إلى تسجيل مصدر تكوين Service Fabric باستخدام واجهة برمجة تطبيقات تكوين ASP.NET Core. يمكنك القيام بذلك عن طريق التحقق من ملحقات AddServiceFabricConfiguration في Microsoft.ServiceFabric.AspNetCore.Configuration مساحة الاسم مقابل IConfigurationBuilder.

using Microsoft.ServiceFabric.AspNetCore.Configuration;

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
        .AddServiceFabricConfiguration() // Add Service Fabric configuration settings.
        .AddEnvironmentVariables();
    Configuration = builder.Build();
}

public IConfigurationRoot Configuration { get; }

الآن يمكن لخدمة ASP.NET Core الوصول إلى إعدادات تكوين نسيج الخدمة، تمامًا مثل أي إعدادات تطبيق أخرى. على سبيل المثال، يمكنك استخدام نمط الخيارات لتحميل الإعدادات إلى كائنات مكتوبة بقوة.

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<MyOptions>(Configuration);  // Strongly typed configuration object.
    services.AddMvc();
}

تعيين المفتاح الافتراضي

افتراضيًا، يتضمن موفر تكوين نسيج الخدمة اسم الحزمة واسم القسم واسم العقار. تُشكل هذه معًا مفتاح تكوين ASP.NET Core، كما يلي:

$"{this.PackageName}{ConfigurationPath.KeyDelimiter}{section.Name}{ConfigurationPath.KeyDelimiter}{property.Name}"

على سبيل المثال، إذا كان لديك حزمة تكوين تسمى MyConfigPackage بالمحتوى التالي، فستتوفر قيمة التكوين على ASP.NET Core IConfiguration من خلال MyConfigPackage:MyConfigSection:MyParameter.

<?xml version="1.0" encoding="utf-8" ?>
<Settings xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2011/01/fabric">  
  <Section Name="MyConfigSection">
    <Parameter Name="MyParameter" Value="Value1" />
  </Section>  
</Settings>

خيارات تكوين نسيج الخدمة

يدعم ServiceFabricConfigurationOptions موفر تكوين Service Fabric أيضا تغيير السلوك الافتراضي لتعيين المفتاح.

الإعدادات المُشَفرة

يدعم نسيج الخدمة الإعدادات المشفرة، وكذلك موفر تكوين نسيج الخدمة. لا يتم فك تشفير الإعدادات المشفرة إلى ASP.NET Core IConfiguration بشكل افتراضي. تُخَزن القيم المشفرة هناك بدلاً من ذلك. ولكن إذا كنت ترغب في فك تشفير القيمة لتخزينها في ASP.NET Core IConfiguration، يمكنك تعيين علامة DecryptValue إلى false في AddServiceFabricConfiguration الملحق، كما يلي:

public Startup()
{
    ICodePackageActivationContext activationContext = FabricRuntime.GetActivationContext();
    var builder = new ConfigurationBuilder()        
        .AddServiceFabricConfiguration(activationContext, (options) => options.DecryptValue = false); // set flag to decrypt the value
    Configuration = builder.Build();
}

حزم تكوين متعددة

يدعم نسيج الخدمة حزم تكوين متعددة. افتراضيًا، يتم تضمين اسم الحزمة في مفتاح التكوين. ولكن يمكنك تعيين العلامة IncludePackageName إلى خطأ، كما يلي:

public Startup()
{
    ICodePackageActivationContext activationContext = FabricRuntime.GetActivationContext();
    var builder = new ConfigurationBuilder()        
        // exclude package name from key.
        .AddServiceFabricConfiguration(activationContext, (options) => options.IncludePackageName = false); 
    Configuration = builder.Build();
}

تعيين المفاتيح المخصصة واستخراج القيمة ومجموعة البيانات

يدعم موفر تكوين Service Fabric أيضا سيناريوهات أكثر تقدما لتخصيص تعيين المفتاح باستخدام ExtractKeyFunc القيم واستخراجها مخصصا باستخدام ExtractValueFunc. يمكنك حتى تغيير عملية ملء البيانات بالكامل من تكوين Service Fabric إلى تكوين ASP.NET Core باستخدام ConfigAction.

توضح الأمثلة التالية كيفية استخدام ConfigAction لتخصيص محتوى البيانات:

public Startup()
{
    ICodePackageActivationContext activationContext = FabricRuntime.GetActivationContext();
    
    this.valueCount = 0;
    this.sectionCount = 0;
    var builder = new ConfigurationBuilder();
    builder.AddServiceFabricConfiguration(activationContext, (options) =>
        {
            options.ConfigAction = (package, configData) =>
            {
                ILogger logger = new ConsoleLogger("Test", null, false);
                logger.LogInformation($"Config Update for package {package.Path} started");

                foreach (var section in package.Settings.Sections)
                {
                    this.sectionCount++;

                    foreach (var param in section.Parameters)
                    {
                        configData[options.ExtractKeyFunc(section, param)] = options.ExtractValueFunc(section, param);
                        this.valueCount++;
                    }
                }

                logger.LogInformation($"Config Update for package {package.Path} finished");
            };
        });
  Configuration = builder.Build();
}

تحديثات التكوين

يدعم موفر تكوين نسيج الخدمة أيضًا تحديثات التكوين. يمكنك استخدام ASP.NET Core IOptionsMonitor لتلقي إعلامات التغيير، ثم استخدام IOptionsSnapshot لإعادة تحميل بيانات التكوين. لمزيد من المعلومات، راجع ASP.NET خيارات Core.

يتم دعم هذه الخيارات افتراضيًا. ليست هناك حاجة إلى مزيد من الترميز لتمكين تحديثات التكوين.

السيناريوهات والتكوينات

يوفر هذا القسم مجموعة من خادم الويب وتكوين المنفذ وخيارات تكامل نسيج الخدمة والإعدادات المتنوعة التي نوصي بها لاستكشاف السيناريوهات التالية وإصلاحها:

  • ASP.NET الأساسية غير المتماثلة المعروضة خارجيًا
  • خدمات ASP.NET الأساسية غير المتماثلة الداخلية فقط
  • الخدمات الداخلية ASP.NET الأساسية فقط

الخدمة المكشوفة خارجيا هي التي تعرض نقطة نهاية يتم استدعاؤها من خارج نظام المجموعة، عادة من خلال موازن تحميل.

الخدمة الداخلية فقط هي خدمة يتم استدعاء نقطة النهاية الخاصة بها فقط من داخل نظام المجموعة.

إشعار

لا ينبغي أن تتعرض نقاط نهاية الخدمة الرائعة بشكل عام للإنترنت. لن تتمكن المجموعات الموجودة خلف موازنات التحميل غير المدركة لدقة خدمة نسيج الخدمة، مثل Azure Load Balancer، من عرض الخدمات ذات الحالة. وذلك لأن موازن التحميل لن يتمكن من تحديد موقع حركة المرور وتوجيهها إلى النسخة المتماثلة المناسبة من الخدمة.

ASP.NET الأساسية غير المتماثلة المعروضة خارجيًا

Kestrel هو خادم الويب المقترح لخدمات الواجهة الأمامية التي تعرض نقاط نهاية HTTP الخارجية التي تواجه الإنترنت. على Windows، يمكن أن يوفر HTTP.sys إمكانية مشاركة المنفذ، ما يسمح لك باستضافة خدمات ويب متعددة على نفس المجموعة من العقد باستخدام نفس المنفذ. في هذا السيناريو، يتم تمييز خدمات ويب حسب اسم المضيف أو المسار، دون الاعتماد على وكيل الواجهة الأمامية أو بوابة لتوفير توجيه HTTP.

عند التعرض للإنترنت، يجب أن تستخدم خدمة غير متماثلة نقطة نهاية معروفة ومستقرة يمكن الوصول إليها من خلال موازن التحميل. ستوفر عنوان URL هذا لمستخدمي تطبيقك. نوصي بإجراء التكوين التالي:

نوع التوصية ملاحظات
خادم الويب Kestrel Kestrel هو خادم الويب المفضل، حيث يُدعم عبر نظامي التشغيل Windows وLinux.
تكوين المنفذ ثابت يجب تكوين منفذ ثابت معروف في Endpoints تكوين ServiceManifest.xml، مثل 80 ل HTTP أو 443 ل HTTPS.
خيارات تكامل نسيج الخدمة بلا ServiceFabricIntegrationOptions.None استخدم الخيار عند تكوين البرنامج الوسيط لتكامل Service Fabric، بحيث لا تحاول الخدمة التحقق من صحة الطلبات الواردة لمعرف فريد. لن يعرف المستخدمون الخارجيون لتطبيقك معلومات التعريف الفريدة التي تستخدمها البرامج الوسيطة.
عدد المثيلات -1 في حالات الاستخدام النموذجية، يجب تعيين إعداد عدد المثيلات إلى -1. يتم ذلك بحيث يتوفر مثيل على جميع العقد التي تتلقى حركة المرور من موازن التحميل.

إذا كانت هناك عدة خدمات معروضة خارجيًا تشترك في نفس مجموعة العقد، فإنه يمكنك استخدام HTTP.sys مع مسار عنوان URL فريد ولكنه مستقر. يمكنك تحقيق ذلك عن طريق تعديل عنوان URL المقدم عند تكوين IWebHost. لاحظ أن هذا ينطبق على HTTP.sys فقط.

new HttpSysCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
    url += "/MyUniqueServicePath";

    return new WebHostBuilder()
        .UseHttpSys()
        ...
        .UseUrls(url)
        .Build();
})

الخدمة الأساسية ASP.NET الداخلية فقط غير المتماثلة

يجب أن تستخدم الخدمات غير المتماثلة التي تُستدعى فقط من داخل المجموعة عناوين URL فريدة ومنافذ معينة ديناميكيًا لضمان التعاون بين خدمات متعددة. نوصي بإجراء التكوين التالي:

نوع التوصية ملاحظات
خادم الويب Kestrel على الرغم من أنه يمكنك استخدام HTTP.sys للخدمات الداخلية غير المتماثلة، فإن Kestrel هو أفضل خادم يسمح لمثيلات خدمة متعددة بمشاركة مضيف.
تكوين المنفذ تعيين ديناميكي قد تشترك النسخ المتماثلة المتعددة لخدمة ذات حالة في عملية مضيف أو نظام تشغيل مضيف، وبالتالي ستحتاج إلى منافذ فريدة.
خيارات تكامل نسيج الخدمة UseUniqueServiceUrl باستخدام تعيين المنفذ الديناميكي، يمنع هذا الإعداد مشكلة الهوية الخاطئة الموضحة سابقًا.
عدد المثيل أي يمكن تعيين إعداد عدد المثيلات إلى أي قيمة ضرورية لتشغيل الخدمة.

الخدمة الأساسية ASP.NET الداخلية فقط

وينبغي أن تستخدم الخدمات الحكومية التي لا تُستدعى إلا من داخل المجموعة المخصصة ديناميكيًا لضمان التعاون بين خدمات متعددة. نوصي بإجراء التكوين التالي:

نوع التوصية ملاحظات
خادم الويب Kestrel HttpSysCommunicationListener لم يتم تصميم للاستخدام من قبل الخدمات ذات الحالة التي تشترك فيها النسخ المتماثلة في عملية مضيف.
تكوين المنفذ تعيين ديناميكي قد تشترك النسخ المتماثلة المتعددة لخدمة ذات حالة في عملية مضيف أو نظام تشغيل مضيف، وبالتالي ستحتاج إلى منافذ فريدة.
خيارات تكامل نسيج الخدمة UseUniqueServiceUrl باستخدام تعيين المنفذ الديناميكي، يمنع هذا الإعداد مشكلة الهوية الخاطئة الموضحة سابقًا.

الخطوات التالية

تصحيح أخطاء تطبيق Service Fabric باستخدام Visual Studio