這一系列文章主要分析nodejs中的核心庫(kù)Libuv衣赶。
我的參考書(shū):
樸靈的深入淺出nodejs
Jeffrey Richter的Windows核心編程
Anthony Williams的C++并發(fā)編程實(shí)戰(zhàn)
暫定為四篇:
1) 征服之初識(shí)篇(背景基礎(chǔ)以及重要的概念伍茄,圖示)
2) 征服之進(jìn)展篇(libuv的編譯淹朋,例子偏塞,內(nèi)部用到的c語(yǔ)言技巧以及QUEUE的使用)
3) 征服之高潮篇(線(xiàn)程池唱蒸,iocp,同步灸叼,并發(fā)神汹,線(xiàn)程間的通信等)
4) 征服之和諧篇(Libuv的初始化,主循環(huán)古今,主線(xiàn)程和線(xiàn)程池之間的和諧交往)
通過(guò)征服Libuv系列文章屁魏,目的是讓大家了解:
1) C語(yǔ)言之美(語(yǔ)法簡(jiǎn)單,功能強(qiáng)大捉腥,貼近硬件氓拼,適合系統(tǒng)級(jí)別編程,有很多技巧)
2) 多線(xiàn)程與線(xiàn)程的同步技術(shù)
3) 線(xiàn)程池技術(shù)
4) windows IOCP技術(shù)
5) 了解與ms PPL, intel TBB以及l(fā)ibdispatch(ios gcd)之間的異同點(diǎn)和優(yōu)缺點(diǎn)抵碟。
6) vs c++中多線(xiàn)程下的debug技巧
之所以稱(chēng)為了解桃漾,而不是掌握,是因?yàn)檫@些技術(shù)偏向于底層的系統(tǒng)編程拟逮,并不是一撮而就的撬统,需要一定的時(shí)間和經(jīng)歷才能沉淀下來(lái)的。因此只能說(shuō)是讓大家了解敦迄。
為了簡(jiǎn)單期間恋追,一些限制條件:
僅關(guān)注windows下的實(shí)現(xiàn)
僅重點(diǎn)分析libuv的通用cpu密集型計(jì)算的框架,了解cpu密集計(jì)算框架罚屋,實(shí)際上異步io就比較容易理解了
因?yàn)閣indows下苦囱,異步io通過(guò)IOCP(完成端口),會(huì)使代碼實(shí)現(xiàn)非常簡(jiǎn)單沿后,而效率非常高沿彭。
在寫(xiě)此篇blog時(shí),突然感覺(jué)到尖滚,是不是應(yīng)該將libuv庫(kù)進(jìn)行拆分喉刘,將核心部分代碼抽離出來(lái)單獨(dú)運(yùn)行瞧柔,這樣的好處就是要分析的代碼量要少很多,僅關(guān)注我們感興趣的代碼睦裳,有利于演示造锅。
還有一個(gè)目的:
就是在簡(jiǎn)化精華版的基礎(chǔ)上升級(jí)一下,看看是否能夠?qū)崿F(xiàn)任務(wù)的動(dòng)態(tài)均衡(ms PPL庫(kù)和intel TBB庫(kù)都有動(dòng)態(tài)均衡廉邑,Work Stealing的功能哥蔚,libuv目前確定沒(méi)有此功能,libdispatch目前沒(méi)發(fā)現(xiàn)蛛蒙,源碼正在閱讀中糙箍,還沒(méi)看到)。這個(gè)實(shí)現(xiàn)難度還是很大的牵祟,就當(dāng)練練手吧,哈哈
我嘗試一下吧深夯,看看是否可行!
1诺苹、背景:
前段時(shí)間咕晋,完成了一個(gè)微信項(xiàng)目,在后臺(tái)選型過(guò)程中收奔,花了將近一個(gè)月考察了java,php幾個(gè)庫(kù)掌呜,但最終卻選擇了nodejs,原因很簡(jiǎn)單:
1坪哄、java的配置實(shí)在是太麻煩了
2质蕉、php實(shí)在不熟悉,特別扭
3损姜、nodejs使用js編程饰剥,我本人還是比較熟悉js的基礎(chǔ)部分(不算es6.0 es7.0標(biāo)準(zhǔn)),并且npm真好用,實(shí)在是資源太豐富了摧阅,有時(shí)選擇太多也是一種痛苦啊绷蹲!
4棒卷、nodejs基于異步io技術(shù),效率非常高祝钢。而且分布式部署簡(jiǎn)單比规。
通過(guò)無(wú)數(shù)次的比較,最終選定了令我非常滿(mǎn)意的組合拦英,感覺(jué)最起碼少寫(xiě)了80%的代碼蜒什。
后臺(tái)配套方案:
framework: strongloop/loopback(被IBM收購(gòu)了忿危,只能說(shuō)強(qiáng)大無(wú)比)
樸靈的: wechat / wechat-api / wechat-oauth
supersheep: wechat-pay
數(shù)據(jù)庫(kù): mongodb用于不需要事務(wù)處理的表 mysql用于支付的事務(wù)處理
因?yàn)闆](méi)經(jīng)驗(yàn)枉证,在支付時(shí)需要事務(wù)處理,所以調(diào)整為使用mysql。不過(guò)從另外一個(gè)角度說(shuō)明loopback的強(qiáng)大邻辉,支持多數(shù)據(jù)源的統(tǒng)一api操作。
前臺(tái)配套方案:
總體而言熄守,該前后臺(tái)配套系統(tǒng)的開(kāi)發(fā)非常令人愉悅励幼。前臺(tái)不好統(tǒng)計(jì),但是微信后臺(tái)雕什,至少少寫(xiě)了80%代碼2场!
我正在做loopback方面的demo,來(lái)分享一下loopback框架和angularjs之間的互動(dòng)贷岸,你會(huì)看到他們的配合是多么的默契壹士。
近期會(huì)有blog以及demo提交github
2、演變:
目前基于異步回調(diào)的開(kāi)發(fā)非常盛行偿警,例如ios中的gcd躏救,android中的基于接口回調(diào)方式。如果有過(guò)這些開(kāi)發(fā)經(jīng)驗(yàn)户敬,你會(huì)覺(jué)得nodejs的異步事件開(kāi)發(fā)模型還是蠻熟悉的落剪。
隨著逐漸熟悉nodejs,深深的喜歡上了nodejs尿庐,因此更想深入的了解一下nodejs是如何實(shí)現(xiàn)的忠怖。
通過(guò)了解nodejs的代碼結(jié)構(gòu),結(jié)合深入淺出nodejs第三章的異步io所示流程圖抄瑟,逐步驗(yàn)證其正確性凡泣。特別是看到libuv中具有深厚c語(yǔ)言功底的老鳥(niǎo)所寫(xiě)的代碼,忍不住想與大家分享c的代碼之美Fぜ佟鞋拟!
題外話(huà):我深入研究過(guò)的或正在研究的以及即將研究的c源碼庫(kù)
隨便說(shuō)一下:現(xiàn)在c/c++貌似不太流行了。但是不管如何惹资,c語(yǔ)言我認(rèn)為是一門(mén)基礎(chǔ)語(yǔ)言贺纲,每個(gè)程序員如果想要深入了解底層,最好學(xué)一下c語(yǔ)言褪测。
我本人很喜歡c語(yǔ)言猴誊,曾經(jīng)花了5年以上的時(shí)間自己研究3D游戲之父-約翰卡馬克的quake系列引擎以及sgi opengl1.21實(shí)現(xiàn)(This is SGI's Sample Implementation of the OpenGL API. It is both a reference implementation and a driver framework used by **almost all commercial 3D hardware vendors **to develop hardware drivers for their systems)。
可以說(shuō)quake引擎以及opengl源碼是形成我科學(xué)程序觀(guān)的基石侮措,是技術(shù)源懈叹。(差點(diǎn)說(shuō)成科學(xué)發(fā)展觀(guān)了,這個(gè)太....)
目前正在閱讀調(diào)試的c庫(kù)源碼:
libdispatch ios gcd中的函數(shù)都是來(lái)源于libdispatch分扎,目前已經(jīng)都移植到linux和windows中了
libuv 跨平臺(tái)的異步io和work庫(kù)
已編譯并運(yùn)行過(guò)demo,計(jì)劃要閱讀的c源碼庫(kù):
libkqueue 一個(gè)跨平臺(tái)的unix kqueue實(shí)現(xiàn)澄成。實(shí)際在libdispatch移植到windows和linux版本時(shí),就包含了libkqueue。因?yàn)閘ibdispatch(源于macos和ios,他們都是基于unix系統(tǒng)的)基于kqueue實(shí)現(xiàn)墨状。
libzmq跨平臺(tái)的異步消息隊(duì)列庫(kù)(內(nèi)部c++實(shí)現(xiàn)卫漫,以c api方式導(dǎo)出,很多庫(kù)也使用這種方式)
zookeeper是一個(gè)分布式應(yīng)用程序協(xié)調(diào)服務(wù),是Hadoop和Hbase的重要組件。目前作為單獨(dú)一個(gè)庫(kù)獨(dú)立出來(lái)了歉胶。
libuv目前基本了解整個(gè)流程了汛兜,其他幾個(gè)等弄明白了,也一起分享吧通今,讓我們一起來(lái)學(xué)c語(yǔ)言!
為什么選這些庫(kù):
1) 提高自身編程水平最好的方式是多閱讀經(jīng)典源碼
2) 多線(xiàn)程粥谬,異步以及分布式、異步消息隊(duì)列等都是目前主流辫塌,這些庫(kù)是最高水平的實(shí)現(xiàn)漏策,被大規(guī)模,廣泛使用臼氨。
3) 這些庫(kù)都是跨平臺(tái)庫(kù)掺喻,代碼量不大,并且實(shí)用性又很高储矩,功能單一感耙,這就是c庫(kù)的魅力所在。
4) 都是c語(yǔ)言實(shí)現(xiàn)持隧,借助于ide的幫助即硼,會(huì)很容易了解清楚整個(gè)流程。
3屡拨、libuv是什么?
libuv is a multi-platform support library with a focus on asynchronous I/O.
It was primarily developed for use by Node.js
由上面的介紹只酥,我們可以知道:
1) 跨平臺(tái):windows linux unix都支持
2) 異步io:windows IOCP 、linux epoll呀狼、unix kqueue
3) 主要目的是用于nodejs裂允,實(shí)際還有很多庫(kù)或程序使用了libuv
例如目前風(fēng)頭正勁的跨平臺(tái).NetCore庫(kù)(就是曾經(jīng)大名鼎鼎的微軟的asp.net)也是使用libuv作為核心
4) libuv不僅僅支持異步io操作,而且還具有一個(gè)強(qiáng)勁的線(xiàn)程池哥艇,用于支持多線(xiàn)程并行的cpu密集型操作绝编。
這個(gè)才是我們重點(diǎn)要分析的模塊
4、nodejs貌踏、google v8 javascript引擎和libuv之間的關(guān)系:
1) nodejs主要由google v8 javascript引擎和libuv組成
2) v8引擎綁定libuv實(shí)現(xiàn)的api瓮增,因此,既能使用ecma js標(biāo)準(zhǔn)語(yǔ)言來(lái)執(zhí)行js代碼哩俭,又能通過(guò)js調(diào)用libuv相關(guān)接口。
3) 由此可見(jiàn)拳恋,libuv本身是獨(dú)立的c語(yǔ)言庫(kù)凡资,既可以直接使用c/c++來(lái)調(diào)用,也可以被綁定到c#(.NetCore)或者其他任何語(yǔ)言,例如java ,lua......
c/c++實(shí)現(xiàn)的庫(kù)最大的好處就是能被各種其他編程語(yǔ)言所綁定和調(diào)用隙赁。
因?yàn)槠渌鞣N編程語(yǔ)言基本都是用c/c++來(lái)實(shí)現(xiàn)的垦藏,都留有接口與c/c++互調(diào)。
借用樸靈 深入淺出nodejs中的兩張圖來(lái)了解整個(gè)流程:
我們libuv源碼分析以上圖為指導(dǎo)伞访,深入挖掘每個(gè)細(xì)節(jié)掂骏,驗(yàn)證其正確性,從而掌握整個(gè)libuv的精髓厚掷!
請(qǐng)將此圖看上100遍弟灼,背出來(lái),肯定有非常大幫助
nodejs就是數(shù)據(jù)通過(guò)v8引擎(主線(xiàn)程:數(shù)據(jù)輸入)傳遞給Libuv進(jìn)行處理(線(xiàn)程池:數(shù)據(jù)處理--根據(jù)數(shù)據(jù)類(lèi)型不同冒黑,io數(shù)據(jù)由IOCP[windows]線(xiàn)程池處理田绑,通用計(jì)算則由自己實(shí)現(xiàn)的線(xiàn)程池處理),libuv處理好后通知v8引擎我已經(jīng)完成了抡爹,你來(lái)進(jìn)行完成處理(主線(xiàn)程:完成回調(diào)掩驱,信息輸出)。
其實(shí)從上面的敘述可以了解到以下幾點(diǎn):
1) v8 javascript引擎是單線(xiàn)程的冬竟,數(shù)據(jù)的輸入欧穴,信息的輸出(完成回調(diào))都是在主線(xiàn)程中處理。這一點(diǎn)以后在源碼分析中我們可以驗(yàn)證泵殴,通過(guò)vs強(qiáng)大的debug功能涮帘,我們可以很清晰的看到具體代碼到底是運(yùn)行在哪個(gè)線(xiàn)程中。
2) 但是數(shù)據(jù)處理模塊(libuv)不是單線(xiàn)程的袋狞,它根據(jù)數(shù)據(jù)請(qǐng)求類(lèi)型是否是io請(qǐng)求(socket,文件讀寫(xiě)或管道等)還是work請(qǐng)求(非io請(qǐng)求)焚辅。不同的請(qǐng)求使用不同的處理策略。例如io請(qǐng)求苟鸯,在windows下用IOCP,在linux下用epool同蜻。而work請(qǐng)求,windows和linux下都是使用統(tǒng)一的早处,自己實(shí)現(xiàn)的線(xiàn)程池湾蔓。而我們的源碼分析就是要證明上面的描述。
下一篇: 征服libuv之進(jìn)展篇
.