Penanganan Pesan Racun

Pesan racun adalah pesan yang telah melebihi jumlah maksimum upaya pengiriman ke aplikasi. Situasi ini dapat muncul ketika aplikasi berbasis antrean tidak dapat memroses pesan karena kesalahan. Untuk memenuhi permintaan keandalan, aplikasi antrian menerima pesan di bawah transaksi. Membatalkan transaksi di mana pesan antrean diterima meninggalkan pesan dalam antrean sehingga pesan dicoba kembali di bawah transaksi baru. Jika masalah yang menyebabkan transaksi dibatalkan tidak diperbaiki, aplikasi penerima bisa terjebak dalam perulangan menerima dan membatalkan pesan yang sama sampai jumlah maksimum upaya pengiriman telah terlampaui dan hasil pesan racun.

Pesan dapat menjadi pesan racun karena berbagai alasan. Alasan paling umum adalah khusus aplikasi. Misalnya, jika aplikasi membaca pesan dari antrean dan melakukan beberapa pemrosesan database, aplikasi mungkin gagal mendapatkan kunci pada database, menyebabkannya membatalkan transaksi. Karena transaksi database dibatalkan, pesan tetap berada dalam antrean, yang menyebabkan aplikasi membaca ulang pesan untuk kedua kalinya dan mencoba lagi untuk mendapatkan kunci pada database. Pesan juga dapat menjadi racun jika berisi informasi yang tidak valid. Misalnya, pesanan pembelian mungkin berisi nomor pelanggan yang tidak valid. Dalam kasus ini, aplikasi dapat secara sukarela membatalkan transaksi dan memaksa pesan menjadi pesan racun.

Pada kesempatan yang jarang terjadi, pesan bisa gagal dikirim ke aplikasi. Lapisan Windows Communication Foundation (WCF) mungkin menemukan masalah dengan pesan, seperti jika pesan memiliki bingkai yang salah, mandat pesan yang tidak valid yang dilampirkan, atau header tindakan yang tidak valid. Dalam kasus ini, aplikasi tidak pernah menerima pesan; namun, pesan tersebut masih bisa menjadi pesan racun dan diproses secara manual.

Menangani Pesan Racun

Di WCF, penanganan pesan racun menyediakan mekanisme untuk aplikasi penerima untuk menangani pesan yang tidak dapat dikirim ke aplikasi atau pesan yang dikirim ke aplikasi tetapi gagal diproses karena alasan tertentu aplikasi. Konfigurasikan penanganan pesan racun dengan properti berikut di setiap pengikatan antrean yang tersedia:

  • ReceiveRetryCount. Nilai bilangan bulat yang menunjukkan berapa kali maksimum untuk mencoba lagi pengiriman pesan dari antrean aplikasi ke aplikasi. Nilai defaultnya adalah 5. Ini cukup dalam kasus di mana percobaan ulang segera memperbaiki masalah, seperti dengan kebuntuan sementara pada database.

  • MaxRetryCycles. Nilai bilangan bulat yang menunjukkan jumlah maksimum siklus percobaan ulang. Siklus percobaan ulang terdiri dari mentransfer pesan dari antrean aplikasi ke subantrean percobaan ulang dan, setelah penundaan yang dapat dikonfigurasi, dari subantrean percobaan ulang kembali ke antrean aplikasi untuk mencoba pengiriman kembali. Nilai defaultnya adalah 2. Pada Windows Vista, pesan dicoba maksimal (ReceiveRetryCount +1) * (MaxRetryCycles + 1) kali. MaxRetryCycles diabaikan pada Windows Server 2003 dan Windows XP.

  • RetryCycleDelay. Waktu penundaan antara siklus percobaan ulang. Nilai defaultnya adalah 30 menit. MaxRetryCycles dan RetryCycleDelay bersama-sama menyediakan mekanisme untuk mengatasi masalah di mana percobaan ulang setelah penundaan berkala memperbaiki masalah. Misalnya, ini menangani kumpulan baris terkunci dalam penerapan transaksi SQL Server tertunda.

  • ReceiveErrorHandling. Enumerasi yang menunjukkan tindakan yang harus diambil untuk pesan yang gagal terkirim setelah jumlah maksimum percobaan ulang telah dicoba. Nilainya dapat Kesalahan, Kehilangan, Tolak, dan Pindahkan. Opsi defaultnya adalah Kesalahan.

  • Kesalahan. Opsi ini mengirimkan kesalahan ke pendengar yang menyebabkan ServiceHost gagal. Pesan harus dihapus dari antrean aplikasi oleh beberapa mekanisme eksternal sebelum aplikasi dapat terus memroses pesan dari antrean.

  • Hilangkan. Opsi ini menghilangkan pesan racun dan pesan tidak pernah dikirimkan ke aplikasi. Jika properti pesan TimeToLive telah kedaluwarsa pada saat ini, maka pesan mungkin muncul dalam antrean surat mati pengirim. Jika tidak, pesan tidak muncul di mana pun. Opsi ini menunjukkan bahwa pengguna belum menentukan apa yang harus dilakukan jika pesan hilang.

  • Tolak. Opsi ini hanya tersedia di Windows Vista. Ini menginstruksikan Message Queuing (MSMQ) untuk mengirim pengakuan negatif kembali ke manajer antrean pengiriman bahwa aplikasi tidak dapat menerima pesan. Pesan ditempatkan di antrean surat mati manajer antrean pengirim.

  • Pindahkan. Opsi ini hanya tersedia di Windows Vista. Ini memindahkan pesan racun ke antrean pesan racun untuk diproses nanti oleh aplikasi penanganan pesan racun. Antrean pesan racun adalah subantrean dari antrean aplikasi. Aplikasi penanganan pesan racun dapat berupa layanan WCF yang membaca pesan dari antrean racun. Antrean racun adalah subantrean dari antrean aplikasi dan dapat dialamatkan sebagai net.msmq://<machine-name>/applicationQueue;poison, tempat nama komputer adalah nama komputer tempat antrean berada dan applicationQueue adalah nama antrean khusus aplikasi.

Berikut ini adalah jumlah maksimum upaya pengiriman yang dilakukan untuk pesan:

  • ((ReceiveRetryCount+1) * (MaxRetryCycles + 1)) di Windows Vista.

  • (ReceiveRetryCount + 1) di Windows Server 2003 dan Windows XP.

Catatan

Tidak ada percobaan ulang yang dibuat untuk pesan yang berhasil dikirimkan.

Untuk melacak berapa kali pesan dibaca dicoba, Windows Vista mempertahankan properti pesan tahan lama yang menghitung jumlah pembatalan dan properti hitungan pemindahan yang menghitung berapa kali pesan berpindah antara antrean aplikasi dan subantrean. Saluran WCF menggunakan ini untuk menghitung jumlah percobaan ulang yang diterima dan jumlah siklus percobaan ulang. Pada Windows Server 2003 dan Windows XP, jumlah pembatalan dipertahankan dalam memori oleh saluran WCF dan diatur ulang jika aplikasi gagal. Selain itu, saluran WCF dapat menyimpan jumlah pembatalan hingga 256 pesan dalam memori setiap saat. Jika pesan ke-257 dibaca, maka jumlah pembatalan pesan terlama akan diatur ulang.

Properti hitungan pembatalan dan jumlah pemindahan tersedia untuk operasi layanan melalui konteks operasi. Contoh kode berikut menunjukkan cara mengaksesnya.

MsmqMessageProperty mqProp = OperationContext.Current.IncomingMessageProperties[MsmqMessageProperty.Name] as MsmqMessageProperty;
Console.WriteLine("Abort count: {0} ", mqProp.AbortCount);
Console.WriteLine("Move count: {0} ", mqProp.MoveCount);
// code to submit purchase order ...

WCF menyediakan dua pengikatan antrean standar:

  • NetMsmqBinding. Pengikatan .NET Framework cocok untuk melakukan komunikasi berbasis antrean dengan titik akhir WCF lainnya.

  • MsmqIntegrationBinding. Pengikatan yang cocok untuk berkomunikasi dengan aplikasi Message Queuing yang ada.

Catatan

Anda dapat mengubah properti dalam pengikatan ini berdasarkan persyaratan layanan WCF Anda. Seluruh mekanisme penanganan pesan racun bersifat lokal untuk aplikasi penerima. Prosesnya tidak terlihat oleh aplikasi pengirim kecuali aplikasi penerima akhirnya berhenti dan mengirimkan pengakuan negatif kembali ke pengirim. Dalam hal ini, pesan dipindahkan ke antrean surat mati pengirim.

Praktik Terbaik: Menangani MsmqPoisonMessageException

Ketika layanan menentukan bahwa pesan adalah racun, transportasi yang diantrekan melempar MsmqPoisonMessageException yang berisi LookupId pesan racun.

Aplikasi penerima dapat menerapkan antarmuka IErrorHandler untuk menangani kesalahan apa pun yang diperlukan aplikasi. Untuk informasi selengkapnya, lihat Memperluas Kontrol Atas Penanganan dan Pelaporan Kesalahan.

Aplikasi mungkin memerlukan beberapa jenis penanganan otomatis pesan racun yang memindahkan pesan racun ke antrean pesan racun sehingga layanan dapat mengakses sisa pesan dalam antrean. Satu-satunya skenario untuk menggunakan mekanisme penanganan kesalahan untuk mendengarkan pengecualian pesan racun adalah ketika pengaturan ReceiveErrorHandling diatur ke Fault. Sampel pesan racun untuk Message Queuing 3.0 menunjukkan perilaku ini. Berikut ini menguraikan langkah-langkah yang harus diambil untuk menangani pesan racun, termasuk praktik terbaik:

  1. Pastikan pengaturan racun Anda mencerminkan persyaratan aplikasi Anda. Saat bekerja dengan pengaturan, pastikan Anda memahami perbedaan antara kemampuan Message Queuing di Windows Vista, Windows Server 2003, dan Windows XP.

  2. Jika perlu, terapkan IErrorHandler untuk menangani kesalahan pesan racun. Karena pengaturan ReceiveErrorHandling ke Fault memerlukan mekanisme manual untuk memindahkan pesan racun keluar dari antrean atau untuk memperbaiki masalah ketergantungan eksternal, penggunaan tipikal adalah untuk menerapkan IErrorHandler ketika ReceiveErrorHandling diatur ke Fault, seperti yang ditunjukkan dalam kode berikut.

    class PoisonErrorHandler : IErrorHandler
    {
        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            // No-op -We are not interested in this. This is only useful if you want to send back a fault on the wire…not applicable for queues [one-way].
        }
    
        public bool HandleError(Exception error)
        {
            if (error != null && error.GetType() == typeof(MsmqPoisonMessageException))
            {
                Console.WriteLine(" Poisoned message -message look up id = {0}", ((MsmqPoisonMessageException)error).MessageLookupId);
                return true;
            }
    
            return false;
        }
    }
    
  3. Buat PoisonBehaviorAttribute yang dapat digunakan oleh perilaku layanan. Perilaku memasang IErrorHandler pada operator. Lihat contoh kode berikut.

    public class PoisonErrorBehaviorAttribute : Attribute, IServiceBehavior
    {
        Type errorHandlerType;
    
        public PoisonErrorBehaviorAttribute(Type errorHandlerType)
        {
            this.errorHandlerType = errorHandlerType;
        }
    
        void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
        {
        }
    
        void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
        {
        }
    
        void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
        {
            IErrorHandler errorHandler;
    
            try
            {
                errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
            }
            catch (MissingMethodException e)
            {
                throw new ArgumentException("The errorHandlerType specified in the PoisonErrorBehaviorAttribute constructor must have a public empty constructor", e);
            }
            catch (InvalidCastException e)
            {
                throw new ArgumentException("The errorHandlerType specified in the PoisonErrorBehaviorAttribute constructor must implement System.ServiceModel.Dispatcher.IErrorHandler", e);
            }
    
            foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
            {
                ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
                channelDispatcher.ErrorHandlers.Add(errorHandler);
            }
        }
    }
    
  4. Pastikan layanan Anda diannotasi dengan atribut perilaku racun.

Selain itu, jika ReceiveErrorHandling diatur ke Fault, kesalahan ServiceHost ketika menemukan pesan racun. Anda dapat menghubungkan ke kejadian yang salah dan mematikan layanan, mengambil tindakan korektif, dan menghidupkan kembali. Misalnya, LookupId dalam MsmqPoisonMessageException yang disebarkan ke IErrorHandler dapat dicatat dan ketika kesalahan host layanan, Anda dapat menggunakan API System.Messaging untuk menerima pesan dari antrean menggunakan LookupId untuk menghapus pesan dari antrean dan menyimpan pesan di beberapa penyimpanan eksternal atau antrean lain. Anda dapat menghidupkan ulangServiceHost untuk melanjutkan pemrosesan normal. Penanganan Pesan Racun di MSMQ 4.0 menunjukkan perilaku ini.

Batas Waktu Transaksi dan Pesan Racun

Kelas kesalahan dapat terjadi antara saluran transportasi yang diantrekan dan kode pengguna. Kesalahan ini dapat dideteksi oleh lapisan di antaranya, seperti lapisan keamanan pesan atau logika pengiriman layanan. Misalnya, sertifikat X.509 yang hilang terdeteksi di lapisan keamanan SOAP dan tindakan yang hilang adalah kasus di mana pesan dikirim ke aplikasi. Ketika ini terjadi, model layanan menghilangkan pesan. Karena pesan dibaca dalam suatu transaksi dan hasil untuk transaksi tersebut tidak dapat diberikan, transaksi tersebut akhirnya waktunya habis, dibatalkan, dan pesan dimasukkan kembali ke dalam antrean. Dengan kata lain, untuk kelas kesalahan tertentu, transaksi tidak langsung dibatalkan tetapi menunggu sampai waktu transaksi habis. Anda dapat mengubah batas waktu transaksi untuk layanan menggunakan ServiceBehaviorAttribute.

Untuk mengubah batas waktu transaksi di seluruh komputer, ubah file machine.config dan atur batas waktu transaksi yang sesuai. Penting untuk dicatat bahwa, tergantung pada batas waktu yang ditetapkan dalam transaksi, transaksi akhirnya dibatalkan dan kembali ke antrean dan jumlah pembatalannya bertambah. Akhirnya, pesan menjadi racun dan disposisi yang tepat dibuat sesuai dengan pengaturan pengguna.

Sesi dan Pesan Racun

Sesi mengalami percobaan ulang dan prosedur penanganan pesan-racun yang sama sebagai satu pesan. Properti yang sebelumnya tercantum untuk pesan racun berlaku untuk seluruh sesi. Ini berarti bahwa seluruh sesi percobaan ulang dan masuk ke antrean pesan racun terakhir atau antrean surat mati pengirim jika pesan ditolak.

Batching dan Pesan Racun

Jika sebuah pesan menjadi pesan racun dan merupakan bagian dari sebuah batch, maka seluruh batch akan digulung balik dan saluran kembali membaca satu pesan pada satu waktu. Untuk informasi selengkapnya tentang pembuatan batch, lihat Pembuatan Batch Pesan dalam Transaksi

Penanganan Pesan Racun untuk Pesan dalam Antrean Racun

Penanganan pesan racun tidak berakhir ketika pesan ditempatkan dalam antrean pesan racun. Pesan dalam antrean pesan racun masih harus dibaca dan ditangani. Anda dapat menggunakan subset dari pengaturan penanganan pesan-racun saat membaca pesan dari subantrean racun terakhir. Pengaturan yang berlaku adalah ReceiveRetryCount dan ReceiveErrorHandling. Anda dapat mengatur ReceiveErrorHandling ke Hilangkan, Tolak, atau Kesalahan. MaxRetryCycles diabaikan dan pengecualian dilemparkan jika ReceiveErrorHandling diatur ke Pindahkan.

Perbedaan Windows Vista, Windows Server 2003, dan Windows XP

Seperti disebutkan sebelumnya, tidak semua pengaturan penanganan pesan racun berlaku untuk Windows Server 2003 dan Windows XP. Perbedaan utama berikut antara Message Queuing pada Windows Server 2003, Windows XP, dan Windows Vista relevan dengan penanganan pesan racun:

  • Message Queuing di Windows Vista mendukung subantrean, sedangkan Windows Server 2003 dan Windows XP tidak mendukung subantrean. Subantrean digunakan dalam penanganan pesan racun. Antrean coba lagi dan antrean racun adalah sub-antrean ke antrean aplikasi yang dibuat berdasarkan setelan penanganan pesan racun. MaxRetryCycles menentukan banyaknya sub-antrean coba lagi yang akan dibuat. Oleh karena itu, saat berjalan di Windows Server 2003 atau Windows XP, MaxRetryCycles diabaikan dan ReceiveErrorHandling.Move tidak diizinkan.

  • Message Queuing di Windows Vista mendukung pengakuan negatif, sementara Windows Server 2003 dan Windows XP tidak mendukung pengakuan negatif. Pengakuan negatif dari pengelola antrean penerima menyebabkan pengelola antrean pengirim menempatkan pesan yang ditolak dalam antrean surat mati. Dengan demikian, ReceiveErrorHandling.Reject tidak diizinkan di Windows Server 2003 dan Windows XP.

  • Message Queuing di Windows Vista mendukung properti pesan yang menghitung berapa kali pengiriman pesan dicoba kembali. Properti jumlah pembatalan ini tidak tersedia di Windows Server 2003 dan Windows XP. WCF mempertahankan jumlah pembatalan dalam memori, jadi ada kemungkinan bahwa properti ini mungkin tidak berisi nilai yang akurat ketika pesan yang sama dibaca oleh lebih dari satu layanan WCF di farm.

Lihat juga