日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

node.js学习总结

發(fā)布時(shí)間:2025/4/14 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 node.js学习总结 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

NodeJS介紹

1.概述:


? ? ? Node.js是基于Chrome JavaScript運(yùn)行時(shí)建立的一個(gè)平臺(tái),實(shí)際上它是對(duì)Google Chrome V8引擎

進(jìn)行了封裝,它主要用于創(chuàng)建快速的、可擴(kuò)展的網(wǎng)絡(luò)應(yīng)用。Node.js采用事件驅(qū)動(dòng)和非阻塞I/O模型,使

其變得輕微和高效,非常適合構(gòu)建運(yùn)行在分布式設(shè)備的數(shù)據(jù)密集型實(shí)時(shí)應(yīng)用。

? ? ? 運(yùn)行于瀏覽器的Javascript,瀏覽器就是Javascript代碼的解析器,而Node.js則是服務(wù)器端JS的

代碼解析器,存于服務(wù)器端的JS代碼由Node.js來(lái)解析和應(yīng)用。

? ? ? JS解析器只是JS代碼運(yùn)行的一種環(huán)境,瀏覽器是JS運(yùn)行的一種環(huán)境,瀏覽器為JS提供了操作DOM對(duì)

象和window對(duì)象等接口。Node.js也是JS的一種運(yùn)行環(huán)境,node.js為JS提供操作文件、創(chuàng)建http服務(wù)、

創(chuàng)建TCP、UDP服務(wù)等接口,所以Node.js可以完成其他后臺(tái)語(yǔ)言能完成的工作。

2.交互式運(yùn)行環(huán)境:PEPL

? ? ? Node.js提供了一個(gè)交互式運(yùn)行環(huán)境,通過這個(gè)環(huán)境,可以立即執(zhí)行JS代碼,使用方法類似于


Chrome瀏覽器中Firebug插件中的Console。


? ? ? 在Linux環(huán)境進(jìn)入終端后,屬于"node"或者“nodejs”進(jìn)入Node.js的交互式運(yùn)行環(huán)境,Ctrl+d可

以退出此環(huán)境。


? ? ? 查看系統(tǒng)中安裝的Node.js版本:node -v or nodejs -v

? ? ? 運(yùn)行JS文件,eg:node file.js or nodejs file.js

3.Node.js模塊和包

? ? ? a.模塊

? ? ? ? ?Node.js官方提供了很多模塊,這些模塊分別實(shí)現(xiàn)了一種功能,如操作文件模塊fs,構(gòu)建http服


務(wù)模塊的http等,每個(gè)模塊都是一個(gè)JS文件,當(dāng)然也可以自己編 ? 寫模塊。


? ? ? 2.包


? ? ? ? ? 包可以將多個(gè)具有依賴關(guān)系的模塊組織在一起,封裝多個(gè)模塊,以方便管理。Node.js采用了


CommonJS規(guī)范,根據(jù)CommonJS規(guī)范規(guī)定,一個(gè)JS文件就是 一個(gè)模塊,而包是一個(gè)文件夾,包內(nèi)必須包含


一個(gè)JSON文件,命名package.json。一般情況下,包內(nèi)bin文件夾存放二進(jìn)制文件,包內(nèi)的lib文件夾存


放JS文件,包內(nèi)的doc文件夾存放文檔,包內(nèi)的test文件夾存放單元測(cè)試。package.json文件中需要包含


的字段及包的使用。


? ? ? 3.npm包管理工具

? ? ? ? ?npm是node.js的包管理工具,npm定義了包依賴關(guān)系標(biāo)準(zhǔn),我們使用npm主要用來(lái)下載第三方包

和管理本地下載的第三方包。
========

為什么我要用 Node.js? 案例逐一介紹


介紹


JavaScript 高漲的人氣帶來(lái)了很多變化,以至于如今使用其進(jìn)行網(wǎng)絡(luò)開發(fā)的形式也變得截然不同了。就


如同在瀏覽器中一樣,現(xiàn)在我們也可以在服務(wù)器上運(yùn)行 JavaScript ,從前端跨越到后端,這樣巨大的


反差讓人難以想象,因?yàn)閮H僅在幾年前 Javascript 還如同 Flash 或者 Java applet 那樣嵌入網(wǎng)頁(yè)在

沙箱環(huán)境中運(yùn)行。

在深入Node.js之前,你可能需要閱讀和了解使用跨棧式JavaScript(JavaScript across the stack)


帶來(lái)的好處,它統(tǒng)一了編程語(yǔ)言和數(shù)據(jù)格式(JSON),讓你能最佳地重用開發(fā)人員資源。由于這更多的


是關(guān)于 JavaScript 的特點(diǎn),這里就不過多討論它。但它確實(shí)是一個(gè)讓人在開發(fā)環(huán)節(jié)中使用 Node 的關(guān)

鍵的優(yōu)點(diǎn)。

正如維基百科 所說(shuō):“Node.js 是谷歌 V8 引擎、libuv平臺(tái)抽象層 以及主體使用 Javscript 編寫的


核心庫(kù)三者集合的一個(gè)包裝外殼。” 除此之外,值得注意的是,Node.js 的作者瑞恩·達(dá)爾 (Ryan?


Dahl) 的目標(biāo)是創(chuàng)建具有實(shí)時(shí)推送能力的網(wǎng)站。在 Node.js 中,他給了開發(fā)者一個(gè)使用事件驅(qū)動(dòng)來(lái)實(shí)現(xiàn)


異步開發(fā)的優(yōu)秀解決方案。(注:V8是谷歌開發(fā)的,目前公認(rèn)最快的 Javascript 解析引擎,libuv 是


一個(gè)開源的、為 Node 定制而生的跨平臺(tái)的異步 IO 庫(kù)。)


簡(jiǎn)而言之:Node.js 在實(shí)時(shí)的 Web應(yīng)用上采用了基于 WebSocket 的推送技術(shù)。這意味著什么樣的革命性


?Well,在經(jīng)過了20多年的基于無(wú)狀態(tài)的請(qǐng)求-返機(jī)制的無(wú)狀態(tài)交互之后,我們終于有了實(shí)時(shí)的,雙向連


接的web應(yīng)用,客戶端和服務(wù)器端都可以發(fā)起通信,能夠自由地交換數(shù)據(jù)。與此形成鮮明對(duì)比的是傳統(tǒng)的?


web響應(yīng)模式,客戶端總是主動(dòng)發(fā)起通信而服務(wù)端被動(dòng)返回。此外,這些都是基于運(yùn)行在標(biāo)準(zhǔn)80端口上的


開放Web組件(HTML、CSS和JS)。


可能有人會(huì)說(shuō),我們已經(jīng)使用 Flash 和 Java Applet 的形式很多年了——但實(shí)際上,這些方式只是使


用網(wǎng)絡(luò)將數(shù)據(jù)傳遞到客戶端上的沙箱環(huán)境。他們都是隔離運(yùn)行的,而且經(jīng)常操作到需要額外的權(quán)限之類


的非標(biāo)準(zhǔn)端口。


憑借其獨(dú)特的優(yōu)勢(shì),Node.js的現(xiàn)在已經(jīng)在許多著名公司的產(chǎn)品中起到了關(guān)鍵作用。


在這篇文章中,我們不僅將討論這些優(yōu)勢(shì)是如何實(shí)現(xiàn)的,而且也會(huì)討論為什么你使用 Node.js 來(lái)替代一


些經(jīng)典的Web應(yīng)用程序模型。


Node.js 是如何工作的?



Node.js 的主要思路是:使用非阻塞的,事件驅(qū)動(dòng)的 I/O 操作來(lái)保持在處理跨平臺(tái) (across?


distributed devices) 數(shù)據(jù)密集型實(shí)時(shí)應(yīng)用時(shí)的輕巧高效。這聽起來(lái)有點(diǎn)繞口。


它的真正含義是,Node.js 不是一個(gè)即將主導(dǎo)Web開發(fā)的世界的銀彈級(jí)的平臺(tái)。相反,它是一個(gè)滿足特別


需求的平臺(tái)。你肯定不會(huì)希望使用 Node.js 去做 CPU密集型操作。事實(shí)上,使用它進(jìn)行繁重的計(jì)算等于


摒棄 Node 幾乎所有的優(yōu)點(diǎn)。Node 真正的亮點(diǎn)在于建設(shè)高性能,高擴(kuò)展性的互聯(lián)網(wǎng)應(yīng)用——因?yàn)樗軌?


處理龐大的并且高吞吐量的并發(fā)連接。


它的工作原理是相當(dāng)有趣的。傳統(tǒng)的網(wǎng)絡(luò)服務(wù)技術(shù),是每個(gè)新增一個(gè)連接(請(qǐng)求)便生成一個(gè)新的線程


,這個(gè)新的線程會(huì)占用系統(tǒng)內(nèi)存,最終會(huì)占掉所有的可用內(nèi)存。而 Node.js 僅僅只運(yùn)行在一個(gè)單線程中


,使用非阻塞的異步 I/O 調(diào)用,所有連接都由該線程處理,在 libuv 的加分下,可以允許其支持?jǐn)?shù)萬(wàn)


并發(fā)連接(全部掛在該線程的事件循環(huán)中)。


toptal-blog-1_B


做一個(gè)簡(jiǎn)單的計(jì)算: 假設(shè)是普通的Web程序,新接入一個(gè)連接會(huì)占用 2M 的內(nèi)存,在有 8GB RAM的系統(tǒng)上


運(yùn)行時(shí), 算上線程之間上下文切換的成本,并發(fā)連接的最大理論值則為 4000 個(gè)。這是在傳統(tǒng) Web服務(wù)


端技術(shù)下的處理情況。而 Node.js 則達(dá)到了約 1M 一個(gè)并發(fā)連接的拓展級(jí)別 (相關(guān)證明).


當(dāng)然,在所有客戶端的請(qǐng)求共享單一線程時(shí)也會(huì)有問題, 這也是一個(gè)編寫 Node.js 應(yīng)用的潛在缺陷. 首


先, 大量的計(jì)算可能會(huì)使得 Node 的單線程暫時(shí)失去反應(yīng), 并導(dǎo)致所有的其他客戶端的請(qǐng)求一直阻塞,?


直到計(jì)算結(jié)束才恢復(fù)正常。 其次,開發(fā)人員需要非常小心,不要讓一個(gè) Exception 阻塞核心的事件循


環(huán),因?yàn)檫@將導(dǎo)致 Node.js 實(shí)例的終止(實(shí)際上就是程序崩潰)。( 筆者注:如 PHP 中某個(gè)頁(yè)面掛掉


是不會(huì)影響網(wǎng)站運(yùn)行的,但是 Nodejs 是一個(gè)線程一個(gè)線程來(lái)處理所有的鏈接,所以不論是計(jì)算卡了或


者是被異常阻塞了都可能會(huì)影響到其他所有的鏈接。解決方案在稍后討論。)


用來(lái)避免異常拋出時(shí)中斷進(jìn)程的方法是將異常使用回調(diào)傳遞出去(而不是拋出他們,就像在其他環(huán)境中


一樣)。即使一些未處理的異常阻塞了程序,依舊有多種應(yīng)對(duì)的解決方案,而且也有很多可用于監(jiān)視?


Node 進(jìn)程來(lái)執(zhí)行必要的崩潰后恢復(fù)工作的策略和工具(雖然你將無(wú)法恢復(fù)用戶的 Session ),最常見


的是使用 Forever 模塊,或者采用其他的外部系統(tǒng)工具如 upstart and monit。


NPM: The Node Package Manager



當(dāng)我們討論 Node.js 的時(shí)候,一個(gè)絕對(duì)不應(yīng)該忽略地方就是默認(rèn)內(nèi)置的模塊管理工具 —— NPM。 其靈


感來(lái)源與 Ruby Gems(具有版本和依賴管理功能,可以通過在線資料庫(kù)便捷安裝可重用的組件的管理工


具)。


一個(gè)完整的公用模塊列表可以在 NPM 的網(wǎng)站上找到(https:://npmjs.org/),或者通過使用與?


Node.js 一同安裝的 NPM CLI 工具放問到。該模塊的生態(tài)系統(tǒng)向所有人開放,任何人都可以發(fā)布自己的


模塊,所有的模塊都可以在 NPM 資料庫(kù)中找到。你可以在 http://howtonode.org/introduction-to-


npm 頁(yè)面找到 NPM 的一個(gè)簡(jiǎn)要介紹(有點(diǎn)舊,但依舊能看)。


目前非常流行的一些 NPM 模塊有:


express – Express.js,是一個(gè)簡(jiǎn)潔而靈活的 node.js Web應(yīng)用框架, 并且已經(jīng)是現(xiàn)在大多數(shù) Node.js?


應(yīng)用的標(biāo)準(zhǔn)框架,你已經(jīng)可以在很多 Node.js 的書籍中看到它了。
connect – Connect 是一個(gè) Node.js 的 HTTP 服務(wù)拓展框架,提供一個(gè)高性能的“插件”集合,以中


間件聞名,是 Express 的基礎(chǔ)部分之一。
socket.io 和 sockjs – 目前服務(wù)端最流行的兩個(gè) websocket 組件。
Jade – 流行的模板引擎之一,并且是 Express.js 的默認(rèn)模板引擎。其靈感來(lái)源于 HAML。
mongo 和 mongojs – 封裝了 MongoDB 的的各種 API,不過筆者平常工作用的是 mongoose 也很推薦。
redis – Redis 的客戶端函數(shù)庫(kù).
coffee-script – CoffeeScript 編譯器,允許開發(fā)者使用 Coffee 來(lái)編寫他們的 Node.js 程序。
underscore (lodash, lazy) – 最流行的 JavaScript 工具庫(kù) , 用于 Node.js 的封裝包,以及兩個(gè)采


取略有不同的實(shí)現(xiàn)方法來(lái)獲得更好性能的同行。
forever – 可能是用來(lái)確保 node 腳本持續(xù)運(yùn)行的最流行的工具。
還有很多好的模塊,這里就不一一列舉了(希望沒有冒犯到?jīng)]列舉的)。


Node.js 應(yīng)該用在什么地方



聊天


聊天是最典型的多用戶實(shí)時(shí)交互的應(yīng)用。從 IRC 開始,有許多開源或者不開源的協(xié)議都運(yùn)行在非標(biāo)準(zhǔn)端

口上,而現(xiàn)在,使用 Node.js 則可以解決這些問題——在標(biāo)準(zhǔn)的80端口運(yùn)行 WebSockets。

聊天應(yīng)用程序是最能體現(xiàn) Node.js 優(yōu)點(diǎn)的例子:輕量級(jí)、高流量并且能良好的應(yīng)對(duì)跨平臺(tái)設(shè)備上運(yùn)行密

集型數(shù)據(jù)(雖然計(jì)算能力低)。同時(shí),聊天也是一個(gè)非常值得學(xué)習(xí)的用例,因?yàn)樗芎?jiǎn)單,并且涵蓋了

目前為止一個(gè)典型的 Node.js 會(huì)用到的大部分解決方案。

讓我們?cè)囍鴣?lái)描繪它如何工作。


在最簡(jiǎn)單的情況下,我們布置了一個(gè)聊天室在我們的網(wǎng)站上,用戶可以在上面發(fā)消息,當(dāng)然是一對(duì)多的

形式。例如,假設(shè)總共有三個(gè)人連接到我們的網(wǎng)站上。

在服務(wù)端這邊, 我們有一個(gè)使用 Express.js 搭建的簡(jiǎn)單站點(diǎn),該站點(diǎn)實(shí)現(xiàn)了兩件事 1) 處理路徑為?

‘/’ 的GET請(qǐng)求時(shí),下發(fā)包括一個(gè)留言板以及一個(gè)發(fā)送信息的 ‘發(fā)送’ 按鈕的頁(yè)面 2) 一個(gè)監(jiān)聽客戶

端發(fā)送新消息的 websockets 服務(wù)。

在客戶端這邊,我們有一個(gè) HTML 頁(yè)面,上面有個(gè)兩個(gè) js 方法,一個(gè)是用于觸發(fā)事件的 “發(fā)送” 按

鈕,這會(huì)把把輸入的消息通過 webscoket 發(fā)送,另一個(gè)方法是用 webscoket 在客戶端上監(jiān)聽服務(wù)端來(lái)

的推送(例如,其他用戶發(fā)送的消息)。

當(dāng)有一個(gè)客戶端發(fā)送消息的時(shí)候,發(fā)生的事情是:


瀏覽器上,點(diǎn)擊發(fā)送按鈕觸發(fā)了 js 函數(shù),將輸入框中的文字通過 websocket 消息發(fā)送到服務(wù)器的?


websocket 客戶端(頁(yè)面初始化加載的時(shí)候連接的)。
服務(wù)端的 websocket 組件收到 消息,然后通過廣播方法轉(zhuǎn)發(fā)到其他所有連接的客戶端。
通過頁(yè)面上運(yùn)行的 websocket 客戶端組件,所有的客戶端都能收到這條推送的新消息。接著 js 處理函


數(shù)可以把這個(gè)消息添加到文字框內(nèi)。
toptal-blog-2_B

這是一個(gè)最簡(jiǎn)單的例子。如果要更好的解決方案,你可以使用 Redis 數(shù)據(jù)庫(kù)做一個(gè)簡(jiǎn)單的緩存。在一個(gè)

更高級(jí)的解決方案中,你可能需要一個(gè)消息路由來(lái)專門處理消息隊(duì)列,并且需要一個(gè)更強(qiáng)健的發(fā)送機(jī)制

,比如發(fā)送的時(shí)候覆蓋上暫時(shí)離線的用戶或者為離線的注冊(cè)用戶存儲(chǔ)尚未接收的消息等等。但是不論你

做了怎么樣的改進(jìn),Node.js 都將遵循一個(gè)基本原則:響應(yīng)事件,處理多個(gè)并發(fā)連接,并保持流動(dòng)性的

用戶體驗(yàn)。

對(duì)象數(shù)據(jù)庫(kù)接口(API ON TOP OF AN OBJECT DB)


盡管,Node.js 確實(shí)非常擅長(zhǎng)實(shí)時(shí)交互的應(yīng)用,同時(shí)它也十分適合通過對(duì)象數(shù)據(jù)庫(kù)(object DB)來(lái)查詢


數(shù)據(jù)(如 MongoDB)。以 JSON 格式存儲(chǔ)的數(shù)據(jù)允許 Node.js 直接處理,不需要糾結(jié)數(shù)據(jù)轉(zhuǎn)換和匹配的

問題。

舉個(gè)例子,如果你正在使用 Rails,你會(huì)將 JSON 數(shù)據(jù)轉(zhuǎn)成 二進(jìn)制的 model,當(dāng)數(shù)據(jù)再被?

Backbone.js, Angular.js 或者 jQuery AJAX 之類的調(diào)用又要轉(zhuǎn)回 JSON。如果是 Nodejs 的話,你可

以通過一個(gè) REST API 簡(jiǎn)單的導(dǎo)出 JSON 對(duì)象以供客戶端使用。另外,從數(shù)據(jù)庫(kù)讀寫時(shí)候如果使用的是?

MongoDB 的話,你也不用擔(dān)心的 JSON 與任何數(shù)據(jù)之間的格式問題。總之,你可以避免多元的數(shù)據(jù)轉(zhuǎn)換

問題,不論是在客戶端、服務(wù)端還是數(shù)據(jù)庫(kù)。

隊(duì)列輸入



如果你正在接收一個(gè)高量并發(fā)的數(shù)據(jù),你的數(shù)據(jù)庫(kù)可能會(huì)成為你處理的瓶頸。正如上面的描述,Node.js?


可以輕松的處理并發(fā)連接。 但是,由于數(shù)據(jù)庫(kù)操作是一個(gè)阻塞的操作(在這種情況下),這就是麻煩的


地方。Node.js的解決方案是,在數(shù)據(jù)真正的寫入之前就承認(rèn)客戶端的數(shù)據(jù)是真實(shí)的。


用這種方法,在高負(fù)載的時(shí)候系統(tǒng)繼續(xù)維持它的響應(yīng),這在當(dāng)客戶端不需要嚴(yán)格確認(rèn)一個(gè)數(shù)據(jù)是否成功


的被寫入時(shí)特別有用。典型的例子包括:日志記錄或者用戶跟蹤數(shù)據(jù)(user-tracking data)的記錄,


這會(huì)被分批處理并且在稍后才使用;同時(shí)也包括最終一致性(so, 常用于 NoSQL)可以接受,不需要立


即反應(yīng)的操作(例如 Facebook 上更新點(diǎn)贊的數(shù)目)。


數(shù)據(jù)通過某些緩存或者消息隊(duì)列的基礎(chǔ)組件(例如 RabbitMQ, ZeroMQ)進(jìn)入隊(duì)列,并且通過一個(gè)獨(dú)立的


數(shù)據(jù)庫(kù)批量寫入進(jìn)程來(lái)一一消化,或者通過一個(gè)更高性能的計(jì)算密集型后端服務(wù)來(lái)進(jìn)行處理。其他的語(yǔ)


言/框架也可以實(shí)現(xiàn)相似的操作,但在相同的配置下是達(dá)不到 nodejs 的高吞吐量與高并發(fā)。


toptal-blog-3_B


簡(jiǎn)單的說(shuō):使用 Node,你可以把數(shù)據(jù)庫(kù)操作扔到一邊并在稍后處理它們,假設(shè)他們成功了一樣繼續(xù)執(zhí)行


下去。(筆者注:在開發(fā)中通常的情況通常是,種耗時(shí)的操作通過回調(diào)函數(shù)來(lái)異步處理,主線程繼續(xù)往


下執(zhí)行)


數(shù)據(jù)流



在較為傳統(tǒng)的網(wǎng)絡(luò)平臺(tái)上,HTTP 的請(qǐng)求和響應(yīng)更像是孤立的事件;然而事實(shí)上,他們都是數(shù)據(jù)流。這一


觀察結(jié)果在 Nodejs 上可以用來(lái)建立一些很酷的功能。因?yàn)閿?shù)據(jù)通以流的形式接收,而我們可以在網(wǎng)站


上在線處理正在上傳中的文件。這樣的話,就可以實(shí)現(xiàn)實(shí)時(shí)的音頻和視頻編碼,以及在不同數(shù)據(jù)源之間


進(jìn)行代碼(代理見下一段)。


(筆者注:Node 有代替如 apache 這樣的 webserver 處理數(shù)據(jù),所以開發(fā)者可以直接收到客戶端一份


一份上傳的數(shù)據(jù),并實(shí)時(shí)處理。上面這段話聽起來(lái)有點(diǎn)抽象,不過各位可以簡(jiǎn)單的想象一下不需要開 YY?


或者 QQ,打開網(wǎng)頁(yè)就能進(jìn)行語(yǔ)音視頻的功能。)


代理



Node.js 可以通過異步的方式處理大量的并發(fā)連接,所以很容易作為服務(wù)端的代理來(lái)使用。這在與不同


響應(yīng)時(shí)間的不同服務(wù)之間進(jìn)行代理,或者是收集來(lái)自多個(gè)來(lái)源的數(shù)據(jù)時(shí)尤其有用。


舉個(gè)例子:考慮一個(gè)服務(wù)器端的應(yīng)用程序和第三方資源進(jìn)行通信以更新自不同來(lái)源的數(shù)據(jù),或者將服務(wù)


端上的一些圖像和視頻資源存儲(chǔ)到第三方云服務(wù)。


雖然專用代理服務(wù)器確實(shí)存在,但是如果你還沒有專用的代理服務(wù)器,或者你需要一個(gè)本地開發(fā)的解決


方案,那么使用 Node 來(lái)做代理可能是更好的選擇。關(guān)于這個(gè)解決方案,我的意思是指當(dāng)你在開發(fā)的時(shí)


候,你可以使用Node.js的開發(fā)環(huán)境搭建一個(gè)服務(wù)來(lái)處理對(duì)資源和代理的請(qǐng)求,而在生產(chǎn)環(huán)境下,你可以


使用專用的代理服務(wù)(比如nginx,HAProxy等)來(lái)處理這些交互。


股票操盤手的儀表盤



讓我們繼續(xù)討論應(yīng)用程序這塊。實(shí)時(shí)網(wǎng)絡(luò)的解決方案可以很輕松的實(shí)現(xiàn)證券交易軟件——用于跟蹤股票


的價(jià)格,執(zhí)行計(jì)算、做技術(shù)分析,同時(shí)生成報(bào)表。


使用一個(gè)實(shí)時(shí)的的基于網(wǎng)頁(yè)的解決方案,將會(huì)允許操盤手輕松的切換工作軟件以及工作地點(diǎn)。相信不久


,我們或許會(huì)在 佛羅里達(dá)州、伊維薩島又或者是巴厘島的海灘上看到他們。


應(yīng)用監(jiān)聽儀盤表



另一種常見的用例中,使用 Node+Web+Socket 非常適合:跟蹤網(wǎng)站訪問者并且可視化實(shí)時(shí)它們之間的實(shí)


時(shí)交互。 (如果你有興趣,可以去看看 Hummingbird)


你可能需要采集用戶的實(shí)時(shí)狀態(tài), 或者甚至當(dāng)他們到達(dá)渠道中某個(gè)特定的點(diǎn)時(shí), 打開一個(gè)交流頻道, 通


過有針對(duì)性的互動(dòng)介紹移動(dòng)到下一個(gè)階段. (如果你感興趣的話,推薦你看看 CANDDi)


想象一下,如果你知道你的訪客的實(shí)時(shí)操作,并能夠形象化地看到他們的交互,這將對(duì)你的業(yè)務(wù)帶來(lái)多


大的提升。隨著實(shí)時(shí)的、雙向 socket 通信的 Node.js ,現(xiàn)在你可以做到了。


系統(tǒng)監(jiān)控儀表


現(xiàn)在,讓我們看看事情的基礎(chǔ)設(shè)施方面。想象一下,比如,希望為其用戶提供服務(wù)監(jiān)控頁(yè)面(例如,

GitHub上的狀態(tài)頁(yè))的 SaaS 運(yùn)營(yíng)商 。通過 Node.js 的事件循環(huán),我們可以創(chuàng)建一個(gè)基于 Web 的功能

強(qiáng)大的儀表板,以異步方式檢查服務(wù)狀態(tài)并且使用的 WebSockets 將數(shù)據(jù)推送到客戶端。

內(nèi)部(公司內(nèi)部)和公共服務(wù)的狀態(tài)都可以使用該項(xiàng)技術(shù)實(shí)現(xiàn)實(shí)時(shí)的上報(bào)。讓我們把這一想法延伸的遠(yuǎn)

一點(diǎn),試著想象一個(gè)電信運(yùn)營(yíng)商中網(wǎng)絡(luò)運(yùn)營(yíng)中心(NOC)的監(jiān)控應(yīng)用,云/網(wǎng)絡(luò)/服務(wù)器運(yùn)營(yíng)商,或者一些

金融機(jī)構(gòu),全都運(yùn)行在這個(gè)由 Node.js 和 WebSocket 組成的應(yīng)用上,而不是 Java 和/或 Java Applet



注意:不要嘗試使用 Node 打造硬實(shí)時(shí)系統(tǒng)(即,響應(yīng)時(shí)間要求一致的系統(tǒng))。 Erlang是可能是該類應(yīng)

用程序的更好的選擇。

什么地方可以使用 Node.js



服務(wù)端 WEB 應(yīng)用


通過 Node.js 使用 Express.js 也可以用來(lái)創(chuàng)建服務(wù)端上的典型的網(wǎng)頁(yè)應(yīng)用。然而,雖然有可能,使用?


Node.js 來(lái)進(jìn)行請(qǐng)求+響應(yīng)的形式來(lái)呈現(xiàn) HTML 并不是最典型的用例。有人贊成也有人反對(duì)這一做法。這


里有一些看法以供參考:


優(yōu)點(diǎn):


如果你不需要進(jìn)行 CPU密集型計(jì)算,你可以從頭到尾甚至是數(shù)據(jù)庫(kù)(比如 MongoDB)都使用 Javascript?


來(lái)開發(fā)。這顯著地減輕了開發(fā)工序(包括成本)。
對(duì)于一個(gè)使用 Node.js 作為服務(wù)端的單頁(yè)應(yīng)用或者 websocket 應(yīng)用,爬蟲可以收到一個(gè)完全 HTML 呈


現(xiàn)的響應(yīng),這是更為SEO友好的。
缺點(diǎn):


任何CPU密集型的計(jì)算都將阻礙 Node.js 的反應(yīng),所以使用多線程的平臺(tái)是一個(gè)更好的方法。或者,您


也可以嘗試向外擴(kuò)展的計(jì)算[*]。
Node.js 使用關(guān)系型數(shù)據(jù)庫(kù)依舊十分痛苦(詳細(xì)見下方)。拜托了,如果你想執(zhí)行關(guān)系型數(shù)據(jù)操作,請(qǐng)


考慮別的環(huán)境:Rails, Django 甚至 ASP.NET MVC 。。。。
【*】另一種解決方案是,為這些CPU密集型的計(jì)算建立一個(gè)高度可擴(kuò)展的MQ支持的環(huán)境與后端處理,以


保持 Node 作為一個(gè)前臺(tái)專員來(lái)異步處理客戶端請(qǐng)求。


Node.js 不應(yīng)該在什么地方使用


使用關(guān)系型數(shù)據(jù)庫(kù)的服務(wù)端 WEB 應(yīng)用


對(duì)比 Node.js 上的 Express.js 和 Ruby on Rails,當(dāng)你使用關(guān)系型數(shù)據(jù)庫(kù)的時(shí)候請(qǐng)毫不猶豫的選擇后

者。

Node.js 的關(guān)系數(shù)據(jù)庫(kù)工具仍處于早期階段,目前還沒有成熟到讓人能夠愉快地使用它。而與此同時(shí),

Rails天生自帶了數(shù)據(jù)訪問組件,連同DB schema遷移的支持工具和一些Gems(一語(yǔ)雙關(guān),一指這些如同

珍寶的工具,二指ruby的gems程序包)。Rails和它的搭檔框架們擁有非常成熟且被證明了的活動(dòng)記錄(

Active Record)或數(shù)據(jù)映射(Data Mapper)的數(shù)據(jù)訪問層的實(shí)現(xiàn),而這些是當(dāng)你在使用純JavaScript

來(lái)復(fù)制這些應(yīng)用的時(shí)候會(huì)非常想要使用的東西。


不過,如果你真的傾向于全部使用 JS(并且做好可能抓狂的準(zhǔn)備),那么請(qǐng)繼續(xù)關(guān)注 Sequelize 和?

Node ORM2 ,雖然這兩者仍然不成熟的,但他們最終會(huì)迎頭趕上。

[*] 使用 Node 光是作為前端而 Rails 做后端來(lái)連接關(guān)系型數(shù)據(jù)庫(kù),這是完全有可能也并不少見的。(

筆者注:國(guó)外有種說(shuō)法,PHP這一類程序員也可以算作是前端)

繁重的服務(wù)端的計(jì)算和處理


當(dāng)涉及到大量的計(jì)算,Node.js 就不是最佳的解決方案。你肯定不希望使用 Node.js 建立一個(gè)斐波那契

數(shù)的計(jì)算服務(wù)。一般情況下,任何 CPU密集型操作 會(huì)削弱掉 Node通過事件驅(qū)動(dòng), 異步 I/O 模型等等

帶來(lái)的在吞吐量上的優(yōu)勢(shì),因?yàn)楫?dāng)線程被非異步的高計(jì)算量占用時(shí)任何傳入的請(qǐng)求將被阻塞。

正如前面所說(shuō),Node.js 是單線程的,只使用一個(gè)單一的CPU核心。至于,涉及到服務(wù)器上多核并發(fā)處理

,Node 的核心團(tuán)隊(duì)已經(jīng)使用 cluster 模塊的形式在這一方面做了一些工作 (參考:

http://nodejs.org/api/cluster.html)。當(dāng)然,您也可以很容易的通過 nginx 的反向代理運(yùn)行多個(gè)?

Node.js 的服務(wù)器實(shí)例來(lái)避免單一線程阻塞的問題。

關(guān)于集群(clustering) ,你應(yīng)該將所有繁重的計(jì)算轉(zhuǎn)移到更合適的語(yǔ)言寫的后臺(tái)進(jìn)程來(lái)處理,同時(shí)讓他

們通過像 RabbitMQ 那樣通過消息隊(duì)列服務(wù)器來(lái)進(jìn)行通信。

即使你的后臺(tái)處理可能最初運(yùn)行在同一臺(tái)服務(wù)器上時(shí)看不出什么優(yōu)點(diǎn),但是這樣的做法具有非常高的可

擴(kuò)展性的潛力。這些后臺(tái)處理服務(wù)可以容易地分割出去,作為單獨(dú)的 worker 服務(wù)器,而不需要配置入

口 web服務(wù)器的負(fù)載。

當(dāng)然,你也可以在其他語(yǔ)言平臺(tái)上用同樣的方法,但使用 Node.js 你可以得到很高的吞吐量,每個(gè)請(qǐng)求


都作為一個(gè)小任務(wù)非常迅速和高效地處理,這一點(diǎn)我們已經(jīng)討論過了。

結(jié)論


我們已經(jīng)從理論到實(shí)踐討論過 Node.js 了,從它的目標(biāo)和野心,到其優(yōu)點(diǎn)和缺點(diǎn)。在 Node.js 的開發(fā)

中99%的問題是由誤用阻塞操作而造成的。

請(qǐng)記住:Node.js 從來(lái)不是用于解決大規(guī)模計(jì)算問題而創(chuàng)建的。它的出現(xiàn)是為了解決大規(guī)模I/O 的問題

,并且在這一點(diǎn)上做的非常好。

綜上,如果你項(xiàng)目需求中不包含CPU密集型操作,也不需要訪問任何阻塞的資源,那么你就可以利用的?


Node.js 的優(yōu)點(diǎn),盡情的享受快速、可擴(kuò)展的網(wǎng)絡(luò)應(yīng)用。
========

一個(gè)Java碼農(nóng)的Node之旅



本篇是一個(gè)Node新手做完實(shí)際項(xiàng)目后的心得總結(jié)。


摘要
如果BOSS要求你在短期內(nèi)快速實(shí)現(xiàn)一套聊天云服務(wù)平臺(tái),實(shí)現(xiàn)成本主要是:


要維護(hù)社交關(guān)系,一大波僵尸POJO正在襲來(lái)。
要存儲(chǔ)數(shù)據(jù)庫(kù),找個(gè)ORM工具。
長(zhǎng)連接吧方面是WebSocket標(biāo)準(zhǔn),亦或Netty、Mina系的框架。
連接斷了需要實(shí)現(xiàn)下重連機(jī)制吧?服務(wù)器端寫完了還有客戶端,也需要幫助指導(dǎo)下實(shí)現(xiàn),問題諸多。
我們的征途是偷懶
如果有現(xiàn)成的輪子偷懶的話,socket.io比較適合:


輕量級(jí)、擴(kuò)展便捷、API簡(jiǎn)單易用。
周邊完善,重連、路由、隔離、單播、廣播等都已實(shí)現(xiàn)。
豐富的客戶端支持,涵蓋了瀏覽器端、Android、iOS。
在仔細(xì)研讀了Flexi傳授如何說(shuō)服自己的老板采用Node.js,并成功說(shuō)服BOSS后,正式開始自己的Node之


旅。


工欲善其事必先利其器
開發(fā)環(huán)境
對(duì)于開發(fā)環(huán)境,無(wú)論你是使用編輯器/編輯器之神,或是sublime/atom/npp之類,亦或是WebStorm高富帥


有錢任性,都是很不錯(cuò)的選擇。


Supervisor可以幫你watch代碼變更,自動(dòng)重啟服務(wù),從而節(jié)省了手工重啟程序的時(shí)間。


關(guān)于調(diào)試
高富帥款:WebStorm
高逼格款:原始打斷點(diǎn)
屌絲款:node-inspector,可以在Chrome中直接調(diào)試,強(qiáng)烈推薦:
圖片描述


離不開的中間件
首先,勾勒出一個(gè)核心的聊天系統(tǒng)大致的雛形:


基本功能


集群實(shí)現(xiàn)
敏感詞過濾
好友


加好友,刪好友
好友之間聊天,發(fā)文字發(fā)圖片發(fā)音頻發(fā)視頻啥的
群組


創(chuàng)建,加入,退出群組
群組內(nèi)廣播聊天
聊天歷史記錄


擴(kuò)展與周邊


集群實(shí)現(xiàn)
敏感詞過濾
分析下大致需要的存儲(chǔ)層和中間件以及是否有相關(guān)的Node實(shí)現(xiàn):


MySQL:存儲(chǔ)一些重要的元數(shù)據(jù),主要是用戶關(guān)系類的,需要事務(wù)支持。(node-mysql)
ZooKeeper:用戶在線離線狀態(tài)存儲(chǔ)。(node-zookeeper-client)
Redis:使用緩存加速一些查詢,PubSub特性用于實(shí)現(xiàn)集群通訊。(ioredis)
HBase:典型的列式存儲(chǔ),用于實(shí)現(xiàn)一些非核心數(shù)據(jù)的快速存儲(chǔ)查詢。(hbase-rpc-client)
LevelDB:本地快速讀寫一些鍵值對(duì)。(LevelUP)
技術(shù)棧
對(duì)比


常年滋潤(rùn)在Java這片潤(rùn)土之上,先來(lái)做個(gè)比較,讓我們對(duì)陌生的技術(shù)棧有所了解。


圖片描述


ES6
ES6是個(gè)好東西, 我覺得比較好用的三點(diǎn):


const: 可以方便地對(duì)不可變的東西進(jìn)行聲明。
let: 只JavaScript初學(xué)者不用擔(dān)憂不知不覺把變量提升的問題。
lambda表達(dá)式: 神器。
核心實(shí)現(xiàn)
流程時(shí)序
仔細(xì)思考,勾勒出大致的時(shí)序圖:


圖片描述


系統(tǒng)架構(gòu):
設(shè)計(jì)下大致的架構(gòu):


圖片描述


步步為贏,各個(gè)擊破
狀態(tài)管理


典型的IM系統(tǒng)中必然存在用戶在線離線的狀態(tài)。每一個(gè)在線狀態(tài),對(duì)于服務(wù)器來(lái)說(shuō),等價(jià)于與客戶端存


在一個(gè)Socket連接。所以對(duì)于單機(jī)環(huán)境下,在內(nèi)存中維護(hù)用戶和Socket的關(guān)系即可,當(dāng)Socket連接和斷


開時(shí)分別做更新操作。當(dāng)切換至集群環(huán)境時(shí),情況變得稍微復(fù)雜,所以我們需要借助ZooKeeper來(lái)實(shí)現(xiàn)。


除了本機(jī)每個(gè)用戶與Socket關(guān)聯(lián)關(guān)系,另外以臨時(shí)節(jié)點(diǎn)的方式在ZooKeeper中進(jìn)行存儲(chǔ),目錄結(jié)構(gòu)為根節(jié)


點(diǎn)/命名空間/用戶標(biāo)識(shí)/Socket標(biāo)識(shí)(臨時(shí)節(jié)點(diǎn))。當(dāng)socket連接被建立的時(shí)候,創(chuàng)建對(duì)應(yīng)的臨時(shí)節(jié)點(diǎn),


socket斷開時(shí)移除臨時(shí)節(jié)點(diǎn)。當(dāng)服務(wù)器意外退出時(shí),除了socket連接全部斷開之外,在其ZooKeeper?


session上的所有對(duì)應(yīng)的臨時(shí)節(jié)點(diǎn)也會(huì)被銷毀。SocketIO的重連機(jī)制會(huì)嘗試重連至其他伺服器并重新建立


起對(duì)應(yīng)關(guān)系。


優(yōu)點(diǎn):


判斷一個(gè)用戶是否在線只需判斷用戶標(biāo)識(shí)節(jié)點(diǎn)的numChildren是否大于零即可。
獲取用戶所有已連接的Socket只需讀取用戶標(biāo)識(shí)下的所有孩子節(jié)點(diǎn)即可。
缺點(diǎn):


多了額外讀寫ZooKeeper的開銷。
用途:


實(shí)現(xiàn)集群的基礎(chǔ)
有了狀態(tài)判定才能實(shí)現(xiàn)離線消息推送
好友關(guān)系、群組關(guān)系


關(guān)系表原本存儲(chǔ)于HBase,但因?yàn)槿狈κ聞?wù)支持,實(shí)際效果不佳,經(jīng)常導(dǎo)致關(guān)系不一致。傳統(tǒng)關(guān)系型數(shù)據(jù)


庫(kù)在這一方面依舊強(qiáng)勢(shì)。這塊比較簡(jiǎn)單,即常見的關(guān)系模型表,在此略過。


點(diǎn)對(duì)點(diǎn)聊天實(shí)現(xiàn)


單機(jī)


A對(duì)B發(fā)送消息,除了基礎(chǔ)的權(quán)限判定,只需查詢內(nèi)存表中對(duì)應(yīng)B的所有socket,然后對(duì)其發(fā)射消息即可。


見下圖:


圖片描述


集群


由于B可能登錄在不同的服務(wù)器上,需要借助消息中間件(Redis Pub/Sub),發(fā)布消息,每個(gè)服務(wù)器訂閱


消息列表,如果存在消息接收者,則找到其注冊(cè)在本機(jī)的socket進(jìn)行發(fā)射消息。流程如下圖:


圖片描述


廣播聊天實(shí)現(xiàn)


廣播類似以上的點(diǎn)對(duì)點(diǎn)實(shí)現(xiàn),只是多了一步查詢成員表依次處理的步驟。此處略。


聊天歷史記錄的實(shí)現(xiàn)


考慮到只需要根據(jù)時(shí)間范圍做分頁(yè)查詢的簡(jiǎn)單需求,這里使用了HBase的寬表。點(diǎn)對(duì)點(diǎn)形式的聊天我們可


以對(duì)兩個(gè)用戶標(biāo)識(shí)進(jìn)行排序,并結(jié)合命名空間生成唯一的哈希值,作為行健,而每個(gè)CELL的值則是時(shí)間


戳,因?yàn)槲覀冃枰钇渥匀坏剐蚺帕?#xff0c;所以針對(duì)時(shí)間戳做了LONG。MAX-時(shí)間戳的處理。綜合起來(lái),大致


的存儲(chǔ)結(jié)構(gòu)如下:


圖片描述


敏感詞過濾


維護(hù)臟詞字典,對(duì)消息進(jìn)行字符串替換?為了實(shí)現(xiàn)正確辨認(rèn)“曹操在操場(chǎng)操美女”中的動(dòng)詞“操”,需


要實(shí)現(xiàn)中文分詞和詞性判斷,于是處理邏輯轉(zhuǎn)變成:


拉取最新的臟詞列表,轉(zhuǎn)換為簡(jiǎn)體中文并寫入LevelDB中。
使用nodejieba進(jìn)行中文分詞:曹操(n)/在(p)/操場(chǎng)(n)/操(v)/美女(n)
對(duì)分詞后的名詞和動(dòng)詞轉(zhuǎn)換為簡(jiǎn)體中文并查詢LevelDB,命中則替換。
返回替換后的字符串得到:曹操在操場(chǎng)*美女
打包部署
PM2
Node本身是單線程的,雖然Node本身提供Cluster模塊,但需要修改代碼。通過PM2這個(gè)工具可以簡(jiǎn)便地


讓其多進(jìn)程部署,充分利用多核CPU資源:


圖片描述


Docker
可以使用官方的node鏡像。但體積比較大,這里推薦基于alpine-node,體積比較小巧,例如:


FROM mhart/alpine-node:4


RUN apk add --no-cache make gcc g++ python


RUN apk add --no-cache imagemagick


WORKDIR /src
ADD . .
RUN npm install --registry=http://registry.npm.taobao.org/


EXPOSE 3000
CMD ["npm","start"]
C1000K測(cè)試
著名的單機(jī)100萬(wàn)連接,由于項(xiàng)目是第一個(gè)版本,限于各方面原因我們暫時(shí)沒有完成這個(gè)測(cè)試。但在這里


簡(jiǎn)短介紹所需的一些配置,以備后續(xù)使用:


服務(wù)器端
修改tcp連接的最小內(nèi)存為4k, 編輯/etc/sysctl.conf
net.ipv4.tcp_wmem = 4096 87380 4161536
net.ipv4.tcp_rmem = 4096 87380 4161536
net.ipv4.tcp_mem = 786432 2097152 3145728
修改系統(tǒng)最大文件描述符, 編輯/etc/sysctl.conf
fs.file-max = 1000000
修改進(jìn)程最大文件描述符, 編輯/etc/security/limits.conf
* ? ? ? ? hard ? ?nofile ? ? ?1000000
* ? ? ? ? soft ? ?nofile ? ? ?1000000
root ? ? ?hard ? ?nofile ? ? ?1000000
root ? ? ?soft ? ?nofile ? ? ?1000000
重載下配置(sysctl -p)或者重啟,檢查下當(dāng)前的設(shè)置 cat /proc/sys/fs/file-nr
*客戶端


因?yàn)槊總€(gè)IP最多可以創(chuàng)建6萬(wàn)多個(gè)連接,不可能找很多服務(wù)器進(jìn)行測(cè)試。所以客戶端除了上述修改,還需


要?jiǎng)?chuàng)建多個(gè)虛擬IP,這樣每個(gè)IP可以提供大約6萬(wàn)的連接,如:
?ifconfig eth0:0 192.168.77.10 netmask 255.255.255.0 up
?ifconfig eth0:1 192.168.77.11 netmask 255.255.255.0 up
?ifconfig eth0:2 192.168.77.12 netmask 255.255.255.0 up
?ifconfig eth0:3 192.168.77.13 netmask 255.255.255.0 up
?ifconfig eth0:4 192.168.77.14 netmask 255.255.255.0 up
?ifconfig eth0:5 192.168.77.15 netmask 255.255.255.0 up
?ifconfig eth0:6 192.168.77.16 netmask 255.255.255.0 up
?ifconfig eth0:7 192.168.77.17 netmask 255.255.255.0 up
?ifconfig eth0:8 192.168.77.18 netmask 255.255.255.0 up
?ifconfig eth0:9 192.168.77.19 netmask 255.255.255.0 up
?ifconfig eth0:10 192.168.77.20 netmask 255.255.255.0 up
?ifconfig eth0:11 192.168.77.21 netmask 255.255.255.0 up
?ifconfig eth0:12 192.168.77.22 netmask 255.255.255.0 up
?ifconfig eth0:13 192.168.77.23 netmask 255.255.255.0 up
?ifconfig eth0:14 192.168.77.24 netmask 255.255.255.0 up
?ifconfig eth0:15 192.168.77.25 netmask 255.255.255.0 up
?ifconfig eth0:16 192.168.77.26 netmask 255.255.255.0 up
?ifconfig eth0:17 192.168.77.27 netmask 255.255.255.0 up
?ifconfig eth0:18 192.168.77.28 netmask 255.255.255.0 up
修改本地端口范圍,編輯/etc/sysctl.conf
? ? net.ipv4.ip_local_port_range = 1024 65535
重載配置或重啟開始測(cè)試
總結(jié)
存在即合理,不要卷入無(wú)謂的語(yǔ)言之爭(zhēng),本猿覺得干這行的最重要莫過于學(xué)習(xí)能力。?
寫代碼之前先理清楚思路和結(jié)構(gòu),不打沒有準(zhǔn)備的仗。


良好的代碼規(guī)范,遵循KISS原則。
========

相關(guān)鏈接


http://www.yiibai.com/nodejs/
http://www.runoob.com/nodejs/nodejs-tutorial.html
http://nodejs.cn/
http://blog.jobbole.com/53736/

http://www.csdn.net/tag/Node/news


總結(jié)

以上是生活随笔為你收集整理的node.js学习总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 影音先锋二区 | 中文字幕一区二区三区精彩视频 | 中文字幕在线高清 | 国产黄在线免费观看 | 你懂的视频网站 | 久久99热这里只有精品 | 国产成人精品二区三区亚瑟 | 精品国产一区二区三区四区 | 无码精品人妻一二三区红粉影视 | 开心激情深爱 | 怡红院亚洲 | 亚洲色图欧美视频 | 国产一区自拍视频 | 日本午夜精华 | 亚洲精品黄色 | 日韩欧美综合在线 | 正在播放久久 | 99精品99| 久久国产精品久久久久久电车 | 精品三级在线观看 | 日本一二区视频 | 亚洲欧美中文字幕 | 亚洲国产91 | 一区二区伦理 | 国产精品乱 | 中文字幕乱码中文字幕 | 国产专区第一页 | 中文字幕亚洲激情 | 小优视频污 | 亚洲毛片大全 | 日本午夜一区 | 久久久99精品国产一区二区三区 | 不卡的av在线免费观看 | 91免费黄色| 婷婷久久精品 | 精品国模一区二区三区 | 亚洲一本之道 | 亚洲无套| 天堂国产一区二区三区 | 看片免费黄在线观看入口 | 波多野结衣亚洲 | 亚洲天堂区 | 日韩白浆| aaa黄色大片 | 国产精品白浆一区二小说 | 国产日韩亚洲欧美 | 成人h视频在线观看 | 男女h网站| 日本黄色天堂 | 色婷婷一区二区 | 日韩影视在线 | 九九九免费| 精品国产乱码久久久久久蜜臀网站 | 天美麻花果冻视频大全英文版 | 香蕉国产精品 | 91ts人妖另类精品系列 | 成人激情电影在线观看 | 国产日韩欧美一二三区 | 久久精品夜色噜噜亚洲a∨ 中文字幕av网 | 精品国产自 | 国产一区二区三区四区 | 美女被啪羞羞粉色视频 | 国产猛男猛女超爽免费视频 | 国产中文视频 | 男女插插插网站 | 超碰国产97 | 四虎啪啪| 亚洲国产精品久 | 天天av天天操 | 99精品免费观看 | 在线观看成人 | 日本黄色生活片 | 真实偷拍激情啪啪对白 | 一级伦理农村妇女愉情 | 天天干免费视频 | 极品91尤物被啪到呻吟喷水 | 色乱码一区二区三在线看 | 国产激情无码一区二区三区 | 麻豆视频免费入口 | 免费看美女被靠到爽的视频 | 美女喷液视频 | 丰满岳妇乱一区二区三区 | 少妇紧身牛仔裤裤啪啪 | 蜜桃成熟时李丽珍国语 | 日韩中文字幕一区二区三区四区 | 日韩精品在线视频 | 欧美精品不卡 | 紧身裙女教师三上悠亚红杏 | 欧美蜜桃视频 | 免费不卡的av | 三点尽露的大尺度国产 | 日韩黄色一区二区 | www.久久精品 | 91人妻一区二区三区 | 亚洲热在线视频 | 国产乱码精品一区二区三区五月婷 | 亚洲久久久久 | 中文字幕 自拍偷拍 | 欧美日韩一区二区综合 |