MiniCDN - 一個 Golang 實現的 CDN

f627 9年前發布 | 26K 次閱讀 MiniCDN

一般來說會推薦采用qiniu或者upyun,又或者是amazon之類大公司的cdn服務,不過當需要一些自己實現的場景,比如企業內部軟件的加速,就需要一個私有的CDN了。

極簡內容分發系統是我在公司里面的一個項目,最近把他開源出來了。可能其他企業或者組織也需要一個類似的東西。

通常來說CDN分為push和pull兩種方式,push比較適合大文件,pull適合小一些的文件,但是使用起來比push要簡單的多。

MiniCDN采用的就是pull這種方式,目前的實現方式是所有緩存的文件存儲在內存中,使用LRU算法淘汰掉就的文件,鏡像的文件受限于緩沖區的大小(目前的緩沖區是512M),如果超過了這個緩沖器大小,就沒有加速的效果了。

沒有所有的智能DNS,直接用的是最簡單的http redirect. 還沒寫負載均衡, 所以redirect的時候,就是隨機返回一個節點(簡單粗暴)

MiniCDN分為manager和peer。都是寫在一個程序里。

我平常用的時候,就只開一個minicdn的Manager來加速我的后端服務器。如果沒有節點的話,manager就會把自己當成一個節點。然后當有特別大的下載即將要沖擊我的服務器的時候。我就會找很多的同事,將minicdn部署到他們平常用的電腦上(window系列, 因為是golang語言寫的,什么平臺的程序都能編譯的出來)。這樣我在短時間內就擁有了一個性能不錯的cdn集群(充分利用同事的資源)。當下載沖擊結束的時候,在把這些節點撤掉就可以了。相當省事

技術優勢

MiniCDN使用了谷歌開源出來的groupcache框架,目前dl.google.com后臺就用到了groupcache,性能而言遠超那些squid或者nginx-proxy-cache.

groupcache的數據獲取過程很有意思,我把他翻譯了過來

groupcache的運行過程

原文地址

查找foo.txt的過程(節點#5 是N個節點中的一個,每個節點的代碼都是一樣的)

  1. 判斷foo.txt是否內存中,并且很熱門(super hot),如果在就直接使用它
  2. 判斷foo.txt是否在內存中,并且當前節點擁有它(譯者注:一致性hash查到該文件屬于節點#5),如果是就使用它
  3. 在所有的節點中, 如果foo.txt的擁有者是節點#5,就加載這個文件。如果其他請求(通過直接的,或者rpc請求),節點#5會阻塞該請求,直接加載完畢,然后給所有請求返回同樣的結果。否則使用rpc請求到擁有者的節點,如果請求失敗,就本地加載(譯者注:這種方式比較慢)

groupcache是2013年寫出來的,軟件也不怎么更新了。里面的HTTPPool還有兩個問題一直沒有修復,這兩個問題直接影響到節點之間不能交換數據。因為官方不用groupcache的這部分,所以連用戶提的issue都不修(真是蛋疼)

https://github.com/codeskyblue/groupcache 是我fork的,把這兩個問題修復了,雖然提了pr,不過感覺他們一時半會不會merge的。

受python-celery的啟發,我實現了peer退出時候的兩種狀態(Warm close and Code close). Warn close可以保證黨節點不在服務的時候才退出。Code close就是強制退出,下載者可能會發現下載中斷的問題。

架構

  • M: Manager

    1. 負責維護Peer的列表,每個peer會去Manager同步這個列表。
    2. 所有的請求會先請求到manager, 然后由manager重定向到不同的peer
  • P: Peer

    1. 提供文件的下載服務
    2. Peer之間會根據從manager拿到的peer列表,同步文件

Manager與Peer是一對多的關系

[M]
 |`------+--------+---......
 |       |        |
[P]     [P]      [P]  ....

Installation

go get -u -v github.com/codeskyblue/minicdn
# run
minicdn -h

Requirements

  • golang
  • 使用golang前需要設置環境變量GOPATH, 通常export GOPATH=$HOME/goworkdir, 編譯后的文件會自動生成到$GOPATH/bin下

Run Manager

命令行啟動

./minicdn -mirror http://localhost:5000 -addr :11000 -log cdn.log
  • 對網站http://localhost:5000進行鏡像加速
  • 監聽11000端口
  • 日志存儲在cdn.log中

源站的所有下載地址,最好都改成這個http://localhost:5000/something

Run Peer

命令行啟動

./minicdn -upstream http://localhost:11000 -addr :8001
  • 指定Server地址http://localhost:11000
  • 監聽8001端口

TODO

  • token
  • use a slave as a master
  • request log
  • cli args to specify cache size

CONTRIBUTING

開源軟件都會有一個這部分,感覺我也不能免俗。

  • 代碼或README中的拼寫錯誤,都是可以提Pull request的。
  • 如果有什么大的改動,請先提issue進行討論。
  • 代碼使用golang默認的fmt

Tests

go test -v

項目主頁:http://www.baiduhome.net/lib/view/home/1437018125099

 本文由用戶 f627 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!