一区二区久久-一区二区三区www-一区二区三区久久-一区二区三区久久精品-麻豆国产一区二区在线观看-麻豆国产视频

在.NET Workflow 3.5中使用多線程提高工作流性能

  最近在工作上碰到一個(gè)性能問(wèn)題,由于項(xiàng)目是基于SOA的架構(gòu),使得整個(gè)系統(tǒng)完全依賴于各種各樣的Service,其中用于處理業(yè)務(wù)邏輯的Business Services全部都用.NET Workflow 3.5實(shí)現(xiàn)(歷史原因,項(xiàng)目還沒升級(jí)到Workflow 4)。在眾多的Business Service中,其中有一個(gè)的主要功能是,通過(guò)調(diào)用不同的Data Service來(lái)獲取數(shù)據(jù),然后根據(jù)業(yè)務(wù)邏輯來(lái)組織這些數(shù)據(jù)并返回給它的調(diào)用者。該Business Service的工作流(Workflow)主要包含三個(gè)活動(dòng)組件(Activity),大致可以用下圖表示:

image

  需要說(shuō)明一下,在實(shí)際項(xiàng)目中,這個(gè)Workflow本身不僅僅只是簡(jiǎn)單地包含上面三個(gè)Activity,通過(guò)性能測(cè)試的數(shù)據(jù)分析,瓶頸就在這三個(gè)Activity上,而每個(gè)Activity的執(zhí)行時(shí)間又主要消耗在反復(fù)調(diào)用Data Service上。在此,為了簡(jiǎn)化問(wèn)題的描述,我把其它不相干的Activity剔除了,于是就得到了上圖的結(jié)構(gòu)。

  圖中的三個(gè)Activity都會(huì)分別去調(diào)用不同的Data Service來(lái)獲得數(shù)據(jù),尤其在getNotesActivity中,Data Service會(huì)被循環(huán)調(diào)用,這使得系統(tǒng)性能大打折扣。原本有一個(gè)解決方案可以在一定程度上提高getNotesActivity的效率,就是修改被調(diào)用的Data Service,使得它能夠一次性接收多個(gè)request的數(shù)據(jù),處理完之后再將所有的結(jié)果一次性返回,這樣就避免了Data Service的循環(huán)調(diào)用,有效地減少了數(shù)據(jù)在網(wǎng)絡(luò)上的來(lái)回次數(shù)。但是,這種解決方案需要更改Data Service的Request Schema,這個(gè)改動(dòng)是很大的,因?yàn)榭赡苡泻芏嗥渌腂usiness Service都在調(diào)用這個(gè)Data Service,牽涉的范圍太廣了。

  根據(jù)實(shí)際項(xiàng)目,稍加分析不難發(fā)現(xiàn),這個(gè)Workflow中的Activity有如下幾個(gè)特點(diǎn):

  • 三個(gè)Activity的輸入屬性參數(shù)都來(lái)自于Workflow(即通過(guò)與Workflow中定義的DependencyProperty進(jìn)行綁定而獲得數(shù)據(jù)),并不存在下游的Activity的輸入?yún)?shù)需要依賴上游Activity的輸出參數(shù)的情況
  • 每個(gè)Activity的輸出屬性參數(shù)都只關(guān)注某一種類型的數(shù)據(jù),在Workflow Runtime執(zhí)行完某個(gè)Activity后,也會(huì)通過(guò)DependencyProperty將處理結(jié)果傳遞給Workflow,而這些輸出屬性參數(shù)之間也并沒有任何關(guān)聯(lián)
  • 三個(gè)Activity所調(diào)用的Data Service也比較獨(dú)立,基本上可以說(shuō)是在做三個(gè)完全不同的工作
  • 時(shí)間主要消耗在Data Service的調(diào)用上,不存在由于復(fù)雜的運(yùn)算邏輯導(dǎo)致CPU利用率近似100%的情況,也不存在由于物理內(nèi)存用完而需要頻繁讀寫虛擬內(nèi)存的情形

  上述的幾個(gè)特點(diǎn)中,第四點(diǎn)為我們引入多線程或并行任務(wù)處理提供了主要依據(jù)。這里需要額外岔開一下。有很多軟件人員認(rèn)為,多線程一定能夠提高系統(tǒng)性能,因?yàn)槭聞?wù)可以分派到多個(gè)線程中進(jìn)行并行處理。我覺得,應(yīng)該這樣去看待這個(gè)問(wèn)題:首先,根據(jù)Martin Fowler的《企業(yè)應(yīng)用架構(gòu)模式》(也就是著名的PoEAA)一書中有關(guān)性能的討論認(rèn)為,有很多術(shù)語(yǔ)可以描述性能,比如:響應(yīng)時(shí)間、響應(yīng)性、等待時(shí)間、吞吐率、負(fù)載、負(fù)載敏感度等。假設(shè)完成某個(gè)任務(wù)需要的時(shí)間很長(zhǎng),比如需要5秒,那么其響應(yīng)時(shí)間就是5秒,而如果讓用戶等待這5秒過(guò)去后,再將系統(tǒng)的控制權(quán)交給用戶,就會(huì)讓用戶明顯感覺很不順,于是響應(yīng)性就很差;但如果能將這個(gè)任務(wù)交給另一個(gè)執(zhí)行體去處理,而程序本身直接將系統(tǒng)控制權(quán)交給用戶,等那個(gè)執(zhí)行體完成任務(wù)處理后,再將結(jié)果提供給用戶,那么,同樣處理這個(gè)任務(wù)需要5秒鐘,這種方式的響應(yīng)性就明顯要好于前者,這也是我們以前做Windows Forms開發(fā)的時(shí)候,要把耗時(shí)的處理交給另一個(gè)線程處理,以不至于因?yàn)橹骶€程的阻塞而導(dǎo)致界面凍結(jié)的尷尬局面。因此,多線程的引入,可以提高系統(tǒng)的響應(yīng)性。

  其次,多線程是否能夠提高系統(tǒng)的響應(yīng)時(shí)間?這也未必,在單核處理器上,多線程是采用時(shí)間片輪循的方式實(shí)現(xiàn)的,也就是說(shuō),相同時(shí)間點(diǎn)上,只有一個(gè)線程在執(zhí)行,只不過(guò)是時(shí)間片足夠小,輪循頻率足夠高,才讓我們感覺線程是并行執(zhí)行的,在這樣一種體系結(jié)構(gòu)下,完成任務(wù)的處理還是需要那么長(zhǎng)時(shí)間,甚至?xí)r間片的切換倒還會(huì)帶來(lái)額外的開銷。在多核系統(tǒng)中,或許真的可以提高響應(yīng)時(shí)間,不過(guò)我目前沒有實(shí)際的測(cè)試數(shù)據(jù)用來(lái)比較,因此在這個(gè)問(wèn)題上,我還沒有足夠的發(fā)言權(quán)。

  而對(duì)于目前項(xiàng)目的情況,Data Service是分布在網(wǎng)絡(luò)上不同位置的資源,如果能讓這些Data Service同時(shí)處理數(shù)據(jù)請(qǐng)求,再讓Business Service去組織分別來(lái)自這些Data Service的處理結(jié)果,那么整個(gè)Business Service的響應(yīng)時(shí)間是可以明顯提高的,響應(yīng)時(shí)間提高了,響應(yīng)性也同樣提高了。假設(shè)第一個(gè)Activity耗時(shí)t1,第二個(gè)Activity耗時(shí)t2,第三個(gè)Activity耗時(shí)t3,那么,如果按上圖中的順序方式執(zhí)行,Business Service的響應(yīng)時(shí)間就是t1+t2+t3。但如果讓這些Activity并行處理(也就相當(dāng)于并行調(diào)用Data Service使其同時(shí)處理數(shù)據(jù)請(qǐng)求),那么Business Service的響應(yīng)時(shí)間應(yīng)該就是max(t1, t2, t3)。

  于是,我打算將上述的Workflow修改一下,采用多線程的方式來(lái)分別運(yùn)行每個(gè)Activity,最后再將結(jié)果匯總。我修改后的Workflow如下所示:

image

  在此需要對(duì)ParallelActivity說(shuō)明一下。.NET Workflow 3.5的ParallelActivity并沒有做到所謂的并行執(zhí)行,因?yàn)閃orkflow Runtime是在單獨(dú)的線程上執(zhí)行Workflow Instance的,因此,要讓多個(gè)Activity真正并行執(zhí)行是做不到的。ParallelActivity的真正用意在于協(xié)調(diào)每個(gè)分支中的SequenceActivity(注意:ParallelActivity的每個(gè)分支只能接收一個(gè)SequenceActivity),使得其中的每個(gè)Activity都有一次執(zhí)行的機(jī)會(huì)。

  某個(gè)分支中的一個(gè)活動(dòng)執(zhí)行過(guò)后,就會(huì)輪到下一個(gè)分支。當(dāng)這個(gè)分支執(zhí)行了一個(gè)活動(dòng)后,執(zhí)行又會(huì)轉(zhuǎn)移到再下一個(gè)分支,以此類推。當(dāng)所有分支都有了執(zhí)行機(jī)會(huì)之后,又會(huì)從第一個(gè)(最左側(cè))分支開始這一過(guò)程,繼續(xù)執(zhí)行第一個(gè)分支的下一個(gè)活動(dòng)(如果存在的話)。因此,在我們的這個(gè)例子中,完全可以不用ParallelActivity,而仍然選擇原來(lái)的結(jié)構(gòu)即可。之前我并沒有完全清楚地了解ParallelActivity,開始一直以為ParallelActivity的意思是,讓W(xué)orkflow Runtime同時(shí)安排(Schedule)每個(gè)分支的執(zhí)行,以便當(dāng)每個(gè)分支都以異步方式運(yùn)行時(shí),所有的分支可以實(shí)現(xiàn)并行處理。

  不過(guò)也不要緊,在這里使用ParallelActivity,雖然沒有有效地利用它的特性,但與原來(lái)的Workflow相比,從可讀性上講,這種結(jié)構(gòu)更容易讓人覺得這是一種并行的運(yùn)行方式。

  另一個(gè)變化是,原本每個(gè)操作都是寫在一個(gè)自定義的Activity中的,通過(guò)重寫Activity的Execute方法來(lái)做業(yè)務(wù)處理,而現(xiàn)在則是用CodeActivity來(lái)代替原來(lái)的Activity,這樣做的好處是,可以將業(yè)務(wù)處理的代碼放在同一個(gè)Context中,這也為線程同步提供了便利,降低了使用線程的復(fù)雜度。

  以下是改進(jìn)后的Workflow的代碼,供參考。

   1. using System;  
2. using System.Collections.Generic;
3. using System.Threading;
4. using System.Workflow.Activities;
5. namespace WorkflowConsoleApplication3
6. {
7. public sealed partial class Workflow1 : SequentialWorkflowActivity
8. {
9. List<Thread> threads = new List<Thread>();
10. public Workflow1()
11. {
12. InitializeComponent();
13. }
14. private void getAdditionalInfoActivity_Execute(object sender, EventArgs e)
15. {
16. var t1 = new Thread(() =>
17. {
18. // Call Data Service 1 to implement business logic...
19. });
20. threads.Add(t1);
21. t1.Start();
22. }
23. private void getNotesActivity_Execute(object sender, EventArgs e)
24. {
25. var t2 = new Thread(() =>
26. {
27. // Call Data Service 2 in a loop to implement business
28. // logic...
29. });
30. threads.Add(t2);
31. t2.Start();
32. }
33.
34. private void getSpecialPointsActivity_Execute(object sender, EventArgs e)
35. {
36. var t3 = new Thread(() =>
37. {
38. // Call Data Service 3 to implement business logic...
39. });
40. threads.Add(t3);
41. t3.Start();
42. }
43.
44. private void syncCodeActivity_Execute(object sender, EventArgs e)
45. {
46. // Wait for all threads to terminate...
47. threads.ForEach(p => p.Join());
48. // TODO: Process with results and exceptions
49. }
50. }
51. }
52. 從上面的代碼中可以看到,每個(gè)

NET技術(shù)在.NET Workflow 3.5中使用多線程提高工作流性能,轉(zhuǎn)載需保留來(lái)源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 九色综合伊人久久富二代 | 国产极品自拍 | 久精品在线观看 | 成年黄网站色视频免费观看 | 精品国产自 | 色黄视频 | 韩国一区二区三区视频 | 自偷自偷自亚洲首页精品 | 亚洲精品www久久久久久 | 国产精品麻豆一区二区 | 成年午夜视频 | 中文字幕亚洲一区二区v@在线 | 久久99久久精品国产只有 | 激情欧美在线 | 国产综合成人观看在线 | 日韩美女在线视频 | 一区二区三区 亚洲区 | 伊人久久大香线蕉资源 | 国产精品国色综合久久 | 国产精品免费观看视频播放 | 久久xxx| 91蝌蚪视频在线观看 | www.色午夜| 午夜毛片视频 | 日日噜噜噜夜夜爽爽狠狠视频 | 欧美人体一区二区三区 | 色一色在线观看视频网站 | 在线亚洲一区二区 | 久久精品亚洲综合一品 | 在线一区二区三区 | 久久精品国产线看观看亚洲 | 加勒比在线免费视频 | 伊人精品在线观看 | 成人午夜无人区一区二区 | 成人怡红院 | 免费国产午夜高清在线视频 | 亚洲手机国产精品 | 国产激情久久久久影 | 综合免费视频 | 亚洲经典激情春色另类 | 亚洲天堂毛片 |