GoCollaborate: 用一百行代碼寫一個基于 Golang 的實時分布式計算應用

為什么我要寫這篇文章

作為一枚技術 Doge携狭,每天總免不了和不懂技術的老板 探(si) 討(bi) 業(yè)務的實現可能性友存;

前一段日子缤剧,老板在深(bi) 入(jiao) 調(jia) 研(ge) 之后決定引入一個第三方 IOT 平臺学辱,通過 RESTful API 實時反饋設備的監(jiān)測數據核畴,而因為公司業(yè)務的特殊性膝但,所獲得的原始監(jiān)測數據我們無法直接使用,而是必須經過一番計算谤草。以為每位登錄后臺的用戶顯示過去一周的實時能源消耗為例跟束,我們需要在十五秒內完成大約 60 MB (120 萬條記錄) 數據的提取、清洗及計算丑孩,而這顯然超出了瀏覽器和單次 HTTP 請求所能承受的極限冀宴。這個需求讓我想起了之前自己學習 Golang 練手時寫過的一個分布式計算模型,于是趁此機會把它擴展了一下温学,寫成框架發(fā)布到社區(qū)里略贮,有興趣的童鞋可以 star 回去試驗一下哦。

為什么要用 Go 重新造輪子

Golang 是 Google 在2007年發(fā)布的一門開源的靜態(tài)編譯型編程語言仗岖,在垃圾回收逃延、結構類型以及并發(fā)編程的處理上擁有自己的獨到之處,近年來更是成為使用頻率上升速度最快的編程語言之一轧拄。 可以參考這篇文章揽祥,Go 在打包編譯后的性能與 Java 或 C++相似。在我們的使用中檩电,Go 一般比 Python 要快 30 倍拄丰。同時府树,其天然支持的 CSP 模型在很多情況下可以免去了消息隊列的使用,對高并發(fā)場景獨到的處理優(yōu)勢愈案,更是能夠大大縮短程序員的開發(fā)時間哦挺尾。

GoCollaborate 是什么?

很多同學看到這里可能會問了,這個框架什么站绪?我又能用它來做什么呢遭铺?

簡而言之,

GoCollaborate 是一個提供分布式服務管理搭建的輕量級通用框架恢准,您可以輕松地用它進行編程魂挂,構建擴展,以及創(chuàng)建自己的高性能分布式服務馁筐。

有相關從業(yè)經驗的同學可能聽說過 Apache Hadoop涂召,Spark,Lightbend 的 Akka敏沉, 阿里的 Dubbo 以及 Facebook 的 Thrift 等等果正,一套工具集下來是不是感覺暈頭轉向呢?不要緊盟迟,我們在這姑且暫時把它當成一個輕量級的 Hadoop 好了秋泳,隨著教程展開,讓我們一起來體驗 Golang 的神奇魅力攒菠。

下面我們用一個簡單的應用展示框架的基本用法和原理迫皱,更多應用請參考官方例庫,或者直接提交 issue辖众,我覺得有價值的會后續(xù)補充上去卓起。

正文

首先是安裝:

go get -u github.com/GoCollaborate/src

然后為你的項目創(chuàng)建基本結構,創(chuàng)建好之后看起來像這樣

[Your_Project_Name]
┬
├ [core]
    ┬
    └ example.go
├ case.json
└ main.go

然后是集群的配置,修改case.json為:

{
    "caseid": "GoCollaborateStandardCase",
    "cards": {
        "localhost:57851": {
            "ip": "localhost",
            "port": 57851,
            "alive": false,
            "seed": false
        },
        "localhost:57852": {
            "ip": "localhost",
            "port": 57852,
            "alive": true,
            "seed": true
        }
    },
    "timestamp": 1508619931,
    "local": {
        "ip": "localhost",
        "port": 57852,
        "alive": true,
        "seed": true
    },
    "coordinator": {
        "ip": "localhost",
        "port": 0,
        "alive": true,
        "seed": false
    }
}

這里有幾個參數凹炸,caseid是集群的自定義id戏阅,id不同的集群之間將無法通信;而cards里面則囊括了當前網絡上已知的主機地址还惠,local作為本機地址饲握,你可以修改為自己喜歡的端口,更多內容請參見我寫的官方文檔蚕键,(目前只完成了英文文檔救欧,后續(xù)會陸續(xù)補充中文部分,著急的同學可以先用谷歌翻譯哈锣光!)笆怠。

然后打開剛才創(chuàng)建的example.go,給我們的計算任務寫幾個函數:

package core

import (
    "fmt"
    "github.com/GoCollaborate/src/artifacts/task"
    "github.com/GoCollaborate/src/wrappers/taskHelper"
    "net/http"
)

// 任務處理器
func ExampleJobHandler(w http.ResponseWriter, r *http.Request) *task.Job {
    // 創(chuàng)建一個 Job 實例
    job := task.MakeJob()
    // 將任務輸入 Job 的隊列
    job.Tasks(&task.Task{task.SHORT,
        task.BASE, "exampleFunc",
        task.Collection{1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4},
        task.Collection{0},
        task.NewTaskContext(struct{}{}), 0})
    // 為當前階段指定執(zhí)行器誊爹,這里我們簡單做一次 Map-Reduce
    job.Stacks("core.ExampleTask.Mapper", "core.ExampleTask.Reducer")
    
    // 這里大家可以根據需要為 HTTP 請求返回內容
    // ...
    
    return job
}

// 任務調用的處理函數
func ExampleFunc(source *task.Collection,
    result *task.Collection,
    context *task.TaskContext) bool {

    fmt.Println("Example Task Executed...")
    
    var total int
    // 計算數據集內數據的總和
    for _, n := range *source {
        total += n.(int)
    }
    
    // 將總和寫入結果集
    result.Append(total)
    return true
}

type SimpleMapper int

func (m *SimpleMapper) Map(inmaps map[int]*task.Task) (map[int]*task.Task, error) {
    // 將任務平均映射成三個子任務
    return taskHelper.Slice(inmaps, 3), nil
}

type SimpleReducer int

func (r *SimpleReducer) Reduce(maps map[int]*task.Task) (map[int]*task.Task, error) {
    var sum int
    
    // 根據返回結果計算總和
    for _, s := range maps {
        for _, r := range (*s).Result {
            sum += r.(int)
        }
    }
    fmt.Printf("The sum of numbers is: %v \n", sum)
    fmt.Printf("The task set is: %v", maps)
    return maps, nil
}


然后在我們的入口文件main.go里蹬刷,把剛才寫的函數都注冊到框架里:

package main

import (
    "./core"
    "github.com/GoCollaborate/src"
)
func main() {
    mp := new(core.SimpleMapper)
    rd := new(core.SimpleReducer)
    collaborate.Set("Function", core.ExampleFunc, "exampleFunc")
    collaborate.Set("Mapper", mp, "core.ExampleTask.Mapper")
    collaborate.Set("Reducer", rd, "core.ExampleTask.Reducer")
    collaborate.Set("Shared", []string{"GET", "POST"}, core.ExampleJobHandler)
    collaborate.Run()
}

跑一下瓢捉,看能運行嗎?

go run main.go -mode=clbt

剛才創(chuàng)建的任務函數將被映射到

http://localhost:8080/core/ExampleJobHandler
image

退出程序办成,我們把剛才創(chuàng)建的項目文件夾復制一份泡态,開始真正的分布式計算:

cp Your_Project_Name Your_Project_Name_Copy

在配置文件case.json內部修改本地端口ip:

{
    "caseid": "GoCollaborateStandardCase",
    "cards": {
        "localhost:57852": {
            "ip": "localhost",
            "port": 57852,
            "alive": true,
            "seed": true
        }
    },
    "timestamp": 1508619931,
    "local": {
        "ip": "localhost",
        "port": 57851,
        "alive": true,
        "seed": false
    },
    "coordinator": {
        "ip": "localhost",
        "port": 0,
        "alive": true,
        "seed": false
    }
}

保存,退出迂卢,然后依次進入不同目錄下啟動兩個項目某弦,這里如果大家在本地運行的話記得加個參數,記得把第二個應用的端口設為8081以免沖突哦:

go run main.go -mode=clbt -port=8081
go run main.go -mode=clbt

現在可以訪問:

http://localhost:8080/core/ExampleJobHandler
// and 
http://localhost:8081/core/ExampleJobHandler

執(zhí)行剛才注冊的任務啦而克,看看控制臺靶壮,是不是輸出了什么?

image

然后還有一個做了一半的 UI员萍,提供一點基本統(tǒng)計分析:

http://localhost:8080


因為是個人項目腾降,肯定還有很多不足,最后再附上 github 鏈接 GoCollaborate 碎绎,歡迎大家提交 issue 或者拍磚螃壤,當然愿意貢獻代碼的大蝦就更歡迎了,謝謝閱讀!

P.S. 框架的全文文檔都在這里筋帖,本文的例子在這里映穗。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市幕随,隨后出現的幾起案子,更是在濱河造成了極大的恐慌宿接,老刑警劉巖赘淮,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異睦霎,居然都是意外死亡梢卸,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門副女,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蛤高,“玉大人,你說我怎么就攤上這事碑幅〈鞫福” “怎么了?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵沟涨,是天一觀的道長恤批。 經常有香客問我,道長裹赴,這世上最難降的妖魔是什么喜庞? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任诀浪,我火速辦了婚禮,結果婚禮上延都,老公的妹妹穿的比我還像新娘雷猪。我一直安慰自己,他們只是感情好晰房,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布求摇。 她就那樣靜靜地躺著,像睡著了一般嫉你。 火紅的嫁衣襯著肌膚如雪月帝。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天幽污,我揣著相機與錄音嚷辅,去河邊找鬼。 笑死距误,一個胖子當著我的面吹牛簸搞,可吹牛的內容都是我干的。 我是一名探鬼主播准潭,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼趁俊,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了刑然?” 一聲冷哼從身側響起寺擂,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎泼掠,沒想到半個月后怔软,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡择镇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年挡逼,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腻豌。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡家坎,死狀恐怖,靈堂內的尸體忽然破棺而出吝梅,到底是詐尸還是另有隱情虱疏,我是刑警寧澤,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布憔涉,位于F島的核電站订框,受9級特大地震影響,放射性物質發(fā)生泄漏兜叨。R本人自食惡果不足惜穿扳,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一衩侥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧矛物,春花似錦茫死、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至忆首,卻和暖如春爱榔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背糙及。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工详幽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人浸锨。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓唇聘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親柱搜。 傳聞我的和親對象是個殘疾皇子迟郎,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現聪蘸,斷路器宪肖,智...
    卡卡羅2017閱讀 134,702評論 18 139
  • 承載量是分布式系統(tǒng)存在的原因 當一個互聯(lián)網業(yè)務獲得大眾歡迎的時候,最顯著碰到的技術問題健爬,就是服務器非常繁忙匈庭。當每天...
    XYLY閱讀 1,462評論 1 48
  • 本文轉載自http://geek.csdn.net/news/detail/112672 WeTest導讀 我們常...
    shineegirl閱讀 1,547評論 0 26
  • 聽說 大自然正在孕育一場風暴 于是我來到這片灘涂 逢一個叫“瑪娃”的孩子 看不見移動的浮萍 河流平靜成了湖泊 水天...
    詩姬閱讀 163評論 2 5
  • 研磨 居住地:湖北利川 身 高:168cm 職 業(yè):經 商 初始體重:162 斤 目前體重:133 斤 初始腰圍:...
    瘦朵朵教練閱讀 366評論 0 0