Teslim Edilemeyen İletiler Sırası
DeadLetter örneği , teslim edilemeyen iletilerin nasıl işleneceğini ve işleneceğini gösterir. İşlem Yapılan MSMQ Bağlama örneğini temel alır. Bu örnek bağlamayı netMsmqBinding
kullanır. Hizmet, kuyruğa alınmış iletileri alan hizmeti gözlemlemenizi sağlayan şirket içinde barındırılan bir konsol uygulamasıdır.
Not
Bu örnek için kurulum yordamı ve derleme yönergeleri bu konunun sonunda yer alır.
Not
Bu örnek, yalnızca Windows Vista'da kullanılabilen her bir uygulama teslim edilemeyen ileti kuyruğunu gösterir. Örnek, Windows Server 2003 ve Windows XP'de MSMQ 3.0 için sistem genelindeki varsayılan kuyrukları kullanacak şekilde değiştirilebilir.
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.
Kuyruğa alınan iletişim belirli bir süre dormancy içerebileceğinden, iletinin süresi geçmişse uygulamaya teslim edilmediğinden emin olmak için iletideki yaşam süresi değerini ilişkilendirmek isteyebilirsiniz. Ayrıca, bir uygulamanın iletinin teslim edilemediği konusunda bilgilendirilmesi gereken durumlar da vardır. İletideki yaşam süresinin dolması veya iletinin teslim edilemediği durumlar gibi tüm bu durumlarda, ileti bir teslim edilemeyen ileti kuyruğuna alınır. Gönderen uygulama daha sonra teslim edilemeyen ileti kuyruğundaki iletileri okuyabilir ve hiçbir işlem yapılmadan başarısız teslimin nedenlerini düzeltmeye ve iletiyi yeniden göndermeye kadar değişen düzeltici eylemler gerçekleştirebilir.
Bağlamadaki NetMsmqBinding
teslim edilemeyen ileti kuyruğu aşağıdaki özelliklerde ifade edilir:
DeadLetterQueue özelliği, istemcinin gerektirdiği teslim edilemeyen ileti kuyruğu türünü ifade eder. Bu numaralandırma aşağıdaki değerlere sahiptir:
None
: İstemci için teslim edilemeyen ileti kuyruğu gerekmez.System
: Sistem teslim edilemeyen ileti kuyruğu, ölü iletileri depolamak için kullanılır. Sistem teslim edilemeyen ileti kuyruğu, bilgisayarda çalışan tüm uygulamalar tarafından paylaşılır.Custom
: Özelliği kullanılarak CustomDeadLetterQueue belirtilen özel bir teslim edilemeyen ileti kuyruğu, ölü iletileri depolamak için kullanılır. Bu özellik yalnızca Windows Vista'da kullanılabilir. Bu, uygulamanın aynı bilgisayarda çalışan diğer uygulamalarla paylaşmak yerine kendi teslim edilemeyen ileti kuyruğunu kullanması gerektiğinde kullanılır.CustomDeadLetterQueue özelliği, teslim edilemeyen bir kuyruk olarak kullanılacak belirli bir kuyruğu ifade eder. Bu yalnızca Windows Vista'da kullanılabilir.
Bu örnekte, istemci bir işlem kapsamından hizmete bir toplu ileti gönderir ve bu iletiler için rastgele olarak düşük bir "yaşam süresi" değeri (yaklaşık 2 saniye) belirtir. İstemci ayrıca süresi dolan iletileri sıralamak için kullanılacak özel bir teslim edilemeyen ileti kuyruğu belirtir.
İstemci uygulaması, teslim edilemeyen ileti kuyruğundaki iletileri okuyabilir ve iletiyi göndermeyi yeniden deneyebilir veya özgün iletinin teslim edilemeyen ileti kuyruğuna yerleştirilmesine ve iletiyi göndermesine neden olan hatayı düzeltebilir. Örnekte istemci bir hata iletisi görüntüler.
Hizmet sözleşmesi, aşağıdaki örnek kodda gösterildiği gibi şeklindedir IOrderProcessor
.
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public interface IOrderProcessor
{
[OperationContract(IsOneWay = true)]
void SubmitPurchaseOrder(PurchaseOrder po);
}
Örnekteki hizmet kodu, İşlem Yapılan MSMQ Bağlamasının kodudur.
Hizmetle iletişim bir işlem kapsamında gerçekleşir. Hizmet kuyruktan iletileri okur, işlemi gerçekleştirir ve işlemin sonuçlarını görüntüler. Uygulama ayrıca, teslim edilemeyen iletiler için bir teslim edilemeyen ileti kuyruğu oluşturur.
//The service contract is defined in generatedClient.cs, generated from the service by the svcutil tool.
//Client implementation code.
class Client
{
static void Main()
{
// Get MSMQ queue name from app settings in configuration
string deadLetterQueueName = ConfigurationManager.AppSettings["deadLetterQueueName"];
// Create the transacted MSMQ queue for storing dead message if necessary.
if (!MessageQueue.Exists(deadLetterQueueName))
MessageQueue.Create(deadLetterQueueName, true);
// Create a proxy with given client endpoint configuration
OrderProcessorClient client = new OrderProcessorClient("OrderProcessorEndpoint");
// Create the purchase order
PurchaseOrder po = new PurchaseOrder();
po.CustomerId = "somecustomer.com";
po.PONumber = Guid.NewGuid().ToString();
PurchaseOrderLineItem lineItem1 = new PurchaseOrderLineItem();
lineItem1.ProductId = "Blue Widget";
lineItem1.Quantity = 54;
lineItem1.UnitCost = 29.99F;
PurchaseOrderLineItem lineItem2 = new PurchaseOrderLineItem();
lineItem2.ProductId = "Red Widget";
lineItem2.Quantity = 890;
lineItem2.UnitCost = 45.89F;
po.orderLineItems = new PurchaseOrderLineItem[2];
po.orderLineItems[0] = lineItem1;
po.orderLineItems[1] = lineItem2;
//Create a transaction scope.
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
// Make a queued call to submit the purchase order
client.SubmitPurchaseOrder(po);
// Complete the transaction.
scope.Complete();
}
client.Close();
Console.WriteLine();
Console.WriteLine("Press <ENTER> to terminate client.");
Console.ReadLine();
}
}
İstemcinin yapılandırması, iletinin hizmete ulaşması için kısa bir süre belirtir. İleti belirtilen süre içinde iletilemezse, iletinin süresi dolar ve teslim edilemeyen ileti kuyruğuna taşınır.
Not
İstemcinin iletiyi belirtilen süre içinde hizmet kuyruğuna teslim etmek mümkündür. Teslim edilemeyen ileti hizmetini çalışır durumda gördüğünüzden emin olmak için, hizmeti başlatmadan önce istemciyi çalıştırmanız gerekir. İleti zaman aşımına uğradı ve teslim edilemeyen ileti hizmetine teslim edildi.
Uygulamanın hangi kuyruğun teslim edilemeyen ileti kuyruğu olarak kullanılacağını tanımlaması gerekir. Herhangi bir kuyruk belirtilmezse, sistem genelinde işlemsel teslim edilemeyen ileti kuyruğu, kullanılmayan iletileri kuyruğa almak için kullanılır. Bu örnekte, istemci uygulaması kendi uygulama teslim edilemeyen ileti kuyruğunu belirtir.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<!-- use appSetting to configure MSMQ Dead Letter queue name -->
<add key="deadLetterQueueName" value=".\private$\ServiceModelSamplesOrdersAppDLQ"/>
</appSettings>
<system.serviceModel>
<client>
<!-- Define NetMsmqEndpoint -->
<endpoint name="OrderProcessorEndpoint"
address="net.msmq://localhost/private/ServiceModelSamplesDeadLetter"
binding="netMsmqBinding"
bindingConfiguration="PerAppDLQBinding"
contract="IOrderProcessor" />
</client>
<bindings>
<netMsmqBinding>
<binding name="PerAppDLQBinding"
deadLetterQueue="Custom"
customDeadLetterQueue="net.msmq://localhost/private/ServiceModelSamplesOrdersAppDLQ"
timeToLive="00:00:02"/>
</netMsmqBinding>
</bindings>
</system.serviceModel>
</configuration>
Teslim edilemeyen ileti hizmeti, teslim edilemeyen ileti kuyruğundan iletileri okur. Teslim edilemeyen ileti hizmeti sözleşmeyi IOrderProcessor
uygular. Ancak uygulama, siparişleri işlemez. Teslim edilemeyen ileti hizmeti bir istemci hizmetidir ve siparişleri işlemek için gerekli tesise sahip değildir.
Not
Teslim edilemeyen ileti kuyruğu bir istemci kuyruğudur ve istemci kuyruğu yöneticisi için yereldir.
Teslim edilemeyen ileti hizmeti uygulaması, bir iletinin teslim edilemediğini denetler ve düzeltici önlemler alır. İleti hatasının nedeni, ve DeliveryStatusolmak üzere iki numaralandırmada yakalanırDeliveryFailure. aşağıdaki örnek kodda gösterildiği gibi 'den OperationContext öğesini alabilirsinizMsmqMessageProperty:
public void SubmitPurchaseOrder(PurchaseOrder po)
{
Console.WriteLine("Submitting purchase order did not succeed ", po);
MsmqMessageProperty mqProp =
OperationContext.Current.IncomingMessageProperties[
MsmqMessageProperty.Name] as MsmqMessageProperty;
Console.WriteLine("Message Delivery Status: {0} ",
mqProp.DeliveryStatus);
Console.WriteLine("Message Delivery Failure: {0}",
mqProp.DeliveryFailure);
Console.WriteLine();
…
}
Teslim edilemeyen ileti kuyruğundaki iletiler, iletiyi işleyen hizmete gönderilen iletilerdir. Bu nedenle, teslim edilemeyen ileti hizmeti kuyruktan iletileri okuduğunda, Windows Communication Foundation (WCF) kanal katmanı uç noktalarda uyuşmazlığı bulur ve iletiyi göndermez. Bu durumda, ileti sipariş işleme hizmetine gider, ancak teslim edilemeyen ileti hizmeti tarafından alınır. Farklı bir uç noktaya yönelik bir ileti almak için, içinde herhangi bir adresle eşleşecek bir adres filtresi belirtilir ServiceBehavior
. Bu, teslim edilemeyen ileti kuyruğundan okunan iletileri başarıyla işlemek için gereklidir.
Bu örnekte, başarısızlığın nedeni iletinin zaman aşımına uğraması ise, teslim edilemeyen ileti hizmeti iletiyi yeniden gönderir. Diğer tüm nedenlerle, aşağıdaki örnek kodda gösterildiği gibi teslim başarısızlığını görüntüler:
// Service class that implements the service contract.
// Added code to write output to the console window.
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Single, AddressFilterMode=AddressFilterMode.Any)]
public class PurchaseOrderDLQService : IOrderProcessor
{
OrderProcessorClient orderProcessorService;
public PurchaseOrderDLQService()
{
orderProcessorService = new OrderProcessorClient("OrderProcessorEndpoint");
}
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void SubmitPurchaseOrder(PurchaseOrder po)
{
Console.WriteLine("Submitting purchase order did not succeed ", po);
MsmqMessageProperty mqProp = OperationContext.Current.IncomingMessageProperties[MsmqMessageProperty.Name] as MsmqMessageProperty;
Console.WriteLine("Message Delivery Status: {0} ", mqProp.DeliveryStatus);
Console.WriteLine("Message Delivery Failure: {0}", mqProp.DeliveryFailure);
Console.WriteLine();
// resend the message if timed out
if (mqProp.DeliveryFailure == DeliveryFailure.ReachQueueTimeout ||
mqProp.DeliveryFailure == DeliveryFailure.ReceiveTimeout)
{
// re-send
Console.WriteLine("Purchase order Time To Live expired");
Console.WriteLine("Trying to resend the message");
// reuse the same transaction used to read the message from dlq to enqueue the message to app. queue
orderProcessorService.SubmitPurchaseOrder(po);
Console.WriteLine("Purchase order resent");
}
}
// Host the service within this EXE console application.
public static void Main()
{
// Create a ServiceHost for the PurchaseOrderDLQService type.
using (ServiceHost serviceHost = new ServiceHost(typeof(PurchaseOrderDLQService)))
{
// Open the ServiceHostBase to create listeners and start listening for messages.
serviceHost.Open();
// The service can now be accessed.
Console.WriteLine("The dead letter service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
}
}
}
Aşağıdaki örnek, bir teslim edilemeyen iletinin yapılandırmasını gösterir:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service
name="Microsoft.ServiceModel.Samples.PurchaseOrderDLQService">
<!-- Define NetMsmqEndpoint in this case, DLQ end point to read messages-->
<endpoint address="net.msmq://localhost/private/ServiceModelSamplesOrdersAppDLQ"
binding="netMsmqBinding"
bindingConfiguration="DefaultBinding"
contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />
</service>
</services>
<client>
<!-- Define NetMsmqEndpoint -->
<endpoint name="OrderProcessorEndpoint"
address="net.msmq://localhost/private/ServiceModelSamplesDeadLetter"
binding="netMsmqBinding"
bindingConfiguration="SystemDLQBinding"
contract="IOrderProcessor" />
</client>
<bindings>
<netMsmqBinding>
<binding name="DefaultBinding" />
<binding name="SystemDLQBinding"
deadLetterQueue="System"/>
</netMsmqBinding>
</bindings>
</system.serviceModel>
</configuration>
Örneği çalıştırırken, her uygulama için teslim edilemeyen ileti kuyruğunun nasıl çalıştığını görmek için çalıştırılacak 3 yürütülebilir dosya vardır; her uygulama için teslim edilemeyen ileti kuyruğundan okuyan ve iletiyi hizmete yeniden gönderebilen istemci, hizmet ve teslim edilemeyen bir hizmet. Tümü konsol pencerelerinde çıkışı olan konsol uygulamalarıdır.
Not
Kuyruğa alma kullanımda olduğundan istemci ve hizmetin aynı anda çalışır durumda olması gerekmez. İstemciyi çalıştırabilir, kapatabilir, ardından hizmeti başlatabilir ve yine de iletilerini alabilirsiniz. Kuyruğun oluşturulabilmesi için hizmeti başlatmanız ve kapatmanız gerekir.
İstemciyi çalıştırırken istemci şu iletiyi görüntüler:
Press <ENTER> to terminate client.
İstemci iletiyi göndermeye çalıştı, ancak kısa bir zaman aşımıyla iletinin süresi doldu ve artık her uygulama için teslim edilemeyen ileti kuyruğunda sıraya alındı.
Ardından, iletiyi okuyan ve hata kodunu görüntüleyen ve iletiyi hizmete yeniden göndererek teslim edilemeyen ileti hizmetini çalıştırırsınız.
The dead letter service is ready.
Press <ENTER> to terminate service.
Submitting purchase order did not succeed
Message Delivery Status: InDoubt
Message Delivery Failure: ReachQueueTimeout
Purchase order Time To Live expired
Trying to resend the message
Purchase order resent
Hizmet başlatılır, sonra yeniden alınan ileti okunur ve işlenir.
The service is ready.
Press <ENTER> to terminate service.
Processing Purchase Order: 97897eff-f926-4057-a32b-af8fb11b9bf9
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
Windows Communication Foundation Örnekleri için Tek Seferlik Kurulum Yordamı'nı gerçekleştirdiğinizden emin olun.
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.
Visual Studio 2012'de Sunucu Yöneticisi açın.
Özellikler sekmesini genişletin.
Özel İleti Kuyrukları'ne sağ tıklayın ve Yeni, Özel Kuyruk'a tıklayın.
İşlem kutusunu işaretleyin.
Yeni kuyruğun adı olarak girin
ServiceModelSamplesTransacted
.
Çö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.
Örneği tek veya bilgisayarlar arası bir yapılandırmada çalıştırmak için sıra adlarını uygun şekilde değiştirin, localhost yerine bilgisayarın tam adını yazın ve Windows Communication Foundation Örneklerini Çalıştırma başlığı altında yer alan yönergeleri izleyin.
Örneği çalışma grubuna katılmış bir bilgisayarda çalıştırmak için
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 özniteliğini ayarlayarak uç noktanın
bindingConfiguration
bağlamayla ilişkilendirildiğinden emin olun.Örneği çalıştırmadan önce DeadLetterService, sunucu ve istemci üzerindeki yapılandırmayı değiştirdiğinizden emin olun.
Not
ayarı
security mode
None
, ayarınaMsmqProtectionLevel
veMessage
güvenliği olarak ayarlamaklaMsmqAuthenticationMode
None
eşdeğerdir.
Açıklamalar
Bağlama aktarımında netMsmqBinding
varsayılan olarak güvenlik etkinleştirilir. ve olmak üzere MsmqAuthenticationMode
MsmqProtectionLevel
iki ö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 Sign
ayarlanır. 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".