以前的文章中,介紹瞭如何將RabbitMQ以WCF方式進行發佈。今天就介紹一下咱們產品中如何使用RabbitMQ的!
在Discuz!NT企業版中,提供了對HTTP錯誤日誌的記錄功能,這一點對企業版很是重要,另外存儲錯誤日誌使用了MongoDB,理由很簡單,MongoDB的添加操做飛快,即便數量過億以後插入速度依舊不減。
在開始正文以前,先說明一下本文的代碼分析順序,即:程序入口==》RabbitMQ客戶端===>RabbitMQ服務端。好了,閒話少說,開始正文!
首先是程序入口,也就是WCF+RabbitMQ客戶端實現:
由於Discuz!NT使用了HttpModule方式來接管HTTP連接請求,而在.NET的HttpModule模板中,能夠經過以下方法來接管程序運行時發生的ERROR,以下:
html
而「記錄錯誤日誌"的功能入口就在這裏:
java
固然從代碼能夠看出,記錄日誌的工做基本是經過配置文件控制的,即「HttpModuleErrLog.Enable」。
而RabbitMQClientHelper是一個封裝類,主要用於反射生成IHttpModuleErrlogClient接口實例,該實例就是「基於WCF發佈的RabbitMQ」的客戶端訪問對象。
mongodb
能夠看出它反射的是Discuz.EntLib.RabbitMQ.dll文件的HttpModuleErrLogClient對象(注:使用反射的緣由主要是解決企業版代碼與廣泛版代碼在項目引用上的相互依賴),下面就是其接口和具體要求實現:
數據庫
能夠看出,AddLog方法與上一篇中的客戶端內容基本上沒什麼太大差異,只不過它提供了同步和異步訪問兩種方式,這樣作的目的主要是用戶可根據生產環境來靈活配置。
下面就來看一下RabbitMQ的服務端實現,首先看一下其運行效果,以下圖:
接着看一下啓動rabbitmq服務的代碼:
app
上面代碼會添加IHttpModuleErrLogService接口實現類HttpModuleErrLogService 的Endpoint,並啓動它,下面就是該接口聲明:
異步
代碼很簡單,就是定義了一個添加日誌的方法:void AddLog(HttpModuleErrLogData httpModuleErrLogData)
下面就是接口的具體實現,首先是類聲明及初始化代碼:
ui
能夠看出,這裏使用了靜態定時器對象,來進行定時訪問隊列信息功能(「非同步出隊」操做),這樣設計的緣由主要是爲用戶提供適合的配置方式,即若是不使用定時器(爲0時),則系統會在日誌入隊後,就當即啓動出隊(「同步出隊」)操做獲取日誌信息並插入到MongoDB數據庫中。
下面介紹一下入隊操做實現:
spa
代碼很簡單,主要構造rabbitmq連接(ConnectionFactory)並初始化相應參數如用戶名,密碼,ROUTING_KEY等。
而後將傳入的日誌對象序列化成字符串對象,賦值給targetBody["body"],這樣作主要是由於我沒找到更好的方法來賦值(以前嘗試直接綁定httpModuleErrLogData到targetBody["body"],但在出隊操做中找不到合適方法將httpModuleErrLogData對象解析出來)。
下面就是出隊操做:
設計
出隊操做也是先實例化連接到rabbitmq 的實例,並循環使用BasicGet方法來單條獲取隊列信息,並最終將res.Body的數據序列化成HttpModuleErrLogData對象,並最終插入到mongodb數據庫中。同時將獲取的隊列消息顯示出來:
3d
這裏使用異步方式顯示出隊的日誌信息,其聲明的delegate 方法「ShowMsg」以下:
同時使用LoadAttachment方法來實現HttpModuleErrLogData到mongodb的Document類型的轉換:
到這裏,主要的功能介紹就差很少了。固然本文所闡述的只是一個原型,相信會隨着對rabbitmq的理解深刻而不斷完善,感興趣的朋友歡迎討論交流,以糾正我認識上的誤差,呵呵。