當前位置:
首頁 > 知識 > Http批量非同步發送和數據保存

Http批量非同步發送和數據保存

先說需求。

有個服務程序定時掃描指定文件夾下一個所有文件,文件包含了多個用戶(客戶)信息及對應的http發送地址和發送數據。現在該服務程序需要提取這些用戶信息,然後批量進行發送;發送完後需要將http返回結果和當前用戶對應上;到最後進行批量保存。當然批量保存是為了減少資料庫壓力。

這裡的批量數據保存使用的sqlbulkcopy 在此就不做介紹了。

這裡談談自己最開始和最後實現的思路及方法。

針對這一需求我的確也是第一次經歷,所以經驗很少。

看到非同步發送,我首先想到了用.Net 4.0裡面的Task,因為task非常簡單易用,代碼也更加直觀而且還是基於線程池的。

談談我看到的task和thread的區別:

同一個任務我用Task、Thread、ThreadPool進行比較下。

測試代碼:

1 static void Main(string[] args)
2 {
3 Console.WriteLine("ThreadPool");
4 for (int i = 0; i < 10; i++) 5 { 6 //用線程池去執行http任務 7 ThreadPool.QueueUserWorkItem(GeneralHttpTest,i); 8 } 9 //延時是為了等待上面的線程跑完 不影響我們觀看後續測試數據 10 Thread.Sleep(5000); 11 Console.WriteLine("Thread"); 12 for (int i = 0; i < 10; i++) 13 { 14 //用線去執行http任務 15 Thread th = new Thread(new ParameterizedThreadStart(GeneralHttpTest)); 16 th.Start(i); 17 } 18 Thread.Sleep(5000); 19 Console.WriteLine("Task"); 20 for (int i = 0; i < 10; i++) 21 { 22 //用task去執行http任務 23 new Task( =>
24 {
25 GeneralHttpTest(i);
26 }).Start;
27 }
28 Console.ReadKey;
29 }
30 static void GeneralHttpTest(object i)
31 {
32 //請求http 並列印http返回結果
33 int status = 0;
34 string respStr = SimpleHttpHelper.HttpGetRequest(url, out status);
35 Console.WriteLine(i + " " + respStr);
36 }

結果:

Http批量非同步發送和數據保存

從這個結果看 我感覺task裡面有個任務緩衝區它等到緩衝區滿了或者間隔時間到了則開始一起執行所有任務。我們循環10次去調用task 每循環一次傳遞一下當前循環的值。在每次循環的時候task好像沒有立即去執行我們的方法,而是等到循環完了 才一起去執行所有方法。所以看到了 每次循環的值 都是10。

當然這裡可以用線程安全的一些類去代替i做這個值傳遞 比如ConcurrentBag、ConCurrentDictionay等等。這個時候用task能夠保證傳遞數據的一致性。

上面說的緩衝區這是我個人的一種描述;或許我這樣去理解也不是很對,因為我對task沒有很深的研究。

最開始我是用的task進行批量發送,用task的 WaitAll進行等待所有任務完成再進行數據保存。這樣最後發現的弊端就是,我們要等待當前這一批(即一個文件內的數據)數據完成後才能進行下一批數據的發送。這樣就會造成性能的損耗,當我有幾十幾千批數據需要發送的時候 這樣速度就顯的非常之慢。

後來一些原因我沒用task進行非同步發送了,後來直接使用 HttpWebRequest的非同步執行方法 BeginGetResponse。

HttpWebRequest非同步發送可以看我的《Http非同步發送之HttpWebRequest的BeginGetResponse》這裡面有我封裝的代碼。

何時對數據進行批量保存

我最開始的保存思路是將每條數據都添加到一條list ,因為要獲取http返回的結果,所以添加時 是在非同步返回結果後進行添加。然後每次非同步發送時附帶上本次總數據有多少,每次請求回調後,對比下當前list總數和傳遞時帶過來的總數比較是否相等。相等則直接保存數據。這樣有個弊端如果中間某個線程丟失,這樣list總數和我們每次請求附帶的總數就不一致了;這樣則會導致數據對不上永遠不會保存了。

最後的方案還是用隊列實現 .Net裡面的Queue或者線程安全的ConcurrentQueue;每次將數據都添加到隊列里,然後定時從隊列里取數據然後進行保存。隊列的好處就在於數據的添加和移除互不影響。在多線程裡面對數據的臨時存儲建議用隊列 少用list.。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 達人科技 的精彩文章:

原創源碼角度分析Android的消息機制系列(六)——Handler的工作原理
優化mysql資料庫的幾個步驟
JAVAEE——spring02:使用註解配置spring、sts插件、junit整合測試和aop演示

TAG:達人科技 |

您可能感興趣

Excel中批量發送郵件
使用Ajax發送非同步請求
PHP 使用 phpmailer 發送電子郵件
Opera Touch瀏覽器Flow同步功能強化:可向桌面發送照片等文件
被指向中國發送數據,Mac App Store下架排名第一的付費安全軟體
php中curl同時發送多個請求curl_multi函數集的用法
Python模擬發送Slack消息
用戶現可用Opera的加密貨幣錢包發送CryptoKitties
Gmail 出現Bug 允許用戶發送匿名郵件
Facebook計劃讓Messenger,Instagram和WhatsApp用戶互相發送消息
SpringBoot中發送QQ郵件
讓 Emacs shell 命令發送桌面通知
Google與T-Mobile達成協議,將用戶位置數據發送至急救中心
python腳本實現定時發送郵件
Servlet 發送電子郵件
用戶發送的「Dear Tim」郵件對蘋果影響很大
Localhost環境下使用Django send_mail發送郵件-以QQ和163郵箱為例
YG要求球迷不要向G-Dragon的單位發送信件
Facebook Messenger將容對發送的消息進行刪除
Verizon發送推送通知給iPhone用戶建議升級到Galaxy S9