{"id":4344,"date":"2023-03-18T00:58:07","date_gmt":"2023-03-17T23:58:07","guid":{"rendered":"https:\/\/gokhan-gokalp.com\/?p=4344"},"modified":"2023-03-18T20:57:03","modified_gmt":"2023-03-18T19:57:03","slug":"how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers","status":"publish","type":"post","link":"https:\/\/gokhan-gokalp.com\/tr\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\/","title":{"rendered":"Azure Service Bus Kullanarak Microservice\u2019lerde Event\u2019ler Nas\u0131l S\u0131ralan\u0131r (FIFO Consumers)"},"content":{"rendered":"<p>Bazen baz\u0131 senaryolar vard\u0131r karma\u015f\u0131kl\u0131\u011f\u0131n\u0131 veya eksi yanlar\u0131n\u0131 bildi\u011fimiz halde implemente etmekten ka\u00e7amad\u0131\u011f\u0131m\u0131z veya implemente etme zorunda kald\u0131\u011f\u0131m\u0131z. Distributed ortamlarda birbirlerine ba\u011fl\u0131 baz\u0131 event&#8217;leri\/message&#8217;lar\u0131 <strong>belirli bir s\u0131ra<\/strong> (publish edildikleri) i\u00e7erisinde i\u015fleyebilmek de bence bunlardan birisi. \u00d6rne\u011fin batch processing yap\u0131yor ve her bir item&#8217;\u0131 belirli bir s\u0131ra i\u00e7erisinde i\u015flememiz gerekiyor olabilir veya bir e-ticaret firmas\u0131n\u0131n fulfillment domain&#8217;inde \u00e7al\u0131\u015f\u0131yor olabilir ve sipari\u015flerin stat\u00fcslerini do\u011fru g\u00fcncelleyebilmek i\u00e7in ilgili event&#8217;leri ger\u00e7ekle\u015fen s\u0131ralar\u0131yla i\u015flememiz gerekiyor olabilir.<\/p>\n<p>Bir \u00e7ok message broker&#8217;\u0131n <em><strong>FIFO<\/strong><\/em> prensibi ile \u00e7al\u0131\u015ft\u0131\u011f\u0131n\u0131 ve normal \u015fartlarda <em>FIFO<\/em> ordering&#8217;i sa\u011flad\u0131klar\u0131n\u0131 d\u00fc\u015f\u00fcn\u00fcrsek, bir publisher ve bir subscriber&#8217;a sahip olarak birbirine ba\u011fl\u0131 baz\u0131 event&#8217;leri publish edildikleri s\u0131ra i\u00e7erisinde kolayl\u0131kla consume edebiliriz. Tabi event i\u015fleme s\u0131ras\u0131nda olu\u015fabilecek network veya uygulama kaynakl\u0131 hatalar\u0131 saymazsak. \u00d6rne\u011fin ge\u00e7ici bir hata y\u00fcz\u00fcnden ilgili event kolayl\u0131kla re-queue olabilir ve ilgili s\u0131ray\u0131 bozabilir veya message broker i\u015flenmi\u015f bir event i\u00e7in yine ge\u00e7ici bir hatadan dolay\u0131 ack bilgisini alamaz ve ilgili event&#8217;i tekrar i\u015flenmeye uygun hale getirebilir ve duplication&#8217;lar olu\u015fturabilir. Alternatif \u00e7\u00f6z\u00fcm olarak event&#8217;ler i\u00e7erisine bir timestamp dahil etmeyi de d\u00fc\u015f\u00fcnebilir ve gerekli kontrolleri ger\u00e7ekle\u015ftirdikten sonra i\u015fleme i\u015flemini ger\u00e7ekle\u015ftirebiliriz. Maalesef bu sefer de race-condition gibi farkl\u0131 problemler ile ba\u015fa \u00e7\u0131kmam\u0131z gerekecektir. Teknik olarak elbette olu\u015fabilecek bu tarz hatalar\u0131 da ele alabilir ve event i\u015fleme s\u0131ras\u0131n\u0131 koruyabilmek ad\u0131na farkl\u0131 logic&#8217;ler kodlayabiliriz. Fakat g\u00f6rd\u00fc\u011f\u00fcm\u00fcz gibi event ordering standart <em>FIFO<\/em> queue&#8217;lar ile kolay eri\u015filebilir gibi g\u00f6r\u00fcnmesine ra\u011fmen, subscriber taraf\u0131nda herhangi bir garanti olmad\u0131\u011f\u0131 i\u00e7in i\u015fler karma\u015f\u0131kla\u015fmaya ba\u015fl\u0131yor.<\/p>\n<p>Daha da \u00f6tesi tek bir subscriber gereklili\u011fi y\u00fcz\u00fcnden <strong>scalability <\/strong>ve <strong>decoupling<\/strong> gibi \u00f6nemli prensipleri de kaybediyor ve genel throughput&#8217;dan fedakarl\u0131k ediyor olaca\u011f\u0131z.<\/p>\n<p>Dolay\u0131s\u0131yla sistemimizi, architecture&#8217;\u0131m\u0131z\u0131 veya event payload&#8217;lar\u0131m\u0131za design ederken bu tarz operasyonlara gerek olmayacak \u015fekilde design etmemiz veya en az\u0131ndan minimuma indirgememiz, ileriye y\u00f6nelik sistemimizin sa\u011fl\u0131\u011f\u0131 a\u00e7\u0131s\u0131ndan olduk\u00e7a \u00f6nem ta\u015f\u0131maktad\u0131r.<\/p>\n<p>Peki, event ordering&#8217;e ihtiyac\u0131m\u0131z oldu\u011funda ve implemente etme durumunda kald\u0131\u011f\u0131m\u0131zda ne yapaca\u011f\u0131z? Bu makale kapsam\u0131nda ise en verimli bi \u015fekilde bu i\u015flemi <em><strong>Azure Service Bus<\/strong><\/em> kullanarak nas\u0131l ger\u00e7ekle\u015ftirebilece\u011fimize de\u011finece\u011fim. Dolays\u0131yla message broker olarak <em>Azure Service Bus<\/em> kulland\u0131\u011f\u0131m\u0131z\u0131 varsayaca\u011f\u0131m ve bu konuda bizlere <em>Azure Service Bus<\/em>&#8216;\u0131n sunmu\u015f oldu\u011fu &#8220;<strong>sessions<\/strong>&#8221; \u00f6zelli\u011finin nas\u0131l yard\u0131mc\u0131 olabilece\u011fine bir bakaca\u011f\u0131z.<\/p>\n<h2>Azure Service Bus &#8211; Sessions<\/h2>\n<p>Normal \u015fartlarda <em>FIFO<\/em> event delivery garantisi sa\u011flayan bir message broker kullan\u0131yorsak, bir publisher ve bir subscriber&#8217;a sahip olarak birbirine ba\u011fl\u0131 baz\u0131 event&#8217;leri publish edildikleri s\u0131ra i\u00e7erisinde consume edebilece\u011fimizi s\u00f6yledik. Fakat subscriber taraf\u0131nda herhangi bir garanti olmad\u0131\u011f\u0131 i\u00e7in bu yakla\u015f\u0131m\u0131n ne kadar k\u0131r\u0131lgan ve karma\u015f\u0131k olabilece\u011finden de bahsettik. Peki bu <em>FIFO<\/em> event delivery garantisini en kolay yoldan subscriber taraf\u0131 i\u00e7in de nas\u0131l sa\u011flayabiliriz?<\/p>\n<p>\u0130\u015fte tam da bu noktada <em>Azure Service Bus<\/em>&#8216;\u0131n<strong><em> sessions<\/em><\/strong> \u00f6zelli\u011fi devreye girmekte. Sessions&#8217;lar\u0131 kullanarak istedi\u011fimiz event&#8217;leri belirleyece\u011fimiz bir &#8220;<em>SessionId<\/em>&#8221; ile etiketleyerek, ilgili event&#8217;lerin bir grup halinde ve publish edildikleri s\u0131ra i\u00e7erisinde i\u015flenebilmelerini sa\u011flayabiliriz. Ayr\u0131ca bu i\u015flemi scalability prensibinden de k\u0131smen fazla \u00f6d\u00fcn vermeden ger\u00e7ekle\u015ftirebilmekteyiz.<\/p>\n<h3>Peki nas\u0131l?<\/h3>\n<figure id=\"attachment_4349\" aria-describedby=\"caption-attachment-4349\" style=\"width: 788px\" class=\"wp-caption aligncenter\"><a href=\"\/wp-content\/uploads\/2023\/03\/azure-service-bus-sessions.png\"><img decoding=\"async\" class=\"wp-image-4349 size-full lazyload\" data-src=\"\/wp-content\/uploads\/2023\/03\/azure-service-bus-sessions.png\" alt=\"\" width=\"788\" height=\"443\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2023\/03\/azure-service-bus-sessions.png 788w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2023\/03\/azure-service-bus-sessions-300x169.png 300w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2023\/03\/azure-service-bus-sessions-768x432.png 768w\" data-sizes=\"(max-width: 788px) 100vw, 788px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 788px; --smush-placeholder-aspect-ratio: 788\/443;\" \/><\/a><figcaption id=\"caption-attachment-4349\" class=\"wp-caption-text\">Ref: https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2019\/09\/word-image.png<\/figcaption><\/figure>\n<p>\u00d6ncelikle bu \u00f6zelli\u011fi kullanabilmek i\u00e7in, <em>Azure Service Bus<\/em>&#8216;\u0131n &#8220;<em>Standard<\/em>&#8221; veya &#8220;<em>Premium<\/em>&#8221; se\u00e7eneklerinden birisini kullan\u0131yor olmam\u0131z gerekmektedir. <em>Azure Service Bus<\/em> \u00fczerinde bir &#8220;<em>queue<\/em>&#8221; veya &#8220;<em>subscription<\/em>&#8221; olu\u015ftururken, message sessions \u00f6zelli\u011fini de aktifle\u015ftirmemiz gerekmektedir. Aktifle\u015ftirme i\u015flemi i\u00e7in <em><a href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/service-bus-messaging\/enable-message-sessions#using-azure-portal\" target=\"_blank\" rel=\"noopener\">buraya<\/a><\/em> g\u00f6z atabilirsiniz.<\/p>\n<blockquote><p><em><strong>NOT<\/strong><\/em>: Sessions&#8217;\u0131n etkinle\u015ftirildi\u011fi queue&#8217;larda t\u00fcm event&#8217;ler bir session id&#8217;si i\u00e7ermesi gerekmektedir.<\/p><\/blockquote>\n<p>Sessions&#8217;\u0131n \u00e7al\u0131\u015fma mant\u0131\u011f\u0131n\u0131 k\u0131saca \u00f6zetlemek gerekirse, event&#8217;ler publish edilirken bir session id&#8217;si ile publish edilmektedir. \u00d6rne\u011fin bir sipari\u015f id&#8217;si. Daha sonra herhangi bir subscriber ilgili queue&#8217;dan hen\u00fcz \u00fczerinde lock bulunmayan bir event&#8217;i al\u0131r ve i\u015fleyebilmek i\u00e7in \u00f6ncelikle o event&#8217;in session id&#8217;si i\u00e7in bir lock i\u015flemi ger\u00e7ekle\u015ftirir. B\u00f6ylelikle queue&#8217;daki ayn\u0131 session id&#8217;sine sahip t\u00fcm event&#8217;ler, lock&#8217;\u0131 tutan subscriber taraf\u0131ndan tek tek publish edildikleri s\u0131ra i\u00e7erisinde i\u015flenebilmektedir. Ayr\u0131ca bu noktada tek bir subscriber&#8217;a sahip olma zorunlulu\u011fumuz da bulunmamaktad\u0131r. Elbette <strong>bir session<\/strong> alt\u0131ndaki event&#8217;leri i\u015flerken paralellikten fedakarl\u0131k etmi\u015f olmaktay\u0131z, fakat <strong>farkl\u0131 session&#8217;lar<\/strong> alt\u0131ndaki ayn\u0131 event&#8217;leri paralel olarak i\u015fleyebilmekteyiz.<\/p>\n<h2>Bir \u00d6rnek Ger\u00e7ekle\u015ftirelim<\/h2>\n<p>Konuyu daha iyi anlayabilmek ad\u0131na basit bir \u00f6rnek ger\u00e7ekle\u015ftirelim. Bir e-ticaret firmas\u0131nda \u00e7al\u0131\u015ft\u0131\u011f\u0131m\u0131z\u0131 varsayal\u0131m ve bir sipari\u015fin m\u00fc\u015fteriye teslim edilene kadar olan stat\u00fcs de\u011fi\u015fikliklerini m\u00fc\u015fteriye g\u00f6stermek istiyoruz.<\/p>\n<p>\u00d6ncelikle <em><strong>Contracts<\/strong><\/em> ad\u0131nda bir .<em>NET 7<\/em> class library projesi olu\u015ftural\u0131m ve i\u00e7erisine a\u015fa\u011f\u0131daki gibi &#8220;<em>OrderStatusChangedEvent<\/em>&#8221; ad\u0131nda bir event tan\u0131mlayal\u0131m.<\/p>\n<pre>namespace Contracts;\r\n\r\npublic class OrderStatusChangedEvent\r\n{\r\n    public OrderStatusChangedEvent(string orderId, string status, DateTime changeDate)\r\n    {\r\n        OrderId = orderId;\r\n        Status = status;\r\n        ChangeDate = changeDate;\r\n    }\r\n\r\n    public string OrderId { get; set; }\r\n    public string Status { get; set; }\r\n    public DateTime ChangeDate { get; set; }\r\n}<\/pre>\n<p>Bu event ile ilgili sipari\u015f \u00f6zelindeki stat\u00fcs de\u011fi\u015fikliklerini publish etti\u011fimizi ve a\u015fa\u011f\u0131daki gibi de stat\u00fcs&#8217;lere sahip oldu\u011fumuzu varsayal\u0131m.<\/p>\n<ul>\n<li>InPreparation<\/li>\n<li>Shipped<\/li>\n<li>DeliveryAttemptFailed<\/li>\n<li>DeliveredToPickupPoint<\/li>\n<li>Completed<\/li>\n<\/ul>\n<h3>Event&#8217;leri Publish Edelim<\/h3>\n<p>\u015eimdi ilgili event&#8217;leri publish edece\u011fimiz basit bir publisher olu\u015ftural\u0131m. Bunun i\u00e7in <em><strong>Publisher<\/strong><\/em> ad\u0131nda bir <em>.NET 7<\/em> console application&#8217;\u0131 olu\u015ftural\u0131m ve i\u00e7erisine <em>NuGet<\/em> \u00fczerinden &#8220;<em>Azure.Messaging.ServiceBus<\/em>&#8221; paketini dahil edelim. Ard\u0131ndan <em><strong>Contracts<\/strong><\/em> projesini de referans olarak ekleyelim.<\/p>\n<p>\u015eimdi &#8220;<em>Program.cs<\/em>&#8221; class&#8217;\u0131n\u0131 a\u015fa\u011f\u0131daki gibi d\u00fczenleyelim.<\/p>\n<pre>using Azure.Messaging.ServiceBus;\r\nusing Contracts;\r\n\r\nvar connectionString = \"Endpoint=sb:\/\/YOUR_SERVICE_BUS.servicebus.windows.net\/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=YOUR_SHAREDACCESSKEY\";\r\nvar queueName = \"order.status.queue\";\r\n\r\nawait using var serviceBusClient = new ServiceBusClient(connectionString);\r\nServiceBusSender serviceBusSender = serviceBusClient.CreateSender(queueName);\r\n\r\nvar orderId = Guid.NewGuid().ToString();\r\n\r\n\/\/ ------------------- Order status: In Preparation -------------------\r\nvar orderStatusChangedToInPreparationEvent = new OrderStatusChangedEvent(\r\n    orderId: orderId,\r\n    status: \"InPreparation\",\r\n    changeDate: DateTime.UtcNow);\r\n\r\nvar orderStatusChangedToInPreparationMessage = new ServiceBusMessage(BinaryData.FromObjectAsJson(orderStatusChangedToInPreparationEvent))\r\n{\r\n    SessionId = orderId\r\n};\r\nawait serviceBusSender.SendMessageAsync(orderStatusChangedToInPreparationMessage);\r\n\r\n\r\n\/\/ ------------------- Order status: Shipped -------------------\r\nvar orderStatusChangedToShippedEvent = new OrderStatusChangedEvent(\r\n    orderId: orderId,\r\n    status: \"Shipped\",\r\n    changeDate: DateTime.UtcNow);\r\n\r\nvar orderStatusChangedToShippedMessage = new ServiceBusMessage(BinaryData.FromObjectAsJson(orderStatusChangedToShippedEvent))\r\n{\r\n    SessionId = orderId\r\n};\r\nawait serviceBusSender.SendMessageAsync(orderStatusChangedToShippedMessage);\r\n\r\n\r\n\/\/ ------------------- Order status: Delivery Attempt Failed -------------------\r\nvar orderStatusChangedToDeliveryAttemptFailedEvent = new OrderStatusChangedEvent(\r\n    orderId: orderId,\r\n    status: \"DeliveryAttemptFailed\",\r\n    changeDate: DateTime.UtcNow);\r\n\r\nvar orderStatusChangedToDeliveryAttemptFailedMessage = new ServiceBusMessage(BinaryData.FromObjectAsJson(orderStatusChangedToDeliveryAttemptFailedEvent))\r\n{\r\n    SessionId = orderId\r\n};\r\nawait serviceBusSender.SendMessageAsync(orderStatusChangedToDeliveryAttemptFailedMessage);\r\n\r\n\r\n\/\/ ------------------- Order status: Delivered to Pickup Point -------------------\r\nvar orderStatusChangedToDeliveredToPickupPointEvent = new OrderStatusChangedEvent(\r\n    orderId: orderId,\r\n    status: \"DeliveredToPickupPoint\",\r\n    changeDate: DateTime.UtcNow);\r\n\r\nvar orderStatusChangedToDeliveredToPickupPointMessage = new ServiceBusMessage(BinaryData.FromObjectAsJson(orderStatusChangedToDeliveredToPickupPointEvent))\r\n{\r\n    SessionId = orderId\r\n};\r\nawait serviceBusSender.SendMessageAsync(orderStatusChangedToDeliveredToPickupPointMessage);\r\n\r\n\r\n\/\/ ------------------- Order status: Completed -------------------\r\nvar orderStatusChangedToCompletedEvent = new OrderStatusChangedEvent(\r\n    orderId: orderId,\r\n    status: \"Completed\",\r\n    changeDate: DateTime.UtcNow);\r\n\r\nvar orderStatusChangedToCompletedMessage = new ServiceBusMessage(BinaryData.FromObjectAsJson(orderStatusChangedToCompletedEvent))\r\n{\r\n    SessionId = orderId,\r\n};\r\norderStatusChangedToCompletedMessage.ApplicationProperties.Add(\"IsLastItem\", true);\r\n\r\nawait serviceBusSender.SendMessageAsync(orderStatusChangedToCompletedMessage);<\/pre>\n<p>Burada basit olarak bize gelen bilgiler do\u011frultusunda ilgil sipari\u015f&#8217;e ait stat\u00fcs de\u011fi\u015fikliklerini s\u0131ras\u0131yla publish etti\u011fimizi varsay\u0131yoruz.<\/p>\n<p>Teknik olarak konu\u015fursak &#8220;<em>ServiceBusClient<\/em>&#8221; ve ard\u0131ndan &#8220;<em>ServiceBusSender<\/em>&#8221; objelerini ilgili queue bilgisini belirterek initialize ediyoruz. Ard\u0131ndan event&#8217;leri publish etti\u011fimiz s\u0131rada subscriber taraf\u0131nda i\u015fleyebilmek i\u00e7in ise, onlar\u0131 bir session id alt\u0131nda topluyoruz. Session id&#8217;si olarak ise burada, ilgili sipari\u015f&#8217;in id bilgisini kulland\u0131k.<\/p>\n<p>Burada \u00f6nemli nokta ise, ilgili session&#8217;\u0131n ne zaman bitece\u011fi bilgisini kendi kontrol\u00fcm\u00fcz alt\u0131nda sa\u011flamak. Bu i\u015flemi ise en son publish edecek oldu\u011fumuz event&#8217;e ekleyece\u011fimiz bir property ile sa\u011flayabilmekteyiz. \u00c7\u00fcnk\u00fc bir subscriber bir session&#8217;\u0131 kabul ettikten ve ilgili session alt\u0131ndaki event&#8217;leri i\u015flemeyi tamamlad\u0131ktan sonra tekrardan farkl\u0131 session&#8217;lar kabul edebilmesi i\u00e7in, kabul etmi\u015f oldu\u011fu session&#8217;\u0131 \u00f6ncelikle release etmesi gerekmektedir. Ger\u00e7ekle\u015ftirmi\u015f oldu\u011fumuz \u00f6rnekte ise sonuncu event&#8217;e eklemi\u015f oldu\u011fumuz &#8220;<em>IsLastItem<\/em>&#8221; property&#8217;si ile session&#8217;\u0131n release edilme i\u015flemini subscriber taraf\u0131nda ger\u00e7ekle\u015ftirece\u011fiz.<\/p>\n<p>Elbette bir subscriber paralel olarak birden \u00e7ok session&#8217;\u0131 i\u015fleyebilmektedir fakat release etmedi\u011fimiz session&#8217;lar, subscriber&#8217;\u0131n paralel olarak maksimum i\u015fleyebilecek oldu\u011fu session limitini olumsuz olarak etkileyecektir.<\/p>\n<h3>\u015eimdi \u0130\u015fleyelim<\/h3>\n<p>\u015eimdi subscriber taraf\u0131na bir g\u00f6z atal\u0131m. Bunun i\u00e7in de <em><strong>Subscriber<\/strong><\/em> ad\u0131nda bir <em>.NET 7<\/em> console application&#8217;\u0131 olu\u015ftural\u0131m ve yine <em>NuGet<\/em> \u00fczerinden &#8220;<em>Azure.Messaging.ServiceBus<\/em>&#8221; paketini dahil edelim. Ard\u0131ndan <em><strong>Contracts<\/strong><\/em> projesini yine referans olarak ekleyelim.<\/p>\n<p>Ard\u0131ndan &#8220;<em>Program.cs<\/em>&#8221; class&#8217;\u0131n\u0131 a\u015fa\u011f\u0131daki gibi d\u00fczenleyelim.<\/p>\n<pre>using Azure.Messaging.ServiceBus;\r\nusing Contracts;\r\n\r\nvar connectionString = \"Endpoint=sb:\/\/YOUR_SERVICE_BUS.servicebus.windows.net\/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=YOUR_SHAREDACCESSKEY\";\r\nvar queueName = \"order.status.queue\";\r\n\r\nawait using var serviceBusClient = new ServiceBusClient(connectionString);\r\nawait using ServiceBusSessionProcessor sessionProcessor = serviceBusClient.CreateSessionProcessor(queueName);\r\n\r\nsessionProcessor.ProcessMessageAsync += ProcessMessages;\r\nsessionProcessor.ProcessErrorAsync += ProcessErrors;\r\n\r\nTask ProcessMessages (ProcessSessionMessageEventArgs args)\r\n{\r\n    var orderStatusChangedEvent = args.Message.Body.ToObjectFromJson&lt;OrderStatusChangedEvent&gt;();\r\n\r\n    Console.WriteLine($\"Session ID: {args.SessionId}\\nOrder ID: {orderStatusChangedEvent?.OrderId}\\nStatus: {orderStatusChangedEvent?.Status}\\nChanged Date: {orderStatusChangedEvent?.ChangeDate}\");\r\n    Console.WriteLine(\"------------------------------\");\r\n\r\n    var appProperties = args.Message.ApplicationProperties;\r\n    if (appProperties != null &amp;&amp; appProperties.TryGetValue(\"IsLastItem\", out var isLastItem))\r\n    {\r\n        if ((bool)isLastItem)\r\n        {\r\n            Console.WriteLine(\"Session closed\");\r\n            args.ReleaseSession();\r\n        }\r\n    }\r\n\r\n    return Task.CompletedTask;\r\n}\r\n\r\nTask ProcessErrors(ProcessErrorEventArgs args)\r\n{\r\n    Console.WriteLine(\"There is an error!\");\r\n    \r\n    return Task.CompletedTask;\r\n}\r\n\r\nawait sessionProcessor.StartProcessingAsync();\r\nConsole.ReadKey();<\/pre>\n<p>Burada \u00f6ncelikle &#8220;<em>ServiceBusSender<\/em>&#8221; yerine &#8220;<em>ServiceBusSessionProcessor<\/em>&#8221; objesini initialise ediyoruz. Ard\u0131ndan event&#8217;leri i\u015fleyebilmek i\u00e7in &#8220;<em>ProcessMessageAsync<\/em>&#8221; ve &#8220;<em>ProcessErrorAsync<\/em>&#8221; event&#8217;lerini tan\u0131ml\u0131yoruz.<\/p>\n<p>Subscriber bu noktada &#8220;<em>order.status.queue<\/em>&#8221; i\u00e7erisinde bulunan ilk event&#8217;i kabul ederek, ilgili session id&#8217;si i\u00e7in bir <strong>lock<\/strong> tutacakt\u0131r. \u0130lgili session boyunca ise session i\u00e7erisinde bulunan event&#8217;leri publish edildikleri s\u0131ra do\u011frultusunda alarak, i\u015fleme i\u015flemini ger\u00e7ekle\u015ftirecektir. Subscriber&#8217;\u0131n ilgili session \u00f6zelinde tuttu\u011fu lock sayesinde de ilgili session alt\u0131ndaki event&#8217;ler, di\u011fer subscriber&#8217;lar taraf\u0131ndan al\u0131namayacak ve event&#8217;lerin <strong>s\u0131ralar\u0131<\/strong> korunarak birer birer i\u015flenmesi sa\u011flanacakt\u0131r.<\/p>\n<p>Default lock modu ise &#8220;<em>PeekLock<\/em>&#8221; d\u0131r. B\u00f6ylece ilgili event, session boyunca ba\u015far\u0131yla i\u015flenmeden queue&#8217;dan silinmeyecektir ve ayr\u0131ca default olarak ack bilgisi otomatik \u015fekilde <em>Azure<\/em> <em>Service Bus<\/em>&#8216;a g\u00f6nderilecektir. E\u011fer bu i\u015flemi manuel olarak kendi kontrol\u00fcm\u00fcz alt\u0131nda ger\u00e7ekle\u015ftirmek istiyorsak da, &#8220;<em>ServiceBusSessionProcessor<\/em>&#8221; objesini initialize ederken a\u015fa\u011f\u0131daki gibi &#8220;<em>AutoCompleteMessages<\/em>&#8221; property&#8217;sini &#8220;<em>false<\/em>&#8221; set etmemiz yeterli olacakt\u0131r.<\/p>\n<pre>var options = new ServiceBusSessionProcessorOptions()\r\n{\r\n    AutoCompleteMessages = false\r\n};\r\nawait using ServiceBusSessionProcessor sessionProcessor = serviceBusClient.CreateSessionProcessor(queueName, options);<\/pre>\n<p>Ard\u0131ndan ilgili event&#8217;i i\u015fledikten sonra a\u015fa\u011f\u0131daki gibi event&#8217;i i\u015fledi\u011fimiz bilgisini kendimiz broker&#8217;a bildirebiliriz.<\/p>\n<pre>await args.CompleteMessageAsync();<\/pre>\n<p>&#8220;<em>ReceiveAndDelete<\/em>&#8221; lock modun da ise ilgili event, ilgili subscriber taraf\u0131ndan kabul edildikten sonra hemen ilgili queue&#8217;dan silinmektedir. Herhangi bir hata an\u0131nda ilgili event&#8217;i kaybetme riski oldu\u011fu i\u00e7in a\u00e7\u0131kcas\u0131 riskli bir yakla\u015f\u0131m.<\/p>\n<p>Ek olarak lock s\u00fcrelerini ise ilgili queue&#8217;lar\u0131 olu\u015ftururken de belirleyebilmekteyiz. \u0130\u015fleyece\u011fimiz event&#8217;lerin i\u015fleme s\u00fcreleri genellikle uzun olacaksa, en az\u0131ndan kendimizi garantiye alabilmek ad\u0131na ilgili lock s\u00fcrelerini uzatmam\u0131z ve yenilememiz faydam\u0131za olacakt\u0131r. Yenileme i\u015flemini ise &#8220;<em>args.RenewSessionLockAsync();<\/em>&#8221; method&#8217;unu \u00e7a\u011f\u0131rarak ger\u00e7ekle\u015ftirebiliriz. Aksi takdirde ilgili lock release edilerek farkl\u0131 subscriber&#8217;lar i\u00e7in de al\u0131nabilir hale getirilecektir.<\/p>\n<p>Ayr\u0131ca bu session i\u015flemleri <strong>broker seviyesinde<\/strong> ger\u00e7ekle\u015fti\u011fi i\u00e7in ilgili subscriber herhangi bir hatadan dolay\u0131 \u00e7al\u0131\u015famaz bir hale geldi\u011finde de, uygun subscriber&#8217;lardan bir tanesi ilgili session&#8217;\u0131 kabul edebilir ve event&#8217;leri ayn\u0131 s\u0131ralar\u0131 korunarak kald\u0131\u011f\u0131 yerden i\u015flemeye devam edebilmektedir.<\/p>\n<p>Ayn\u0131 \u015fekilde bir event&#8217;i i\u015fleme s\u0131ras\u0131nda herhangi bir ge\u00e7ici hata olu\u015ftu\u011funda da belirlenen retry policy&#8217;sine g\u00f6re ilgili event, s\u0131ras\u0131 korunarak tekrardan i\u015flenmeye \u00e7al\u0131\u015f\u0131lmaktad\u0131r. Bu noktada dikkat etmemiz gereken nokta ise, ilgili event maksimum retry say\u0131s\u0131na ula\u015ft\u0131\u011f\u0131nda ise <strong>dead letter queue&#8217;ya<\/strong> ta\u015f\u0131nmaktad\u0131r. Bu retry i\u015fleminin ise ne kadar ger\u00e7ekle\u015fece\u011fini ister ilgili queue&#8217;yu olu\u015ftururken, istersek de &#8220;<em>ServiceBusClient<\/em>&#8221; &#8216;\u0131 initialise ederken a\u015fa\u011f\u0131daki gibi belirleyebiliriz.<\/p>\n<pre>var clientOptions = new ServiceBusClientOptions\r\n{\r\n    RetryOptions = new ServiceBusRetryOptions()\r\n    {\r\n        MaxRetries = 10,\r\n        MaxDelay = TimeSpan.FromMinutes(1)\r\n    }\r\n};\r\n\r\nawait using var serviceBusClient = new ServiceBusClient(connectionString, clientOptions);<\/pre>\n<p>&#8220;<em>ProcessMessages<\/em>&#8221; method&#8217;u i\u00e7erisinde ise ilgili session&#8217;\u0131 release edebilmek i\u00e7in, a\u015fa\u011f\u0131daki gibi event property&#8217;lerine eri\u015fiyoruz ve belirlemi\u015f oldu\u011fumuz &#8220;<em>IsLastItem<\/em>&#8221; property&#8217;sini kontrol ederek session&#8217;\u0131n release i\u015flemini ger\u00e7ekle\u015ftiriyoruz.<\/p>\n<p>&#8220;<em>ProcessErrors<\/em>&#8221; method&#8217;u i\u00e7erisinde ise ilgili event&#8217;i i\u015fleme s\u0131ras\u0131nda herhangi bir hata olu\u015fursa, yapmak istedi\u011fimiz i\u015flemleri ger\u00e7ekle\u015ftirebiliriz. Ard\u0131ndan retry mekanizmas\u0131 devreye girmektedir.<\/p>\n<p>Ayr\u0131ca bunlara ek olarak istedi\u011fimiz bir subscriber&#8217;\u0131n spesifik session id&#8217;leri i\u00e7in \u00e7al\u0131\u015fmas\u0131n\u0131 da sa\u011flayabiliriz. Bunun i\u00e7in yine &#8220;<em>ServiceBusSessionProcessor<\/em>&#8221; objesini initialize ederken a\u015fa\u011f\u0131daki gibi session id&#8217;lerini set etmemiz yeterli olacakt\u0131r.<\/p>\n<pre>var options = new ServiceBusSessionProcessorOptions()\r\n{\r\n    SessionIds = { \"my-x-sessions\", \"my-y-sessions\" }\r\n};<\/pre>\n<p>Dilersek event&#8217;leri i\u015flerken ilgili session \u00f6zelinde de daha sonra kullanmak \u00fczere state bilgileri tutabilmekteyiz.<\/p>\n<pre>async Task ProcessMessages(ProcessSessionMessageEventArgs args)\r\n{\r\n    await args.SetSessionStateAsync(BinaryData.FromString(\"some state\"));\r\n    string someState = (await args.GetSessionStateAsync()).ToString();\r\n}<\/pre>\n<p>\u015eimdi h\u0131zl\u0131 bir test ger\u00e7ekle\u015ftirebilmek i\u00e7in ise 2 subscriber ve 1 publisher \u00e7al\u0131\u015ft\u0131ral\u0131m.<\/p>\n<p><a href=\"\/wp-content\/uploads\/2023\/03\/asb-session-sub.jpg\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-4364 lazyload\" data-src=\"\/wp-content\/uploads\/2023\/03\/asb-session-sub.jpg\" alt=\"\" width=\"2388\" height=\"916\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2023\/03\/asb-session-sub.jpg 2388w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2023\/03\/asb-session-sub-300x115.jpg 300w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2023\/03\/asb-session-sub-1024x393.jpg 1024w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2023\/03\/asb-session-sub-768x295.jpg 768w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2023\/03\/asb-session-sub-1536x589.jpg 1536w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2023\/03\/asb-session-sub-2048x786.jpg 2048w\" data-sizes=\"(max-width: 2388px) 100vw, 2388px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 2388px; --smush-placeholder-aspect-ratio: 2388\/916;\" \/><\/a><\/p>\n<p>G\u00f6rd\u00fc\u011f\u00fcm\u00fcz gibi session&#8217;\u0131 ilk kabul eden sa\u011f tarafdaki subscriber, session i\u00e7erisindeki ilgili t\u00fcm event&#8217;leri publish edildikleri s\u0131ra i\u00e7erisinde i\u015fledi ve ilgili session&#8217;\u0131 kapatt\u0131.<\/p>\n<h2>Toparlayal\u0131m<\/h2>\n<p>Makalenin ba\u015f\u0131nda da dedi\u011fim gibi, maalesef bazen baz\u0131 logic&#8217;leri istemedi\u011fimiz \u015fekilde implemente etmek zorunda kalabiliyoruz. S\u0131rf bu y\u00fczden y\u0131llar \u00f6nce sadece tek bir instance ile \u00e7al\u0131\u015fmas\u0131 gereken bir ka\u00e7 subscriber&#8217;lar\u0131m\u0131z vard\u0131 ve ilgili event i\u015fleme s\u0131ralar\u0131n\u0131 koruyabilmek ad\u0131na farkl\u0131 taklalar at\u0131yorduk.<\/p>\n<p>Bu tarz senaryoya gereksinim \u00e7\u0131kartmayacak \u015fekilde event&#8217;lerimizi\/sistemimizi design etmemiz, olduk\u00e7a faydam\u0131za olacakt\u0131r. Elbette business karma\u015f\u0131kl\u0131\u011f\u0131na ve o anki gereksinimlerine g\u00f6re de\u011fi\u015fiklilik g\u00f6sterecektir.<\/p>\n<p>Bu makale kapsam\u0131nda ise bu tarz bir ihtiya\u00e7 kar\u015f\u0131s\u0131nda, <em>Azure Service Bus<\/em> ve <em>sessions<\/em> \u00f6zelli\u011fini kullanarak, subscriber taraf\u0131nda minimum efor ile <em>FIFO<\/em> s\u0131ralama ve i\u015fleme i\u015flemini nas\u0131l ger\u00e7ekle\u015ftirebilece\u011fimizi g\u00f6stermeye \u00e7al\u0131\u015ft\u0131m. Ayr\u0131ca bahsetti\u011fim gibi subscriber taraf\u0131nda event&#8217;leri i\u015flerken &#8220;<em>session lock duration<\/em>&#8220;, &#8220;<em>timeouts<\/em>&#8221; ve &#8220;<em>retry<\/em>&#8221; gibi konfig\u00fcrasyonlar\u0131 dikkatlice yapmam\u0131z gerekti\u011fini de unutmamam\u0131z gerekmektedir.<\/p>\n<h2>Referanslar<\/h2>\n<blockquote><p><em>https:\/\/learn.microsoft.com\/en-us\/azure\/service-bus-messaging\/message-sessions<\/em><\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>Bazen baz\u0131 senaryolar vard\u0131r karma\u015f\u0131kl\u0131\u011f\u0131n\u0131 veya eksi yanlar\u0131n\u0131 bildi\u011fimiz halde implemente etmekten ka\u00e7amad\u0131\u011f\u0131m\u0131z veya implemente etme zorunda kald\u0131\u011f\u0131m\u0131z. Distributed ortamlarda birbirlerine ba\u011fl\u0131 baz\u0131 event&#8217;leri\/message&#8217;lar\u0131 belirli bir s\u0131ra (publish edildikleri) i\u00e7erisinde i\u015fleyebilmek de bence bunlardan birisi. \u00d6rne\u011fin batch processing yap\u0131yor ve her bir item&#8217;\u0131 belirli bir&#8230;<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/gokhan-gokalp.com\/tr\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\/\">Devam\u0131n\u0131 okuyun<span class=\"screen-reader-text\">Azure Service Bus Kullanarak Microservice\u2019lerde Event\u2019ler Nas\u0131l S\u0131ralan\u0131r (FIFO Consumers)<\/span><\/a><\/div>\n","protected":false},"author":1,"featured_media":4372,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,505,418,285,368],"tags":[660,666,659,650,672,675,674,673,671],"class_list":["post-4344","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net","category-net-core","category-azure","category-messaging","category-microservices","tag-azure-service-bus","tag-c","tag-dotnet","tag-event-driven","tag-event-ordering","tag-fifo-message-broker","tag-fifo-subscriber","tag-message-ordering","tag-session","entry"],"translation":{"provider":"WPGlobus","version":"3.0.2","language":"tr","enabled_languages":["en","tr"],"languages":{"en":{"title":true,"content":true,"excerpt":false},"tr":{"title":true,"content":true,"excerpt":false}}},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Azure Service Bus Kullanarak Microservice\u2019lerde Event\u2019ler Nas\u0131l S\u0131ralan\u0131r (FIFO Consumers) - G\u00f6khan G\u00f6kalp<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/gokhan-gokalp.com\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Azure Service Bus Kullanarak Microservice\u2019lerde Event\u2019ler Nas\u0131l S\u0131ralan\u0131r (FIFO Consumers) - G\u00f6khan G\u00f6kalp\" \/>\n<meta property=\"og:url\" content=\"https:\/\/gokhan-gokalp.com\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\/\" \/>\n<meta property=\"og:site_name\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n<meta property=\"article:published_time\" content=\"2023-03-17T23:58:07+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-03-18T19:57:03+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2023\/03\/azure-service-bus-fifo-consumers.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"675\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"24 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\\\/\"},\"author\":{\"name\":\"G\u00f6khan G\u00f6kalp\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"headline\":\"Azure Service Bus Kullanarak Microservice\u2019lerde Event\u2019ler Nas\u0131l S\u0131ralan\u0131r (FIFO Consumers)\",\"datePublished\":\"2023-03-17T23:58:07+00:00\",\"dateModified\":\"2023-03-18T19:57:03+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\\\/\"},\"wordCount\":4093,\"commentCount\":7,\"publisher\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"image\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2023\\\/03\\\/azure-service-bus-fifo-consumers.jpg\",\"keywords\":[\"azure service bus\",\"C#\",\"dotnet\",\"event driven\",\"event ordering\",\"fifo message broker\",\"fifo subscriber\",\"message ordering\",\"session\"],\"articleSection\":[\".NET\",\".NET Core\",\"Azure\",\"Messaging\",\"Microservices\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/gokhan-gokalp.com\\\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\\\/\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\\\/\",\"name\":\"Azure Service Bus Kullanarak Microservice\u2019lerde Event\u2019ler Nas\u0131l S\u0131ralan\u0131r (FIFO Consumers) - G\u00f6khan G\u00f6kalp\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2023\\\/03\\\/azure-service-bus-fifo-consumers.jpg\",\"datePublished\":\"2023-03-17T23:58:07+00:00\",\"dateModified\":\"2023-03-18T19:57:03+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\\\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/gokhan-gokalp.com\\\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\\\/#primaryimage\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2023\\\/03\\\/azure-service-bus-fifo-consumers.jpg\",\"contentUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2023\\\/03\\\/azure-service-bus-fifo-consumers.jpg\",\"width\":1200,\"height\":675},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/gokhan-gokalp.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to Order Events in Microservices by Using Azure Service Bus (FIFO Consumers)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#website\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/\",\"name\":\"G\u00f6khan G\u00f6kalp\",\"description\":\"C# &amp; Python lover\",\"publisher\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/gokhan-gokalp.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\",\"name\":\"G\u00f6khan G\u00f6kalp\",\"pronouns\":\"he\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"contentUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"caption\":\"G\u00f6khan G\u00f6kalp\"},\"logo\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\"},\"sameAs\":[\"https:\\\/\\\/gokhan-gokalp.com\"],\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/tr\\\/author\\\/gok-gokalp\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Azure Service Bus Kullanarak Microservice\u2019lerde Event\u2019ler Nas\u0131l S\u0131ralan\u0131r (FIFO Consumers) - G\u00f6khan G\u00f6kalp","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/gokhan-gokalp.com\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\/","og_locale":"tr_TR","og_type":"article","og_title":"Azure Service Bus Kullanarak Microservice\u2019lerde Event\u2019ler Nas\u0131l S\u0131ralan\u0131r (FIFO Consumers) - G\u00f6khan G\u00f6kalp","og_url":"https:\/\/gokhan-gokalp.com\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\/","og_site_name":"G\u00f6khan G\u00f6kalp","article_published_time":"2023-03-17T23:58:07+00:00","article_modified_time":"2023-03-18T19:57:03+00:00","og_image":[{"width":1200,"height":675,"url":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2023\/03\/azure-service-bus-fifo-consumers.jpg","type":"image\/jpeg"}],"author":"G\u00f6khan G\u00f6kalp","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"G\u00f6khan G\u00f6kalp","Tahmini okuma s\u00fcresi":"24 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/gokhan-gokalp.com\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\/#article","isPartOf":{"@id":"https:\/\/gokhan-gokalp.com\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\/"},"author":{"name":"G\u00f6khan G\u00f6kalp","@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"headline":"Azure Service Bus Kullanarak Microservice\u2019lerde Event\u2019ler Nas\u0131l S\u0131ralan\u0131r (FIFO Consumers)","datePublished":"2023-03-17T23:58:07+00:00","dateModified":"2023-03-18T19:57:03+00:00","mainEntityOfPage":{"@id":"https:\/\/gokhan-gokalp.com\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\/"},"wordCount":4093,"commentCount":7,"publisher":{"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"image":{"@id":"https:\/\/gokhan-gokalp.com\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\/#primaryimage"},"thumbnailUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2023\/03\/azure-service-bus-fifo-consumers.jpg","keywords":["azure service bus","C#","dotnet","event driven","event ordering","fifo message broker","fifo subscriber","message ordering","session"],"articleSection":[".NET",".NET Core","Azure","Messaging","Microservices"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/gokhan-gokalp.com\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/gokhan-gokalp.com\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\/","url":"https:\/\/gokhan-gokalp.com\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\/","name":"Azure Service Bus Kullanarak Microservice\u2019lerde Event\u2019ler Nas\u0131l S\u0131ralan\u0131r (FIFO Consumers) - G\u00f6khan G\u00f6kalp","isPartOf":{"@id":"https:\/\/gokhan-gokalp.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/gokhan-gokalp.com\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\/#primaryimage"},"image":{"@id":"https:\/\/gokhan-gokalp.com\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\/#primaryimage"},"thumbnailUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2023\/03\/azure-service-bus-fifo-consumers.jpg","datePublished":"2023-03-17T23:58:07+00:00","dateModified":"2023-03-18T19:57:03+00:00","breadcrumb":{"@id":"https:\/\/gokhan-gokalp.com\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/gokhan-gokalp.com\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\/"]}]},{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/gokhan-gokalp.com\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\/#primaryimage","url":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2023\/03\/azure-service-bus-fifo-consumers.jpg","contentUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2023\/03\/azure-service-bus-fifo-consumers.jpg","width":1200,"height":675},{"@type":"BreadcrumbList","@id":"https:\/\/gokhan-gokalp.com\/how-to-order-events-in-microservices-by-using-azure-service-bus-fifo-consumers\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/gokhan-gokalp.com\/"},{"@type":"ListItem","position":2,"name":"How to Order Events in Microservices by Using Azure Service Bus (FIFO Consumers)"}]},{"@type":"WebSite","@id":"https:\/\/gokhan-gokalp.com\/#website","url":"https:\/\/gokhan-gokalp.com\/","name":"G\u00f6khan G\u00f6kalp","description":"C# &amp; Python lover","publisher":{"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/gokhan-gokalp.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe","name":"G\u00f6khan G\u00f6kalp","pronouns":"he","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","url":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","contentUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","caption":"G\u00f6khan G\u00f6kalp"},"logo":{"@id":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659"},"sameAs":["https:\/\/gokhan-gokalp.com"],"url":"https:\/\/gokhan-gokalp.com\/tr\/author\/gok-gokalp\/"}]}},"_links":{"self":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/4344","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/comments?post=4344"}],"version-history":[{"count":22,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/4344\/revisions"}],"predecessor-version":[{"id":4375,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/4344\/revisions\/4375"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/media\/4372"}],"wp:attachment":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/media?parent=4344"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/categories?post=4344"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/tags?post=4344"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}