關于大型ASP.NET應用系統的架構—如何做到高性能高可伸縮性
簡介
前面一篇《關于大型asp.net應用系統的架構-架構的選擇》寫完之后,有一些同仁熱心回復,有的是提問題,同時希望能舉一些例子來說明;有的是提建議,希望下一篇寫得更詳細點;還有的同仁提出不同的觀點。感謝大家的參與。會繼續努力的。本文將針對Layer和Tier的區別做個辨析。并詳細介紹3 Tier / N Tier架構中各Tier的開發。各Tier的分布式方式。以及為了達到高性能,低延遲,高可伸縮性,需要采取哪些方法和手段。
關于“大型asp.net應用系統 ”的概念
意指能支持同時在線用戶數目很多的asp.net應用系統。同時在線用戶數目要達到多少才算大型。其實也沒有一個可以作為共識的定義,個人認為如果一個應用系統能做到7x24小時同時在線用戶數不少于5000的,應該可以稱為大型應用系統。例如:微軟的官網(www.microsoft.com),7x24小時都有來自全球的人訪問,有查閱MSDN的,有訪問微軟博客的,有看微軟產品信息的,有逛微軟論壇的,等等等等。同時訪問微軟官網的人太多了,遠多于5000。還有Myspace。 它有總數為幾千萬的用戶,它的同時在線用戶數也是相當驚人的。它之所以能服務眾多的用戶,是因其背后有一個龐大的系統來支撐。
層Layer和排Tier的辨析
這里針對上篇的評論,對層Layer和排Tier做個辨析。上篇提到了分層Layer的架構只能部署在同一臺服務上,有同仁在評論里提出不同意見,說分層的架構也可以部署到多臺服務器上的。層Layer是指應用程序各功能在邏輯上的分組,而排Tier表示了應用程序各功能是物理分部在多臺計算機上。層Layer很好理解,就是相同功能的類被邏輯上分到了一組,如:數據存取的類都放到了一塊,在同一個名稱空間下,在同一個程序集里,商務邏輯的類也是一樣進行分組,各組之間有統一的調用形式。如商務邏輯的類引用數據存取的類,調用其方法,取得返回結果。同時UI層可調用商務邏輯層的類。商務邏輯層的類既有服務UI層的功能,也有調用數據訪問層的功能。是個承上啟下的層。這些層都是按照功能來劃分的。層Layer是一種邏輯上的劃分。排Tier是特指物理的劃分,應用程序的各功能,分別被放在了不同的服務器上,如UI功能單獨占用一些服務器,商務邏輯功能占用另外的一些服務器。這兩種功能部件之間有服務器的邊界,那么就有專門負責分布式調用的功能部件。如果單從功能邏輯上看,排Tier中也是有層Layer的,只是比傳統層Layer的劃分多了一些用于分布式調用的層Layer。排Tier是各層Layer物理分離后,再加入一些負責分布式調用的層Layer才形成的。排Tier和層Layer是有著聯系的。從這個意義上說,排Tier是層Layer物理分離時的特例。有層Layer物理分離的情況下,可以稱之為分層的架構,但是實際上這并不準確,因為排Tier是專門為這個場景定義的。有物理分離,就叫排Tier更準確些。層Layer只要一做物理分離,就轉化成了排Tier。
從部署角度試圖來區別分層Layer的架構和3 排Tier / N 排Tier的架構。因為物理分離的場景已經被定義成排Tier,那么剩下的就只能是物理不分離的場景了。所以分層Layered架構就特指部署在同一臺服務上的場景(即物理不分離),3 排Tier / N 排Tier架構就特指各層Layer物理分離的場景。分層的架構部署到多臺服務器上,理論上是可以的,但是光靠原有的層是不夠的,有了服務器的邊界之后,原來在同一個進程里面的方法調用就不再可行,必須新加一些層來做分布式的調用,才能讓原來的各層運行起來。等做完這一切,發現這個架構再叫分層Layered的架構就不合適了,必須得叫3 排Tier / N 排Tier架構才合適。
層Layer和排Tier之間有聯系,分層Layered的架構和3排Tier / N 排Tier架構可以互相轉化。
整體映象
從前面的描述中可以得知應用系統的每一排Tier都是由許多服務器來完成的。比如UI排Tier,可以是幾十個服務器,幾百個服務器,甚至是幾千個服務器。具體每一個排Tier所需服務器的數目根據實際的需要來配置。所謂實際的需要就是看這一排Tier服務器的硬件資源利用率。比如CPU, 內存,磁盤讀寫等情況,如果相當高,就必須加入新的服務器部署該排Tier同樣的應用到新服務器上。讓新的服務器也能分擔些壓力。其實這就是要讓應用程序能支持高可伸縮性。在每一個排Tier之間有硬件負載均衡,再其后就是下一個排Tier的服務接口了。在其服務接口之后才是該排Tier的服務。
除了高伸縮性之外,還有如何保證高性能。即應用程序必須是良好設計的。在每一個排Tier的內部,可以采取一些措施讓應用程序的執行效率達到最高。讓硬件的資源得到充分的利用。這有一些策略,如緩存。減少訪問數據庫的次數,等等。以下是一個可伸縮的asp.net應用系統的整體映象圖:
1. 首先經硬件負載均衡處理,選定一個Web服務器來響應這個請求,然后將該請求交給該服務器。
2. 此Web服務器執行所請求的頁面,該頁面的后端代碼先查詢緩存服務器,即調用緩存服務接口查詢是否已經有緩存,如果有,就直接返回緩存的結果。
3. 如果緩存里沒有就調用商務邏輯服務接口,進而調用商務邏輯服務。商務邏輯服務執行時,如果需要訪問數據庫,會先檢查緩存中是否有緩存的數據庫內容,如果有,就會用緩存的數據庫內容來進行商務邏輯的計算。如果沒有緩存,就會調用數據訪問接口以存取數據。
4. 類似地,數據訪問服務也會查看緩存,然后根據所要求的數據內容去訪問相應的數據庫,如果是只讀的請求,數據訪問服務可以將數據庫訪問請求發給做日志復制的數據庫服務器。如果是寫的請求,可以發給主數據庫服務器。
5. 數據庫服務器執行應用的Sql請求,返回結果。再由數據服務返回給商務邏輯服務。
6. 商務邏輯服務再返回給Web服務器,由Web服務器生成頁面內容返回給互聯網上的用戶。
以上過程與分層Layered的架構類似,只是比分層Layered的架構多經過了幾個服務接口。如果沒有這些服務接口,因為UI排Tier,商務邏輯排Tier,數據訪問排Tier是在不同的服務器上的,它們根本就不能直接對話。因為它們是在不同的.net VM中的。它們必須得借助與這些服務接口才能互相之間進行調用。這些服務接口具體的組成技術可以是WCF,也可以是.net remoting,等。應該說目前最好的選擇是WCF。
UI排Tier
關于SessionState的技術方案
為了讓應用程序具有可伸縮性,必須讓每一排Tier都有負載均衡的特性,也就是要做到用戶的請求由任何一個同一排Tier中的服務器來處理都不會有任何問題。關于用戶的Session的處理就必須有一個妥善的解決方案。有不少人不贊同采用SessionState,覺得SessionState對ASP.NET應用的性能影響比較大。還有人寫文章說同一個SessionID的AcquireRequestState會在頁面代碼前獲得對Session對象的鎖,因此容易有較大的延遲,對性能影響不小。另外的人認為Session占用服務器的內存比較多,同時需要一些CPU資源來將Session中的對象序列化和反序列化。所以一種比較普遍的觀點是不采用ASP.NET本身提供的Session機制。其實采用SessionState和不采用SessionState都各有特點。了解其特點后再做權衡取舍才比較合適。
完全不采用SesstionState
完全不采用SesstionState是在Web.config中寫上<sessionState mode=”Off”/> 或者 <Pages enableSessionState=”Off”/>來禁止SessionState。那整個應用的所有頁面都不會用SessionState。其實這不全面,http請求處理周期里還有一個系統默認的httpmodule在處理SessionState。還須在Web.config加一句:
<remove name="Session" />
</httpModules>
應用程序里完全不采用ASP.NET本身提供的SessionState機制,但是應用的需求是要求應用程序有類似于Session的機制的。比如購物車的概念。記住用戶選擇了哪些商品,在用戶點了買單時才處理用戶選擇了的商品。如果不用ASP.NET本身提供的SessionState機制,就必須自己實現一個Session機制。比如可以在數據庫中有一張表來記錄自定義的Session數據。如果用戶瀏覽器支持cookie,可以用該cookie存儲自定義的Session ID值。這個Session ID值用于到數據庫中去查詢存儲的Session數據。如果用戶瀏覽器不支持cookie,那么就可以在頁面中放置隱藏的字段(hidden field)。此隱藏字段用于存儲自定義的Session ID。還可以用URL中參數放一個Session參數的辦法。這樣獲得的Session機制是自己管理的Session機制。需要將Session的創建,過時失效,查詢Session數據,刪除舊Session等都管理起來。
這樣的自定義的Session機制將Session數據存儲到了數據庫。那么就可以不依賴與某一臺具體的服務器。從而獲得的可伸縮的特性。
采用SessionState
采用SessionState是ASP.NET默認的機制。ASP.NET的SessionState有幾種模式。InProc,StateServer,SqlServer模式和自定義模式。InProc不支持負載均衡的場景。只有StateServer和SqlServer模式才支持。自定義模式是指我們自己實現Session數據的持久化,比如將Session數據放到Oracle數據庫或者MySql數據庫中,自定義模式也可以支持負載均衡。在StateServer和SqlServer模式時,放入Session中的數據都必須是能序列化的。建議采用SqlServer模式的Session機制。配置是這樣的:
<sessionState mode=" Off | InProc | StateServer | SQLServer "
cookieless=" true | false "
timeout=" number of minutes "
stateConnectionString=" tcpip=server:port "
sqlConnectionString=" sql connection string "
stateNetworkTimeout=" number of seconds " />
</system.web>
Session采用了SqlServer模式之后,所有數據都會經序列化,并存儲到SqlServer數據庫中。采用這種模式的Session機制,其Session可以由任何一個UI排Tier的服務器來處理,因為Session數據是存儲在專門的數據庫中的。如果是采用這種模式的Session機制,那么最好有專門的數據庫服務器供存儲Session數據。通過上述安排,ASP.NET應用就獲得了負載均衡,可伸縮的能力。
采用了ASP.NET的SessionState的之后,同一個Session ID下的不同頁面請求會有一定的制約。注意這里說的同一個Session ID下的不同頁面。這就象數據庫的鎖機制一樣。默認的ASP頁面設置都是能對Session對象進行讀和寫。那么如果同一個Session ID的兩個不同請求訪問兩個不同的頁面,就會因為都去鎖住Session對象,而造成有一個請求被阻塞較長時間,因為要等另一個請求處理完畢。有同仁可能覺得奇怪,怎么會有同一個Session ID請求兩個不同的頁面。其實這與頁面中的iframe,frameset和AJAX技術有關。包含iframe, frameset的頁面已經要存取Session了,iframe或者frameset里面的頁面也要存取Session,就有可能造成一先一后,都是同一個Session ID,后面的頁面被前面的頁面鎖住,直到前面的頁面都處理完,釋放對Session的鎖,才能處理后面的頁面。AJAX也類似。也存在這個問題。這個默認的機制所帶來的延遲在小型的ASP.NET應用中可以不用理睬。但是在大型的ASP.NET應用中是必須解決的問題。要解決這個問題,只能從應用的角度盡力減少需要寫Session的范圍,即明確確定哪些頁面需要讀且寫Session數據。還需要確定哪些頁面是只需要讀Session數據。另外還需要確定哪些頁面不需要參與讀或者寫Session數據,即與Session數據無關的頁面。通過這樣的工作,就確定了Session的范圍。對于需要讀且寫Session的頁面,可以顯示地在頁面中寫上< % @Page enableSessionState=”On”% >。對于只需要讀Session的頁面,可以寫上< % @Page enableSessionState=”ReadOnly”% >。對于不需要Session的頁面,可以寫上< % @Page enableSessionState=”Off”% >。在一個iframe相關的所有頁面中,不要所有的頁面都去讀寫Session,這樣就可以避免Session爭鎖所帶來的延遲。AJAX所涉及的頁面也是如此,盡可能地減少讀寫Session,發生這種Session爭鎖的延遲就會少一些。鎖越少,整個UI排Tier的處理能力就會越大。
關于ViewState的技術方案
ViewState使服務器控件可以在往返行程中重新填充它們的屬性值,而程序員不需要編寫任何代碼。這些屬性值包括可見的屬性,也包括不可見的。可見的屬性如Text屬性,不可見的是某些控件的ControlState。ControlState是比較特殊的內容,它總是存儲在ViewState字段中。即使用EnableViewState="false"禁止了ViewState,ViewState字段還是有一些內容,這些內容就是ControlState。
曾經聽到不少人抱怨說ViewState大,有時光ViewState就幾百K。一個頁面的HTML,很大的部分是ViewState占用了。微軟的文章也在說不需要ViewState的地方就禁止ViewState。所以合理決定應用程序哪些地方需要ViewState。畢竟ViewSate也一定程度上帶給程序員一些方便。禁止ViewState是可以在整個應用的級別,頁面的級別,和控件的級別來禁止。整個應用的級別禁止ViewState: <pages enableViewState="false" enableViewStateMac="false" enableEventValidation="false"></pages>,頁面的級別如:< % @ Page EnableViewState="false" % >,控件的級別如:<asp:datagrid EnableViewState="false" datasource="..." runat="server"/>。禁止了ViewState之后,頁面中的__ViewState字段已經大大減小了,但是還是存在。上面已經提到了,__ViewState字段里剩下的內容就是ControlState的。如果想讓__ViewState字段沒有內容,可以改寫Page類的此兩方法:
{
}
protected override object LoadPageStateFromPersistenceMedium()
{
return null;
}
這樣__ViewState字段就完全沒有內容了。當然我們可以在此兩方法里面設計出自己的持久化ViewState內容的方案。比如將ViewState持久化到緩存中去,或者持久化到SqlServer中去。那么ViewState的內容就不再需要發送的到用戶瀏覽器中了。上面介紹了一些在某些地方禁用ViewState的方法。下面就由開發者和用戶來決定哪些頁面或者控件需要ViewState,還是完全不要ViewState。ViewState機制具有兩面性,一方面方便了程序員,另一方面可能對性能造成影響。所以要小心對待。
減少與服務器的交互次數和不必要的服務器端處理
Page.IsPostBack
Page.IsPostBack可以判斷是否有Form提交。第一次訪問時的處理和有Form提交的處理是不一樣的。這樣可以避免不必要的服務器端處理。
AutoPostBack屬性
許多服務器端控件都有AutoPostBack,能禁止的都禁止了。
多做客戶端的數據驗證
用戶在瀏覽器里面的輸入,盡量先用客戶端JavaScript驗證處理,等通過了在提交給服務器。這樣減少向服務器提交請求的次數。
AJAX的請求量進行控制
AJAX帶來了很炫的效果,但是能適當地減少調用AJAX調用次數,比如能否合并AJAX的調用。
用Server.Transfer不用Response.Redirect
Server.Transfer發生在服務器端,而Response.Redirect發生在用戶瀏覽器中。會多一次HTTP請求。
去除不必要的默認httpModule
如不要SessionState,不要WindowsAuthentication,不要PassportAuthentication等等:
<remove name="Session" />
<remove name="WindowsAuthentication" />
<remove name="PassportAuthentication" />
<remove name="AnonymousIdentification" />
<remove name="UrlAuthorization" />
<remove name="FileAuthorization" />
</httpModules>
設置processModel
手動設置processModel參數中的MaxWorkerThreads 和 MaxIOThreads 屬性,通過觀察效果帶調整參數。如果機器資源允許,可以稍微多點。
設置Web garden
只要服務器資源允許,就可以建立Web garden,在同一個服務器上多開幾個工作者進程。32位Windows上一個進程通常只能占用2G-3G內存(因為高地址的2G或者1G是Windows本身用來裝配系統文件用的)。64位Windows上一個進程能占用的內存相對32位大一點,但是服務器有比如100多G的內存,可以適當多開幾個工作者進程。這可以增加單臺服務器的處理能力。要設置Webgarden可以先在IIS管理器里面找到對應的應用程序池,在查看該應用程序池的高級屬性,再找到最大工作者進程參數,見圖。
ASP.NET中可用的緩存主要有:頁面級的緩存,控件級,System.Web.Caching.Cache,以及分布式緩存如Velocity和memcahced。頁面級的緩存可以在ASPX頁面用< % @ OutputCache Duration="10" VaryByParam="none" % >,在用戶控件中可以用< % @ OutputCache Duration="10" VaryByParam="none" VaryByControl=””% >,與頁面級的cache相比,多了VaryByControl參數。必須得指出這些頁面級的和控件級的緩存是存儲在特定的Web服務器上的。除非在負載均衡的硬件上做特殊的設置,否則這些頁面級和控件級的緩存都意義不大。因為這些頁面級的和控件級的緩存是存儲在特定的Web服務器上的,第一次用戶的請求是由此服務器處理的,然后有了頁面緩存,如果負載均衡硬件將第一次以后的請求交由其他服務器處理,那么這個處理第一次請求所做的頁面和控件級緩存都失去了意義。只有進行了特殊設置后,負載均衡的硬件才能知道剛才這個請求是哪個服務器處理的,就繼續向該服務器轉發HTTP請求。那么保存的頁面等緩存Cache才會起到相應的作用。System.Web.Caching.Cache是個很好的緩存機制,可以給程序員利用來緩存一些內容。可惜它不是分布式的。它的存儲限定在特定的服務器上。所以它對負載均衡是不支持的。要支持負載均衡,需要使用分布式的緩存如Velocity或memcached,在UI排Tier緩存的內容可以是數據庫查詢結果。如果是自己管理的Session機制,可以將分布式緩存作為Session的存儲,所有Session中的對象,可以存儲在分布式緩存中。還有ViewState,如果希望客戶瀏覽器不下載ViewState但是又要用ViewState,可以重載Page類的SavePageStateToPersistenceMedium和LoadPageStateFromPersistenceMedium方法,并在此方法中將ViewState存儲到分布式緩存。
考慮預編譯
將所有ASP.NET頁面都預先編譯。可以減少第一次訪問時由于ASP.NET編譯頁面所帶來的延遲。
在生產環境禁用調試模式
生產環境使用Release模式的編譯,會使程序運行稍微快一點。
盡量避免異常
異常是非正常的程序控制流。發生異常多對性能的影響比較大。所以在程序中多對可能的情況進行檢測,比如判斷某對象是否為空。此同樣適用于其他排Tier。
盡量避免鎖住資源
在多線程的場景下,盡可能地去避免鎖住資源。盡量各線程都用私有的資源。此同樣適用于其他排Tier。
壓縮頁面和相關文件
比如可以打開IIS的gzip,還有用一個自制的HTTP module壓縮頁面的HTML, .js文件。去掉不顯示的回車和空格。進行盡可能多的壓縮。
商務邏輯排Tier
商務邏輯服務接口
前面已經提到,服務接口可以考慮用WCF, Remoting等技術。目前最好的是采用WCF。原因是WCF支持事務,支持多種通信方式。商務邏輯服務有時是必須在互聯網上公開。所以WCF可以選用基于Web service的通信方式,這樣支持的外部系統比較多。如果商務邏輯服務只是在內部使用,可以選用TCP/IP socket的通信方式。這個商務邏輯服務接口其實就是后面的商務邏輯服務的包裝。商務邏輯服務提供哪些方法,就用相應的接口進行對應。
商務邏輯
事務的控制
商務邏輯這里應該對事務進行控制。這與WCF接口支持事務想匹配的。
預取與緩存
比如翻頁,可以在用戶取第一頁時,取出5頁,緩存起來,用戶往后翻幾頁時就可以不再查詢數據庫。減少對數據庫的查詢次數。有些查詢特別多的數據,直接都在分布式緩存里面存著。只有緩存里沒有的時候,才去查詢數據庫。
對數據庫的訪問也是可以分布式的調用
大家看到了上面的圖,對數據庫的訪問也是需要通過分布式的調用才能完成。數據庫查詢的結果通過自定義的對象集合來傳遞。
采用自定義的對象作為商務邏輯的處理對象
這些自定義的對象其實就是一個數據庫中數據的在內存中的反映。商務邏輯的處理對象最好用自定義的對象。不要用DataSet。
商務邏輯排Tier最好是無狀態的
該排Tier最好是狀態無關的。與商務有關的數據都存儲到分布式緩存里面。服務器內存里面不長時間存儲商務有關的數據。這樣,一個對商務邏輯的請求就可以由任何一臺商務邏輯排Tier的服務器來處理,這樣就做到了負載均衡。
長時間計算型的任務最好交給其他系統來在后臺處理
有些計算密集的任務,最好交給其他系統在后臺運行。與計算密集的系統交互就只通過數據文件進行交互。
數據訪問排Tier
數據訪問服務接口
類似于商務邏輯服務接口,數據訪問服務接口可以考慮用WCF, Remoting等技術。目前最好的是采用WCF。原因是WCF支持事務,支持多種通信方式。可以選用基于Web service的通信方式,也可以選用TCP/IP socket的通信方式。這個數據訪問服務接口其實就是后面的數據訪問服務的包裝。
數據訪問
對事務的支持
如前所述,商務邏輯控制著事務,數據訪問排Tier只是作為商務邏輯控制的事務的一部分。數據訪問排Tier中有許多數據庫的操作,如,查詢,更新等。建議所有的數據庫操作都用存儲過程來實現。這些數據庫操作都作為商務邏輯控制的事務的一部分。不要在存儲過程中實現商務邏輯。這些數據庫操作都只是替商務邏輯服務完成數據庫查詢或者存儲數據到數據庫的任務。所以不要在存儲過程或者數據訪問排Tier實現任何商務邏輯的內容。
數據庫讀寫分離的支持
如前圖所示,數據庫有只讀模式的。可以將部分讀的請求分流到只讀模式的數據庫服務器上。只有寫的請求才流到主數據庫服務器上。這就要求分別支持不同的連接。
連接池的管理
每臺數據庫服務器所允許的連接數是一定的。需要管理好個數據訪問服務的數據庫連接。管理好每臺數據訪問服務服務器連接池。
在讀的時候用SqlDataReader
讀取數據的時候,可用SqlDataReader來讀取快速只進的數據流。
緩存
將數據庫訪問獲得的內容緩存到分布式緩存服務器上。
數據庫的設計和安排
讀寫分離
主數據庫服務器是集群的數據庫服務器。SqlServer 2008 R2 / Windows Server 2008 最多支持16臺服務器的集群。可以架設一些只讀模式數據庫服務器,采用日志復制方式,將主數據庫的所有日志復制到只讀模式的數據庫服務器上。那么只讀模式數據庫服務器內容就可以保持和主數據庫服務器一致。這些只讀數據庫服務器就可以用于分擔讀的壓力。
庫表的分離
從應用的角度將某一些數據分到多個數據庫來存儲。比如Myspace有7000多萬用戶,它把每一百萬用戶存放于一個數據庫。這樣每個數據庫都小了很多。查詢起來相對快一些,但是程序就會設計得復雜一點。分開的數據庫可以放在不同的服務器,也可在同意服務器。請根據實際情況來決定。
表的設計
3NF, BCNF是肯定要達到的。這不多說了。主要想說說聚集索引。表的聚集索引是很關鍵的一個索引。需要從應用角度考慮,最多的查詢是什么樣的,然后按照使用最頻繁的查詢來設計聚集索引。一般來說聚集索引需要選用短的,基本數據類型的字段。比如整數, 固定長度的文本,日期之類的字段作為聚集索引的字段。而且具有單向遞增的特性,比如日期,自增的字段。良好的聚集索引的設計,對最頻繁的查詢的性能改進是很有幫助的,同時對插入,更新都有較大的幫助。插入時是在物理的表記錄末尾加入新記錄,引起的磁盤IO較小;更新時也可按照索引來很快查找到記錄并更新。同時也得考慮刪除時的效率。如果可能的話盡量不要刪除記錄,只將需要刪除的記錄置成刪除狀態。
除了聚集索引,還有普通索引,合適的普通索引對查詢的性能也是有幫助的。還是分析應用可能的查詢,可以將次優先的那些查詢分析一下,這些查詢主要用到哪些字段作為搜索條件。然后可以適當地建立普通索引。這些聚集索引和普通索引對查詢的性能是有幫助的。
創建表分區
將表的記錄按一定規則來分到不同的數據文件上存儲。可以分區的字段也是基本的類型。比如日期,文本等。創建分區的表的IO可以由多個線程同時來讀寫不同的數據文件。在IO上可以有所改進。
合理使用視圖
創建一定數量的試圖,可以對查詢性能起到幫助。
分布式調用越少越好?
前面一篇文章<<關于大型asp.net應用系統的架構-架構的選擇>>有同仁提出分布式調用越少越好的觀點。這里可以說一下。如果只有一臺服務器的時候,單純比較用分布式調用和非分布式調用,分布式調用肯定比非分布式調用慢,因為分布式調用要多一些中間接口的處理。但是非分布式調用能同時支持那么多人同時訪問嗎?非分布式調用能將用戶的請求交由任何一個服務器來處理而不出現問題嗎?萬一一臺服務器出現了問題,那么這臺服務器上的用戶就丟失他/她的會話和數據嗎?大家看吧。
當然也有這種可能,就是整個系統中某些地方采用分布式調用,另外一些地方采用非分布式調用。例如:商務邏輯服務和數據訪問服務之間就不用分布式調用了。那么整個系統的圖就成了這樣:
這樣做不是不可以,就是有其優缺點,優點是商務邏輯調用數據訪問可以比全部分布式的更快,缺點就有可能是,商務邏輯服務器多到一定程度,就會發現,數據庫連接卻不能再往上增加了,而要同一調度數據庫連接也是很困難的。商務邏輯與數據訪問的耦合度是否有點高?
結束語
對于大型的ASP.NET來說,首先要保證負載均衡和可伸縮性,再來做到每一臺服務器的性能最大化。要使整個系統的服務能力最大化,需要使用軟件硬件的所有手段。這里談到的只是一些方面,不夠全面。
<remove name="Session" />
</httpModules>