簡介
前面一篇<<關於大型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做個辨析。上篇提到了Layered(分層)的架構只能部署在同一台服務上,有同仁在評論裡提出不同意見,說Layered的架構也可以部署到多台伺服器上的。Layer是指應用程式各功能在邏輯上的分組,而Tier表示了應用程式各功能是物理分部在多台電腦上。Layer很好理解,就是相同功能的類被邏輯上分到了一組,如:資料存取的類都放到了一塊,在同一個名稱空間下,在同一個程式集裡,商務邏輯的類也是一樣進行分組,各組之間有統一的調用形式。如商務邏輯的類引用資料存取的類,調用其方法,取得返回結果。同時UI層可調用商務邏輯層的類。商務邏輯層的類既有服務UI層的功能,也有調用資料訪問層的功能。是個承上啟下的Layer。這些Layer都是按照功能來劃分的。Layer是一種邏輯上的劃分。Tier是特指物理的劃分,應用程式的各功能,分別被放在了不同的伺服器上,如UI功能單獨佔用一些伺服器,商務邏輯功能佔用另外的一些伺服器。這兩種功能組件之間有伺服器的邊界,那麼就有專門負責分布式調用的功能組件。如果單從功能邏輯上看,Tier中也是有Layer的,只是比傳統Layer的劃分多了一些用於分布式調用的Layer。Tier是各Layer物理分離後,再加入一些負責分布式調用的Layer才形成的。Tier和Layer是有著聯絡的。從這個意義上說,Tier是Layer物理分離時的特例。有Layer物理分離的情況下,可以稱之為Layered的架構,但是實際上這並不準確,因為Tier是專門為這個情境定義的。有物理分離,就叫Tier更準確些。Layer只要一做物理分離,就轉化成了Tier。
從部署角度試圖來區別Layered的架構和3 Tier / N Tier的架構。因為物理分離的情境已經被定義成Tier,那麼剩下的就只能是物理不分離的情境了。所以Layered架構就特指部署在同一台服務上的情境(即物理不分離),3 Tier / N Tier架構就特指各Layer物理分離的情境。Layered的架構部署到多台伺服器上,理論上是可以的,但是光靠原有的Layer是不夠的,有了伺服器的邊界之後,原來在同一個進程裡面的方法調用就不再可行,必須新加一些Layer來做分布式的調用,才能讓原來的各Layer運行起來。等做完這一切,發現這個架構再叫Layered的架構就不合適了,必須得叫3 Tier / 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加一句:
<httpModules>
<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機制。配置是這樣的:
<system.web>
<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 void SavePageStateToPersistenceMedium(object viewState)
{
}
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等等:
<httpModules>
<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的記憶體,可以適當多開幾個工作者進程。這可以增加單台伺服器的處理能力。要設定Web garden可以先在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請求。那麼儲存的頁面等緩衝才會起到相應的作用。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是肯定要達到的。這不多說了。主要想說說叢集索引。表的叢集索引是很關鍵的一個索引。需要從應用角度考慮,最多的查詢是什麼樣的,然後按照使用最頻繁的查詢來設計叢集索引。一般來說叢集索引需要選用短的,基礎資料型別 (Elementary Data Type)的欄位。比如整數, 固定長度的文本,日期之類的欄位作為叢集索引的欄位。而且具有單向遞增的特性,比如日期,自增的欄位。良好的叢集索引的設計,對最頻繁的查詢的效能改進是很有協助的,同時對插入,更新都有較大的協助。插入時是在物理的表記錄末尾加入新記錄,引起的磁碟IO較小;更新時也可按照索引來很快尋找到記錄並更新。同時也得考慮刪除時的效率。如果可能的話盡量不要刪除記錄,只將需要刪除的記錄置成刪除狀態。
除了叢集索引,還有普通索引,合適的普通索引對查詢的效能也是有協助的。還是分析應用可能的查詢,可以將次優先的那些查詢分析一下,這些查詢主要用到哪些欄位作為搜尋條件。然後可以適當地建立普通索引。這些叢集索引和普通索引對查詢的效能是有協助的。
建立表分區
將表的記錄按一定規則來分到不同的資料檔案上儲存。可以分區的欄位也是基本的類型。比如日期,文本等。建立分區的表的IO可以由多個線程同時來讀寫不同的資料檔案。在IO上可以有所改進。
合理使用視圖
建立一定數量的試圖,可以對查詢效能起到協助。
分布式調用越少越好?
前面一篇文章<<關於大型asp.net應用系統的架構-架構的選擇>>有同仁提出分布式調用越少越好的觀點。這裡可以說一下。如果只有一台伺服器的時候,單純比較用分布式調用和非分布式調用,分布式調用肯定比非分布式調用慢,因為分布式調用要多一些中間介面的處理。但是非分布式調用能同時支援那麼多人同時訪問嗎?非分布式調用能將使用者的請求交由任何一個伺服器來處理而不出現問題嗎?萬一一台伺服器出現了問題,那麼這台伺服器上的使用者就丟失他/她的會話和資料嗎?大家看吧。
當然也有這種可能,就是整個系統中某些地方採用分布式調用,另外一些地方採用非分布式調用。例如:商務邏輯服務和資料訪問服務之間就不用分布式調用了。那麼整個系統的圖就成了這樣:
這樣做不是不可以,就是有其優缺點,優點是商務邏輯調用資料訪問可以比全部分布式的更快,缺點就有可能是,商務邏輯伺服器多到一定程度,就會發現,資料庫連接卻不能再往上增加了,而要統一調度資料庫連接也是很困難的。商務邏輯與資料訪問的耦合度是否有點高?
結束語
對於大型的ASP.NET來說,首先要保證負載平衡和延展性,再來做到每一台伺服器的效能最大化。要使整個系統的服務能力最大化,需要使用軟體硬體的所有手段。這裡談到的只是一些方面,不夠全面。
來源:http://www.cnblogs.com/mikelij/archive/2010/11/30/1892261.html