[Azure] C# 使用 Azure.Storage.Queues 寫入佇列(Queue) + 延遲顯示( VisibilityTimeout )

2022-08-12

上一篇文章 (C# 使用 Azure.Storage.Queues 寫入佇列(Queue) + 取得資料 )我們談到了簡單操控 Azure Queue ,當作一個可以跨機器跨系統的 Queue 的實作方式,傳統很多時候會用到 Redis 來解決,但是用這應該便宜很多

不過上篇文章說到,他有一個問題,就是你取用後,如果時間沒有到他只會紀錄取用次數跟一般你理解的 Dequeue  不太一樣。



首先,其實在 SendMessage 可以傳入一個參數 visibilityTimeout 這是代表在一個時間後可以顯示,所以我就設計一個案例

我先寫入十筆資料都顯示延遲五秒後再出現,之後再寫入200筆立即出現的資料(但是我有延遲一秒寫一筆為了方便觀測),之後有一個執行緒是一直做 ReceiveMessage的動作


1. 寫入資料

private static void TestEnqueueDataWithVisibilityTimeout() { var queueName = "test-azure-queue"; var queue = new Azure.Storage.Queues.QueueClient(ConnectionString, queueName); queue.CreateIfNotExists(); //寫入十筆資料&#65292;並且延遲五秒後再出現 for (var i = 1; i <= 10; i++) { var res = queue.SendMessage("延遲執行 " + i + "," + DateTime.Now.ToString(), visibilityTimeout: new TimeSpan(0, 0, 5)); } //之後執行連續寫入馬上出現的&#65292;沒有設定延遲出現 for (var i = 1; i <= 200; i++) { var res = queue.SendMessage("馬上執行 " + i + "," + DateTime.Now.ToString()).Value; System.Threading.Thread.Sleep(1000); } }


2.讀取資料

private static void TestDequeueData() { var queueName = "test-azure-queue"; for (var i = 1; i <= 300; i++) { var queue = new Azure.Storage.Queues.QueueClient(ConnectionString, queueName); var res = queue.ReceiveMessage().Value; if (res != null) { Console.WriteLine("查詢=>" + res.Body.ToString()); } else { Console.WriteLine("NO DATA!!"); } System.Threading.Thread.Sleep(millisecondsTimeout: 1000); } }


3.呼叫

new Thread(() => { TestDequeueData(); }).Start(); new Thread(() => { TestEnqueueDataWithVisibilityTimeout(); }).Start();


結果

NO DATA!! 查詢=>馬上執行 1,2022/8/12 下午 02:17:44 查詢=>馬上執行 2,2022/8/12 下午 02:17:46 查詢=>馬上執行 3,2022/8/12 下午 02:17:47 查詢=>馬上執行 4,2022/8/12 下午 02:17:48 查詢=>馬上執行 5,2022/8/12 下午 02:17:49 查詢=>延遲執行 1,2022/8/12 下午 02:17:44 查詢=>延遲執行 2,2022/8/12 下午 02:17:44 查詢=>延遲執行 3,2022/8/12 下午 02:17:44 查詢=>延遲執行 4,2022/8/12 下午 02:17:44 查詢=>延遲執行 5,2022/8/12 下午 02:17:44 查詢=>延遲執行 6,2022/8/12 下午 02:17:44 查詢=>延遲執行 7,2022/8/12 下午 02:17:44 查詢=>延遲執行 8,2022/8/12 下午 02:17:44 查詢=>延遲執行 9,2022/8/12 下午 02:17:44 查詢=>延遲執行 10,2022/8/12 下午 02:17:44 查詢=>馬上執行 6,2022/8/12 下午 02:17:50 查詢=>馬上執行 7,2022/8/12 下午 02:17:51 查詢=>馬上執行 8,2022/8/12 下午 02:17:52 查詢=>馬上執行 9,2022/8/12 下午 02:17:53 查詢=>馬上執行 10,2022/8/12 下午 02:17:54 查詢=>馬上執行 11,2022/8/12 下午 02:17:55 查詢=>馬上執行 12,2022/8/12 下午 02:17:56 查詢=>馬上執行 13,2022/8/12 下午 02:17:57 查詢=>馬上執行 14,2022/8/12 下午 02:17:58 查詢=>馬上執行 15,2022/8/12 下午 02:17:59 查詢=>馬上執行 16,2022/8/12 下午 02:18:00 查詢=>馬上執行 17,2022/8/12 下午 02:18:02 查詢=>馬上執行 18,2022/8/12 下午 02:18:03 查詢=>馬上執行 19,2022/8/12 下午 02:18:04 查詢=>馬上執行 20,2022/8/12 下午 02:18:05 ... 下面省略




因為一開始寫入的資料都延遲了五秒,所以再立即的佇列部分會被先取出來,一直到被延遲的資料時間到了就會出現

這設計可以應用在一些地方,像是限時開始搶票的東西,大概就先寫到這之後有些心得我再繼續分享..



reference:

https://docs.microsoft.com/zh-tw/dotnet/api/azure.storage.queues.queueclient.sendmessage?view=azure-dotnet#azure-storage-queues-queueclient-sendmessage(system-binarydata-system-nullable((system-timespan))-system-nullable((system-timespan))-system-threading-cancellationtoken)


當麻許的碎念筆記 2014 | Donma Hsu Design.