Some tips about crawling large external data with bcs connector

爲了讓SharePoint的搜索組件能夠檢索外部內容源(外部的數據庫、業務系統、二進制文件等等等等),通常需要創建一個自定義的Indexing Connector。Indexing Connector是一種基於SharePoint 2010中的Business Connectivity ServicesSearch Connector Framework的組件,它替代了以前的Protocol Handler,成爲了SharePoint 2010(和FAST Search for SharePoint 2010)所支持的主要的外部數據爬網擴展方式。(SharePoint 2010仍然支持自定義的Protocol Handler。)

在通過BCS的方式創建一個Connector之後,可能面臨的問題之一,就是需要使用它去爬非常大的數據量。比如,幾百萬甚至上千萬的數據項。如果Connector需要面對這樣的挑戰,那麼就需要小心的設計Connector。

首先,Connector需要能夠良好的支持增量爬網。你肯定不希望在增量爬網的速度和完全爬網一樣。

Connector可以以兩種方式來支持增量爬網:基於最後修改時間(Timestamp-based),和基於修改日誌(Changelog-based)。基於最後修改時間也就是你需要指定一個日期時間字段,Crawler會將此字段作爲數據項的最後修改時間,當增量爬網時,Crawler會通過比對這個數據,來知道自己是否需要對一個數據項重新進行處理。基於修改日誌則是專門通過額外的方法,直接將某個時間之後新增、被修改、被刪除的數據項,返回給搜索引擎,這樣搜索引擎就直接知道了從上次爬網到現在,有哪些數據項需要重新處理。

如果外部內容源的數據量非常龐大,即使是第一次的完全爬網,也可能導致Crawler不能正常工作,或者導致外部內容源在短時間內承受過大的壓力。

首先,慎重考慮是否直接使用一個Finder方法,來一次性的從外部內容源返回所有所需要的數據(類似於select * from db_table操作)。在小數據量的情況下,這樣做很方便,但是如果數據量太大,這麼做很可能是不合適的。

比較謹慎的做法,是僅僅使用IdEnumerator方法和SpecificFinder方法獲取數據。IdEnumerator方法(類似於select id from db_table)可以返回數據項的ID,然後使用這些ID,重複調用SpecificFinder方法(類似於select * from db_table where id=@id),來一個一個的獲取數據項。這時,你需要告訴Connector,這個IdEnumerator方法纔是整個Entity的RootFinder。在大部分情況下,你甚至不需要去定義一個Finder方法,因爲Crawler根本就不應該一次從外部內容源獲取過多的數據。

image

如果數據量超大,甚至IdEnumerator方法的執行可能也是有問題的。想象一下,一次性從外部數據源返回所有幾千萬個數據項的ID。這個時候就需要更進一步,讓IdEnumerator方法每次只返回特定數量(比如1000)的數據項ID。

我們可以爲IdEnumerator方法定義一個類型爲LastId的篩選器和對應的輸入參數(即方向爲In的Parameter),這樣Crawler會嘗試重複調用IdEnumerator方法,每次都將上一次調用後所得到的最後一個ID,作爲參數傳入。在IdEnumerator方法的實現代碼中,就可以根據這個傳入的參數,僅從外部內容源檢索此ID之後的數據項ID。

image

image

Crawler會嘗試以下面這種方式,來重複調用IdEnumerator方法,直到它返回0個結果項爲止。(每次調用返回多少數據項,只取決於我們在IdEnumerator方法的實現代碼裏面返回了多少項。)

image

搜索引擎的Crawler有可能會多次調用SpecificFinder方法來獲取同一個數據項(具體原因未知...),所以在Connector裏面,可以考慮使用一些cache的技巧,來減少向外部內容源請求數據的次數。如果內容源的數據量很大,將所有數據都一股腦保存到內存裏面並不是一個好主意。可以考慮使用HttpRuntime.Cache,雖然看起來它僅能用於Web程序,但實際上只需要在程序中引用System.Web這個程序集,在你的Connector裏面使用它是沒有問題的(注:微軟MSDN文檔中註明了它在非ASP.NET程序中可能無法正常工作,但似乎並不存在無法正常工作的情況,但我並不擔保...)。這個Cache的實現已經內置了諸如自動清除、優先級設置、緩存時間設置等等功能,比自己寫一個要方便很多。另外EntLib裏面也有一個可以用於任意類型程序的Cache實現。

除了上面所說的這些之外,Eric Wang還貢獻過一個idea。那就是,(按照他的觀點,)一次性獲取大量數據是沒有問題的,如果真的碰到超大規模的數據,可以在搜索管理中創建多個內容源,每個內容源針對外部數據的一部分進行爬網。比如,如果外部數據有200萬項,可以考慮創建4個內容源,每個內容源根據某種劃分規則,獲取並爬網其中的50萬項數據。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章