1. 基本思路:
2. 模組劃分
整體分為4個模組:
3. 核心流程
http伺服器獲取使用者的請求並處理,將資料傳給cgi程式。
cgi程式提取資料獲取有用的資訊(query),提交到搜尋伺服器端
搜尋伺服器端處理資訊進行檢索操作,把結果反饋給cgi程式
cgi程式將檢索結果進行html格式化後,傳送給http伺服器
http伺服器收到結果將其列印到頁面上
4. 搜尋伺服器的核心流程
對請求進行解析
對查詢次進行分詞 (cppjieba分詞)
根據每個分詞結果 ,查詢包含相應網頁內容的檔案id
將找到的所有結果進行排序(檔案id集合)
根據對應的檔案id,獲取相應**資訊
構造響應,傳回http伺服器
5. 流程圖
使用到google提供的 protobuf, gflag, glog 等開源框架來完成開發
搜尋原理是以正排索引加倒排索引相結合的方式進行檢索
http伺服器以cgi的方式呼叫搜尋客戶端完成搜尋功能
http伺服器使用epoll模型,提高了併發的響應速度
這裡只介紹搜尋伺服器有關的實現,對於http伺服器請檢視:基於cgi協議的http伺服器專案
1. 索引模組核心結構的定義
實現乙個搜尋引擎,必須要考慮到的問題有:怎麼存放資料?怎麼傳輸資料?怎麼進行檢索?
首先關於存放資料:我們就要為其定義乙個較為完整的結構,這個結構包括了檔案的id號(我們為了方便資料的檢索,為每乙個獲取到的檔案進行編號),檔案的標題,檔案的正文,檔案的url(我們要進行網頁搜尋)
傳輸資料並不是簡單的在同一臺主機上進行,而是在網路上不同主機間進行,需要資料的序列化與反序列化,我們得為此構建乙個較為健全的序列化方法。
綜合上述問題,我們決定使用google提供的 protobuf 序列化開源框架來實現,protobuf具有
的特點,非常適合我們來對資料的管理,即對資訊的傳輸,很好的滿足了我們的需求,還有乙個重要的特點,這個protobuf是c++實現的,我們這個專案也是乙個c++專案,也就不存在什麼相容性的問題了。
關於protobuf來構建索引的核心結構,可以參考:利用 google protobuf 構建索引核心結構
2. 索引模組的構建
bool index::build(const
std::string& input_path)
//4. 對倒排結果中的資料進行排序
sortinverted();
file.close();
return
true;
}
讀取所有要構成索引的資料,我們這裡的資料是經過處理的,每一行每一條索引資訊,包括了網頁url,**標題,**正文
構建的過程,每次從檔案中讀取一行的資訊,將這一行構成乙個正排索引的結點,並利用cppjieba
分詞工具對標題和正文內容進行分詞操作,得到乙個乙個分詞結果,這裡分詞使用記錄開始位置和結束位置以左閉又開的區間方式儲存,方便之後新增倒排索引。
當資料統計後,並且所有的倒排結果更新完成後,需要對倒排索引的中資料進行排序,為了更好的滿足使用者需求,我們必須將與關鍵字匹配度最高的資料放到最前面。
排序完成後我們索引結構也就構造好了,接下來我們只需把結果寫入乙個檔案儲存下來。
3. 索引模組的載入
bool index::load(const
std::string& index_path)
從由構建函式儲存下來的檔案中,讀取整個索引結構放到字串中,由於該字串是經過序列化的,因此我們要進行反序列化,並反序列化的結果放進我們所定義好的結構體中,完成將索引資料從磁碟到記憶體的讀取。
4. 搜尋伺服器端的實現
sofa-pbrpc
也是基於protobuf
所完成的,因此我們同樣需要構建protobuf
檔案,我們需要編寫乙個以.proto
為副檔名的檔案內容如下:
syntax="proto2";
package doc_server_proto;
option cc_generic_services= true;
//------------ request ---------------------
message request
;//------------ response ---------------------
message item
;message response
;//------------ service ---------------------
service docserverapi
;
內容很簡單,分為請求結構,響應結構,和服務函式三部分,服務函式的結構是固定的,這個服務函式最終分成兩個部分,乙個在伺服器端重寫,另外乙個在客戶端使用。
伺服器端的**如下:
int main(int argc, char* argv)
總體來說,伺服器端所要做的就是將索引模組載入進來,完成rpc服務端的配置,等待rpc客戶端的訪問
關於rpc服務端的配置,借用sofa-pbrpc
框架完成,首先定義乙個操作類,來設定相關的操作,如執行緒的個數,利用這個操作物件構建乙個rpc服務物件,繫結好ip位址和埠號,定義乙個函式物件的指標,然後註冊到伺服器物件中,讓伺服器執行起來即可。
在伺服器端乙個重要的操作就是用繼承從proto檔案中編寫的服務類,並且要重寫那個服務函式,而這個重寫的函式就是我們整個伺服器真正要執行操作:
//從doc_server_protr中繼承過來
class docserverapiimpl : public doc_server_proto::docserverapi
};
關於伺服器的計算過程,具體過程實現如下:
// 這個類是完成搜尋的核心類
class docsearcher ;
5. 搜尋客戶端的實現
//此函式為客戶端請求服務區的入口函式
void callserver()
客戶端主要分三步,第一步構造響應,為了獲取query_string,並且生成乙個相應的請求,第二部,根據請求呼叫相應的rpc函式,來訪問搜尋客戶端,得到響應;第三步,將響應根據html模板包裝成http響應,傳回http伺服器,搜尋過程也就完成了
本專案主要針對外部庫的使用,包括資料的存放,傳輸,rpc框架的呼叫等等,雖然使用的並不是很熟練,但是還是完整的實現了搜尋伺服器這個專案!
搜尋引擎專案
server端 linux centos6.0 g version 4.4 client端 p hpsrc 存放系統的原始檔 cpp include 存放系統的標頭檔案 h bin 存放系統的可執行程式。conf 存放系統程式中所需的相關配置資訊。lib 存放系統程式中所使用的庫檔案。data 存放...
搜尋引擎 索引
正排索引 文件編號,單詞編號,單詞的數量,單詞出現的位置。倒排索引 1,單詞詞典,儲存單詞以及統計資訊,單詞在記錄表中的便宜,可常駐記憶體,用雜湊表儲存。2,記錄表,單詞對應的文件集合,記錄單詞出現的數目 位置。文件採用差分變長編碼。其中文件可按編號公升序排列 可利用差分編碼 也可按出現次數排列,可...
MySQL搜尋引擎程式 mysql搜尋引擎
mysql是我們比較常用的一種資料庫軟體。它有著諸多的優點,如開源的,免費的等等。其實它還有乙個很好的特點,那就是有多種引擎可以供你選擇。如果賽車手能根據不同的路況,地形隨手更換與之最適宜的引擎,那麼他們將創造奇蹟。然而目前他們還做不到那樣便捷的更換引擎,但是我們卻可以 所謂知己知彼方可百戰不殆,要...