Concurrency
早在十八年前的1999年匾浪,千兆網(wǎng)卡還是一個(gè)新玩意兒皇帮,想當(dāng)年有吉比特帶寬卻只能支持10K客戶端,還是個(gè)值得研究的問題蛋辈,畢竟Nginx在2009年才出來属拾,在這之前大家還在內(nèi)核折騰過HTTP服務(wù)器,服務(wù)器領(lǐng)域還在討論如何解決C10K問題,C10K中文翻譯在這里捌年。讀這個(gè)文章瓢娜,感覺進(jìn)入了繁忙服務(wù)器工廠的車間,成千上萬錯(cuò)綜復(fù)雜的電纜交織在一起礼预,甚至還有古老的驚群(thundering herd)問題眠砾,驚群像遠(yuǎn)古狼人一樣就算是在21世紀(jì)還是偶然能聽到它的傳說。現(xiàn)在大家討論的都是如何支持C10M托酸,也就是千萬級并發(fā)的問題褒颈。
并發(fā),無疑是服務(wù)器領(lǐng)域永遠(yuǎn)無法逃避的話題励堡,是服務(wù)器軟件工程師的基本能力谷丸。Go的撒手锏之一無疑就是并發(fā)處理,如果要從Go眾多優(yōu)秀的特性中挑一個(gè)应结,那就是并發(fā)和工程化刨疼,如果只能選一個(gè)的話,那就是并發(fā)的支持鹅龄。大規(guī)模軟件揩慕,或者云計(jì)算,很大一部分都是服務(wù)器編程扮休,服務(wù)器要處理的幾個(gè)基本問題:并發(fā)迎卤、集群、容災(zāi)玷坠、兼容蜗搔、運(yùn)維,這些問題都可以因?yàn)镚o的并發(fā)特性得到改善八堡,按照《人月神話》的觀點(diǎn)樟凄,并發(fā)無疑是服務(wù)器領(lǐng)域的固有復(fù)雜度(Essential Complexity)之一。Go之所以能迅速占領(lǐng)云計(jì)算的市場兄渺,Go的并發(fā)機(jī)制是至關(guān)重要的不同。
借用《人月神話》中關(guān)于固有復(fù)雜度(Essential Complexity)的概念,能比較清晰的說明并發(fā)問題溶耘。就算沒有讀過這本書二拐,也肯定聽過軟件開發(fā)“沒有銀彈”,要保持軟件的“概念完整性”凳兵,Brooks作為硬件和軟件的雙重專家和出色的教育家始終活躍在計(jì)算機(jī)舞臺上百新,在計(jì)算機(jī)技術(shù)的諸多領(lǐng)域中都作出了巨大的貢獻(xiàn),在1964年(33歲)領(lǐng)導(dǎo)了IBM System/360和IBM OS/360的研發(fā)庐扫,于1993年(62歲)獲得馮諾依曼獎(jiǎng)饭望,并于1999年(68歲)獲得圖靈獎(jiǎng)仗哨,在2010年(79歲)獲得虛擬現(xiàn)實(shí)(VR)的獎(jiǎng)項(xiàng)IEEE Virtual Reality Career Award (2010)。
在軟件領(lǐng)域铅辞,很少能有像《人月神話》一樣具有深遠(yuǎn)影響力和暢銷不衰的著作厌漂。Brooks博士為人們管理復(fù)雜項(xiàng)目提供了具有洞察力的見解,既有很多發(fā)人深省的觀點(diǎn)斟珊,又有大量軟件工程的實(shí)踐苇倡。本書內(nèi)容來自Brooks博士在IBM公司System/360家族和OS/360中的項(xiàng)目管理經(jīng)驗(yàn),該項(xiàng)目堪稱軟件開發(fā)項(xiàng)目管理的典范囤踩。該書英文原版一經(jīng)面世旨椒,即引起業(yè)內(nèi)人士的強(qiáng)烈反響,后又譯為德堵漱、法综慎、日、俄勤庐、中示惊、韓等多種文字,全球銷售數(shù)百萬冊愉镰。確立了其在行業(yè)內(nèi)的經(jīng)典地位米罚。
Brooks是我最崇拜的人,有理論有實(shí)踐岛杀,懂硬件懂軟件,致力于大規(guī)模軟件(當(dāng)初還沒有云計(jì)算)系統(tǒng)崭孤,足夠(長達(dá)十年甚至二十年)的預(yù)見性类嗤,孜孜不倦奮斗不止,強(qiáng)烈推薦軟件工程師讀《人月神話》辨宠。
短暫的廣告回來遗锣,繼續(xù)討論并發(fā)(Concurrency)的問題,要理解并發(fā)的問題就必須從了解并發(fā)問題本身,以及并發(fā)處理模型開始。2012年我在當(dāng)時(shí)中國最大的CDN公司藍(lán)汛設(shè)計(jì)和開發(fā)流媒體服務(wù)器時(shí)涩嚣,學(xué)習(xí)了以高并發(fā)聞名的NGINX的并發(fā)處理機(jī)制EDSM(Event-Driven State Machine Architecture)逞刷,自己也照著這套機(jī)制實(shí)現(xiàn)了一個(gè)流媒體服務(wù)器,和HTTP的Request-Response模型不同侦镇,流媒體的協(xié)議比如RTMP非常復(fù)雜中間狀態(tài)非常多,特別是在做到集群Edge時(shí)和上游服務(wù)器的交互會(huì)導(dǎo)致系統(tǒng)的狀態(tài)機(jī)翻倍,當(dāng)時(shí)請教了公司的北美研發(fā)中心的架構(gòu)師Michael叶组,Michael推薦我用一個(gè)叫做ST(StateThreads)的技術(shù)解決這個(gè)問題,ST實(shí)際上使用setjmp和longjmp實(shí)現(xiàn)了用戶態(tài)線程或者叫協(xié)程历造,協(xié)程和goroutine是類似的都是在用戶空間的輕量級線程甩十,當(dāng)時(shí)我本沒有懂為什么要用一個(gè)完全不懂的協(xié)程的東西船庇,后來我花時(shí)間了解了ST后豁然開朗,原來服務(wù)器的并發(fā)處理有幾種典型的并發(fā)模型侣监,流媒體服務(wù)器中超級復(fù)雜的狀態(tài)機(jī)鸭轮,也廣泛存在于各種服務(wù)器領(lǐng)域中,屬于這個(gè)復(fù)雜協(xié)議服務(wù)器領(lǐng)域不可Remove的一種固有復(fù)雜度(Essential Complexity)橄霉。
我翻譯了ST(StateThreads)總結(jié)的并發(fā)處理模型高性能窃爷、高并發(fā)、高擴(kuò)展性和可讀性的網(wǎng)絡(luò)服務(wù)器架構(gòu):State Threads for Internet Applications酪劫,這篇文章也是理解Go并發(fā)處理的關(guān)鍵吞鸭,本質(zhì)上ST就是C語言的協(xié)程庫(騰訊微信也開源過一個(gè)libco協(xié)程庫),而goroutine是Go語言級別的實(shí)現(xiàn)覆糟,本質(zhì)上他們解決的領(lǐng)域問題是一樣的刻剥,當(dāng)然goroutine會(huì)更廣泛一些,ST只是一個(gè)網(wǎng)絡(luò)庫滩字。我們一起看看并發(fā)的本質(zhì)目標(biāo)造虏,一起看圖說話吧,先從并發(fā)相關(guān)的性能和伸縮性問題說起:
- 橫軸是客戶端的數(shù)目麦箍,縱軸是吞吐率也就是正常提供服務(wù)需要能吐出的數(shù)據(jù)漓藕,比如
1000
個(gè)客戶端在觀看500Kbps
碼率的視頻時(shí),意味著每個(gè)客戶端每秒需要500Kb的數(shù)據(jù)挟裂,那么服務(wù)器需要每秒吐出500*1000Kb=500Mb
的數(shù)據(jù)才能正常提供服務(wù)享钞,如果服務(wù)器因?yàn)樾阅軉栴}CPU跑滿了都無法達(dá)到500Mbps的吞吐率,客戶端必定就會(huì)開始卡頓诀蓉。 - 圖中黑色的線是客戶端要求的最低吞吐率栗竖,假設(shè)每個(gè)客戶端都是一樣的,那么黑色的線就是一條斜率固定的直線渠啤,也就是客戶端越多吞吐率就越多狐肢,基本上和客戶端數(shù)目成正比。比如1個(gè)客戶端需要500Kbps的吞吐率沥曹,1000個(gè)就是500Mbps吞吐率份名。
- 圖中藍(lán)色的實(shí)線,是服務(wù)器實(shí)際能達(dá)到的吞吐率妓美。在客戶端比較少時(shí)僵腺,由于CPU空閑,服務(wù)器(如果有需要)能夠以超過客戶端要求的最低吞吐率給數(shù)據(jù)壶栋,比如點(diǎn)播服務(wù)器的場景想邦,客戶端看500Kbps碼率的點(diǎn)播視頻,每秒最少需要500Kb的數(shù)據(jù)委刘,那么服務(wù)器可以以800Kbps的吞吐率給客戶端數(shù)據(jù)丧没,這樣客戶端自然不會(huì)卡頓鹰椒,客戶端會(huì)將數(shù)據(jù)保存在自己的緩沖區(qū),只是如果用戶放棄播放這個(gè)視頻時(shí)會(huì)導(dǎo)致緩存的數(shù)據(jù)浪費(fèi)呕童。
- 圖中藍(lán)色實(shí)線會(huì)有個(gè)天花板漆际,也就是服務(wù)器在給定的CPU資源下的最高吞吐率,比如某個(gè)版本的服務(wù)器再4CPU下由于性能問題只能達(dá)到1Gbps的吞吐率夺饲,那么黑線和藍(lán)線的交叉點(diǎn)奸汇,就是這個(gè)服務(wù)器能正常服務(wù)的最多客戶端比如2000個(gè)。理論上如果超過這個(gè)最大值比如10K個(gè)往声,服務(wù)器吞吐率還是保持在最大吞吐率比如1Gbps擂找,但是由于客戶端的數(shù)目持續(xù)增加需要繼續(xù)消耗系統(tǒng)資源,比如10K個(gè)FD和線程的切換會(huì)搶占用于網(wǎng)絡(luò)收發(fā)的CPU時(shí)間浩销,那么就會(huì)出現(xiàn)藍(lán)色虛線贯涎,也就是超負(fù)載運(yùn)行的服務(wù)器,吞吐率會(huì)降低慢洋,導(dǎo)致服務(wù)器無法正常服務(wù)已經(jīng)連接的客戶端塘雳。
- 負(fù)載伸縮性(Load Scalability)就是指黑線和藍(lán)線的交叉點(diǎn),系統(tǒng)的負(fù)載能力如何普筹,或者說是否并發(fā)模型能否盡可能的將CPU用在網(wǎng)絡(luò)吞吐上败明,而不是程序切換上,比如多進(jìn)程的服務(wù)器太防,負(fù)載伸縮性就非常差妻顶,有些空閑的客戶端也會(huì)Fork一個(gè)進(jìn)程服務(wù),這無疑是浪費(fèi)了CPU資源的蜒车。同時(shí)多進(jìn)程的系統(tǒng)伸縮性會(huì)很好讳嘱,增加CPU資源時(shí)吞吐率基本上都是線性的。
- 系統(tǒng)伸縮性(System Scalability)是指吞吐率是否隨系統(tǒng)資源線性增加醇王,比如新增一倍的CPU呢燥,是否吞吐率能翻倍崭添。圖中綠線寓娩,就是增加了一倍的CPU,那么好的系統(tǒng)伸縮性應(yīng)該系統(tǒng)的吞吐率也要增加一倍呼渣。比如多線程程序中棘伴,由于要對競爭資源加鎖或者多線程同步,增加的CPU并不能完全用于吞吐率屁置,多線程模型的系統(tǒng)伸縮性就不如多進(jìn)程模型焊夸。
并發(fā)的模型包括幾種,總結(jié)Existing Architectures如下表:
Arch | Load Scalability | System Scalability | Robust | Complexity | Example |
---|---|---|---|---|---|
Multi-Process | Poor | Good | Great | Simple | Apache1.x |
Multi-Threaded | Good | Poor | Poor | Complex | Tomcat, FMS/AMS |
Event-Driven State Machine |
Great | Great | Good | Very Complex |
Nginx, CRTMPD |
StateThreads | Great | Great | Good | Simple | SRS, Go |
- MP(Multi-Process)多進(jìn)程模型:每個(gè)連接Fork一個(gè)進(jìn)程服務(wù)蓝角。系統(tǒng)的魯棒性非常好阱穗,連接彼此隔離互不影響饭冬,就算有進(jìn)程掛掉也不會(huì)影響其他連接。負(fù)載伸縮性(Load Scalability)非常差(Poor)揪阶,系統(tǒng)在大量進(jìn)程之間切換的開銷太大昌抠,無法將盡可能多的CPU時(shí)間使用在網(wǎng)絡(luò)吞吐上,比如4CPU的服務(wù)器啟動(dòng)1000個(gè)繁忙的進(jìn)程基本上無法正常服務(wù)鲁僚。系統(tǒng)伸縮性(System Scalability)非常好炊苫,增加CPU時(shí)一般系統(tǒng)吞吐率是線性增長的。目前比較少見純粹的多進(jìn)程服務(wù)器了冰沙,特別是一個(gè)連接一個(gè)進(jìn)程這種侨艾。雖然性能很低,但是系統(tǒng)復(fù)雜度低(Simple)拓挥,進(jìn)程很獨(dú)立唠梨,不需要處理鎖或者狀態(tài)。
- MT(Multi-Threaded)多線程模型:有的是每個(gè)連接一個(gè)線程撞叽,改進(jìn)型的是按照職責(zé)分連接姻成,比如讀寫分離的線程,幾個(gè)線程讀愿棋,幾個(gè)線程寫科展。系統(tǒng)的魯棒性不好(Poor),一個(gè)連接或線程出現(xiàn)問題糠雨,影響其他的線程才睹,彼此互相影響。負(fù)載伸縮性(Load Scalability)比較好(Good)甘邀,線程比進(jìn)程輕量一些琅攘,多個(gè)用戶線程對應(yīng)一個(gè)內(nèi)核線程,但出現(xiàn)被阻塞時(shí)性能會(huì)顯著降低松邪,變成和多進(jìn)程一樣的情況坞琴。系統(tǒng)伸縮性(System Scalability)比較差(Poor),主要是因?yàn)榫€程同步逗抑,就算用戶空間避免鎖剧辐,在內(nèi)核層一樣也避免不了;增加CPU時(shí)邮府,一般在多線程上會(huì)有損耗荧关,并不能獲得多進(jìn)程那種幾乎線性的吞吐率增加。多線程的復(fù)雜度(Complex)也比較高褂傀,主要是并發(fā)和鎖引入的問題忍啤。
- EDSM(Event-Driven State Machine)事件驅(qū)動(dòng)的狀態(tài)機(jī)。比如select/poll/epoll仙辟,一般是單進(jìn)程單線程同波,這樣可以避免多進(jìn)程的鎖問題鳄梅,為了避免單程的系統(tǒng)伸縮問題可以使用多進(jìn)程單線程,比如NGINX就是這種方式未檩。系統(tǒng)魯棒性比較好(Good)卫枝,一個(gè)進(jìn)程服務(wù)一部分的客戶端,有一定的隔離讹挎。負(fù)載伸縮性(Load Scalability)非常好(Great)校赤,沒有進(jìn)程或線程的切換,用戶空間的開銷也非常少筒溃,CPU幾乎都可以用在網(wǎng)絡(luò)吞吐上马篮。系統(tǒng)伸縮性(System Scalability)很好,多進(jìn)程擴(kuò)展時(shí)幾乎是線性增加吞吐率怜奖。雖然效率很高浑测,但是復(fù)雜度也非常高(Very Complex),需要維護(hù)復(fù)雜的狀態(tài)機(jī)歪玲,特別是兩個(gè)耦合的狀態(tài)機(jī)迁央,比如客戶端服務(wù)的狀態(tài)機(jī)和回源的狀態(tài)機(jī)。
- ST(StateThreads)協(xié)程模型滥崩。在EDSM的基礎(chǔ)上岖圈,解決了復(fù)雜狀態(tài)機(jī)的問題,從堆開辟協(xié)程的棧钙皮,將狀態(tài)保存在棧中蜂科,在異步IO等待(EAGAIN)時(shí),主動(dòng)切換(setjmp/longjmp)到其他的協(xié)程完成IO短条。也就是ST是綜合了EDSM和MT的優(yōu)勢导匣,不過ST的線程是用戶空間線程而不是系統(tǒng)線程,用戶空間線程也會(huì)有調(diào)度的開銷茸时,不過比系統(tǒng)的開銷要小很多贡定。協(xié)程的調(diào)度開銷,和EDSM的大循環(huán)的開銷差不多可都,需要循環(huán)每個(gè)激活的客戶端缓待,逐個(gè)處理。而ST的主要問題汹粤,在于平臺的適配命斧,由于glibc的setjmp/longjmp是加密的無法修改SP棧指針田晚,所以ST自己實(shí)現(xiàn)了這個(gè)邏輯嘱兼,對于不同的平臺就需要自己適配,目前Linux支持比較好贤徒,Windows不支持芹壕,另外這個(gè)庫也不在維護(hù)有些坑只能繞過去汇四,比較偏僻使用和維護(hù)者都很少,比如ST Patch修復(fù)了一些問題踢涌。
我將Go也放在了ST這種模型中通孽,雖然它是
多線程+協(xié)程
,和SRS不同是多進(jìn)程+協(xié)程
(SRS本身是單進(jìn)程+協(xié)程
可以擴(kuò)展為多進(jìn)程+協(xié)程
)睁壁。
從并發(fā)模型看Go的goroutine背苦,Go有ST的優(yōu)勢,沒有ST的劣勢潘明,這就是Go的并發(fā)模型厲害的地方了行剂。當(dāng)然Go的多線程是有一定開銷的,并沒有純粹多進(jìn)程單線程那么高的負(fù)載伸縮性钳降,在活躍的連接過多時(shí)厚宰,可能會(huì)激活多個(gè)物理線程,導(dǎo)致性能降低遂填。也就是Go的性能會(huì)比ST或EDSM要差铲觉,而這些性能用來交換了系統(tǒng)的維護(hù)性,個(gè)人認(rèn)為很值得吓坚。除了goroutine撵幽,另外非常關(guān)鍵的就是chan。Go的并發(fā)實(shí)際上并非只有g(shù)oroutine礁击,而是goroutine+chan并齐,chan用來在多個(gè)goroutine之間同步。實(shí)際上在這兩個(gè)機(jī)制上客税,還有標(biāo)準(zhǔn)庫中的context况褪,這三板斧是Go的并發(fā)的撒手锏。
- goroutine: Go對于協(xié)程的語言級別原生支持更耻,一個(gè)go就可以啟動(dòng)一個(gè)協(xié)程测垛。ST是通過函數(shù)來實(shí)現(xiàn)。
- chan和select: goroutine之間通信的機(jī)制秧均,ST如果要實(shí)現(xiàn)兩個(gè)協(xié)程的消息傳遞和等待食侮,只能自己實(shí)現(xiàn)queue和cond。如果要同步多個(gè)呢目胡?比如一個(gè)協(xié)程要處理多種消息锯七,包括用戶取消,超時(shí)誉己,其他線程的事件眉尸,Go提供了select關(guān)鍵字。參考
Share Memory By Communicating
。 - context: 管理goroutine的組件噪猾,參考GOLANG使用Context管理關(guān)聯(lián)goroutine以及GOLANG使用Context實(shí)現(xiàn)傳值霉祸、超時(shí)和取消。參考
Go Concurrency Patterns: Timing out, moving on
和Go Concurrency Patterns: Context
袱蜡。
由于Go是多線程的丝蹭,關(guān)于多線程或協(xié)程同步,除了chan也提供了Mutex坪蚁,其實(shí)這兩個(gè)都是可以用的奔穿,而且有時(shí)候比較適合用chan而不是用Mutex,有時(shí)候適合用Mutex不適合用chan敏晤,參考Mutex or Channel
巫橄。
Channel | Mutex |
---|---|
passing ownership of data,<br />distributing units of work,<br /> communicating async results | caches,<br />state |
特別提醒:不要懼怕使用Mutex,不要什么都用chan茵典,千里馬可以一日千里卻不能抓老鼠湘换,HelloKitty跑不了多快抓老鼠卻比千里馬強(qiáng)。
Context
實(shí)際上goroutine的管理统阿,在真正高可用的程序中是非常必要的彩倚,我們一般會(huì)需要支持幾種gorotine的控制方式:
- 錯(cuò)誤處理:比如底層函數(shù)發(fā)生錯(cuò)誤后,我們是忽略并告警(比如只是某個(gè)連接受到影響)扶平,還是選擇中斷整個(gè)服務(wù)(比如LICENSE到期)帆离。
- 用戶取消:比如升級時(shí),我們需要主動(dòng)的遷移新的請求到新的服務(wù)结澄,或者取消一些長時(shí)間運(yùn)行的goroutine哥谷,這就叫熱升級。
- 超時(shí)關(guān)閉:比如請求的最大請求時(shí)長是30秒麻献,那么超過這個(gè)時(shí)間们妥,我們就應(yīng)該取消請求。一般客戶端的服務(wù)響應(yīng)是有時(shí)間限制的勉吻。
- 關(guān)聯(lián)取消:比如客戶端請求服務(wù)器监婶,服務(wù)器還要請求后端很多服務(wù),如果中間客戶端關(guān)閉了連接齿桃,服務(wù)器應(yīng)該中止惑惶,而不是繼續(xù)請求完所有的后端服務(wù)。
而goroutine的管理短纵,最開始只有chan和sync带污,需要自己手動(dòng)實(shí)現(xiàn)goroutine的生命周期管理,參考Go Concurrency Patterns: Timing out, moving on
和Go Concurrency Patterns: Context
香到,這些都是goroutine的并發(fā)范式鱼冀。
直接使用原始的組件管理goroutine太繁瑣了报破,后來在一些大型項(xiàng)目中出現(xiàn)了context這些庫,并且Go1.7之后變成了標(biāo)準(zhǔn)庫的一部分雷绢。具體參考GOLANG使用Context管理關(guān)聯(lián)goroutine以及GOLANG使用Context實(shí)現(xiàn)傳值、超時(shí)和取消理卑。
Context也有問題:
- 支持Cancel翘紊、Timeout和Value,這些都是擴(kuò)張Context樹的節(jié)點(diǎn)藐唠。Cancel和Timeout在子樹取消時(shí)會(huì)刪除子樹帆疟,不會(huì)一直膨脹;Value沒有提供刪除的函數(shù)宇立,如果他們有公共的根節(jié)點(diǎn)踪宠,會(huì)導(dǎo)致這個(gè)Context樹越來越龐大;所以Value類型的Context應(yīng)該掛在Cancel的Context樹下面妈嘹,這樣在取消時(shí)GC會(huì)回收柳琢。
- 會(huì)導(dǎo)致接口不一致或者奇怪,比如io.Reader其實(shí)第一個(gè)參數(shù)應(yīng)該是context润脸,比如
Read(Context, []byte)
函數(shù)柬脸。或者提供兩套接口毙驯,一種帶Contex倒堕,一種不帶Context。這個(gè)問題還蠻困擾人的爆价,一般在應(yīng)用程序中垦巴,推薦第一個(gè)參數(shù)是Context。 - 注意Context樹铭段,如果因?yàn)镃losure導(dǎo)致樹越來越深骤宣,會(huì)有調(diào)用棧的性能問題。比如十萬個(gè)長鏈序愚,會(huì)導(dǎo)致CPU占用500%左右涯雅。
備注:關(guān)于對Context的批評,可以參考Context should go away for Go 2展运,作者覺得在標(biāo)準(zhǔn)庫中加context作為第一個(gè)參數(shù)不能理解活逆,比如
Read(ctx context.Context
等。
Links
由于簡書限制了文章字?jǐn)?shù)拗胜,只好分成不同章節(jié):
- Overview 為何Go有時(shí)候也叫Golang?為何要選擇Go作為服務(wù)器開發(fā)的語言蔗候?是沖動(dòng)?還是騷動(dòng)埂软?Go的重要里程碑和事件锈遥,當(dāng)年吹的那些牛逼纫事,都實(shí)現(xiàn)了哪些?
- Could Not Recover 君可知所灸,有什么panic是無法recover的丽惶?包括超過系統(tǒng)線程限制,以及map的競爭寫爬立。當(dāng)然一般都能recover钾唬,比如Slice越界、nil指針侠驯、除零抡秆、寫關(guān)閉的chan等。
- Errors 為什么Go2的草稿3個(gè)有2個(gè)是關(guān)于錯(cuò)誤處理的吟策?好的錯(cuò)誤處理應(yīng)該怎么做儒士?錯(cuò)誤和異常機(jī)制的差別是什么?錯(cuò)誤處理和日志如何配合檩坚?
- Logger 為什么標(biāo)準(zhǔn)庫的Logger是完全不夠用的着撩?怎么做日志切割和輪轉(zhuǎn)?怎么在混成一坨的服務(wù)器日志中找到某個(gè)連接的日志匾委?甚至連接中的流的日志睹酌?怎么做到簡潔又夠用?
- Interfaces 什么是面向?qū)ο蟮腟OLID原則剩檀?為何Go更符合SOLID憋沿?為何接口組合比繼承多態(tài)更具有正交性?Go類型系統(tǒng)如何做到looser, organic, decoupled, independent, and therefore scalable沪猴?一般軟件中如果出現(xiàn)數(shù)學(xué)辐啄,要么真的牛逼要么裝逼。正交性這個(gè)數(shù)學(xué)概念在Go中頻繁出現(xiàn)运嗜,是神仙還是妖怪壶辜?為何接口設(shè)計(jì)要考慮正交性?
- Modules 如何避免依賴地獄(Dependency Hell)担租?小小的版本號為何會(huì)帶來大災(zāi)難砸民?Go為什么推出了GOPATH、Vendor還要搞module和vgo奋救?新建了16個(gè)倉庫做測試岭参,碰到了9個(gè)坑,搞清楚了gopath和vendor如何遷移尝艘,以及vgo with vendor如何使用(畢竟生產(chǎn)環(huán)境不能每次都去外網(wǎng)下載)演侯。
- Concurrency & Control 服務(wù)器中的并發(fā)處理難在哪里?為什么說Go并發(fā)處理優(yōu)勢占領(lǐng)了云計(jì)算開發(fā)語言市場背亥?什么是C10K秒际、C10M問題悬赏?如何管理goroutine的取消、超時(shí)和關(guān)聯(lián)取消娄徊?為何Go1.7專門將context放到了標(biāo)準(zhǔn)庫闽颇?context如何使用,以及問題在哪里寄锐?
- Engineering Go在工程化上的優(yōu)勢是什么兵多?為什么說Go是一門面向工程的語言?覆蓋率要到多少比較合適锐峭?什么叫代碼可測性中鼠?為什么良好的庫必須先寫Example可婶?
- Go2 Transition Go2會(huì)像Python3不兼容Python2那樣作嗎沿癞?C和C++的語言演進(jìn)可以有什么不同的收獲?Go2怎么思考語言升級的問題矛渴?
- SRS & Others Go在流媒體服務(wù)器中的使用椎扬。Go的GC靠譜嗎?Twitter說相當(dāng)?shù)目孔V具温,有圖有真相蚕涤。為何Go的聲明語法是那樣?C的又是怎樣铣猩?是拍的大腿揖铜,還是拍的腦袋?