成人怡红院-成人怡红院视频在线观看-成人影视大全-成人影院203nnxyz-美女毛片在线看-美女免费黄

站長資訊網(wǎng)
最全最豐富的資訊網(wǎng)站

深入解析NodeJS中的進(jìn)程管理

深入解析NodeJS中的進(jìn)程管理

熟悉 js 的朋友都知道,js 是單線程的,在 Node 中,采用的是 多進(jìn)程單線程 的模型。由于javascript單線程的限制,在多核服務(wù)器上,我們往往需要啟動(dòng)多個(gè)進(jìn)程才能最大化服務(wù)器性能。

Node.js 進(jìn)程集群可用于運(yùn)行多個(gè) Node.js 實(shí)例,這些實(shí)例可以在其應(yīng)用程序線程之間分配工作負(fù)載。 當(dāng)不需要進(jìn)程隔離時(shí),請(qǐng)改用 worker_threads 模塊,它允許在單個(gè) Node.js 實(shí)例中運(yùn)行多個(gè)應(yīng)用程序線程。

零、NodeJS多進(jìn)程

  • 進(jìn)程總數(shù),其中一個(gè)主進(jìn)程,cpu 個(gè)數(shù) x cpu 核數(shù) 個(gè) 子進(jìn)程
  • 無論 child_process 還是 cluster,都不是多線程模型,而是多進(jìn)程模型
  • 應(yīng)對(duì)單線程問題,通常使用多進(jìn)程的方式來模擬多線程

一、核心模塊cluster集群

Node 在 V0.8 版本之后引入了 cluster模塊,通過一個(gè)主進(jìn)程 (master) 管理多個(gè)子進(jìn)程 (worker) 的方式實(shí)現(xiàn)集群

集群模塊可以輕松創(chuàng)建共享服務(wù)器端口的子進(jìn)程。

cluster 底層是 child_process 模塊,除了可以發(fā)送普通消息,還可以發(fā)送底層對(duì)象 TCPUDP 等, cluster 模塊是 child_process 模塊和 net 模塊的組合應(yīng)用。 cluster 啟動(dòng)時(shí),內(nèi)部會(huì)啟動(dòng) TCP 服務(wù)器,將這個(gè) TCP 服務(wù)器端 socket 的文件描述符發(fā)給工作進(jìn)程。

cluster 模塊應(yīng)用中,一個(gè)主進(jìn)程只能管理一組工作進(jìn)程,其運(yùn)作模式?jīng)]有 child_process 模塊那么靈活,但是更加穩(wěn)定:

深入解析NodeJS中的進(jìn)程管理

1.cluster配置詳情

1.1 引入cluster

const cluster = require('cluster')復(fù)

1.2 cluster常用屬性

  • .isMaster 標(biāo)識(shí)主進(jìn)程, Node<16
  • .isPrimary 標(biāo)識(shí)主進(jìn)程, Node>16
  • .isWorker 標(biāo)識(shí)子進(jìn)程
  • .worker 對(duì)當(dāng)前工作進(jìn)程對(duì)象的引用【子進(jìn)程中】
  • .workers 存儲(chǔ)活動(dòng)工作進(jìn)程對(duì)象的哈希,以 id 字段為鍵。 這樣可以很容易地遍歷所有工作進(jìn)程。 它僅在主進(jìn)程中可用。cluster.wokers[id] === worker【主進(jìn)程中】
  • .settings 只讀, cluster配置項(xiàng)。在調(diào)用 .setupPrimary()或.fork()方法之后,此設(shè)置對(duì)象將包含設(shè)置,包括默認(rèn)值。之前為空對(duì)象。此對(duì)象不應(yīng)手動(dòng)更改或設(shè)置。

cluster.settings配置項(xiàng)詳情:

- `execArgv` <string[]>傳給 Node.js 可執(zhí)行文件的字符串參數(shù)列表。 **默認(rèn)值:**  `process.execArgv`。 - `exec` <string> 工作進(jìn)程文件的文件路徑。 **默認(rèn)值:** `process.argv[1]`。 - `args` <string[]> 傳給工作進(jìn)程的字符串參數(shù)。 **默認(rèn)值:**`process.argv.slice(2)`。 - `cwd` <string>工作進(jìn)程的當(dāng)前工作目錄。 **默認(rèn)值:**  `undefined` (從父進(jìn)程繼承)。 - `serialization` <string>指定用于在進(jìn)程之間發(fā)送消息的序列化類型。 可能的值為 `'json'` 和 `'advanced'`。  **默認(rèn)值:**  `false`。 - `silent` <boolean>是否將輸出發(fā)送到父進(jìn)程的標(biāo)準(zhǔn)輸入輸出。 **默認(rèn)值:**  `false`。 - `stdio` <Array>配置衍生進(jìn)程的標(biāo)準(zhǔn)輸入輸出。 由于集群模塊依賴 IPC 來運(yùn)行,因此此配置必須包含 `'ipc'` 條目。 提供此選項(xiàng)時(shí),它會(huì)覆蓋 `silent`。 - `uid` <number>設(shè)置進(jìn)程的用戶標(biāo)識(shí)。  - `gid` <number>設(shè)置進(jìn)程的群組標(biāo)識(shí)。 - `inspectPort` <number> | <Function> 設(shè)置工作進(jìn)程的檢查器端口。 這可以是數(shù)字,也可以是不帶參數(shù)并返回?cái)?shù)字的函數(shù)。 默認(rèn)情況下,每個(gè)工作進(jìn)程都有自己的端口,從主進(jìn)程的 `process.debugPort` 開始遞增。 - `windowsHide` <boolean> 隱藏通常在 Windows 系統(tǒng)上創(chuàng)建的衍生進(jìn)程控制臺(tái)窗口。 **默認(rèn)值:**  `false`。

1.3 cluster常用方法

  • .fork([env]) 衍生新的工作進(jìn)程【主進(jìn)程中】
  • .setupPrimary([settings]) Node>16
  • .setupMaster([settings]) 用于更改默認(rèn)的 'fork' 行為,用后設(shè)置將出現(xiàn)在 cluster.settings 中。任何設(shè)置更改只會(huì)影響未來對(duì) .fork()的調(diào)用,而不會(huì)影響已經(jīng)運(yùn)行的工作進(jìn)程。上述默認(rèn)值僅適用于第一次調(diào)用。Node 小于 16【主進(jìn)程中】
  • .disconnect([callback]) 當(dāng)所有工作進(jìn)程斷開連接并關(guān)閉句柄時(shí)調(diào)用【主進(jìn)程中】

1.4 cluster常用事件

為了讓集群更加穩(wěn)定和健壯,cluster 模塊也暴露了許多事件:

  • 'message' 事件, 當(dāng)集群主進(jìn)程接收到來自任何工作進(jìn)程的消息時(shí)觸發(fā)。
  • 'exit' 事件, 當(dāng)任何工作進(jìn)程死亡時(shí),則集群模塊將觸發(fā) 'exit' 事件。
cluster.on('exit', (worker, code, signal) => {   console.log('worker %d died (%s). restarting...',               worker.process.pid, signal || code);   cluster.fork(); });
  • 'listening'事件,從工作進(jìn)程調(diào)用 listen() 后,當(dāng)服務(wù)器上觸發(fā) 'listening' 事件時(shí),則主進(jìn)程中的 cluster 也將觸發(fā) 'listening' 事件。
cluster.on('listening', (worker, address) => {   console.log(     `A worker is now connected to ${address.address}:${address.port}`); });
  • 'fork' 事件,當(dāng)新的工作進(jìn)程被衍生時(shí),則集群模塊將觸發(fā) 'fork' 事件。
cluster.on('fork', (worker) => {   timeouts[worker.id] = setTimeout(errorMsg, 2000); });
  • 'setup' 事件,每次調(diào)用 .setupPrimary()時(shí)觸發(fā)。
  • disconnect事件,在工作進(jìn)程 IPC 通道斷開連接后觸發(fā)。 當(dāng)工作進(jìn)程正常退出、被殺死、或手動(dòng)斷開連接時(shí)
cluster.on('disconnect', (worker) => {   console.log(`The worker #${worker.id} has disconnected`); });

1.5 Worker類

Worker 對(duì)象包含了工作進(jìn)程的所有公共的信息和方法。 在主進(jìn)程中,可以使用 cluster.workers 來獲取它。 在工作進(jìn)程中,可以使用 cluster.worker 來獲取它。

1.5.1 worker常用屬性

  • .id 工作進(jìn)程標(biāo)識(shí),每個(gè)新的工作進(jìn)程都被賦予了自己唯一的 id,此 id 存儲(chǔ)在 id。當(dāng)工作進(jìn)程存活時(shí),這是在 cluster.workers 中索引它的鍵。
  • .process 所有工作進(jìn)程都是使用 child_process.fork() 創(chuàng)建,此函數(shù)返回的對(duì)象存儲(chǔ)為 .process。 在工作進(jìn)程中,存儲(chǔ)了全局的 process

1.5.2 worker常用方法

  • .send(message[, sendHandle[, options]][, callback]) 向工作進(jìn)程或主進(jìn)程發(fā)送消息,可選擇使用句柄。在主進(jìn)程中,這會(huì)向特定的工作進(jìn)程發(fā)送消息。 它與 ChildProcess.send()相同。在工作進(jìn)程中,這會(huì)向主進(jìn)程發(fā)送消息。 它與 process.send() 相同。
  • .destroy()
  • .kill([signal])此函數(shù)會(huì)殺死工作進(jìn)程。kill() 函數(shù)在不等待正常斷開連接的情況下殺死工作進(jìn)程,它與 worker.process.kill() 具有相同的行為。為了向后兼容,此方法別名為 worker.destroy()
  • .disconnect([callback])發(fā)送給工作進(jìn)程,使其調(diào)用自身的 .disconnect()將關(guān)閉所有服務(wù)器,等待那些服務(wù)器上的 'close' 事件,然后斷開 IPC 通道。
  • .isConnect() 如果工作進(jìn)程通過其 IPC 通道連接到其主進(jìn)程,則此函數(shù)返回 true,否則返回 false。 工作進(jìn)程在創(chuàng)建后連接到其主進(jìn)程。
  • .isDead()如果工作進(jìn)程已終止(由于退出或收到信號(hào)),則此函數(shù)返回 true。 否則,它返回 false

1.5.3 worker常用事件

為了讓集群更加穩(wěn)定和健壯,cluster 模塊也暴露了許多事件:

  • 'message' 事件, 在工作進(jìn)程中。
cluster.workers[id].on('message', messageHandler);
  • 'exit' 事件, 當(dāng)任何工作進(jìn)程死亡時(shí),則當(dāng)前worker工作進(jìn)程對(duì)象將觸發(fā) 'exit' 事件。
if (cluster.isPrimary) {   const worker = cluster.fork();   worker.on('exit', (code, signal) => {     if (signal) {       console.log(`worker was killed by signal: ${signal}`);     } else if (code !== 0) {       console.log(`worker exited with error code: ${code}`);     } else {       console.log('worker success!');     }   }); }
  • 'listening'事件,從工作進(jìn)程調(diào)用 listen() ,對(duì)當(dāng)前工作進(jìn)程進(jìn)行監(jiān)聽。
cluster.fork().on('listening', (address) => {   // 工作進(jìn)程正在監(jiān)聽 });
  • disconnect事件,在工作進(jìn)程 IPC 通道斷開連接后觸發(fā)。 當(dāng)工作進(jìn)程正常退出、被殺死、或手動(dòng)斷開連接時(shí)
cluster.fork().on('disconnect', () => {   //限定于當(dāng)前worker對(duì)象觸發(fā) });

2. 進(jìn)程通信

Node中主進(jìn)程和子進(jìn)程之間通過進(jìn)程間通信 (IPC) 實(shí)現(xiàn)進(jìn)程間的通信,進(jìn)程間通過 .send()(a.send表示向a發(fā)送)方法發(fā)送消息,監(jiān)聽 message 事件收取信息,這是 cluster模塊 通過集成 EventEmitter 實(shí)現(xiàn)的。還是一個(gè)簡單的官網(wǎng)的進(jìn)程間通信例子

  • 子進(jìn)程:process.on('message')process.send()
  • 父進(jìn)程:child.on('message')child.send()
# cluster.isMaster # cluster.fork() # cluster.workers # cluster.workers[id].on('message', messageHandler); # cluster.workers[id].send(); # process.on('message', messageHandler);  # process.send();   const cluster = require('cluster'); const http = require('http');  # 主進(jìn)程 if (cluster.isMaster) {   // Keep track of http requests   console.log(`Primary ${process.pid} is running`);   let numReqs = 0;      // Count requests   function messageHandler(msg) {     if (msg.cmd && msg.cmd === 'notifyRequest') {       numReqs += 1;     }   }    // Start workers and listen for messages containing notifyRequest   // 開啟多進(jìn)程(cpu核心數(shù))   // 衍生工作進(jìn)程。   const numCPUs = require('os').cpus().length;   for (let i = 0; i < numCPUs; i++) {     console.log(i)     cluster.fork();   }  // cluster worker 主進(jìn)程與子進(jìn)程通信   for (const id in cluster.workers) {     // ***監(jiān)聽來自子進(jìn)程的事件     cluster.workers[id].on('message', messageHandler);           // ***向子進(jìn)程發(fā)送     cluster.workers[id].send({                                  type: 'masterToWorker',         from: 'master',         data: {             number: Math.floor(Math.random() * 50)         }     });   }   cluster.on('exit', (worker, code, signal) => {     console.log(`worker ${worker.process.pid} died`);   });  } else {    # 子進(jìn)程    // 工作進(jìn)程可以共享任何 TCP 連接   // 在本示例中,其是 HTTP 服務(wù)器   // Worker processes have a http server.   http.Server((req, res) => {     res.writeHead(200);     res.end('hello worldn');      //****** !!!!Notify master about the request !!!!!!*******     //****** 向process發(fā)送     process.send({ cmd: 'notifyRequest' });           //****** 監(jiān)聽從process來的     process.on('message', function(message) {          // xxxxxxx     })   }).listen(8000);   console.log(`Worker ${process.pid} started`); }

深入解析NodeJS中的進(jìn)程管理

2.1 句柄發(fā)送與還原

NodeJS 進(jìn)程之間通信只有消息傳遞,不會(huì)真正的傳遞對(duì)象。

send() 方法在發(fā)送消息前,會(huì)將消息組裝成 handle 和 message,這個(gè) message 會(huì)經(jīng)過 JSON.stringify 序列化,也就是說,傳遞句柄的時(shí)候,不會(huì)將整個(gè)對(duì)象傳遞過去,在 IPC 通道傳輸?shù)亩际亲址瑐鬏敽笸ㄟ^ JSON.parse 還原成對(duì)象。

2.2 監(jiān)聽共同端口

代碼里有 app.listen(port) 在進(jìn)行 fork 時(shí),為什么多個(gè)進(jìn)程可以監(jiān)聽同一個(gè)端口呢?

原因是主進(jìn)程通過 send() 方法向多個(gè)子進(jìn)程發(fā)送屬于該主進(jìn)程的一個(gè)服務(wù)對(duì)象的句柄,所以對(duì)于每一個(gè)子進(jìn)程而言,它們?cè)谶€原句柄之后,得到的服務(wù)對(duì)象是一樣的,當(dāng)網(wǎng)絡(luò)請(qǐng)求向服務(wù)端發(fā)起時(shí),進(jìn)程服務(wù)是搶占式的,所以監(jiān)聽相同端口時(shí)不會(huì)引起異常。

  • 看下端口被占用的情況:
# master.js  const fork = require('child_process').fork; const cpus = require('os').cpus();  for (let i=0; i<cpus.length; i++) {     const worker = fork('worker.js');     console.log('worker process created, pid: %s ppid: %s', worker.pid, process.pid); }
# worker.js  const http = require('http'); http.createServer((req, res) => { 	res.end('I am worker, pid: ' + process.pid + ', ppid: ' + process.ppid); }).listen(3000);

以上代碼示例,控制臺(tái)執(zhí)行 node master.js 只有一個(gè) worker 可以監(jiān)聽到 3000 端口,其余將會(huì)拋出 Error: listen EADDRINUSE :::3000 錯(cuò)誤。

  • 那么多進(jìn)程模式下怎么實(shí)現(xiàn)多進(jìn)程端口監(jiān)聽呢?答案還是有的,通過句柄傳遞 Node.js v0.5.9 版本之后支持進(jìn)程間可發(fā)送句柄功能
/**  * http://nodejs.cn/api/child_process.html#child_process_subprocess_send_message_sendhandle_options_callback  * message  * sendHandle  */ subprocess.send(message, sendHandle)

當(dāng)父子進(jìn)程之間建立 IPC 通道之后,通過子進(jìn)程對(duì)象的 send 方法發(fā)送消息,第二個(gè)參數(shù) sendHandle 就是句柄,可以是 TCP套接字、TCP服務(wù)器、UDP套接字等,為了解決上面多進(jìn)程端口占用問題,我們將主進(jìn)程的 socket 傳遞到子進(jìn)程。

# master.js  const fork = require('child_process').fork; const cpus = require('os').cpus(); const server = require('net').createServer(); server.listen(3000); process.title = 'node-master'  for (let i=0; i<cpus.length; i++) {     const worker = fork('worker.js');          # 句柄傳遞     worker.send('server', server);     console.log('worker process created, pid: %s ppid: %s', worker.pid, process.pid); }
// worker.js let worker; process.title = 'node-worker' process.on('message', function (message, sendHandle) {   if (message === 'server') {     worker = sendHandle;     worker.on('connection', function (socket) {       console.log('I am worker, pid: ' + process.pid + ', ppid: ' + process.ppid)     });   } });

驗(yàn)證一番,控制臺(tái)執(zhí)行 node master.js

深入解析NodeJS中的進(jìn)程管理

深入解析NodeJS中的進(jìn)程管理

深入解析NodeJS中的進(jìn)程管理

2.3 進(jìn)程負(fù)載均衡

了解 cluster 的話會(huì)知道,子進(jìn)程是通過 cluster.fork() 創(chuàng)建的。在 linux 中,系統(tǒng)原生提供了 fork 方法,那么為什么 Node 選擇自己實(shí)現(xiàn) cluster模塊 ,而不是直接使用系統(tǒng)原生的方法?主要的原因是以下兩點(diǎn):

  • fork的進(jìn)程監(jiān)聽同一端口會(huì)導(dǎo)致端口占用錯(cuò)誤

  • fork的進(jìn)程之間沒有負(fù)載均衡,容易導(dǎo)致驚群現(xiàn)象

cluster模塊 中,針對(duì)第一個(gè)問題,通過判斷當(dāng)前進(jìn)程是否為 master進(jìn)程,若是,則監(jiān)聽端口,若不是則表示為 fork 的 worker進(jìn)程,不監(jiān)聽端口。

針對(duì)第二個(gè)問題,cluster模塊 內(nèi)置了負(fù)載均衡功能, master進(jìn)程 負(fù)責(zé)監(jiān)聽端口接收請(qǐng)求,然后通過調(diào)度算法(默認(rèn)為 Round-Robin,可以通過環(huán)境變量 NODE_CLUSTER_SCHED_POLICY 修改調(diào)度算法)分配給對(duì)應(yīng)的 worker進(jìn)程

3. 異常捕獲

3.1 未捕獲異常

當(dāng)代碼拋出了異常沒有被捕獲到時(shí),進(jìn)程將會(huì)退出,此時(shí) Node.js 提供了 process.on('uncaughtException', handler) 接口來捕獲它,但是當(dāng)一個(gè) Worker 進(jìn)程遇到未捕獲的異常時(shí),它已經(jīng)處于一個(gè)不確定狀態(tài),此時(shí)我們應(yīng)該讓這個(gè)進(jìn)程優(yōu)雅退出:

  • 關(guān)閉異常 Worker 進(jìn)程所有的 TCP Server(將已有的連接快速斷開,且不再接收新的連接),斷開和 Master 的 IPC 通道,不再接受新的用戶請(qǐng)求。
  • Master 立刻 fork 一個(gè)新的 Worker 進(jìn)程,保證在線的『工人』總數(shù)不變。
  • 異常 Worker 等待一段時(shí)間,處理完已經(jīng)接受的請(qǐng)求后退出。
+---------+                 +---------+ |  Worker |                 |  Master | +---------+                 +----+----+      | uncaughtException         |      +------------+              |      |            |              |                   +---------+      | <----------+              |                   |  Worker |      |                           |                   +----+----+      |        disconnect         |   fork a new worker    |      +-------------------------> + ---------------------> |      |         wait...           |                        |      |          exit             |                        |      +-------------------------> |                        |      |                           |                        |     die                          |                        |                                  |                        |                                  |                        |

3.2 OOM、系統(tǒng)異常

當(dāng)一個(gè)進(jìn)程出現(xiàn)異常導(dǎo)致 crash 或者 OOM 被系統(tǒng)殺死時(shí),不像未捕獲異常發(fā)生時(shí)我們還有機(jī)會(huì)讓進(jìn)程繼續(xù)執(zhí)行,只能夠讓當(dāng)前進(jìn)程直接退出,Master 立刻 fork 一個(gè)新的 Worker。


二、子進(jìn)程

1. child_process模塊

child_process 模塊提供了衍生子進(jìn)程的能力, 簡單來說就是執(zhí)行cmd命令的能力。 默認(rèn)情況下, stdin、 stdout 和 stderr 的管道會(huì)在父 Node.js 進(jìn)程和衍生的子進(jìn)程之間建立。 這些管道具有有限的(且平臺(tái)特定的)容量。 如果子進(jìn)程寫入 stdout 時(shí)超出該限制且沒有捕獲輸出,則子進(jìn)程會(huì)阻塞并等待管道緩沖區(qū)接受

贊(0)
分享到: 更多 (0)
?
網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)
农民人伦一区二区三区| 美女下部裸体张开腿视频| 久久99精品国产99久久| 久久精品国产亚洲AV蜜桃AV| 老司机久久一区二区三区| 欧美性猛交XXXX黑人| 色噜噜狠狠色综合久色AⅤ网视频| 日韩欧群交P片内射中文| 铜铜铜铜铜铜铜铜好大好深黄| 午夜无遮挡男女啪啪免费软件| 小BBW小BBW小BBW小| 亚洲日韩一区二区三区黑人| √天堂网WWW最新版| 宝贝乖女你的奶真大水真多| 国产精品久久久久久亚洲影视| 国产性自爱拍偷在在线播放| 久久久久久AV无码免费网站| 欧美综合在线激情专区| 十八禁乳露裸体奶头WWW网站| 无码国模大尺度视频在线观看| 亚洲AV无码不卡在线观看下载| 亚洲人精品午夜射精日韩| 99RE6热这里只精品首页| 第一夜被弄得又红又肿| 狠痕鲁狠狠爱2021在| 免费啪啪全程无遮挡60分钟| 肉色超薄丝袜脚交一区二区| 亚洲AV无码精品色午夜果冻不卡| 游泳教练在水里含我奶小说| WINDOWS乱码的乱码大全| 国产精品拍天天在线| 久久久久久精品免费免费999| 免费A级毛片无码A| 少妇高潮喷水久久久久久久久久| 亚洲国产成人久久精品99 | 国产精品亚洲VA在线| 久久精品人人看人人爽| 日本无遮挡吸乳视频| 亚洲AV成人无码网站| 涨乳催乳改造调教公主| 国产成人8X视频网站| 久久久久99精品成人品| 日韩一区国产二区欧美三区| 亚洲乱码尤物193YW| ZOOM人与ZOOM| 狠狠躁夜夜躁AV网站色| 欧美最婬乱婬爆婬牲视| 亚洲AV无码成人精品区一本二本 | 亚洲AV综合色区无码一二三区| 18禁止福利午夜体验试看| 国产精品IGAO视频网网址| 美国一面亲上边一面膜下边| 玩两个丰满老熟女久久网| 中国女人熟毛茸茸A毛片| 国产成人精品午夜福利APP色多| 久久久久亚洲AV成人网人人软件| 日韩精品无码区免费专区| 亚洲一区二区三区国产精华液| 把腿张开老子cao烂你在线视频| 国产自国产自愉自愉免费24区| 欧美 日韩 国产 亚洲 色| 亚洲AV无码专区亚洲AV伊甸园| DIPTYQUE含羞草香薰| 精品无码黑人又粗又大又长AV| 日本少妇人妻XXXXX18免费| 艳妇乳肉豪妇荡乳AV无码福利| 大炕上的肉体交换| 久久综合九色综合欧美98| 无码免费一区二区三区| MM131美女大尺度私密照尤果 | 无码国产成人久久| AV片在线观看免费| 精品无码一区二区三区| 他趴在两腿中间舔我私密有事| 中国成熟IPHONE| 果冻传媒一区二区天美传媒| 日日噜噜夜夜狠狠视频| 最新无码国产在线视频9299| 国内精品久久久久久久影视麻豆| 人妻熟妇乱又伦精品视频| 亚洲中文字幕无码超碰| 国产无人区一卡二卡3卡4卡在线| 人妻精品无码一区二区三区| 在线观看一区二区三区AV| 怀孕挺大肚子疯狂高潮AV毛片| 日本熟妇色XXXXXBBB日本| 中文字幕日本六区小电影| 精品噜噜噜噜久久久久久久久| 熟女高潮喷水一区二区三区| WWW.一区二区三区在线 || 老外免费CSGO交易网站下载| 亚洲国产AV高清无码| 国产乱XXXX搡XXXXX搡| 色欲人妻AAAAAAA无码| JAPANESE55丰满成熟妇| 美女图片禁欲系高级感| 亚洲色大成网站WWW尤物| 国内精品视频在线观看九九| 同学要做吗PO爱喝花茶的小酥肉| YELLOW在线资源免费观看| 免费观看大片的APP视频| 亚洲综合AV在线在线播放| 禁欲少校大哥的囚禁| 亚洲 都市 无码 校园 激情| 国产成人精品久久久久精品日日| 人妻无码全彩里番ACG视频| 99RIAV国产精品视频| 老师办公室被吃奶好爽在线观看| 亚洲第一综合天堂另类专| 国产亚洲精久久久久久无码777| 少妇的BBW性大片| 成为全校公交车的日常生活| 日本VA欧美VA欧美VA精品| WYC忘忧草在线看WWW| 欧美色欧美亚洲另类二区| 18禁亲胸揉胸膜下刺激免费网站| 久久久久久久女国产乱让韩| 亚洲人成线无码7777| 娇妻被黑人杂交呻吟| 亚洲精品国产综合麻豆久久99| 国产免费一区二区三区在线观看| 四季AV无码专区AV| 丰满少妇大叫太大太粗| 日韩人妻中文字幕| 潮喷大喷水系列无码久久精品| 漂亮人妻被中出中文字幕| CSGO大姐姐AWP多少钱| 漂亮人妻洗澡被公强啪啪| СЕКС高清ВИДЕ学生妹| 欧美极度残忍另类| HEZYO加勒比 一本高手机在| 欧洲Av无码放荡人妇网站| 啊轻点灬大JI巴太粗太长了欧美 | 高清成人爽A毛片免费| 特黄做受又硬又粗又大视频18| 俄罗斯1317大但人文艺术| 熟女少妇a性色生活片毛片| 国产高潮国产高潮久久久| 午夜福利1000 92免费| 国模小黎大尺度精品(02)[| 亚洲AV永久精品无码| 精品久久无码中文字幕| 一本加勒比HEZYO无码人妻 | 国产免费AV片在线观看| 亚洲AV无码AV男人的天堂| 久久AⅤ天堂AV无码AV| 真人无码作爱免费视频禁HNN| 老乞丐没完没了73节| 99亚洲乱人伦AⅤ精品| 人人妻人人藻人人爽欧美一区| 波多野结衣AV中文一区二区三区 | 国产乱人伦偷精品视频下| 亚洲国产精品VA在线播放| 久久久无码精品国产一区| 999久久久国产精品消防器材| 欧美日韩精品人妻一区二区三区| 八戒八戒神马影院在线观看5| 色AV综合AV综合无码网站| 国产麻豆精选AV| 亚洲一级 片内射无码| 女儿国免费观看完整版在线| 凹凸视频免费在线| 无码人妻精品一区二区三 | 超清纯白嫩大学生无码网站| 无码熟妇人妻AV在线影片| 久久99精品国产99久久6| 18性欧美XXXⅩ性满足| 三上悠亚AV资源站| 国产熟睡乱子伦视频在线观看| 亚洲AV综合色区无码另类小说| 久久久久久一区国产精品| FREE护士XXXXⅩONHD| 特大巨黑吊XXXX高潮| 精品久久久久久无码专区不卡| 一面亲上边一面膜| 日本老熟妇人妻妇毛多多| 国产日韩AⅤ无码一区二区三区| 亚洲第一最快AV网站| 欧美黑人巨大XXXX黑人猛| 国产AV免费一区二区三区| 亚洲国产午夜精品理论片| 男人的天堂AV网站| 国产A1A2A3| 野花影视视频在线观看免费| 日本精品VIDEOSSE×少妇 | 婷婷成人综合激情在线视频播放| 狠狠久久亚洲欧美专区| 69无人区码一码二码三码区别| 少妇高潮惨叫久久久久久电影| 韩国的无码AV看免费大片在线| 一夲道中文字幕AV高清片| 日本在线人数最多的MMORPG| 娇小性XXXXX极品娇小| JEΑL0USVUE成熟50M| 小婷又软又嫩又紧水又多的软件| 久久天天躁夜夜躁狠狠85| 嗯啊开小嫩苞HHH好深男男| 亚洲日本VA中文字幕久久道具| 亲情会王芳高敏大团圆| 极品少妇的粉嫩小泬看片|