微軟的站點搜索引擎內幕

Search 開發負責人 Larry Jordan、開發人員 Michael Ruggiero 和 Michael Stanton 以及 .NET 框架項目經理 Hari Sekhar 在暗中構建了基於 .NET 技術的 Microsoft Web 站點搜索引擎新版本。迄今爲止,只有參加過今年 7 月在奧蘭多舉行的“專業開發人員討論會”中的一次特別會議的少數外部開發人員略知一些細節。現在終於可以將實情公諸於衆了。

如果您經常訪問“內幕新聞”站點,您就會知道,Microsoft Web 組在 2000 年 7 月份召開的“專業開發人員討論會”之前推出了其 Search 引擎的新型改進版本。您已知道該版本引入了先進的同義詞匹配、可返回最爲相關的加按語搜索結果的擴展 Best Bets 邏輯,以及對最常用搜索的智能緩存。

然而,有關該版本的內幕消息遠比表面上的東西多。

我們當然會興奮不已,因爲該搜索版本的豐富的功能以及經改進的搜索結果明顯地能爲客戶帶來更佳的搜索體驗(參閱 Search 2.5 技術內幕)。但是,大多數人當時並未意識到,我們同時在幕後將傳統的基於 ASP(Active Server Page 活動服務器頁面)的 Search 2.5 版移植到新型的 Microsoft .NET 框架。

對搜索組而言,這是最具前沿性的開發。因爲我們已經深入到 Internet 服務的未來。而且我們希望如此。下面來談談箇中緣由。

爲何要移植到 .NET?
顯而易見,我們正在進入 Internet 的下一個階段。我們正在跨越通常意義上的 Web 頁面,並在開發功能強大的 Web 服務。在這一階段,使資源和信息有計劃地得到利用是極爲重要的。這樣,我們就可以把這些資源和信息作爲服務來利用,而不是讓其停留在雜亂無章的數據倉庫中。

可擴展標記語言 (XML) 是在超級分佈式系統之間實現多數據集傳輸的一種手段。它同時可以使開發人員以更具價值的新型方式聚集和組合各種來源的數據 – 這樣用戶就可以直接從中受益。

就 Search 而言,我們爲多種自定義和本地化 Search 版本設計了在 microsoft.com 上查找信息的核心功能。我們組在如何使數據訪問兼備靈活性和可用性方面面臨挑戰。在 .NET 出現之前,我們確實無法使客戶在不使用安全端口上的 DCOM (分佈式組件對象模型)的情況下針對我們的功能設計程序,或者客戶只得將我們的多種軟件版本安裝在其服務器上以便訪問代碼和 COM。

我們組對即將推出的 .NET 技術進行了研究,並認識到可以通過將代碼移植到 .NET 框架來解決所有遠程性問題。而且,還有一個意外收穫,我們還可以實現 HTTP 和 SOAP 的無處不在的連接。對絕大多數人而言,是否有某個人在 Microsoft 或在世界的某個地方,使用我們的 Web 服務在內部開發用於完全不同用途的應用程序,無關緊要。我們對兩種情況均予以支持,同時我們也可以免費獲得技術方面的好處。

最新的 Search 2.5 版如今運行在 Site Server 3.0 上,並仍然使用 COM 從搜索目錄獲得結果。該應用程序的其它各個方面都基於 XML。XML 作爲一種將數據(例如,Vocabulary 和 Best Bets)發佈到 Web 服務器的手段,使我們能夠輕而易舉地擴大我們的 Web 空間。

我們同時執行了一項緩存客戶請求的最爲常用的查詢和結果的方案,這是通過將這些查詢和結果保留在 Web 服務器上來實現的,並因此增強了可擴展性,進一步提高了性能。由於我們的核心體系結構是基於 XML 的,因而,移植到一個將利用 .NET 框架 Web 服務的模型確實非常簡單,而這些 .NET 框架 Web 服務是建立在新型 ASP+ 技術基礎之上的(ASP+ 技術被稱爲活動服務器方法 (ASMX) 頁面)。

轉換
Search 體系結構由三個組件組成:
Word Parsing and Vocabulary
Best Bets
Search Results
Search 的 .NET 端口的體系結構與基於 ASP 的版本相同(參見圖 1)。下面讓我們深入瞭解一下各個組件。

圖 1.用戶提交查詢後,(1) 將查詢先提交給解析器 (Parser) 進行詞條分割和詞彙解析,(2) 將找到的項目的顯示術語 (Display Term) 傳給 Best Bets,(3) 將找到的項目的首選術語 (Preferred Term) 和剩餘項目傳給 Search Results,(4) 使用 XSL 樣式表編譯生成的 XML 文檔,(5) 給用戶的 Web 瀏覽器提交 HTML。單擊以放大。

Word Parsing and Vocabulary _ 這是一個包含一個 C++ COM 對象的 Windows 腳本組件,它暴露出 Search 中所支持的所有語言的各種詞條分割程序。這種設計之所以必要是因爲詞條分割程序的接口不容易編寫成腳本,並且通常需要一種 C++ 可編腳本的封裝(儘管這是有辦法做到的:以後將對此進行詳細解釋)。在向 .NET 框架移植的過程中,我們使用了 C++ 對象上的類型列表導出程序 (TLBIMP.EXE),並通過 .NET 中的 Interop 技術對其進行調用,這樣您就可以調用現有的 COM 對象了。

Vocabulary Object 運行 Xpath(查詢 XML 文檔的語言)查詢,以便將搜索詞條映射到首選術語。它同時去除了干擾詞條,併產生一種格式化的數據結構,適合於 Best Bets 和 Search Results 組件進行消耗。一項重要成果是,這個相當複雜的小腳本得以移植到 C#,我們還可以繼續從中調用傳統對象。下面是 Vocabulary Object 中的一個小代碼示例:


// We return an array of VocabularyObjects after parsing the user's search
// text. This ability to create simple typed structures in C# vastly improves
// our code modularity and self-documentation. Here is the definition of
// VocabularyObject:
public struct VocabularyObject {
public string PREFERREDTERM; // structure members
public string DISPLAYTERM;
public bool FOUND;
public string ORIGPHRASE;
public bool MULTITERM;
public bool MULTIWORD;

// Constructor
public VocabularyObject(string preferredterm,bool found,string origphrase,
bool multiterm,bool multiword,string displayterm) {
PREFERREDTERM = preferredterm;
FOUND = found;
ORIGPHRASE = origphrase;
MULTITERM = multiterm;
MULTIWORD = multiword;
DISPLAYTERM=displayterm;
}
}

// Example usage. Because the parameters to the objects constructor are
// typed, we'll get a compiler error message if we passed an integer
// where a string was expected, for example. This is a very nice feature
// over traditional scripting environments!
VocabularyObject vo("Microsoft DirectX",true,"dx",false,false,"DirectX");
.NET 環境的其中一個優點就是,您可以創建用於整個代碼的多數據結構。上面最後一行是闡明如何使用這些 Vocabulary Object 的代碼結構的語句實例。

Best Bets _ 這是一個小腳本組件,它可提供對本地化 XML 文檔的 XPath 查詢,並可產生加按語的 URL 鏈接。XML 文檔裝載於每個 Search 應用程序實例的應用範圍,並既可單獨工作,又可與 Vocabulary 對象的方法緊密耦合。移植小腳本是 100% 向 .NET 框架的轉換,並可利用 System.IO 和 XML DataNavigator 類 (System.NewXml 命名空間)。

這是最簡單的移植組件。它幾乎是行對行地從 Jscript 向 C# 的轉換。我們僅在某些地方對代碼作了一些更改,以便利用新的 XML DataNavigator 類 - 用來查詢並更新 XML 文檔的 .NET 通用語言運行時間部分。

Search Results - 這一複雜的組件與 Site Server 3.0 相接,從而獲得與客戶的搜索查詢相匹配的實際頁面描述和鏈接。它還包含一種完善的緩存算法。

構建並行解決方案
當時我們遇到的最大挑戰是,我們在開發 Search 2.5 的同時,也在將整個 Search 應用程序移植到 .NET 框架的 ASP+ 技術。由於要在 PDC 日期之前推出此應用程序並將其移植到 .NET,週轉時間緊,因此我們當時決定同時推出這兩種版本,並將它們同時上市。很明顯,這是一項艱鉅的任務,因爲我們必須管理新的版本,瞭解新型 .NET 框架的所有功能和新的語言隱喻,構建具有各種軟件平臺服務的服務器,等等。

關於我們是如何搞成這個項目的,還有一段有趣的故事呢。爲了確保同時推出兩種版本(Search 2.5 和 .NET 框架,我們在項目規劃階段確定了首先把握住哪些組件不變、哪些組件在開發過程中變化最大以及哪些組件適合於哪種技術和語言。

我們還及早確定目標,努力分解此應用程序,並按照客戶可能會採用的方式移植。因爲我們 microsoft.com 的人總是認真對待客戶在進行技術決策和研究投資回報時面臨的各種問題,所以,我們將此應用程序移植過程分解成許多部分,每個部分都儘可能與客戶可能採取的方法接近。我們希望確保做好每項工作,其中包括最簡單的移植(即,小腳本移植到 Jscript 類)直到最大的時間和技術利益投入 – 充分利用 C# 編程語言完全移植到 .NET 框架 (100% 可管理的代碼空間)。

下面是我們在應對這個挑戰時所採取的一些步驟:
首先,我們將主要的 ASP 頁面轉換爲 ASP+。最初,我們是通過 .NET Reflection 技術調用小腳本,這樣我們可以在運行時通過查詢類型庫來調用典型的 COM 對象。
重要知識:我們從具有 ASP 的編程模型出發(其中,數據、業務邏輯以及表示全都被混合在一起),然後採用 ASP+ 的一種完全面向對象的方法,最後是數據分離、編程以及 UI。
其次,處理最簡單的小腳本並將其移植。BestBets 是最簡單的組件,並且不依賴於 COM 組件。我們決定使用 System.IO、XML Data Navigator 以及 C# 編程語言將這個組件作爲 DLL 移植。我們希望將這個組件完全移植到受控環境,並使其充分利用 XML Data Navigator。
重要知識:我們瞭解了 NewXml 命名空間。同時,我們在移植組件時去除了 .NET Reflection。這樣我們就可以在本地調用這些組件。
然後,我們以同樣方式處理 Vocabulary 小腳本。這個組件在複雜性和代碼行方面處於此應用程序的中間。它由一個小腳本組成,這個小腳本包含用於 Search 的業務和文本解析規則,並對 C++ 組件進行調用,我們創建該組件的目的是包裝 COM 對斷字程序的引導調用。這個組件在移向受控空間方面具有最大優點。這個複雜組件被全部移植到 .NET 框架和 C# 編程語言。這需要一些技巧,因爲,它包含更爲複雜的函數邏輯,並需要利用一個自定義 COM 對象。但這還不算太難。下一步將拋棄 C++ 包裝並直接調用這些接口。
重要知識:我們更改了函數和邏輯以便受益於象類型安全這樣的 C# 的關鍵優勢。在使用 Jscript 時,開發人員必須銘記每個變量的類型(整數、字符串)。C# 會爲您做到這一點。所有變量在聲明時確定,並且 C# 會檢查您的工作以便確保沒有越界。這在處理複雜代碼時幫助很大。備註: 在 JScript 的下一個版本中,程序員將可以選擇完全確定變量的類型。
移植最終組件:SearchResults。最初,我們通過 .NET Reflection 調用這個組件,而且情況良好。由於這個代碼太大並相當複雜,同時由於在我們推出 Search 2.5 版本之前對該版本作了一些根本性的更改,因此移植該代碼的工作一直持續到現在。在 .NET 測試版中找不到它,但該項工作已取得重大進展。10 月份晚些時候將發佈該版本的更新。


總之,這個體系結構是一個傑作。我們擁有一些真正的 C# .NET 組件,我們擁有所有的 ASMX 頁面。而且,我們演示了可以通過 Interop 調用自定義 COM 對象,以及通過 .NET Reflection 調用小腳本。傳統的對象(比如,SearchResults)可以消耗由 C# 對象(比如,Vocabulary) 創建的數據結構,這是非常好的事。

在您審查 .NET Search 測試版之前值得一提的是,這個體系結構中沒有用戶界面。您所看到的是一項 Web 服務的默認情況。我們本來是可以添加一個 UI 的,但是我們之所以保留成現在這樣,是想讓您看到其本來面目。

如果您經常訪問“內幕新聞”站點,您就會知道,Microsoft Web 組在 2000 年 7 月份召開的“專業開發人員討論會”之前推出了其 Search 引擎的新型改進版本。您已知道該版本引入了先進的同義詞匹配、可返回最爲相關的加按語搜索結果的擴展 Best Bets 邏輯,以及對最常用搜索的智能緩存。

然而,有關該版本的內幕消息遠比表面上的東西多。

我們當然會興奮不已,因爲該搜索版本的豐富的功能以及經改進的搜索結果明顯地能爲客戶帶來更佳的搜索體驗(參閱 Search 2.5 技術內幕)。但是,大多數人當時並未意識到,我們同時在幕後將傳統的基於 ASP(Active Server Page 活動服務器頁面)的 Search 2.5 版移植到新型的 Microsoft .NET 框架。

對搜索組而言,這是最具前沿性的開發。因爲我們已經深入到 Internet 服務的未來。而且我們希望如此。下面來談談箇中緣由。

爲何要移植到 .NET?
顯而易見,我們正在進入 Internet 的下一個階段。我們正在跨越通常意義上的 Web 頁面,並在開發功能強大的 Web 服務。在這一階段,使資源和信息有計劃地得到利用是極爲重要的。這樣,我們就可以把這些資源和信息作爲服務來利用,而不是讓其停留在雜亂無章的數據倉庫中。

可擴展標記語言 (XML) 是在超級分佈式系統之間實現多數據集傳輸的一種手段。它同時可以使開發人員以更具價值的新型方式聚集和組合各種來源的數據 – 這樣用戶就可以直接從中受益。

就 Search 而言,我們爲多種自定義和本地化 Search 版本設計了在 microsoft.com 上查找信息的核心功能。我們組在如何使數據訪問兼備靈活性和可用性方面面臨挑戰。在 .NET 出現之前,我們確實無法使客戶在不使用安全端口上的 DCOM (分佈式組件對象模型)的情況下針對我們的功能設計程序,或者客戶只得將我們的多種軟件版本安裝在其服務器上以便訪問代碼和 COM。

我們組對即將推出的 .NET 技術進行了研究,並認識到可以通過將代碼移植到 .NET 框架來解決所有遠程性問題。而且,還有一個意外收穫,我們還可以實現 HTTP 和 SOAP 的無處不在的連接。對絕大多數人而言,是否有某個人在 Microsoft 或在世界的某個地方,使用我們的 Web 服務在內部開發用於完全不同用途的應用程序,無關緊要。我們對兩種情況均予以支持,同時我們也可以免費獲得技術方面的好處。

最新的 Search 2.5 版如今運行在 Site Server 3.0 上,並仍然使用 COM 從搜索目錄獲得結果。該應用程序的其它各個方面都基於 XML。XML 作爲一種將數據(例如,Vocabulary 和 Best Bets)發佈到 Web 服務器的手段,使我們能夠輕而易舉地擴大我們的 Web 空間。

我們同時執行了一項緩存客戶請求的最爲常用的查詢和結果的方案,這是通過將這些查詢和結果保留在 Web 服務器上來實現的,並因此增強了可擴展性,進一步提高了性能。由於我們的核心體系結構是基於 XML 的,因而,移植到一個將利用 .NET 框架 Web 服務的模型確實非常簡單,而這些 .NET 框架 Web 服務是建立在新型 ASP+ 技術基礎之上的(ASP+ 技術被稱爲活動服務器方法 (ASMX) 頁面)。

轉換
Search 體系結構由三個組件組成:
Word Parsing and Vocabulary
Best Bets
Search Results
Search 的 .NET 端口的體系結構與基於 ASP 的版本相同(參見圖 1)。下面讓我們深入瞭解一下各個組件。

圖 1.用戶提交查詢後,(1) 將查詢先提交給解析器 (Parser) 進行詞條分割和詞彙解析,(2) 將找到的項目的顯示術語 (Display Term) 傳給 Best Bets,(3) 將找到的項目的首選術語 (Preferred Term) 和剩餘項目傳給 Search Results,(4) 使用 XSL 樣式表編譯生成的 XML 文檔,(5) 給用戶的 Web 瀏覽器提交 HTML。單擊以放大。

Word Parsing and Vocabulary _ 這是一個包含一個 C++ COM 對象的 Windows 腳本組件,它暴露出 Search 中所支持的所有語言的各種詞條分割程序。這種設計之所以必要是因爲詞條分割程序的接口不容易編寫成腳本,並且通常需要一種 C++ 可編腳本的封裝(儘管這是有辦法做到的:以後將對此進行詳細解釋)。在向 .NET 框架移植的過程中,我們使用了 C++ 對象上的類型列表導出程序 (TLBIMP.EXE),並通過 .NET 中的 Interop 技術對其進行調用,這樣您就可以調用現有的 COM 對象了。

Vocabulary Object 運行 Xpath(查詢 XML 文檔的語言)查詢,以便將搜索詞條映射到首選術語。它同時去除了干擾詞條,併產生一種格式化的數據結構,適合於 Best Bets 和 Search Results 組件進行消耗。一項重要成果是,這個相當複雜的小腳本得以移植到 C#,我們還可以繼續從中調用傳統對象。下面是 Vocabulary Object 中的一個小代碼示例:


// We return an array of VocabularyObjects after parsing the user's search
// text. This ability to create simple typed structures in C# vastly improves
// our code modularity and self-documentation. Here is the definition of
// VocabularyObject:
public struct VocabularyObject {
public string PREFERREDTERM; // structure members
public string DISPLAYTERM;
public bool FOUND;
public string ORIGPHRASE;
public bool MULTITERM;
public bool MULTIWORD;

// Constructor
public VocabularyObject(string preferredterm,bool found,string origphrase,
bool multiterm,bool multiword,string displayterm) {
PREFERREDTERM = preferredterm;
FOUND = found;
ORIGPHRASE = origphrase;
MULTITERM = multiterm;
MULTIWORD = multiword;
DISPLAYTERM=displayterm;
}
}

// Example usage. Because the parameters to the objects constructor are
// typed, we'll get a compiler error message if we passed an integer
// where a string was expected, for example. This is a very nice feature
// over traditional scripting environments!
VocabularyObject vo("Microsoft DirectX",true,"dx",false,false,"DirectX");
.NET 環境的其中一個優點就是,您可以創建用於整個代碼的多數據結構。上面最後一行是闡明如何使用這些 Vocabulary Object 的代碼結構的語句實例。

Best Bets _ 這是一個小腳本組件,它可提供對本地化 XML 文檔的 XPath 查詢,並可產生加按語的 URL 鏈接。XML 文檔裝載於每個 Search 應用程序實例的應用範圍,並既可單獨工作,又可與 Vocabulary 對象的方法緊密耦合。移植小腳本是 100% 向 .NET 框架的轉換,並可利用 System.IO 和 XML DataNavigator 類 (System.NewXml 命名空間)。

這是最簡單的移植組件。它幾乎是行對行地從 Jscript 向 C# 的轉換。我們僅在某些地方對代碼作了一些更改,以便利用新的 XML DataNavigator 類 - 用來查詢並更新 XML 文檔的 .NET 通用語言運行時間部分。

Search Results - 這一複雜的組件與 Site Server 3.0 相接,從而獲得與客戶的搜索查詢相匹配的實際頁面描述和鏈接。它還包含一種完善的緩存算法。

構建並行解決方案
當時我們遇到的最大挑戰是,我們在開發 Search 2.5 的同時,也在將整個 Search 應用程序移植到 .NET 框架的 ASP+ 技術。由於要在 PDC 日期之前推出此應用程序並將其移植到 .NET,週轉時間緊,因此我們當時決定同時推出這兩種版本,並將它們同時上市。很明顯,這是一項艱鉅的任務,因爲我們必須管理新的版本,瞭解新型 .NET 框架的所有功能和新的語言隱喻,構建具有各種軟件平臺服務的服務器,等等。

關於我們是如何搞成這個項目的,還有一段有趣的故事呢。爲了確保同時推出兩種版本(Search 2.5 和 .NET 框架,我們在項目規劃階段確定了首先把握住哪些組件不變、哪些組件在開發過程中變化最大以及哪些組件適合於哪種技術和語言。

我們還及早確定目標,努力分解此應用程序,並按照客戶可能會採用的方式移植。因爲我們 microsoft.com 的人總是認真對待客戶在進行技術決策和研究投資回報時面臨的各種問題,所以,我們將此應用程序移植過程分解成許多部分,每個部分都儘可能與客戶可能採取的方法接近。我們希望確保做好每項工作,其中包括最簡單的移植(即,小腳本移植到 Jscript 類)直到最大的時間和技術利益投入 – 充分利用 C# 編程語言完全移植到 .NET 框架 (100% 可管理的代碼空間)。

下面是我們在應對這個挑戰時所採取的一些步驟:
首先,我們將主要的 ASP 頁面轉換爲 ASP+。最初,我們是通過 .NET Reflection 技術調用小腳本,這樣我們可以在運行時通過查詢類型庫來調用典型的 COM 對象。
重要知識:我們從具有 ASP 的編程模型出發(其中,數據、業務邏輯以及表示全都被混合在一起),然後採用 ASP+ 的一種完全面向對象的方法,最後是數據分離、編程以及 UI。
其次,處理最簡單的小腳本並將其移植。BestBets 是最簡單的組件,並且不依賴於 COM 組件。我們決定使用 System.IO、XML Data Navigator 以及 C# 編程語言將這個組件作爲 DLL 移植。我們希望將這個組件完全移植到受控環境,並使其充分利用 XML Data Navigator。
重要知識:我們瞭解了 NewXml 命名空間。同時,我們在移植組件時去除了 .NET Reflection。這樣我們就可以在本地調用這些組件。
然後,我們以同樣方式處理 Vocabulary 小腳本。這個組件在複雜性和代碼行方面處於此應用程序的中間。它由一個小腳本組成,這個小腳本包含用於 Search 的業務和文本解析規則,並對 C++ 組件進行調用,我們創建該組件的目的是包裝 COM 對斷字程序的引導調用。這個組件在移向受控空間方面具有最大優點。這個複雜組件被全部移植到 .NET 框架和 C# 編程語言。這需要一些技巧,因爲,它包含更爲複雜的函數邏輯,並需要利用一個自定義 COM 對象。但這還不算太難。下一步將拋棄 C++ 包裝並直接調用這些接口。
重要知識:我們更改了函數和邏輯以便受益於象類型安全這樣的 C# 的關鍵優勢。在使用 Jscript 時,開發人員必須銘記每個變量的類型(整數、字符串)。C# 會爲您做到這一點。所有變量在聲明時確定,並且 C# 會檢查您的工作以便確保沒有越界。這在處理複雜代碼時幫助很大。備註: 在 JScript 的下一個版本中,程序員將可以選擇完全確定變量的類型。
移植最終組件:SearchResults。最初,我們通過 .NET Reflection 調用這個組件,而且情況良好。由於這個代碼太大並相當複雜,同時由於在我們推出 Search 2.5 版本之前對該版本作了一些根本性的更改,因此移植該代碼的工作一直持續到現在。在 .NET 測試版中找不到它,但該項工作已取得重大進展。10 月份晚些時候將發佈該版本的更新。


總之,這個體系結構是一個傑作。我們擁有一些真正的 C# .NET 組件,我們擁有所有的 ASMX 頁面。而且,我們演示了可以通過 Interop 調用自定義 COM 對象,以及通過 .NET Reflection 調用小腳本。傳統的對象(比如,SearchResults)可以消耗由 C# 對象(比如,Vocabulary) 創建的數據結構,這是非常好的事。

在您審查 .NET Search 測試版之前值得一提的是,這個體系結構中沒有用戶界面。您所看到的是一項 Web 服務的默認情況。我們本來是可以添加一個 UI 的,但是我們之所以保留成現在這樣,是想讓您看到其本來面目。

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