Meluncurkan versi baru dalam operasi tempur selalu merupakan peristiwa yang menegangkan. Apalagi jika prosesnya melibatkan banyak operasi manual. Faktor manusia adalah hal yang mengerikan. "Akan menyenangkan untuk mengotomatisasi proses ini" - ide ini setua seluruh dunia TI. Dan ada istilah untuk ini - Penyebaran Berkelanjutan. Ya, masalahnya adalah, tidak ada cara unik untuk mengonfigurasi penerapan berkelanjutan ini. Sangat banyak proses ini terkait dengan tumpukan teknologi proyek dan lingkungannya.
Pada artikel ini saya ingin berbagi pengalaman praktis dalam menyiapkan pembaruan sistem otomatis tanpa mengganggu operasinya untuk lingkungan teknologi tertentu, yaitu: ASP.NET MVC + Azure SQL + aplikasi kerangka kerja Entitas dalam mode Code Pertama, aplikasi ini digunakan di Azure sebagai Layanan Aplikasi , dan perakitan dan penyebaran dilakukan melalui Azure DevOps (sebelumnya Visual Studio Team Services).

Sekilas, semuanya sangat sederhana, Azure App Service memiliki konsep slot penempatan - unduh versi baru di sana dan nyalakan. Tetapi akan sederhana jika proyek didasarkan pada DBMS non-relasional, di mana tidak ada skema data yang kaku. Dalam hal ini, ya - hanya versi baru yang mengambil traffic dan voila. Tetapi dengan DBMS relasional, semuanya agak lebih rumit.
Faktor utama yang mencegah kami menerapkan penyebaran berkelanjutan untuk tumpukan teknologi kami adalah sebagai berikut:
- Versi aplikasi yang lama tidak dapat berfungsi dengan struktur basis data yang baru
- Memperbarui struktur basis data dapat memakan waktu yang cukup lama dan tidak selalu memungkinkan menggunakan aplikasi itu sendiri melalui mekanisme migrasi otomatis.
Saya akan jelaskan. Misalkan Anda menggunakan versi baru di slot paralel atau di pusat data cadangan dan memulai aplikasi migrasi. Misalkan kita memiliki tiga migrasi dan, horor, dua telah bergulir, dan yang ketiga telah jatuh. Pada saat ini, tidak ada yang akan terjadi pada server yang berfungsi, Entity Framework tidak memeriksa versi untuk setiap permintaan, tetapi Anda mungkin tidak akan dapat dengan cepat menyelesaikan masalah. Pada saat ini, beban pada aplikasi dapat meningkat, dan platform akan meluncurkan instance tambahan aplikasi untuk Anda, dan itu ... secara alami tidak akan dimulai, karena struktur basis data telah berubah. Sebagian besar pengguna akan mulai menerima kesalahan. Dengan demikian, risiko aplikasi migrasi otomatis menjadi besar.

Adapun poin kedua, migrasi Anda mungkin berisi beberapa jenis perintah yang waktu eksekusi melebihi 30 detik dan prosedur standar akan habis. Nah, selain poin-poin ini, saya pribadi tidak suka fakta bahwa selama migrasi otomatis Anda dipaksa untuk meningkatkan bagian dari infrastruktur ke versi baru. Dan jika untuk mode dengan slot di Azure ini tidak begitu menakutkan, maka untuk mode dengan pusat data cadangan, Anda mendapatkan bagian dari infrastruktur dengan aplikasi yang dikenal tidak beroperasi. Itu semua berbahaya, itu akan menembak pada saat yang paling tidak tepat.
Apa yang harus dilakukan
Mari kita mulai dengan yang paling sulit - dengan database. Jadi, alangkah baiknya jika entah bagaimana secara otomatis memperbarui struktur basis data sehingga versi lama aplikasi terus bekerja. Selain itu, akan lebih baik untuk mempertimbangkan fakta bahwa ada pembaruan seperti itu di mana perintah terpisah dapat dieksekusi untuk waktu yang cukup lama, yang berarti kita perlu memperbarui basis data tidak menggunakan mekanisme bawaan tetapi dengan menjalankan skrip SQL terpisah. Pertanyaan: bagaimana menyiapkannya? Anda dapat membuat proses manual ini. Jika Anda memiliki peran manajer rilis terpisah di tim, Anda bisa memaksanya untuk menjalankan perintah di Visual Studio:
update-database -script
Dia akan menghasilkan skrip, dan orang ini akan meletakkan skrip ini di folder proyek tertentu. Tetapi Anda harus mengakui, ini masih merepotkan, pertama, faktor manusia, dan kedua, kesulitan yang tidak perlu jika ada lebih dari satu migrasi antar rilis. Atau karena alasan tertentu, satu rilis dilewati pada sistem target. Kami harus membuat semacam taman rumit dengan melacak migrasi mana yang sudah ada dan yang perlu diluncurkan. Ini sulit dan, yang paling penting, ini adalah sepeda yang sama yang telah dibuat dalam mekanisme migrasi.
Dan akan benar untuk membangun pembuatan skrip dan proses eksekusi ke dalam proses perhitungan rilis. Untuk menghasilkan skrip migrasi, Anda bisa menggunakan utilitas migrate.exe, yang disertakan dengan Entity Framework. Saya menarik perhatian Anda pada fakta bahwa Anda memerlukan Entity Framework versi 6.2 atau lebih tinggi, karena opsi pembuatan skrip muncul di utilitas ini hanya pada bulan April 2017. Panggilan utilitas terlihat seperti ini:
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
Nama rakitan ditunjukkan di mana Konteks Anda berada, string koneksi ke database target, penyedia, dan, yang sangat penting, direktori awal, yang berisi rakitan dengan konteks dan rakitan Entity Framework. Jangan bereksperimen dengan nama-nama direktori kerja, lebih sederhana. Kami menemukan fakta bahwa migrate.exe tidak dapat membaca direktori, dengan nama yang ada spasi dan karakter non-huruf.
Di sini perlu untuk melakukan penyimpangan penting. Faktanya adalah bahwa setelah menjalankan perintah di atas, satu skrip SQL akan dihasilkan berisi semua perintah untuk semua migrasi yang perlu diterapkan ke database target. Untuk Microsoft SQL Server, ini tidak terlalu baik. Faktanya adalah bahwa server mengeksekusi perintah tanpa pemisah GO sebagai paket tunggal, dan beberapa operasi tidak dapat dilakukan bersama dalam satu paket tunggal.
Misalnya, dalam beberapa kasus, menambahkan bidang ke tabel dan segera membuat indeks pada tabel ini dengan bidang baru tidak berfungsi. Tetapi ini tidak cukup, beberapa perintah memerlukan pengaturan lingkungan tertentu ketika menjalankan skrip. Pengaturan tersebut diaktifkan secara default ketika Anda terhubung ke SQL Server melalui SQL Server Management Studio, tetapi ketika skrip dieksekusi melalui utilitas konsol SQLCMD, mereka harus diatur secara manual. Untuk memperhitungkan semua ini, Anda harus memodifikasi proses pembuatan skrip migrasi dengan file. Untuk melakukan ini, buat kelas tambahan di sebelah konteks tanggal, yang melakukan semua yang Anda butuhkan:
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; } }
Dan agar Kerangka Entitas dapat menggunakannya, daftarkan di kelas Konfigurasi, yang biasanya terletak di folder Migrasi:
public Configuration() { SetSqlGenerator("System.Data.SqlClient", new MigrationScriptBuilder()); β¦. }
Setelah itu, skrip migrasi yang dihasilkan akan berisi GO di antara setiap pernyataan, dan pada awal file akan berisi SET QUOTED_IDENTIFIER ON;
Hore, persiapan sudah selesai, masih untuk mengkonfigurasi proses itu sendiri. Secara umum, sebagai bagian dari proses rilis di Azure DevOps (VSTS / TFS), ini sudah cukup sederhana. Kita perlu membuat skrip PowerShell seperti ini:
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===="
Dan tambahkan unit eksekusi skrip PowerShell ke proses perhitungan rilis. Blok dan pengaturannya mungkin terlihat seperti ini:

Pengaturan PowerShell terlihat seperti ini:

Penting untuk tidak lupa menambahkan file migrate.exe ke proyek dari folder <YourProject> /packages/EntityFramework.6.2.0/tools/ dan atur properti Copy Always ke sana sehingga utilitas ini disalin ke direktori output ketika proyek dibangun dan Anda dapat mengaksesnya di Rilis Azure DevOps.
Nuansa itu . Jika proyek Anda juga menggunakan WebJob saat menggunakan untuk Layanan Aplikasi Azure, maka menambahkan Migrate.exe ke proyek Anda tidak aman. Kami dihadapkan dengan fakta bahwa di folder tempat WebJob Anda diterbitkan, platform Azure memulai dengan bodoh file exe pertama yang muncul. Dan jika WebJob Anda secara alfabetis biaya migrate.exe nanti (dan kami lakukan), maka ia mencoba menjalankan migrate.exe alih-alih proyek Anda!
Jadi, kami mempelajari cara memperbarui versi database dengan membuat skrip selama proses rilis, hal yang sederhana adalah: matikan pemeriksaan versi migrasi sehingga jika ada kegagalan dalam proses eksekusi skrip, versi lama kode kami terus berfungsi. Saya pikir tidak perlu mengatakan bahwa migrasi Anda harus tidak merusak. Yaitu perubahan pada struktur basis data seharusnya tidak mengganggu kinerja versi sebelumnya, tetapi lebih baik dari dua versi sebelumnya. Untuk menonaktifkan verifikasi, Anda hanya perlu menambahkan blok berikut ke Web.config:
<entityFramework> <contexts> <context type="<full namespace for your DataContext class>, MyAssembly" disableDatabaseInitialization="true"/> </contexts> </entityFramework>
Di mana
full namespace for your DataContext class
adalah namespace penuh untuk keturunan Anda dari DbContext, dan MyAssembly adalah nama majelis tempat konteks Anda berada.
Dan akhirnya, sangat diinginkan bagi kami untuk memastikan aplikasi ini memanas sebelum mengalihkan pengguna ke versi baru. Untuk melakukan ini, tambahkan blok khusus ke web.config dengan tautan yang secara otomatis keluar dari aplikasi Anda selama proses inisialisasi:
<system.webServer> <applicationInitialization doAppInitAfterRestart="true"> <add initializationPage="/" hostName="" /> </applicationInitialization> </system.webServer>
Anda dapat menambahkan beberapa tautan hanya dengan menambahkan
/>
Ada argumen bahwa di Azure, ketika berpindah slot, platform menunggu aplikasi diinisialisasi dan baru kemudian mengalihkan lalu lintas ke versi baru.
Tapi bagaimana dengan proyek di .NET Core?
Semuanya jauh lebih sederhana dan pada saat yang sama berbeda. Skrip migrasi dapat dibuat menggunakan alat biasa, tetapi tidak didasarkan pada perakitan yang selesai, tetapi berdasarkan pada file proyek. Dengan demikian, skrip harus dibentuk sebagai bagian dari proses perakitan proyek dan harus dimasukkan sebagai artefak perakitan. Dalam hal ini, skrip akan berisi semua perintah semua migrasi dari awal waktu. Tidak ada masalah dalam hal ini, karena skrip idempoten, yaitu itu dapat diterapkan ke basis target berulang kali tanpa konsekuensi. Ini memiliki konsekuensi lain yang bermanfaat: kita tidak perlu memodifikasi proses pembuatan skrip untuk memisahkan perintah menjadi paket, semuanya sudah dilakukan untuk ini.
Secara khusus, langkah-langkah prosesnya terlihat seperti ini. Dalam proses pembuatan, tambahkan tugas:

Kami mengonfigurasinya untuk menghasilkan file dengan migrasi:

Jangan lupa untuk menambahkan skrip ke proyek PowerShell yang akan melakukan migrasi (dijelaskan di atas) dan file migrasi itu sendiri. Akibatnya, setelah membangun proyek, artefak mungkin terlihat seperti ini (selain arsip aktual bersama majelis, ada skrip PS tambahan dan skrip SQL dengan migrasi):

Tetap hanya dalam langkah Rilis yang tepat untuk mengkonfigurasi pelaksanaan skrip PowerShell ini dengan cara yang sama seperti yang dijelaskan di atas.
Tentang penulis

Pavel Kutakov adalah pakar teknologi cloud, pengembang dan arsitek sistem perangkat lunak di berbagai sektor bisnis - mulai dari IP perbankan yang beroperasi di seluruh dunia dari AS hingga Papua Nugini, hingga solusi cloud untuk operator lotere nasional.