يعد إطلاق الإصدار الجديد في العمليات القتالية دائمًا حدثًا عصبيًا. خاصة إذا كانت العملية تنطوي على العديد من العمليات اليدوية. العامل البشري هو شيء فظيع. "سيكون من الجيد أتمتة هذه العملية" - هذه الفكرة قديمة قدم عالم تكنولوجيا المعلومات بأكمله. وهناك مصطلح لهذا - نشر مستمر. نعم ، المشكلة هي أنه لا توجد طريقة فريدة لتكوين هذا النشر المستمر. ترتبط هذه العملية كثيرًا بالمجموعة التكنولوجية للمشروع وبيئته.
في هذه المقالة ، أريد مشاركة الخبرة العملية في إعداد تحديثات النظام التلقائية دون مقاطعة تشغيلها لبيئة تكنولوجية محددة ، وهي: تطبيق ويب ASP.NET MVC + Azure SQL + Entity Framework في وضع Code First ، يتم نشر التطبيق في Azure كخدمة تطبيقات ويتم التجميع والنشر من خلال Azure DevOps (المعروف سابقًا باسم Visual Studio Team Services).

للوهلة الأولى ، كل شيء بسيط للغاية ، لدى Azure App Service مفهوم لمفتاح النشر - قم بتنزيل الإصدار الجديد هناك وتشغيله. ولكن سيكون الأمر بسيطًا إذا كان المشروع يستند إلى قواعد بيانات إدارة قواعد البيانات غير العلائقية ، حيث لا يوجد مخطط بيانات جامد. في هذه الحالة ، نعم - فقط الإصدار الجديد يلتقط حركة المرور وفويلا. ولكن مع نظام إدارة قواعد البيانات العلائقية ، كل شيء أكثر تعقيدًا إلى حد ما.
فيما يلي العوامل الرئيسية التي تمنعنا من تنفيذ النشر المتواصل لمكدس التكنولوجيا الخاص بنا:
- لا يمكن أن يعمل الإصدار القديم من التطبيق مع بنية قاعدة البيانات الجديدة
- قد يستغرق تحديث بنية قاعدة البيانات وقتًا كبيرًا ولا يمكن دائمًا استخدام التطبيق نفسه من خلال آلية الترحيل التلقائي.
ساوضح. افترض أنك قمت بنشر إصدار جديد في فتحة موازية أو في مركز بيانات النسخ الاحتياطي وبدأت تطبيق عمليات الترحيل. لنفترض أن لدينا ثلاث هجرات ، والرعب واثنان قد تدحرجت ، والثالثة سقطت. في هذه اللحظة ، لن يحدث شيء للخوادم العاملة ، ولا يتحقق Entity Framework من الإصدار لكل طلب ، ولكن من المحتمل أن تفشل في حل المشكلة بسرعة. في هذا الوقت ، قد يزداد الحمل على التطبيق ، وستطلق النظام الأساسي مثيلًا إضافيًا للتطبيق نيابة عنك ، ولن يبدأ تشغيله ... بطبيعة الحال ، حيث تم تغيير بنية قاعدة البيانات. سيبدأ جزء كبير من المستخدمين في تلقي الأخطاء. وبالتالي ، فإن خطر التطبيق التلقائي للهجرات كبير.

بالنسبة للنقطة الثانية ، فقد تتضمن عملية الترحيل نوعًا من الأوامر التي يتجاوز وقت تنفيذها 30 ثانية وسينتهي الإجراء القياسي. حسنًا ، بالإضافة إلى هذه النقاط ، أنا شخصياً لا أحب حقيقة أنه أثناء عمليات الترحيل التلقائي ، تُجبر على ترقية جزء من البنية التحتية إلى إصدار جديد. وإذا كان الوضع مع وجود فتحات في Azure ، فإن هذا ليس مخيفًا للغاية ، ثم بالنسبة إلى وضع مع مركز بيانات النسخ الاحتياطي ، لديك جزء من البنية التحتية مع تطبيق غير فعال معروف. الأمر كله خطير ، سيطلق النار في أكثر اللحظات غير المناسبة.
ما يجب القيام به
لنبدأ بالأصعب - مع قاعدة البيانات. لذلك ، سيكون من الجيد تحديث هيكل قاعدة البيانات تلقائيًا بطريقة ما بحيث تستمر الإصدارات القديمة من التطبيق في العمل. بالإضافة إلى ذلك ، سيكون من الجميل مراعاة حقيقة أن هناك مثل هذه التحديثات التي يمكن أن يستغرقها أمر منفصل وقتًا كبيرًا ، مما يعني أننا بحاجة إلى تحديث قاعدة البيانات لا باستخدام الآليات المضمنة ، ولكن عن طريق تنفيذ برنامج نصي SQL منفصل. السؤال: كيفية تحضيره؟ يمكنك جعل هذا دليل العملية. إذا كان لديك دور مدير إصدار منفصل في الفريق ، يمكنك إجباره على تنفيذ الأمر في Visual Studio:
update-database -script
ستقوم بإنشاء نص ، وسيضع هذا الشخص هذا النص في مجلد مشروع محدد. ولكن يجب أن تعترف ، هذا لا يزال غير مريح ، أولاً ، العامل البشري ، وثانياً ، الصعوبات غير الضرورية إذا كان هناك أكثر من هجرة واحدة بين الإطلاقات. أو لسبب ما ، تم تخطي إصدار واحد على النظام الهدف. سيتعين علينا إنشاء حديقة معقدة مع تتبع عمليات الترحيل الموجودة بالفعل والتي يجب إطلاقها. إنه أمر صعب ، والأهم من ذلك ، أنه نفس الدراجة التي صنعت بالفعل في آلية الهجرة.
وسيكون من الصحيح بناء عملية إنشاء وتنفيذ البرنامج النصي في عملية حساب الإصدار. لإنشاء برنامج نصي لترحيل ، يمكنك استخدام الأداة المساعدة migrate.exe ، المضمنة في Entity Framework. أوجه انتباهكم إلى حقيقة أنك تحتاج إلى إصدار الوحدة أو الإصدار 6.2 أو أعلى ، نظرًا لأن خيار إنشاء البرنامج النصي لم يظهر في هذه الأداة المساعدة إلا في أبريل 2017. استدعاء الأداة المساعدة يشبه هذا:
migrate.exe Context.dll /connectionString="Data Source=localhost;Initial Catalog=myDB;User Id=sa;Password=myPassword;" /connectionProviderName="System.Data.SqlClient" /sc /startUpDirectory="c:\projects\MyProject\bin\Release" /verbose
تتم الإشارة إلى اسم التجميع حيث يوجد السياق الخاص بك ، وسلسلة الاتصال بقاعدة البيانات الهدف ، والموفر ، والأهم من ذلك ، دليل البدء ، والذي يحتوي على التجميع مع السياق وتجميع Entity Framework. لا تجرّب أسماء دليل العمل ، وكن أكثر بساطة. لقد تعثرنا في حقيقة أن migrate.exe لم يتمكن من قراءة الدليل ، الذي توجد به مسافات وأحرف لا تحتوي على أحرف.
هنا لا بد من جعل استطرادا هاما. الحقيقة هي أنه بعد تنفيذ الأمر أعلاه ، سيتم إنشاء برنامج نصي SQL واحد يحتوي على جميع الأوامر لجميع عمليات الترحيل التي تحتاج إلى تطبيقها على قاعدة البيانات الهدف. بالنسبة إلى Microsoft SQL Server ، هذا ليس جيدًا جدًا. الحقيقة هي أن الخادم ينفذ الأوامر بدون فاصل GO كحزمة واحدة ، ولا يمكن تنفيذ بعض العمليات معًا في حزمة واحدة.
على سبيل المثال ، في بعض الحالات ، لا تعمل إضافة حقل إلى جدول وإنشاء فهرس في هذا الجدول على الفور بحقل جديد. ولكن هذا لا يكفي ، تتطلب بعض الأوامر إعدادات بيئة معينة عند تشغيل البرنامج النصي. يتم تمكين هذه الإعدادات افتراضيًا عند الاتصال بـ SQL Server من خلال SQL Server Management Studio ، ولكن عند تنفيذ البرنامج النصي من خلال الأداة المساعدة لوحدة التحكم SQLCMD ، يجب تعيينها يدويًا. لأخذ كل هذا في الاعتبار ، سيكون عليك تعديل عملية إنشاء برنامج نصي الترحيل مع ملف. للقيام بذلك ، قم بإنشاء فصل إضافي بجانب سياق التاريخ ، يقوم بكل ما تحتاجه:
public class MigrationScriptBuilder : SqlServerMigrationSqlGenerator { public override IEnumerable<MigrationStatement> Generate(IEnumerable<MigrationOperation> migrationOperations, string providerManifestToken) { var statements = base.Generate(migrationOperations, providerManifestToken); var result = new List<MigrationStatement>(); result.Add(new MigrationStatement { Sql = "SET QUOTED_IDENTIFIER ON;" }); foreach (var item in statements) { item.BatchTerminator = "GO"; result.Add(item); } return result; } }
ولكي يتمكن Entity Framework من استخدامه ، قم بتسجيله في فئة Configuration ، والتي توجد عادةً في مجلد Migrations:
public Configuration() { SetSqlGenerator("System.Data.SqlClient", new MigrationScriptBuilder()); …. }
بعد ذلك ، سيحتوي برنامج الترحيل الناتج على GO بين كل عبارة ، وفي بداية الملف سيحتوي SET QUOTED_IDENTIFIER ON؛
الصيحة ، يتم الإعداد ، يبقى لتكوين العملية نفسها. بشكل عام ، كجزء من عملية الإصدار في Azure DevOps (VSTS / TFS) ، هذا أمر بسيط جدًا بالفعل. نحتاج إلى إنشاء برنامج نصي PowerShell مثل هذا:
param ( [string] [Parameter(Mandatory=$true)] $dbserver, [string] [Parameter(Mandatory=$true)] $dbname, [string] [Parameter(Mandatory=$true)] $dbserverlogin, [string] [Parameter(Mandatory=$true)] $dbserverpassword, [string] [Parameter(Mandatory=$true)] $rootPath, [string] [Parameter(Mandatory=$true)] $buildAliasName, [string] [Parameter(Mandatory=$true)] $contextFilesLocation, ) Write-Host "Generating migration script..." $fullpath="$rootPath\$buildAliasName\$contextFilesLocation" Write-Host $fullpath & "$fullpath\migrate.exe" Context.dll /connectionProviderName="System.Data.SqlClient" /connectionString="Server=tcp:$dbserver.database.windows.net,1433;Initial Catalog=$dbname;Persist Security Info=False;User ID=$dbserverlogin;Password=$dbserverpassword;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" /startUpDirectory=$fullpath /verbose /scriptFile=1.SQL Write-Host "Running migration script..." & "SQLCMD" -S "$dbserver.database.windows.net" -U $dbserverlogin@$dbserver -P $dbserverpassword -d $dbname -i 1.SQL Write-Host "====Finished with migration script===="
وإضافة وحدة تنفيذ البرنامج النصي PowerShell إلى عملية حساب الإصدار. قد تبدو الكتلة وإعداداتها كما يلي:

يبدو إعداد PowerShell مثل هذا:

من المهم ألا تنسَ إضافة ملف migrate.exe إلى المشروع من المجلد <YourProject> /packages/EntityFramework.6.2.0/tools/ وتعيين خاصية Copy Always إليه بحيث يتم نسخ هذه الأداة المساعدة إلى دليل الإخراج عند إنشاء المشروع ويمكنك الوصول إليه في الافراج عن أزور DevOps.
فارق بسيط . إذا كان مشروعك يستخدم WebJob أيضًا عند النشر إلى Azure App Service ، فإن إضافة Migrate.exe إلى مشروعك غير آمن. نواجه حقيقة أنه في المجلد الذي يتم فيه نشر WebJob الخاص بك ، تبدأ منصة Azure بغباء أول ملف exe يظهر. وإذا كان WebJob الخاص بك أبجديًا يتكلف لاحقًا migrate.exe (وقد فعلنا ذلك) ، فسيحاول تشغيل migrate.exe بدلاً من المشروع الخاص بك!
لذلك ، تعلمنا كيفية تحديث إصدار قاعدة البيانات عن طريق إنشاء برنامج نصي أثناء عملية الإصدار ، والأمر البسيط هو: إيقاف تشغيل التحقق من إصدار الترحيل ، لذلك إذا استمرت أي إخفاقات في عملية تنفيذ البرنامج النصي ، فسيظل الإصدار القديم من التعليمات البرمجية يعمل. أعتقد أنه ليست هناك حاجة للقول إن عمليات الترحيل يجب أن تكون غير مدمرة. أي يجب ألا تتداخل التغييرات في بنية قاعدة البيانات مع أداء الإصدار السابق ، ولكن أفضل من الإصدارين السابقين. لتعطيل التحقق ، تحتاج فقط إلى إضافة الكتلة التالية إلى Web.config:
<entityFramework> <contexts> <context type="<full namespace for your DataContext class>, MyAssembly" disableDatabaseInitialization="true"/> </contexts> </entityFramework>
حيث تكون
full namespace for your DataContext class
هي مساحة الاسم الكاملة لأحفادك من DbContext ، و MyAssembly هو اسم التجميع حيث يكمن السياق الخاص بك.
وأخيرًا ، من المستحسن للغاية أن نضمن أن التطبيق يعمل على الاحماء قبل تحويل المستخدمين إلى الإصدار الجديد. للقيام بذلك ، أضف كتلة خاصة إلى web.config مع الروابط التي يتم إنهاء تطبيقك تلقائيًا أثناء عملية التهيئة:
<system.webServer> <applicationInitialization doAppInitAfterRestart="true"> <add initializationPage="/" hostName="" /> </applicationInitialization> </system.webServer>
يمكنك إضافة العديد من الروابط ببساطة عن طريق إضافة
/>
يقال أنه في Azure ، عند التبديل بين فتحات ، تنتظر النظام الأساسي للتطبيق لبدء التشغيل وعندها فقط ينتقل حركة المرور إلى الإصدار الجديد.
ولكن ماذا عن مشروع على .NET Core؟
كل شيء أبسط بكثير وفي الوقت نفسه مختلف. يمكن إنشاء برنامج نصي للترحيل باستخدام أدوات عادية ، لكنه لا يعتمد على التجميع النهائي ، ولكن يعتمد على ملف المشروع. وبالتالي ، يجب أن يتم تكوين البرنامج النصي كجزء من عملية تجميع المشروع ويجب أن يتم تضمينه كأداة تجميع. في هذه الحالة ، سيحتوي البرنامج النصي على جميع أوامر جميع عمليات الترحيل من بداية الوقت. لا توجد مشاكل في هذا ، نظرًا لأن البرنامج النصي عديم المعنى ، أي يمكن تطبيقها على القاعدة المستهدفة بشكل متكرر دون أي عواقب. هذا له نتيجة أخرى مفيدة: لسنا بحاجة إلى تعديل عملية إنشاء البرنامج النصي لفصل الأوامر في حزم ، لقد تم كل شيء بالفعل لهذا الغرض.
حسنًا ، على وجه التحديد ، تبدو خطوات العملية هكذا. في عملية الإنشاء ، أضف المهمة:

نقوم بتكوينه لإنشاء ملف بهجرة:

لا تنس إضافة برنامج نصي إلى مشروع PowerShell الذي سيؤدي عملية الترحيل (المذكورة أعلاه) وملف الترحيل نفسه. نتيجة لذلك ، بعد بناء المشروع ، قد تبدو القطع الأثرية مثل هذا (بالإضافة إلى الأرشيف الفعلي مع التجميع ، هناك نص PS إضافي ونص SQL مزود بترحيل):

يبقى فقط في خطوة الإصدار المناسبة لتكوين تنفيذ البرنامج النصي PowerShell بنفس الطريقة الموضحة أعلاه.
عن المؤلف

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