Golang 在十二讚的深度應用
我們是“十二贊”,一個致力於幫助電商賣家進入小程式的小團隊,我們的主頁是http://www.12zan.cn/。 在實際執行中,我們使用了大量由golang寫就的小工具,幾乎每一個工具程式碼量都超短,一般在200行左右就完成了一個獨立的功能,同時擔當了相當重要的角色;像代理伺服器,程式碼量一共500行多一點點,卻是我們的核心支柱,壓測時QPS也直追nginx,表現優異。
基於Docker的基礎結構
做為基礎架構,我介紹一下我們的機器架構。 我們的整個業務構建於阿里雲之上,有5臺server,每一對都有獨立的外網IP,同時也在同一個內網之中。在每一臺機器上都跑了一個我們自己用golang寫的守護程式,這個程式負責監聽一些業務重啟、新增域名等類似的指令並執行(這些指令最後都傳遞給了docker)。同時,每臺機器上都有一個consul程式,這些consul都join到了一起。另外,我們每一臺機器上,都用docker跑了一個nginx來做80埠的服務,同時跑了一個用golang自己寫的HTTP代理。nginx做做日誌啊基礎的功能之後就把請求丟給這個http代理 ,HTTP代理會到consul裡去查應該將請求轉發到哪個IP的哪個埠上。
400行Golang程式碼寫的HTTP Proxy
在架構選型的第一天,我們就決定,我們會服務化,會大量使用http 介面來提供服務,並使用自己的http proxy來分發請求、新增自有的一些業務邏輯比如API的許可權驗證等邏輯。我們限定,所有業務,域名都是*.app.12zan.net,比如我們要上一個聊天服務,請求的介面就會是chat.app.12zan.net,哪天再上個評論服務,請求的介面就是comment.app.12zan.net。 確定域名後我第一件事情,就是拿golang自己寫了一個非常簡單的基於consul的http proxy server;感謝Golang這完善的HTTP庫,我們只用了幾百行程式碼就完成了所有功能。每當有http請求過來時,這個proxy server就會根據HTTP請求中HTTP_HOST 欄位去consul去查,有哪些後端是用這個域名名稱來註冊服務的,並根據指定的演算法,取出一臺後端來,把這個HTTP請求Proxy過去。每個具體的業務,可能執行在我們5臺機器中的任何一臺之中的docker上,也可能是多個docker例項上。所以這裡有一個機制,選擇哪個實際的docker例項來服務這個請求的問題。我們現在支援隨機選取、按客戶端IP地址做hash之後選取、按URL做Hash選取、按負載選取幾種方式。
WEB服務的服務註冊
基於php+laralel和nodejs+koajs兩種場景,我們製作了自己的docker映象。這個映象除開可以將php+nginx和nodejs構建的web服務執行起來之外,還包含一個golang寫的consul客戶端。在docker容器裡,這個客戶端隨著php+nginx或是nodejs的web服務一起啟動,啟動之後會向宿主機的consul 程式註冊自己這個服務,註冊的時候會通知說,某某應用,在某某IP某某埠提供服務啦,如果前面有到**.app.12zan.net的請求你可以轉發給我;同時會每隔一秒上報自己的程式數、當前機器CPU佔用、記憶體佔用情況。也是一樣的簡單,幾百行golang程式碼,就鼓搗出了這個consul客戶端。為什麼使用golang呢?第一個原因當然是因為consul天生是golang陣營,第二個,是因為我們的docker容器種類較多,所以這個客戶端直接就是在Mac上跨平臺編譯出來的在linux64平臺上執行的,不管docker容器是python為基準的還是ruby為基準的,還是nodejs的,只要把這個二進位制檔案拷貝進去就能正確執行,不像別的語言需要解決依賴問題。
我們還開發了一個web console介面,在這裡,我們可以註冊app,也可以為app新增例項。註冊app時,我們要指定程式碼倉庫的地址(對了,我們的程式碼管理是用的golang寫的gogs),指定對外服務的域名,指定是nodejs應用還是php+laravel應用。新增應用之後,可以在這個應用下新建例項,讓系統在指定的IP上去跑這個例項。例項執行的過程實際就是下發一個通知到某個機器上,去執行一個docker例項啟動的過程。docker啟動的時候帶了一些環境變數,比如當前內網IP、docker監聽的埠、對外提供服務時是用何域名提供服務。
日誌和儲存
前面這種架構有一個問題,就是後端可能是在任何一臺機器上執行的,今天可能是A,明天可能是B,那我要是把檔案存在A上了是不是讓B來提供服務的時候就掛掉了?所以我們想了這麼一個辦法(也是因為窮。。。。),我們把所有的檔案都挪到阿里雲的OSS服務上。同時為了不管是Nodejs應用還是php應用 還是python寫的應用都能做到把使用者上傳的檔案或是系統生成的檔案存到oss上面,我們很省事地寫了一個ossUploader,編譯好的可執行檔案釋出,只需要執行它,傳進來本地路徑和oss上的目標路徑,就保證給你上傳到oss上去就完整,不需要再在nodejs、php、python、ruby、java各種平臺下都琢磨一遍oss的SDK。
對日誌的處理是一樣的, 所有的日誌檔案的內容,都會被一個golang寫的工具gtail監聽著(就像linux 的tail -f命令一樣),所有新產生的內容都會被gtail挪到oss上去儲存。當然,也是可執行檔案釋出的。
這個實現之後, 我們的實際業務就真正可以在5臺機器上之間任意騰挪了。
訊息廣播
得益於golang的一些開源倉庫,我們還做了一些好玩的東西。 比如,看到https://github.com/gorilla/websocket這個東東,我們忍不住擼了一個websocket server,或是說叫群聊伺服器更好一點。 接下來,我們看到有一個golang的庫叫go-mysql-elasticsearch,偽裝了一個mysql的slave,去MySQL的master機器上去讀binlog,讀到binlog以後就將MySQL裡的資料傳送給ElasticSearch去索引資料。 我們就結合了一個,把這兩個結合起來,修改了一下go-mysql-elastichsearch,讓它監聽到MySQL的資料變更之後,在WebSocket server的某個群聊裡推送出來,形成一個資料變更的廣播。 再接下來我們就可以用nodejs寫一個應用,連上這個websocket server,加入特定的某個群聊,就源源不斷地收聽到資料變更的訊息。這個nodejs端的程式碼就非常簡潔了,只需要不到100行程式碼可以做各種好玩的事情,比如監聽到使用者留言表有新增,可以發郵件讓運營馬上去稽核。還有比如說,每當訂單表有成交的時候,我們某個小小的nodejs應用因為監聽了資料庫訊息,第一時間就知道了,馬上就去追溯使用者來源,來計算返利;同時這個nodejs的程式碼更新是和訂單主邏輯完全不相關的,寫這個業務的開發人員只需要知道訂單表的結構,不需要了解訂單應用後臺程式碼。
相關文章
- 超讚!iOS7應用介面設計深度剖析iOS
- 深度學習在OC中的應用深度學習
- Json序列化在golang中的應用JSONGolang
- 深度學習在股票市場的應用深度學習
- AI在汽車中的應用:實用深度學習AI深度學習
- golang執行緒池在IO多路複用中的應用Golang執行緒
- 深度學習在醫療領域的應用深度學習
- 【AI in 美團】深度學習在OCR中的應用AI深度學習
- 深度學習在乳腺癌上的應用!深度學習
- 深度學習在攜程攻略社群的應用深度學習
- 深度學習在小米電商業務的應用實踐深度學習
- 【AI in 美團】深度學習在文字領域的應用AI深度學習
- 【譯】十二因子應用(四)
- 深度學習在自動駕駛感知領域的應用深度學習自動駕駛
- 乾貨 | 深度學習在文字分類中的應用深度學習文字分類
- 【深度學習】深度解讀:深度學習在IoT大資料和流分析中的應用深度學習大資料
- golang RPC 應用(1) :net/rpc的應用GolangRPC
- TiDB 在摩拜單車的深度實踐及應用TiDB
- 深度學習模型在序列標註任務中的應用深度學習模型
- 深度學習在視覺搜尋和匹配中的應用深度學習視覺
- 如何理解雅克比矩陣在深度學習中的應用?矩陣深度學習
- 深度學習在美團搜尋廣告排序的應用實踐深度學習排序
- 深度學習利器:TensorFlow在智慧終端中的應用深度學習
- 深度學習在搜狗無線搜尋廣告中的應用深度學習
- 簡述遷移學習在深度學習中的應用遷移學習深度學習
- Flink 在螞蟻實時特徵平臺的深度應用特徵
- 卷積操作的概念及其在深度學習中的應用卷積深度學習
- gRPC的Golang簡單應用RPCGolang
- golang應用平滑重啟Golang
- 深度模型DNN在個性化推薦場景中的應用模型DNN
- 深度學習在攜程搜尋詞義解析中的應用深度學習
- 深度學習技術在網路入侵檢測中的應用深度學習
- 【長篇乾貨】深度學習在文字分類中的應用深度學習文字分類
- 深度學習在騰訊的平臺化和應用實踐(全)深度學習
- 深度學習在攝影技術中的應用與發展深度學習
- 深度學習在推薦系統中的應用綜述(最全)深度學習
- Elasticsearch深度應用(上)Elasticsearch
- Elasticsearch深度應用(下)Elasticsearch