1. 程式人生 > >CMU15-440-P0:Implementing a key-value messaging system

CMU15-440-P0:Implementing a key-value messaging system

準備繼續更新blog。

最近工作上一直在寫業務,看些課程換換腦子。

15-440是CMU的一個分散式課程 http://www.cs.cmu.edu/~15-440/syllabus.html ,其實之前在學校的時候就上過分散式的課程,當時用的MIT 6.824的課件,可惜當時很多paper沒有仔細去看,只是把作業做了下,除了lab1都沒有寫blog記錄,導致後來有時間寫blog的時候很多細節都不記得了。

這門課程的作業也是用的go語言,不過go語言在一些低版本中存在某些bug,所以如果使用 go的話儘量升級到最新

今年的P0是實現一個 kv messaging system,相對來講是一個比較簡單的系統。很久沒有寫過go,我也通過這個系統複習了下go語言中的一些特性,然後瞭解到了一些api的相關用法。

這個系統的要求是這樣的:

有一個kv server, kv有兩個介面, get 和put

有若干client,通過網路去呼叫kv server的這兩個介面,去獲取kv中某個key的value或者修改某個key的value。  

並且server還需提供一個介面count,返回的是當前與server連線的client個數。

要求單個server支援多個client的同時訪問,並且執行緒安全

其中還有一個特殊的要求是,client當中可能會有一些是slow reading client,它的特性就是不會立即讀取來自server的訊息,如果server持續的向client寫資料而client一直不讀的話,會導致tcp連線的output buffer爆掉。這種情況需要server對每個client開一個message queue,如果message的數量超過一定數量就自動drop掉。

實現思路如下:

首先這個系統的要求只是單機server支援多client,因此我們要考慮的東西就少了很多。

最簡單的實現思路就是生產者消費者模型,client是生產者,server是消費者,而go語言中實現這個模型最簡單的就是使用channel,channel本質上就是一個加鎖的佇列。

具體實現中

最開始開啟兩個執行緒,一個執行緒為工作執行緒,另外一個執行緒為accept執行緒,用來監聽埠獲取新加入的client連線。

工作執行緒要處理5種操作,需要使用5種channel處理

1. 新client連線的接入:新連線的檢測是通過accept執行緒監聽埠來獲得,然後將連線塞進相應的channel裡。 對於每個新連線進來的client,在server本地維護該client 連線的狀態,並且新建兩個執行緒,分別用來從client讀取資料和向client寫資料, 讀執行緒不斷的從client連線中讀取資料,而寫程序不斷的從client對應的message queue中拉資料寫給client

2. client連線的退出:對於每個要退出的client,移除在本地的維護,關閉有關執行緒。

3. client 發來的具體請求:get或put, get得到的訊息放入對應client的message queue中,如果message queue滿了就drop掉

4. client連線總數的查詢: 收到該請求後,將答案放入相關channel。

5. 關閉server的請求:  將所有連線關閉,每個連線的相關執行緒關閉,然後退出工作執行緒

其中在實現中需要了解的是net包中有關tcp連線的使用方法。

server端 listener := net.Listen("tcp", ":80")即可監聽80埠的連線。

然後通過conn := listener.Accept()即可在服務端獲取該連線

每次讀取client發來的請求:

clientReader := bufio.NewReader(conn)   

message, err := clientReader.ReadBytes('\n')

即每次讀訊息讀到換行符結束即可獲取client傳送來的單次請求

用go語言有時候就是對這些包不太瞭解所以會產生一些問題。

其他程式碼就先不貼了