讓Delphi的DataSnap發揮最大效率
一個DataSnap的應用程式由兩個層組成:
DataSnap伺服器,它有一個帶有一個或者更多DataSetProvider元件的遠端資料子產品;DataSnap用戶端,它帶有一個xxxConnection元件和一個或者多個連接配接到DataSetProviders的ClientDataSets。
你可以不使用ClientDataSet而換用XMLBroker元件,後者是專門用在InternetExpress Web伺服器應用程式上的。 DataSetProviders的作用是把資料導出到外部世界,而ClientDataSets的功能是接收資料(并把請求和更新發送回DataSetProvider)。許多DataSnap用戶端都可以連接配接到單個DataSnap伺服器,向伺服器請求資料,而伺服器往往就是資料吞吐量瓶頸發生的地方。
讓我們開始吧 讓我們就從這個問題的解決開始,确認線路上發送資料的真實量是很有必要的。是以,我們不會去研究(請求和接收資料的)ClientDataSets,而是要研究一下DataSetProvider元件——它會回應資料請求進而發送資料。
幸運的是,DataSetProvider元件有一些有用的虛拟方法,它們能夠被用來強制替代(别的方法)以及包含我們的“追蹤”代碼,這樣你就能夠了解資料吞吐的真實情況。 一旦了解了情況,你就可以開始着手降低吞吐量了。當然,你不能因為能夠優化就開始進行優化;總得有個原因。但是一旦有幾百個用戶端連接配接到你的DataSnap伺服器,所有用戶端都會請求成兆的資料,你就要因為這個原因而立即開始優化了。 DataSnap就是原來的MIDAS DataSnap技術是MIDAS的新名字,它在Delphi企業版裡(或者C++Builder企業版裡)被用來建立多層應用程式。當我談到DataSnap的效率時,我主要關心的是資料吞吐量的瓶頸,包括限制從伺服器層發送到客戶層的資料量進而防止瓶頸的方法。在你能夠限制吞吐量之前,你首先要測量它。
在本文的後半部分裡,我會假設你有一個DataSnap伺服器和用戶端可用。如果你需要的話,可以在Delphi6DemosMidasMstrDtl獲得一個DataSnap主從複合結構(master-detail)的示例項目。為了測量資料量,你把TdataSetProvider元件用一個叫做TB42DataSetProvider的專用版本替換掉。新的元件有一個BytesTransferred屬性,它會包含自從其被建立以來被傳送的位元組數量。 它會強制替代InternalGetRecords方法,以增加FbytesTransferred裡的值,并報告所傳送的位元組數量,還會報告新的資料包已經被發送,包括記錄的數目以及資料包的大小。這兩個方法(見Listing A)會被ClientDataSet或者XMLBroker元件調用,用以響應DataSnap用戶端的資料請求。 要注意,eBob42PRO單元裡的代碼會使用InternalGetRecords和CreateDataPacket方法裡的簡單writeln聲明。這就意味着你必須把{$APPTYPE CONSOLE}這一行添加到你DataSnap伺服器的主項目裡,這樣才能為調式的輸出打開一個控制台視窗。如果你忘了做這個,那也不用擔心DataSnap伺服器會向你報I/O錯誤了,因為IsConsole的檢查會確定writeln聲明隻在控制台應用程式裡被确實地調用。 要使用這個元件很簡單:把TB42DataSetProvider元件添加到元件調色盤裡的一個Delphi工具包裡,并使用TB42DataSetProvider替換掉你遠端資料子產品上的普通TdataSetProvider。 ClientDataSet的PacketRecords 使用ClientDataSet連接配接到DataSetProvider(它指向整個表格)的潛在危險之一是:當你打開ClientDataSet的時候,它會預設地從DataSetProvider請求所有的資料。這就意味着(伺服器端)表格的全部内容都要通過線路送到ClientDataSet。對于Delphi自己的示例資料庫表格當然是沒有問題的,舉個例子的話,因為消費者和訂單的表格所包含的記錄會少于100條。但是,在現實生活中,公司的消費者會多于100個(而訂單的數量會更多),擷取所有客戶(的資訊)會花上一段時間,在你每次打開ClientDataSet的時候把表格的内容從DataSnap伺服器發送到DataSnap用戶端也要花上一段時間。 解決這個問題的一種方法是使用ClientDataSet元件的PacketRecords屬性。這個屬性會對資料的初始請求進行修改,讓其包含被請求資料包的大小(以記錄的形式)。是以如果有上千條記錄存在的話,你隻用取得檔案X,而檔案X是PacketRecords屬性的值。在預設條件下,這個屬性被設定為-1,即“把所有的記錄都給我”。