Aracılığıyla paylaş


MSMQ 4.0'da Zehirli İleti İşleme

MSMQ4 örneği, bir hizmette zehirli ileti işlemenin nasıl gerçekleştirileceklerini gösterir. Bu örnek, İşlem Yapılan MSMQ Bağlama örneğini temel alır. Bu örnekte kullanılır netMsmqBinding. Hizmet, kuyruğa alınmış iletileri alan hizmeti gözlemlemenizi sağlayan şirket içinde barındırılan bir konsol uygulamasıdır.

Kuyruğa alınan iletişimde, istemci bir kuyruk kullanarak hizmetle iletişim kurar. Daha kesin olarak, istemci bir kuyruğa ileti gönderir. Hizmet kuyruktan iletiler alır. Bu nedenle hizmet ve istemcinin kuyruk kullanarak iletişim kurmak için aynı anda çalışması gerekmez.

Zehirli ileti, iletiyi okuyan hizmet iletiyi işleyemediğinde ve bu nedenle iletinin okunduğu işlemi sonlandırdığında kuyruktan sürekli olarak okunan bir iletidir. Böyle durumlarda ileti yeniden denenecektir. İletiyle ilgili bir sorun varsa bu teorik olarak sonsuza kadar devam edebilir. Bu durum yalnızca kuyruktan okumak ve hizmet işlemini çağırmak için işlemleri kullandığınızda oluşabilir.

MSMQ sürümüne bağlı olarak, NetMsmqBinding zehirli iletilerin tam algılanması için sınırlı algılamayı destekler. İleti zehirlenmiş olarak algılandıktan sonra, çeşitli yollarla işlenebilir. NetMsmqBinding, MSMQ sürümüne bağlı olarak zehirli iletilerin tam olarak işlenmesi için sınırlı işlemeyi destekler.

Bu örnek, Windows Server 2003 ve Windows XP platformunda sağlanan sınırlı zehir tesislerini ve Windows Vista'da sağlanan tam zehir tesislerini göstermektedir. Her iki örnekte de amaç zehirli iletiyi kuyruktan başka bir kuyruğa taşımaktır. Daha sonra bu kuyruğa zehirli ileti hizmeti tarafından hizmet ve edilebilir.

MSMQ v4.0 Zehir İşleme Örneği

Windows Vista'da MSMQ, zehirli iletileri depolamak için kullanılabilecek bir zehirli alt sorgu özelliği sağlar. Bu örnek, Windows Vista kullanarak zehirli iletilerle başa çıkmanın en iyi uygulamasını gösterir.

Windows Vista'da zehirli ileti algılama gelişmiştir. Algılamaya yardımcı olan 3 özellik vardır. ReceiveRetryCount, belirli bir iletinin kuyruktan yeniden okunma ve işleme için uygulamaya gönderilme sayısıdır. İleti uygulamaya gönderilemediğinden veya uygulama hizmet işlemindeki işlemi geri döndürdiğinden, ileti kuyruğa geri alındığında kuyruktan yeniden okunur. MaxRetryCycles , iletinin yeniden deneme kuyruğuna taşınma sayısıdır. Ulaşıldığında ReceiveRetryCount , ileti yeniden deneme kuyruğuna taşınır. özelliği RetryCycleDelay , iletinin yeniden deneme kuyruğundan ana kuyruğa geri taşındığı gecikme süresidir. ReceiveRetryCount 0 olarak sıfırlanır. İleti yeniden denendi. İletiyi okumaya yönelik tüm girişimler başarısız olduysa, ileti zehirli olarak işaretlenir.

İleti zehirli olarak işaretlendikten sonra, ileti numaralandırmadaki ReceiveErrorHandling ayarlara göre ele alınılır. Olası değerleri yinelemek için:

  • Hata (varsayılan): Dinleyiciyi ve hizmet ana bilgisayarını da hataya neden olan.

  • Bırak: İletiyi bırakmak için.

  • Taşı: İletiyi zehirli ileti alt sıraya taşımak için. Bu değer yalnızca Windows Vista'da kullanılabilir.

  • Reddet: İletiyi reddetmek için iletiyi gönderenin teslim edilemeyen ileti kuyruğuna geri gönderin. Bu değer yalnızca Windows Vista'da kullanılabilir.

Örnek, zehirli iletinin Move edatını kullanmayı gösterir. Move , iletinin zehirli alt sıraya taşınmasına neden olur.

Hizmet sözleşmesi, IOrderProcessorkuyruklarla kullanıma uygun tek yönlü bir hizmeti tanımlayan şeklindedir.

[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public interface IOrderProcessor
{
    [OperationContract(IsOneWay = true)]
    void SubmitPurchaseOrder(PurchaseOrder po);
}

Hizmet işlemi, siparişi işlediğini belirten bir ileti görüntüler. Zehirli ileti işlevselliğini göstermek için hizmet işlemi, SubmitPurchaseOrder hizmetin rastgele çağrısında işlemi geri almak için bir özel durum oluşturur. Bu, iletinin kuyruğa geri alınmasına neden olur. Sonunda ileti zehir olarak işaretlenir. Yapılandırma, zehirli iletiyi zehirli alt sıraya taşıyacak şekilde ayarlanır.

// Service class that implements the service contract.
// Added code to write output to the console window.
public class OrderProcessorService : IOrderProcessor
{
    static Random r = new Random(137);

    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void SubmitPurchaseOrder(PurchaseOrder po)
    {

        int randomNumber = r.Next(10);

        if (randomNumber % 2 == 0)
        {
            Orders.Add(po);
            Console.WriteLine("Processing {0} ", po);
        }
        else
        {
            Console.WriteLine("Aborting transaction, cannot process purchase order: " + po.PONumber);
            Console.WriteLine();
            throw new Exception("Cannot process purchase order: " + po.PONumber);
        }
    }

    public static void OnServiceFaulted(object sender, EventArgs e)
    {
        Console.WriteLine("Service Faulted");
    }

    // Host the service within this EXE console application.
    public static void Main()
    {
        // Get MSMQ queue name from app settings in configuration.
        string queueName = ConfigurationManager.AppSettings["queueName"];

        // Create the transacted MSMQ queue if necessary.
        if (!System.Messaging.MessageQueue.Exists(queueName))
            System.Messaging.MessageQueue.Create(queueName, true);

        // Get the base address that is used to listen for WS-MetaDataExchange requests.
        // This is useful to generate a proxy for the client.
        string baseAddress = ConfigurationManager.AppSettings["baseAddress"];

        // Create a ServiceHost for the OrderProcessorService type.
        ServiceHost serviceHost = new ServiceHost(typeof(OrderProcessorService), new Uri(baseAddress));

        // Hook on to the service host faulted events.
        serviceHost.Faulted += new EventHandler(OnServiceFaulted);

        // Open the ServiceHostBase to create listeners and start listening for messages.
        serviceHost.Open();

        // The service can now be accessed.
        Console.WriteLine("The service is ready.");
        Console.WriteLine("Press <ENTER> to terminate service.");
        Console.WriteLine();
        Console.ReadLine();

        if(serviceHost.State != CommunicationState.Faulted) {
            serviceHost.Close();
        }

    }
}

Hizmet yapılandırması aşağıdaki zehirli ileti özelliklerini içerir: receiveRetryCount, maxRetryCycles, retryCycleDelayve receiveErrorHandling aşağıdaki yapılandırma dosyasında gösterildiği gibi.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <!-- Use appSetting to configure MSMQ queue name. -->
    <add key="queueName" value=".\private$\ServiceModelSamplesPoison" />
    <add key="baseAddress" value="http://localhost:8000/orderProcessor/poisonSample"/>
  </appSettings>
  <system.serviceModel>
    <services>
      <service
              name="Microsoft.ServiceModel.Samples.OrderProcessorService">
        <!-- Define NetMsmqEndpoint -->
        <endpoint address="net.msmq://localhost/private/ServiceModelSamplesPoison"
                  binding="netMsmqBinding"
                  bindingConfiguration="PoisonBinding"
                  contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />
      </service>
    </services>

    <bindings>
      <netMsmqBinding>
        <binding name="PoisonBinding"
                 receiveRetryCount="0"
                 maxRetryCycles="1"
                 retryCycleDelay="00:00:05"
                 receiveErrorHandling="Move">
        </binding>
      </netMsmqBinding>
    </bindings>
  </system.serviceModel>
</configuration>

Zehirli ileti kuyruğundan iletileri işleme

Zehirli ileti hizmeti, son zehirli ileti kuyruğundaki iletileri okur ve işler.

Zehirli ileti kuyruğundaki iletiler, zehirli ileti hizmet uç noktasından farklı olabilecek, iletiyi işleyen hizmete gönderilen iletilerdir. Bu nedenle, zehirli ileti hizmeti kuyruktan iletileri okuduğunda, WCF kanal katmanı uç noktalarda uyuşmazlığı bulur ve iletiyi göndermez. Bu durumda, ileti sipariş işleme hizmetine giderilir ancak zehirli ileti hizmeti tarafından alınır. İleti farklı bir uç noktaya adreslenmiş olsa bile iletiyi almaya devam etmek için, eşleşme ölçütlerinin iletinin ele alındığı herhangi bir hizmet uç noktasıyla eşleşeceği adresleri filtrelemek için bir ServiceBehavior eklememiz gerekir. Bu, zehirli ileti kuyruğundan okuduğunuz iletileri başarıyla işlemek için gereklidir.

Zehirli ileti hizmeti uygulamasının kendisi hizmet uygulamasına çok benzer. Sözleşmeyi uygular ve siparişleri işler. Kod örneği aşağıdaki gibidir.

// Service class that implements the service contract.
// Added code to write output to the console window.
[ServiceBehavior(AddressFilterMode=AddressFilterMode.Any)]
public class OrderProcessorService : IOrderProcessor
{
    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void SubmitPurchaseOrder(PurchaseOrder po)
    {
        Orders.Add(po);
        Console.WriteLine("Processing {0} ", po);
    }

    public static void OnServiceFaulted(object sender, EventArgs e)
    {
        Console.WriteLine("Service Faulted...exiting app");
        Environment.Exit(1);
    }

    // Host the service within this EXE console application.
    public static void Main()
    {

        // Create a ServiceHost for the OrderProcessorService type.
        ServiceHost serviceHost = new ServiceHost(typeof(OrderProcessorService));

        // Hook on to the service host faulted events.
        serviceHost.Faulted += new EventHandler(OnServiceFaulted);

        serviceHost.Open();

        // The service can now be accessed.
        Console.WriteLine("The poison message service is ready.");
        Console.WriteLine("Press <ENTER> to terminate service.");
        Console.WriteLine();
        Console.ReadLine();

        // Close the ServiceHostBase to shutdown the service.
        if(serviceHost.State != CommunicationState.Faulted)
        {
            serviceHost.Close();
        }
    }

Sipariş kuyruğundan iletileri okuyan sipariş işleme hizmetinden farklı olarak, zehirli ileti hizmeti zehirli alt sorgudaki iletileri okur. Zehir kuyruğu, ana kuyruğun bir alt sırasıdır, "zehir" olarak adlandırılır ve MSMQ tarafından otomatik olarak oluşturulur. Buna erişmek için, aşağıdaki örnek yapılandırmada gösterildiği gibi ana kuyruk adını ve ardından bir ";" ve alt sıra adını (bu örnekte -"poison" ) sağlayın.

Not

MSMQ v3.0 örneğinde zehir kuyruğu adı, iletiyi taşıdığımız kuyruk yerine bir alt kuyruk değildir.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="Microsoft.ServiceModel.Samples.OrderProcessorService">
        <!-- Define NetMsmqEndpoint -->
        <endpoint address="net.msmq://localhost/private/ServiceModelSamplesPoison;poison"
                  binding="netMsmqBinding"
                  contract="Microsoft.ServiceModel.Samples.IOrderProcessor" >
        </endpoint>
      </service>
    </services>

  </system.serviceModel>
</configuration>

Örneği çalıştırdığınızda, istemci, hizmet ve zehirli ileti hizmeti etkinlikleri konsol pencerelerinde görüntülenir. Hizmetin istemciden ileti aldığını görebilirsiniz. Hizmetleri kapatmak için her konsol penceresinde ENTER tuşuna basın.

Hizmet çalışmaya, siparişleri işlemeye başlar ve rastgele işlemeyi sonlandırmaya başlar. İleti siparişi işlediğini belirtiyorsa, hizmetin gerçekten bir iletiyi sonlandırdığını görene kadar istemciyi yeniden çalıştırarak başka bir ileti gönderebilirsiniz. Yapılandırılan zehir ayarlarına bağlı olarak, ileti son zehir kuyruğuna taşınmadan önce işlenmek üzere bir kez denendi.

The service is ready.
Press <ENTER> to terminate service.

Processing Purchase Order: 0f063b71-93e0-42a1-aa3b-bca6c7a89546
        Customer: somecustomer.com
        OrderDetails
                Order LineItem: 54 of Blue Widget @unit price: $29.99
                Order LineItem: 890 of Red Widget @unit price: $45.89
        Total cost of this order: $42461.56
        Order status: Pending

Processing Purchase Order: 5ef9a4fa-5a30-4175-b455-2fb1396095fa
        Customer: somecustomer.com
        OrderDetails
                Order LineItem: 54 of Blue Widget @unit price: $29.99
                Order LineItem: 890 of Red Widget @unit price: $45.89
        Total cost of this order: $42461.56
        Order status: Pending

Aborting transaction, cannot process purchase order: 23e0b991-fbf9-4438-a0e2-20adf93a4f89

Zehirli kuyruktan zehirli iletiyi okumak için zehirli ileti hizmetini başlatın. Bu örnekte zehirli ileti hizmeti iletiyi okur ve işler. Sonlandırılan ve zehirlenen satın alma siparişinin zehirli ileti hizmeti tarafından okunduğunu görebilirsiniz.

The service is ready.
Press <ENTER> to terminate service.

Processing Purchase Order: 23e0b991-fbf9-4438-a0e2-20adf93a4f89
        Customer: somecustomer.com
        OrderDetails
                Order LineItem: 54 of Blue Widget @unit price: $29.99
                Order LineItem: 890 of Red Widget @unit price: $45.89
        Total cost of this order: $42461.56
        Order status: Pending

Örneği ayarlamak, derlemek ve çalıştırmak için

  1. Windows Communication Foundation Örnekleri için Tek Seferlik Kurulum Yordamı'nı gerçekleştirdiğinizden emin olun.

  2. Hizmet önce çalıştırılırsa kuyruğun mevcut olduğundan emin olmak için denetler. Kuyruk yoksa, hizmet bir kuyruk oluşturur. Kuyruğu oluşturmak için önce hizmeti çalıştırabilir veya MSMQ Kuyruk Yöneticisi aracılığıyla bir kuyruk oluşturabilirsiniz. Windows 2008'de kuyruk oluşturmak için bu adımları izleyin.

    1. Visual Studio 2012'de Sunucu Yöneticisi açın.

    2. Özellikler sekmesini genişletin.

    3. Özel İleti Kuyrukları'ne sağ tıklayın ve Yeni, Özel Kuyruk'a tıklayın.

    4. İşlem kutusunu işaretleyin.

    5. Yeni kuyruğun adı olarak girin ServiceModelSamplesTransacted .

  3. Çözümün C# veya Visual Basic .NET sürümünü oluşturmak için Windows Communication Foundation Örnekleri Oluşturma başlığındaki yönergeleri izleyin.

  4. Örneği tek veya bilgisayarlar arası bir yapılandırmada çalıştırmak için, kuyruk adlarını localhost yerine gerçek konak adını yansıtacak şekilde değiştirin ve Windows Communication Foundation Örneklerini Çalıştırma başlığı altında yer alan yönergeleri izleyin.

Bağlama aktarımında netMsmqBinding varsayılan olarak güvenlik etkinleştirilir. ve olmak üzere MsmqAuthenticationModeMsmqProtectionLeveliki özellik, aktarım güvenliğinin türünü birlikte belirler. Varsayılan olarak, kimlik doğrulama modu olarak ve Windows koruma düzeyi olarak ayarlanır Sign. MSMQ'nun kimlik doğrulama ve imzalama özelliğini sağlaması için bir etki alanının parçası olması gerekir. Bu örneği etki alanının parçası olmayan bir bilgisayarda çalıştırırsanız şu hatayı alırsınız: "Kullanıcının iç ileti kuyruğa alma sertifikası yok".

Örneği çalışma grubuna katılmış bir bilgisayarda çalıştırmak için

  1. Bilgisayarınız bir etki alanının parçası değilse, aşağıdaki örnek yapılandırmada gösterildiği gibi kimlik doğrulama modunu ve koruma düzeyini None olarak ayarlayarak aktarım güvenliğini kapatın:

    <bindings>
        <netMsmqBinding>
            <binding name="TransactedBinding">
                <security mode="None"/>
            </binding>
        </netMsmqBinding>
    </bindings>
    

    Uç noktanın bindingConfiguration özniteliğini ayarlayarak uç noktanın bağlamayla ilişkilendirildiğinden emin olun.

  2. Örneği çalıştırmadan önce PoisonMessageServer, sunucu ve istemci üzerindeki yapılandırmayı değiştirdiğinizden emin olun.

    Not

    ayarı security modeNone, , MsmqProtectionLevelve Message güvenliğini olarak ayarlamakla MsmqAuthenticationModeNoneeşdeğerdir.

  3. Meta Veri Değişimi'nin çalışması için http bağlaması ile bir URL kaydederiz. Bunun için hizmetin yükseltilmiş bir komut penceresinde çalıştırılması gerekir. Aksi takdirde, şöyle bir özel durum alırsınız: Unhandled Exception: System.ServiceModel.AddressAccessDeniedException: HTTP could not register URL http://+:8000/ServiceModelSamples/service/. Your process does not have access rights to this namespace (see https://go.microsoft.com/fwlink/?LinkId=70353 for details). ---> System.Net.HttpListenerException: Access is denied.