Pengelolaan Versi Layanan

Setelah penyebaran awal, dan berpotensi beberapa kali selama masa pakainya, layanan (dan titik akhir yang diekspos) mungkin perlu diubah karena berbagai alasan, seperti mengubah kebutuhan bisnis, persyaratan teknologi informasi, atau untuk mengatasi masalah lain. Setiap perubahan memperkenalkan versi baru layanan. Topik ini menjelaskan cara mempertimbangkan penerapan versi di Windows Communication Foundation (WCF).

Empat Kategori Perubahan Layanan

Perubahan pada layanan yang mungkin diperlukan dapat diklasifikasikan ke dalam empat kategori:

  • Perubahan kontrak: Misalnya, operasi mungkin ditambahkan, atau elemen data dalam pesan mungkin ditambahkan atau diubah.

  • Perubahan alamat: Misalnya, layanan berpindah ke lokasi lain di mana titik akhir memiliki alamat baru.

  • Perubahan pengikatan: Misalnya, mekanisme keamanan berubah atau pengaturannya berubah.

  • Perubahan implementasi: Misalnya, ketika implementasi metode internal berubah.

Beberapa perubahan ini disebut "pemutusan" dan yang lainnya "tidak mengganggu." Perubahan tidak mengganggu jika semua pesan yang telah berhasil diproses di versi sebelumnya berhasil diproses dengan sukses di versi baru. Setiap perubahan yang tidak memenuhi kriteria itu adalah perubahan yang melanggar .

Orientasi dan Penerapan Versi Layanan

Salah satu tenet orientasi layanan adalah bahwa layanan dan klien bersifat otonom (atau independen). Antara lain, ini menyiratkan bahwa pengembang layanan tidak dapat mengasumsikan bahwa mereka mengontrol atau bahkan tahu tentang semua klien layanan. Ini menghilangkan opsi untuk membangun kembali dan menyebarkan ulang semua klien saat layanan mengubah versi. Topik ini berasumsi bahwa layanan mematuhi prinsip ini dan oleh karena itu harus diubah atau diberi versi baru secara independen dari kliennya.

Dalam kasus di mana perubahan besar tidak terduga dan tidak dapat dihindari, aplikasi dapat memilih untuk mengabaikan prinsip ini dan mengharuskan klien untuk dibangun ulang dan di-deploy ulang dengan versi layanan yang baru.

Penerapan Versi Kontrak

Kontrak yang digunakan oleh klien tidak perlu sama dengan kontrak yang digunakan oleh layanan; mereka hanya perlu kompatibel.

Untuk kontrak layanan, kompatibilitas berarti operasi baru yang diekspos oleh layanan dapat ditambahkan tetapi operasi yang ada tidak dapat dihapus atau diubah secara semantik.

Untuk kontrak data, kompatibilitas berarti definisi jenis skema baru dapat ditambahkan tetapi definisi jenis skema yang ada tidak dapat diubah dengan cara yang melanggar. Perubahan signifikan mungkin termasuk menghapus anggota data atau mengubah jenis data mereka sehingga menjadi tidak kompatibel. Fitur ini memungkinkan layanan beberapa lintang dalam mengubah versi kontraknya tanpa melanggar klien. Dua bagian berikutnya menjelaskan perubahan yang tidak memutus dan yang memutus yang dapat dilakukan pada data WCF dan kontrak layanan.

Penerapan Versi Kontrak Data

Bagian ini berkaitan dengan penerapan versi data saat menggunakan kelas DataContractSerializer dan DataContractAttribute.

Versi Ketat

Dalam banyak skenario saat mengubah versi adalah masalah, pengembang layanan tidak memiliki kontrol atas klien dan oleh karena itu tidak dapat membuat asumsi tentang bagaimana mereka akan bereaksi terhadap perubahan dalam pesan XML atau skema. Dalam kasus ini, Anda harus menjamin bahwa pesan baru akan memvalidasi terhadap skema lama, karena dua alasan:

  • Klien lama dikembangkan dengan asumsi bahwa skema tidak akan berubah. Mereka mungkin gagal memproses pesan yang tidak pernah dirancang untuk mereka.

  • Klien lama dapat melakukan validasi skema aktual terhadap skema lama bahkan sebelum mencoba memproses pesan.

Pendekatan yang direkomendasikan dalam skenario tersebut adalah memperlakukan kontrak data yang ada sebagai tidak dapat diubah dan membuat yang baru dengan nama xml unik yang memenuhi syarat. Pengembang layanan kemudian akan menambahkan metode baru ke kontrak layanan yang ada atau membuat kontrak layanan baru dengan metode yang menggunakan kontrak data baru.

Sering kali pengembang layanan perlu menulis beberapa logika bisnis yang harus berjalan dalam semua versi kontrak data ditambah kode bisnis khusus versi untuk setiap versi kontrak data. Lampiran di akhir topik ini menjelaskan bagaimana antarmuka dapat digunakan untuk memenuhi kebutuhan ini.

Penerapan Versi Lax

Dalam banyak skenario lain, pengembang layanan dapat membuat asumsi bahwa menambahkan anggota baru yang opsional ke kontrak data tidak akan memutus klien yang ada. Ini mengharuskan pengembang layanan untuk menyelidiki apakah klien yang ada tidak melakukan validasi skema dan mereka mengabaikan anggota data yang tidak diketahui. Dalam skenario ini, dimungkinkan untuk memanfaatkan fitur kontrak data untuk menambahkan anggota baru tanpa mengganggu keberlangsungan. Pengembang layanan dapat membuat asumsi ini dengan percaya diri jika fitur kontrak data untuk penerapan versi sudah digunakan untuk versi pertama layanan.

WCF, ASP.NET Web Services, dan banyak tumpukan layanan Web lainnya mendukung penerapan versi laks: artinya, mereka tidak melemparkan pengecualian untuk anggota data baru yang tidak diketahui dalam data yang diterima.

Sangat mudah untuk secara keliru percaya bahwa menambahkan anggota baru tidak akan merusak klien yang ada. Jika Anda tidak yakin bahwa semua klien dapat menangani versi longgar, disarankan untuk menggunakan pedoman versi yang ketat dan memperlakukan kontrak data sebagai tetap.

Untuk panduan terperinci tentang versi kontrak data yang longgar dan ketat, lihat Praktik Terbaik: Versi Kontrak Data.

Membedakan Antara Kontrak Data dan Jenis .NET

Kelas atau struktur .NET dapat diproyeksikan sebagai kontrak data dengan menerapkan DataContractAttribute atribut ke kelas . Jenis .NET dan proyeksi kontrak datanya adalah dua hal yang berbeda. Dimungkinkan untuk memiliki beberapa jenis .NET dengan proyeksi kontrak data yang sama. Perbedaan ini sangat berguna dalam memungkinkan Anda mengubah jenis .NET sambil mempertahankan kontrak data yang diproyeksikan, sehingga mempertahankan kompatibilitas dengan klien yang ada bahkan dalam arti kata yang ketat. Ada dua hal yang harus selalu Anda lakukan untuk mempertahankan perbedaan ini antara jenis .NET dan kontrak data:

  • Tentukan Name dan Namespace. Anda harus selalu menentukan nama dan namespace kontrak data Anda untuk mencegah nama dan namespace layanan jenis .NET Anda terekspos dalam kontrak. Dengan cara ini, jika Anda memutuskan nanti untuk mengubah namespace layanan .NET atau nama jenis, kontrak data Anda tetap sama.

  • Tentukan Name. Anda harus selalu menentukan nama anggota data Anda untuk mencegah nama anggota .NET Anda terekspos dalam kontrak. Dengan cara ini, jika Anda memutuskan nanti untuk mengubah nama .NET anggota, kontrak data Anda tetap sama.

Mengubah atau Menghapus Anggota

Mengubah nama atau tipe data anggota, atau menghapus anggota data adalah perubahan signifikan meskipun versi lunak diizinkan. Jika perlu, buat kontrak data baru.

Jika kompatibilitas layanan sangat penting, Anda mungkin mempertimbangkan untuk mengabaikan anggota data yang tidak digunakan dalam kode Anda dan membiarkannya di tempatnya. Jika Anda membagi anggota data menjadi beberapa anggota, Anda mungkin mempertimbangkan untuk meninggalkan anggota yang ada sebagai properti yang dapat melakukan pemisahan dan agregasi ulang yang diperlukan untuk klien tingkat bawah (klien yang tidak ditingkatkan ke versi terbaru).

Demikian pula, perubahan pada nama atau namespace kontrak data adalah perubahan mendasar.

Round-Trips Data Yang Tidak Diketahui

Dalam beberapa skenario, ada kebutuhan untuk "pengolahan kembali" data tambahan yang belum dikenal yang berasal dari anggota yang ditambahkan dalam versi baru. Misalnya, layanan "versionNew" mengirim data dengan beberapa anggota yang baru ditambahkan ke klien "versionOld". Klien tersebut mengabaikan anggota yang baru ditambahkan saat memproses pesan, tetapi ia mengirim ulang data yang sama, termasuk anggota yang baru ditambahkan, kembali ke layanan versi baru. Skenario umum untuk ini adalah pembaruan data di mana data diambil dari layanan, diubah, dan dikembalikan.

Untuk mengaktifkan round-tripping untuk jenis tertentu, jenis harus mengimplementasikan IExtensibleDataObject antarmuka. Antarmuka ini berisi satu properti ExtensionData yang mengembalikan tipe ExtensionDataObject. Properti digunakan untuk menyimpan data apa pun dari versi kontrak data yang akan datang yang tidak diketahui oleh versi saat ini. Data ini tidak terlihat oleh klien, tetapi ketika instans diserialisasikan, konten properti ExtensionData ditulis bersama dengan data anggota kontrak lainnya.

Disarankan agar semua tipe menerapkan antarmuka ini untuk mengakomodasi anggota baru dan yang belum diketahui di masa mendatang.

Repositori Kontrak Data

Mungkin ada koleksi pustaka kontrak data di mana kontrak-kontrak tersebut diterbitkan ke repositori pusat, dan penerap layanan serta tipe menerapkan dan mengekspos kontrak-kontrak data dari repositori tersebut. Dalam hal ini, ketika Anda menerbitkan kontrak data ke repositori, Anda tidak memiliki kontrol atas siapa yang membuat jenis yang menerapkannya. Dengan demikian, Anda tidak dapat memodifikasi kontrak setelah diterbitkan, mengakibatkan kontrak tersebut menjadi tidak dapat diubah secara efektif.

Saat Menggunakan XmlSerializer

Prinsip penerapan versi yang sama berlaku saat menggunakan XmlSerializer kelas . Saat penerapan versi yang ketat diperlukan, perlakukan kontrak data sebagai tidak dapat diubah dan buat kontrak data baru dengan nama unik dan memenuhi syarat untuk versi baru. Ketika Anda yakin bahwa penggunaan penentuan versi yang longgar dapat diterapkan, Anda dapat menambahkan anggota baru yang dapat diserialisasikan dalam versi baru tetapi tidak mengubah atau menghapus anggota yang sudah ada.

Nota

XmlSerializer menggunakan atribut XmlAnyElementAttribute dan XmlAnyAttributeAttribute untuk mendukung round-tripping data yang tidak diketahui.

Versi Kontrak Pesan

Panduan untuk penerapan versi kontrak pesan sangat mirip dengan pembuatan versi kontrak data. Jika penerapan versi yang ketat diperlukan, Anda tidak boleh mengubah isi pesan tetapi membuat kontrak pesan baru dengan nama unik yang memenuhi syarat. Jika Anda tahu bahwa Anda dapat menggunakan versi yang longgar, Anda dapat menambahkan bagian isi pesan baru tetapi tidak boleh mengubah atau menghapus yang sudah ada. Panduan ini berlaku untuk kontrak pesan tanpa pembungkus dan terbungkus.

Header pesan selalu dapat ditambahkan, bahkan jika penerapan versi yang ketat sedang digunakan. Penanda MustUnderstand dapat memengaruhi pengelolaan versi. Secara umum, model penerapan versi untuk header di WCF seperti yang dijelaskan dalam spesifikasi SOAP.

Versi Kontrak Layanan

Mirip dengan penerapan versi kontrak data, penerapan versi kontrak layanan juga melibatkan penambahan, perubahan, dan penghapusan operasi.

Menentukan Nama, Namespace, dan Tindakan

Secara default, nama kontrak layanan adalah nama antarmuka. Namespace defaultnya adalah http://tempuri.org, dan setiap tindakan operasi adalah http://tempuri.org/contractname/methodname. Disarankan agar Anda secara eksplisit menentukan nama dan namespace untuk kontrak layanan, dan tindakan untuk setiap operasi untuk menghindari penggunaan http://tempuri.org dan untuk mencegah nama antarmuka dan metode terekspos dalam kontrak layanan.

Menambahkan Parameter dan Operasi

Menambahkan operasi layanan yang disediakan oleh layanan adalah perubahan yang tidak merusak karena klien yang ada tidak perlu memikirkan operasi baru tersebut.

Nota

Menambahkan operasi ke kontrak panggilan balik dupleks adalah perubahan yang merusak kompatibilitas.

Mengubah Parameter Operasi atau Jenis Pengembalian

Mengubah parameter atau jenis pengembalian umumnya adalah perubahan yang melanggar kecuali jenis baru mengimplementasikan kontrak data yang sama yang diterapkan oleh jenis lama. Untuk membuat perubahan seperti itu, tambahkan operasi baru ke kontrak layanan atau tentukan kontrak layanan baru.

Menghapus Operasi

Menghapus operasi juga merupakan perubahan yang mengganggu. Untuk membuat perubahan seperti itu, tentukan kontrak layanan baru dan ekspos pada titik akhir baru.

Kontrak Kegagalan

Atribut ini FaultContractAttribute memungkinkan pengembang kontrak layanan untuk menentukan informasi tentang kesalahan yang dapat dikembalikan dari operasi kontrak.

Daftar kesalahan yang dijelaskan dalam kontrak layanan tidak dianggap lengkap. Setiap saat, suatu proses dapat mengembalikan kesalahan yang tidak dijelaskan dalam kontraknya. Oleh karena itu mengubah set kesalahan yang dijelaskan dalam kontrak tidak dianggap melanggar. Misalnya, menambahkan kesalahan baru ke kontrak menggunakan FaultContractAttribute atau menghapus kesalahan yang ada dari kontrak.

Pustaka Kontrak Layanan

Organisasi mungkin memiliki pustaka kontrak di mana kontrak diterbitkan ke repositori pusat dan pelaksana layanan menerapkan kontrak dari repositori tersebut. Dalam hal ini, ketika Anda menerbitkan kontrak layanan ke repositori, Anda tidak memiliki kontrol atas siapa yang membuat layanan yang menerapkannya. Oleh karena itu, Anda tidak dapat mengubah kontrak layanan setelah diterbitkan, membuatnya tidak dapat diubah. WCF mendukung pewarisan kontrak, yang dapat digunakan untuk membuat kontrak baru yang memperpanjang kontrak yang ada. Untuk menggunakan fitur ini, tentukan antarmuka kontrak layanan baru yang mewarisi dari antarmuka kontrak layanan lama, lalu tambahkan metode ke antarmuka baru. Anda kemudian mengubah layanan yang mengimplementasikan kontrak lama untuk menerapkan kontrak baru dan mengubah definisi titik akhir "versionOld" untuk menggunakan kontrak baru. Untuk klien "versionOld", titik akhir akan terus terlihat mengekspos perjanjian "versionOld"; untuk klien "versionNew", titik akhir akan terlihat mengekspos perjanjian "versionNew".

Versi Alamat dan Pengikatan

Perubahan pada alamat titik akhir dan pengikatan adalah perubahan yang merusak kecuali jika klien mampu menemukan alamat atau pengikatan titik akhir baru secara dinamis. Salah satu mekanisme untuk menerapkan kemampuan ini adalah dengan menggunakan registri Universal Discovery Description and Integration (UDDI) dan Pola Pemanggilan UDDI di mana klien mencoba berkomunikasi dengan titik akhir dan, setelah kegagalan, meminta registri UDDI terkenal untuk metadata titik akhir saat ini. Klien kemudian menggunakan alamat dan pengikatan dari metadata ini untuk berkomunikasi dengan titik akhir. Jika komunikasi ini berhasil, klien akan menyimpan alamat dan informasi pengikatan untuk digunakan di masa mendatang.

Layanan Perutean dan Penerapan Versi

Jika perubahan yang dilakukan pada layanan merupakan perubahan yang merusak dan Anda harus menjalankan dua atau lebih versi layanan yang berbeda secara bersamaan, Anda dapat menggunakan Layanan Perutean WCF untuk merutekan pesan ke instance layanan yang tepat. Layanan Perutean WCF menggunakan perutean berbasis konten, dengan kata lain, layanan ini menggunakan informasi dalam pesan untuk menentukan tempat merutekan pesan. Untuk informasi selengkapnya tentang Layanan Perutean WCF, lihat Layanan Perutean. Untuk contoh cara menggunakan Layanan Perutean WCF untuk penerapan versi layanan, lihat Cara: Penerapan Versi Layanan.

Lampiran

Panduan penerapan versi kontrak data umum saat penerapan versi yang ketat diperlukan adalah memperlakukan kontrak data sebagai tidak dapat diubah dan membuat yang baru ketika perubahan diperlukan. Kelas baru perlu dibuat untuk setiap kontrak data baru, sehingga mekanisme diperlukan untuk menghindari harus mengambil kode yang ada yang ditulis dalam hal kelas kontrak data lama dan menulis ulang dalam hal kelas kontrak data baru.

Salah satu mekanisme tersebut adalah menggunakan antarmuka untuk menentukan anggota setiap kontrak data dan menulis kode implementasi internal dalam hal antarmuka daripada kelas kontrak data yang mengimplementasikan antarmuka. Kode berikut untuk versi 1 layanan menunjukkan IPurchaseOrderV1 antarmuka dan PurchaseOrderV1:

public interface IPurchaseOrderV1
{
    string OrderId { get; set; }
    string CustomerId { get; set; }
}

[DataContract(
Name = "PurchaseOrder",
Namespace = "http://examples.microsoft.com/WCF/2005/10/PurchaseOrder")]
public class PurchaseOrderV1 : IPurchaseOrderV1
{
    [DataMember(...)]
    public string OrderId {...}
    [DataMember(...)]
    public string CustomerId {...}
}

Ketika operasi kontrak layanan akan ditulis dalam istilah PurchaseOrderV1, logika bisnis yang sesungguhnya akan dalam istilah IPurchaseOrderV1. Kemudian, di versi 2, akan ada antarmuka baru IPurchaseOrderV2 dan kelas baru PurchaseOrderV2 seperti yang ditunjukkan dalam kode berikut:

public interface IPurchaseOrderV2
{
    DateTime OrderDate { get; set; }
}

[DataContract(
Name = "PurchaseOrder",
Namespace = "http://examples.microsoft.com/WCF/2006/02/PurchaseOrder")]
public class PurchaseOrderV2 : IPurchaseOrderV1, IPurchaseOrderV2
{
    [DataMember(...)]
    public string OrderId {...}
    [DataMember(...)]
    public string CustomerId {...}
    [DataMember(...)]
    public DateTime OrderDate { ... }
}

Kontrak layanan akan diperbarui untuk menyertakan operasi baru yang ditulis berdasarkan PurchaseOrderV2. Logika bisnis yang saat ini ditulis dalam hal IPurchaseOrderV1 akan terus bekerja untuk PurchaseOrderV2, sedangkan logika bisnis baru yang membutuhkan properti OrderDate akan ditulis dalam hal IPurchaseOrderV2.

Lihat juga