توزيع التطبيقات وإزالتها باستخدام FabricClient
بمجرد حزم نوع التطبيق، يصبح جاهزاً للتوزيع في نظام مجموعة Azure Service Fabric. يتضمن التوزيع الخطوات الثلاث التالية:
- تحميل حزمة التطبيق إلى مخزن الصور
- تسجيل نوع الطلب
- بادر بإزالة حزمة التطبيق من مخزن الصور
- بادر بإنشاء مثيل التطبيق
بعد أن توزع تطبيق وتشغِّل مثيل في نظام المجموعة، يمكنك حذف مثيل التطبيق ونوع التطبيق خاصته. بادر بإزالة تطبيق تماماً من نظام المجموعة باتباع الخطوات التالية:
- بادر بإزالة (أو حذف) مثيل التطبيق قيد التشغيل
- بادر بإلغاء تسجيل نوع الطلب إذا لم تعد بحاجة إليه
إذا كنت تستخدم Visual Studio لتوزيع التطبيقات وتتبع أخطائها على نظام مجموعة التطوير المحلي لديك، تتعامل جميع الخطوات السابقة تلقائياً من خلال برنامج PowerShell نصي. تم العثور على هذا البرنامج النصي في مجلد البرامج النصية لمشروع التطبيق. توفر هذه المقالة خلفية عما يقوم به هذا البرنامج النصي بحيث يمكنك تنفيذ العمليات نفسها خارج Visual Studio.
الاتصال بنظام المجموعة
الاتصال بنظام المجموعة عن طريق إنشاء مثيل FabricClient قبل تشغيل أي من أمثلة التعليمات البرمجية في هذه المقالة. للحصول على أمثلة للاتصال بمجموعة تطوير محلية أو نظام مجموعة أو مجموعة بعيدة مؤمنة باستخدام معرف Microsoft Entra أو شهادات X509 أو Windows Active Directory، راجع الاتصال بمجموعة آمنة. للاتصال بنظام مجموعة التطوير المحلي، بادر بتشغيل المثال التالي:
// Connect to the local cluster.
FabricClient fabricClient = new FabricClient();
تحميل حزمة التطبيق
لنفترض أنك أنشأت وحزمت تطبيقاً باسم MyApplication في Visual Studio. بشكل افتراضي، اسم نوع التطبيق المدرج في ApplicationManifest.xml هو "MyApplicationType". توجد حزمة التطبيق، التي تحتوي على بيان التطبيق الضروري، وبيانات الخدمة، وحزم التعليمات البرمجية/التكوين/البيانات، في C:\Users<؛ username>\Documents\Visual Studio 2019\Projects\MyApplication\MyApplication\pkg\Debug.
يؤدي تحميل حزمة التطبيق إلى وضعها في موقع يمكن الوصول إليه بواسطة مكونات Service Fabric الداخلية. تتحقق Service Fabric من حزمة التطبيق أثناء تسجيل حزمة التطبيق. ومع ذلك، إذا كنت ترغب في التحقق من حزمة التطبيق محلياً (أي قبل التحميل)، فاستخدم الأمر Test-ServiceFabricApplicationPackage cmdlet.
تحمِّل واجهة برمجة تطبيقات CopyApplicationPackage حزمة التطبيق إلى مخزن صور نظام المجموعة.
إذا كانت حزمة التطبيق كبيرة وتحتوي على العديد من الملفات أو أيٍ من الأمرين، فيمكنك ضغطها ونسخها إلى مخزن الصور باستخدام PowerShell. يقلل الضغط من حجم الملفات وعددها.
راجع فهم سلسلة اتصال مخزن الصور للحصول على معلومات تكميلية عن مخزن الصور وسلسلة اتصال مخزن الصور.
تسجيل حزمة التطبيق
يصبح نوع التطبيق والإصدار المعلن عنهما في بيان التطبيق متاحين للاستخدام عند تسجيل حزمة التطبيق. يقرأ النظام الحزمة التي تم تحميلها في الخطوة السابقة، ويتحقق من الحزمة، ويعالج محتويات الحزمة، وينسخ الحزمة المعالجة إلى موقع نظام داخلي.
تسجل واجهة برمجة تطبيقات ProvisionApplicationAsync نوع التطبيق في المجموعة وإتاحته للتوزيع.
توفر واجهة برمجة تطبيقات GetApplicationTypeListAsync معلومات عن كافة أنواع التطبيقات المسجلة بنجاح. يمكنك استخدام واجهة برمجة التطبيقات هذه لتحديد وقت الانتهاء من التسجيل.
بادر بإزالة حزمة التطبيق من مخزن الصور
يوصى بحذف حزمة التطبيق بعد تسجيل التطبيق بنجاح. يؤدي حذف حزم التطبيقات من مخزن الصور إلى تحرير موارد النظام. يؤدي الاحتفاظ بحزم التطبيقات غير المستخدمة إلى استهلاك مساحة تخزين القرص وإلى مشكلات في أداء التطبيقات. احذف حزمة التطبيق من مخزن الصور باستخدام واجهة برمجة تطبيقات RemoveApplicationPackage.
بادر بإنشاء مثيل التطبيق
يمكنك إنشاء مثيل لتطبيق من أي نوع من أنواع التطبيقات تم تسجيله بنجاح باستخدام واجهة برمجة التطبيقات CreateApplicationAsync. يجب أن يبدأ اسم كل تطبيق بالمخطط "fabric:"، ويجب أن يكون فريداً لكل مثيل تطبيق (ضمن نظام المجموعة). يتم أيضًا إنشاء أي خدمات افتراضية محددة في بيان التطبيق لنوع التطبيق الهدف.
يمكن إنشاء مثيلات تطبيقات متعددة لأي إصدار معين من نوع تطبيق مسجل. يتم تشغيل كل مثيل تطبيق بمعزلٍ عن الآخر، مع دليل العمل ومجموعة العمليات خاصته.
لمعرفة التطبيقات والخدمات المُسماة التي يتم تشغيلها في المجموعة، بادر بتشغيل واجهتي برمجة تطبيقات GetApplicationListAsync و GetServiceListAsync.
بادر بإنشاء مثيل خدمة
يمكنك إنشاء مثيل خدمة من نوع خدمة باستخدام واجهة برمجة تطبيقات CreateServiceAsync. إذا تم الإعلان عن الخدمة كخدمة افتراضية في بيان التطبيق، يتم إنشاء مثيل للخدمة عند إنشاء مثيل للتطبيق. سيؤدي استدعاء واجهة برمجة تطبيقات CreateServiceAsync لخدمة تم إنشاؤها بالفعل إلى إرجاع استثناء من النوع FabricException. سيحتوي الاستثناء على رمز خطأ بقيمة FabricErrorCode.ServiceAlreadyExists.
بادر بإزالة مثيل خدمة
عندما لا تكون هناك حاجة إلى مثيل خدمة، يمكنك إزالته من مثيل التطبيق قيد التشغيل عن طريق استدعاء واجهة برمجة تطبيقات DeleteServiceAsync.
تحذير
لا يمكن عكس هذه العملية، ولا يمكن استرداد حالة الخدمة.
بادر بإزالة مثيل التطبيق
عندما لا يعود هناك حاجة إلى مثيل تطبيق، يمكنك إزالته بشكل دائم حسب الاسم باستخدام واجهة برمجة التطبيقات DeleteApplicationAsync. DeleteApplicationAsync تزيل تلقائياً جميع الخدمات التي تنتمي إلى التطبيق كذلك، مما يزيل حالة الخدمة بأكملها نهائياً.
تحذير
لا يمكن عكس هذه العملية، ولا يمكن استرداد حالة التطبيق.
إلغاء تسجيل نوع طلب
عندما لا تكون هناك حاجة إلى إصدار معين من نوع التطبيق، يجب إلغاء تسجيل ذلك الإصدار المحدد من نوع التطبيق باستخدام واجهة برمجة التطبيقات Unregister-ServiceFabricApplicationType. يؤدي إلغاء تسجيل الإصدارات غير المُستخدمة من أنواع التطبيقات إلى تحرير مساحة التخزين التي يستخدمها مخزن الصور. يمكن إلغاء تسجيل إصدار من نوع التطبيق طالما لم يتم إنشاء مثيل لأي تطبيقات مقابل هذا الإصدار من نوع التطبيق. أيضاً، لا يمكن أن يكون لنوع التطبيق أي ترقيات معلقة للتطبيق تشير إلى هذا الإصدار من نوع التطبيق.
استكشاف الأخطاء وإصلاحها
تطلب Copy-ServiceFabricApplicationPackage للحصول على ImageStoreConnectionString
يجب أن تحتوي بيئة Service Fabric SDK بالفعل على إعداد القيم الافتراضية الصحيحة. ولكن إذا لزم الأمر، يجب أن تتطابق ImageStoreConnectionString لكافة الأوامر مع القيمة التي يستخدمها نظام مجموعة Service Fabric. يمكنك العثور على ImageStoreConnectionString في بيان نظام المجموعة، الذي تم استرداده باستخدام الأمرين Get-ServiceFabricClusterManifest وGet-ImageStoreConnectionStringFromClusterManifest:
PS C:\> Get-ImageStoreConnectionStringFromClusterManifest(Get-ServiceFabricClusterManifest)
يتم استخدام الأمر cmdlet Get-ImageStoreConnectionStringFromClusterManifest، وهو جزء من الوحدة Service Fabric SDK PowerShell، للحصول على سلسلة اتصال مخزن الصور. لاستيراد وحدة عدة تطوير البرامج، قم بتشغيل ما يلي:
Import-Module "$ENV:ProgramFiles\Microsoft SDKs\Service Fabric\Tools\PSModule\ServiceFabricSDK\ServiceFabricSDK.psm1"
تم العثور على ImageStoreConnectionString في بيان نظام المجموعة:
<ClusterManifest xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" Name="Server-Default-SingleNode" Version="1.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
[...]
<Section Name="Management">
<Parameter Name="ImageStoreConnectionString" Value="file:D:\ServiceFabric\Data\ImageStore" />
</Section>
[...]
راجع فهم سلسلة اتصال مخزن الصور للحصول على معلومات تكميلية عن مخزن الصور وسلسلة اتصال مخزن الصور.
توزيع حزمة تطبيق كبيرة
المشكلة: انتهت مهلة واجهة برمجة التطبيقات CopyApplicationPackage لحزمة تطبيق كبيرة (ترتيب جيجابايت). جرّب:
- حدد مهلة أكبر لأسلوب CopyApplicationPackage، باستخدام المعلمة
timeout
. مدة المهلة هي 30 دقيقة بشكل افتراضي. - تحقق من اتصال الشبكة بين الجهاز المصدر ونظام المجموعة لديك. إذا كان الاتصال بطيئاً، ففكر في استخدام جهاز مزود باتصال شبكة أفضل. إذا كان الجهاز العميل في منطقة أخرى غير نظام المجموعة، ففكر في استخدام جهاز عميل في منطقة أقرب أو نفس المنطقة مثل نظام المجموعة.
- تحقق مما إذا كنت تصل إلى التحكم بالنطاق الترددي الخارجي أم لا. على سبيل المثال، عند تكوين مخزن الصور لاستخدام تخزين azure، قد يتم تقييد التحميل.
المشكلة: اكتمل تحميل الحزمة بنجاح، ولكن انتهت مهلة واجهة برمجة تطبيقات ProvisionApplicationAsync. حاول:
- ضغط الحزمة قبل النسخ إلى مخزن الصور. يقلل الضغط من حجم الملفات وعددها، مما يقلل بدوره من كمية نسبة استخدام الشبكة والعمل الذي يجب على Service Fabric القيام به. قد تكون عملية التحميل أبطأ (خاصة إذا بادرت بتضمين وقت الضغط)، ولكن تسجيل نوع التطبيق وإلغاء تسجيله أسرع.
- حدد مهلة أكبر لواجهة برمجة تطبيقات ProvisionApplicationAsync مع المعلمة
timeout
.
توزيع حزمة التطبيقات مع العديد من الملفات
المشكلة: انتهاء مهلة ProvisionApplicationAsync لحزمة تطبيق تحتوي على العديد من الملفات (بترتيب الآلاف). جرّب:
- ضغط الحزمة قبل النسخ إلى مخزن الصور. يقلل الضغط من عدد الملفات.
- حدد مهلة أكبر لـ ProvisionApplicationAsync مع المعلمة
timeout
.
مثال على التعليمات البرمجية
ينسخ المثال التالي حزمة تطبيق إلى مخزن الصور ويوفر نوع التطبيق. ثم، ينشئ المثال مثيل تطبيق كما ينشئ مثيل خدمة. وأخيراً، يزيل المثال مثيل التطبيق ويلغي تزويد نوع التطبيق ثم يحذف حزمة التطبيق من مخزن الصور.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Threading.Tasks;
using System.Fabric;
using System.Fabric.Description;
using System.Threading;
namespace ServiceFabricAppLifecycle
{
class Program
{
static void Main(string[] args)
{
string clusterConnection = "localhost:19000";
string appName = "fabric:/MyApplication";
string appType = "MyApplicationType";
string appVersion = "1.0.0";
string serviceName = "fabric:/MyApplication/Stateless1";
string imageStoreConnectionString = "file:C:\\SfDevCluster\\Data\\ImageStoreShare";
string packagePathInImageStore = "MyApplication";
string packagePath = "C:\\Users\\username\\Documents\\Visual Studio 2019\\Projects\\MyApplication\\MyApplication\\pkg\\Debug";
string serviceType = "Stateless1Type";
// Connect to the cluster.
FabricClient fabricClient = new FabricClient(clusterConnection);
// Copy the application package to a location in the image store
try
{
fabricClient.ApplicationManager.CopyApplicationPackage(imageStoreConnectionString, packagePath, packagePathInImageStore);
Console.WriteLine("Application package copied to {0}", packagePathInImageStore);
}
catch (AggregateException ae)
{
Console.WriteLine("Application package copy to Image Store failed: ");
foreach (Exception ex in ae.InnerExceptions)
{
Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
}
}
// Provision the application. "MyApplicationV1" is the folder in the image store where the application package is located.
// The application type with name "MyApplicationType" and version "1.0.0" (both are found in the application manifest)
// is now registered in the cluster.
try
{
fabricClient.ApplicationManager.ProvisionApplicationAsync(packagePathInImageStore).Wait();
Console.WriteLine("Provisioned application type {0}", packagePathInImageStore);
}
catch (AggregateException ae)
{
Console.WriteLine("Provision Application Type failed:");
foreach (Exception ex in ae.InnerExceptions)
{
Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
}
}
// Delete the application package from a location in the image store.
try
{
fabricClient.ApplicationManager.RemoveApplicationPackage(imageStoreConnectionString, packagePathInImageStore);
Console.WriteLine("Application package removed from {0}", packagePathInImageStore);
}
catch (AggregateException ae)
{
Console.WriteLine("Application package removal from Image Store failed: ");
foreach (Exception ex in ae.InnerExceptions)
{
Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
}
}
// Create the application instance.
try
{
ApplicationDescription appDesc = new ApplicationDescription(new Uri(appName), appType, appVersion);
fabricClient.ApplicationManager.CreateApplicationAsync(appDesc).Wait();
Console.WriteLine("Created application instance of type {0}, version {1}", appType, appVersion);
}
catch (AggregateException ae)
{
Console.WriteLine("CreateApplication failed.");
foreach (Exception ex in ae.InnerExceptions)
{
Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
}
}
// Create the stateless service description. For stateful services, use a StatefulServiceDescription object.
StatelessServiceDescription serviceDescription = new StatelessServiceDescription();
serviceDescription.ApplicationName = new Uri(appName);
serviceDescription.InstanceCount = 1;
serviceDescription.PartitionSchemeDescription = new SingletonPartitionSchemeDescription();
serviceDescription.ServiceName = new Uri(serviceName);
serviceDescription.ServiceTypeName = serviceType;
// Create the service instance. If the service is declared as a default service in the ApplicationManifest.xml,
// the service instance is already running and this call will fail.
try
{
fabricClient.ServiceManager.CreateServiceAsync(serviceDescription).Wait();
Console.WriteLine("Created service instance {0}", serviceName);
}
catch (AggregateException ae)
{
Console.WriteLine("CreateService failed.");
foreach (Exception ex in ae.InnerExceptions)
{
Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
}
}
// Delete a service instance.
try
{
DeleteServiceDescription deleteServiceDescription = new DeleteServiceDescription(new Uri(serviceName));
fabricClient.ServiceManager.DeleteServiceAsync(deleteServiceDescription);
Console.WriteLine("Deleted service instance {0}", serviceName);
}
catch (AggregateException ae)
{
Console.WriteLine("DeleteService failed.");
foreach (Exception ex in ae.InnerExceptions)
{
Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
}
}
// Delete an application instance from the application type.
try
{
DeleteApplicationDescription deleteApplicationDescription = new DeleteApplicationDescription(new Uri(appName));
fabricClient.ApplicationManager.DeleteApplicationAsync(deleteApplicationDescription).Wait();
Console.WriteLine("Deleted application instance {0}", appName);
}
catch (AggregateException ae)
{
Console.WriteLine("DeleteApplication failed.");
foreach (Exception ex in ae.InnerExceptions)
{
Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
}
}
// Un-provision the application type.
try
{
fabricClient.ApplicationManager.UnprovisionApplicationAsync(appType, appVersion).Wait();
Console.WriteLine("Un-provisioned application type {0}, version {1}", appType, appVersion);
}
catch (AggregateException ae)
{
Console.WriteLine("Un-provision application type failed: ");
foreach (Exception ex in ae.InnerExceptions)
{
Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
}
}
Console.WriteLine("Hit enter...");
Console.Read();
}
}
}