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

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

聊聊Node.js中的多進程和多線程

大家都知道 Node 是單線程的,卻不知它也提供了多進(線)程模塊來加速處理一些特殊任務(wù),本文便帶領(lǐng)大家了解下 Node.js 的多進(線)程,希望對大家有所幫助!

聊聊Node.js中的多進程和多線程

我們都知道 Node.js 采用的是單線程、基于事件驅(qū)動的異步 I/O 模型,其特性決定了它無法利用 CPU 多核的優(yōu)勢,也不善于完成一些非 I/O 類型的操作(比如執(zhí)行腳本、AI 計算、圖像處理等),為了解決此類問題,Node.js 提供了常規(guī)的多進(線程)方案(關(guān)于進程、線程的討論,可參見筆者的另一篇文章 Node.js 與并發(fā)模型),本文便為大家介紹 Node.js 的多進(線)程機制。

child_process

我們可使用 child_process 模塊創(chuàng)建 Node.js 的子進程,來完成一些特殊的任務(wù)(比如執(zhí)行腳本),該模塊主要提供了 exec、execFile、fork、spwan 等方法,下面我們就簡單介紹下這些方法的使用。

exec

const { exec } = require('child_process');  exec('ls -al', (error, stdout, stderr) => {   console.log(stdout); });

該方法根據(jù) options.shell 指定的可執(zhí)行文件處理命令字符串,在命令的執(zhí)行過程中緩存其輸出,直到命令執(zhí)行完成后,再將執(zhí)行結(jié)果以回調(diào)函數(shù)參數(shù)的形式返回。

該方法的參數(shù)解釋如下:

  • command:將要執(zhí)行的命令(比如 ls -al);

  • options:參數(shù)設(shè)置(可不指定),相關(guān)屬性如下:

    • cwd:子進程的當(dāng)前工作目錄,默認(rèn)取 process.cwd() 的值;

    • env:環(huán)境變量設(shè)置(為鍵值對對象),默認(rèn)取 process.env 的值;

    • encoding:字符編碼,默認(rèn)值為:utf8

    • shell:處理命令字符串的可執(zhí)行文件,Unix 上默認(rèn)值為 /bin/sh,Windows 上默認(rèn)值取 process.env.ComSpec 的值(如為空則為 cmd.exe);比如:

      const { exec } = require('child_process');  exec("print('Hello World!')", { shell: 'python' }, (error, stdout, stderr) => {   console.log(stdout); });

      運行上面的例子將輸出 Hello World!,這等同于子進程執(zhí)行了 python -c "print('Hello World!')" 命令,因此在使用該屬性時需要注意,所指定的可執(zhí)行文件必須支持通過 -c 選項來執(zhí)行相關(guān)語句。

      注:碰巧 Node.js 也支持 -c 選項,但它等同于 --check 選項,只用來檢測指定的腳本是否存在語法錯誤,并不會執(zhí)行相關(guān)腳本。

    • signal:使用指定的 AbortSignal 終止子進程,該屬性在 v14.17.0 以上可用,比如:

      const { exec } = require('child_process');  const ac = new AbortController(); exec('ls -al', { signal: ac.signal }, (error, stdout, stderr) => {});

      上例中,我們可通過調(diào)用 ac.abort() 來提前終止子進程。

    • timeout:子進程的超時時間(如果該屬性的值大于 0,那么當(dāng)子進程運行時間超過指定值時,將會給子進程發(fā)送屬性 killSignal 指定的終止信號),單位毫米,默認(rèn)值為 0

    • maxBuffer:stdout 或 stderr 所允許的最大緩存(二進制),如果超出,子進程將會被殺死,并且將會截斷任何輸出,默認(rèn)值為 1024 * 1024;

    • killSignal:子進程終止信號,默認(rèn)值為 SIGTERM

    • uid:執(zhí)行子進程的 uid;

    • gid:執(zhí)行子進程的 gid;

    • windowsHide:是否隱藏子進程的控制臺窗口,常用于 Windows 系統(tǒng),默認(rèn)值為 false

  • callback:回調(diào)函數(shù),包含 errorstdout、stderr 三個參數(shù):

    • error:如果命令行執(zhí)行成功,值為 null,否則值為 Error 的一個實例,其中 error.code 為子進程的退出的錯誤碼,error.signal 為子進程終止的信號;
    • stdoutstderr:子進程的 stdoutstderr,按照 encoding 屬性的值進行編碼,如果 encoding 的值為 buffer,或者 stdoutstderr 的值是一個無法識別的字符串,將按照 buffer 進行編碼。

execFile

const { execFile } = require('child_process');  execFile('ls', ['-al'], (error, stdout, stderr) => {   console.log(stdout); });

該方法的功能類似于 exec,唯一的區(qū)別是 execFile 在默認(rèn)情況下直接用指定的可執(zhí)行文件(即參數(shù) file 的值)處理命令,這使得其效率略高于 exec(如果查看 shell 的處理邏輯,筆者感覺這效率可忽略不計)。

該方法的參數(shù)解釋如下:

  • file:可執(zhí)行文件的名字或路徑;

  • args:可執(zhí)行文件的參數(shù)列表;

  • options:參數(shù)設(shè)置(可不指定),相關(guān)屬性如下:

    • shell:值為 false 時表示直接用指定的可執(zhí)行文件(即參數(shù) file 的值)處理命令,值為 true 或其它字符串時,作用等同于 exec 中的 shell,默認(rèn)值為 false
    • windowsVerbatimArguments:在 Windows 中是否對參數(shù)進行引號或轉(zhuǎn)義處理,在 Unix 中將忽略該屬性,默認(rèn)值為 false;
    • 屬性 cwd、env、encoding、timeout、maxBuffer、killSignal、uid、gid、windowsHidesignal 在上文中已介紹,此處不再重述。
  • callback:回調(diào)函數(shù),等同于 exec 中的 callback,此處不再闡述。

fork

const { fork } = require('child_process');  const echo = fork('./echo.js', {   silent: true }); echo.stdout.on('data', (data) => {   console.log(`stdout: ${data}`); });  echo.stderr.on('data', (data) => {   console.error(`stderr: ${data}`); });  echo.on('close', (code) => {   console.log(`child process exited with code ${code}`); });

該方法用于創(chuàng)建新的 Node.js 實例以執(zhí)行指定的 Node.js 腳本,與父進程之間以 IPC 方式進行通信。

該方法的參數(shù)解釋如下:

  • modulePath:要運行的 Node.js 腳本路徑;

  • args:傳遞給 Node.js 腳本的參數(shù)列表;

  • options:參數(shù)設(shè)置(可不指定),相關(guān)屬性如:

    • detached:參見下文對 spwanoptions.detached 的說明;

    • execPath:創(chuàng)建子進程的可執(zhí)行文件;

    • execArgv:傳遞給可執(zhí)行文件的字符串參數(shù)列表,默認(rèn)取 process.execArgv 的值;

    • serialization:進程間消息的序列號類型,可用值為 jsonadvanced,默認(rèn)值為 json;

    • slient: 如果為 true,子進程的 stdin、stdoutstderr 將通過管道傳遞給父進程,否則將繼承父進程的 stdin、stdoutstderr;默認(rèn)值為 false

    • stdio:參見下文對 spwanoptions.stdio 的說明。這里需要注意的是:

      • 如果指定了該屬性,將忽略 slient 的值;
      • 必須包含一個值為 ipc 的選項(比如 [0, 1, 2, 'ipc']),否則將拋出異常。
    • 屬性 cwdenv、uid、gid、windowsVerbatimArguments、signaltimeout、killSignal 在上文中已介紹,此處不再重述。

spwan

const { spawn } = require('child_process');  const ls = spawn('ls', ['-al']); ls.stdout.on('data', (data) => {   console.log(`stdout: ${data}`); });  ls.stderr.on('data', (data) => {   console.error(`stderr: ${data}`); });  ls.on('close', (code) => {   console.log(`child process exited with code ${code}`); });

該方法為 child_process 模塊的基礎(chǔ)方法,exec、execFilefork 最終都會調(diào)用 spawn 來創(chuàng)建子進程。

該方法的參數(shù)解釋如下:

  • command:可執(zhí)行文件的名字或路徑;

  • args:傳遞給可執(zhí)行文件的參數(shù)列表;

  • options:參數(shù)設(shè)置(可不指定),相關(guān)屬性如下:

    • argv0:發(fā)送給子進程 argv[0] 的值,默認(rèn)取參數(shù) command 的值;

    • detached:是否允許子進程可以獨立于父進程運行(即父進程退出后,子進程可以繼續(xù)運行),默認(rèn)值為 false,其值為 true 時,各平臺的效果如下所述:

      • Windows 系統(tǒng)中,父進程退出后,子進程可以繼續(xù)運行,并且子進程擁有自己的控制臺窗口(該特性一旦啟動后,在運行過程中將無法更改);
      • 在非 Windows 系統(tǒng)中,子進程將作為新進程會話組的組長,此刻不管子進程是否與父進程分離,子進程都可以在父進程退出后繼續(xù)運行。

      需要注意的是,如果子進程需要執(zhí)行長時間的任務(wù),并且想要父進程提前退出,需要同時滿足以下幾點:

      • 調(diào)用子進程的 unref 方法從而將子進程從父進程的事件循環(huán)中剔除;
      • detached 設(shè)置為 true
      • stdioignore

      比如下面的例子:

      // hello.js const fs = require('fs'); let index = 0; function run() {   setTimeout(() => {     fs.writeFileSync('./hello', `index: ${index}`);     if (index < 10) {       index += 1;       run();     }   }, 1000); } run();  // main.js const { spawn } = require('child_process'); const child = spawn('node', ['./hello.js'], {   detached: true,   stdio: 'ignore' }); child.unref();
    • stdio:子進程標(biāo)準(zhǔn)輸入輸出配置,默認(rèn)值為 pipe,值為字符串或數(shù)組:

      • 值為字符串時,會將其轉(zhuǎn)換為含有三個項的數(shù)組(比如 pipe 被轉(zhuǎn)換為 ['pipe', 'pipe', 'pipe']),可用值為 pipeoverlappedignore、inherit;
      • 值為數(shù)組時,其中數(shù)組的前三項分別代表對 stdinstdoutstderr 的配置,每一項的可用值為 pipeoverlappedignore、inherit、ipc、Stream 對象、正整數(shù)(在父進程打開的文件描述符)、null(如位于數(shù)組的前三項,等同于 pipe,否則等同于 ignore)、undefined(如位于數(shù)組的前三項,等同于 pipe,否則等同于 ignore)。
    • 屬性 cwd、env、uid、gid、serializationshell(值為 booleanstring)、windowsVerbatimArgumentswindowsHide、signal、timeoutkillSignal 在上文中已介紹,此處不再重述。

小結(jié)

上文對 child_process 模塊中主要方法的使用進行了簡短介紹,由于 execSync、execFileSync、forkSync、spwanSync 方法是 execexecFile、spwan 的同步版本,其參數(shù)并無任何差異,故不再重述。

cluster

通過 cluster 模塊我們可以創(chuàng)建 Node.js 進程集群,通過 Node.js 進程進群,我們可以更加充分地利用多核的優(yōu)勢,將程序任務(wù)分發(fā)到不同的進程中以提高程序的執(zhí)行效率;下面將通過例子為大家介紹 cluster 模塊的使用:

const http = require('http'); const cluster = require('cluster'); const numCPUs = require('os').cpus().length;  if (cluster.isPrimary) {   for (let i = 0; i < numCPUs; i++) {     cluster.fork();   } } else {   http.createServer((req, res) => {     res.writeHead(200);     res.end(`${process.pid}n`);   }).listen(8000); }

上例通過 cluster.isPrimary 屬性判斷(即判斷當(dāng)前進程是否為主進程)將其分為兩個部分:

  • 為真時,根據(jù) CPU 內(nèi)核的數(shù)量并通過 cluster.fork 調(diào)用來創(chuàng)建相應(yīng)數(shù)量的子進程;
  • 為假時,創(chuàng)建一個 HTTP server,并且每個 HTTP server 都監(jiān)聽同一個端口(此處為 8000)。

運行上面的例子,并在瀏覽器中訪問 http://localhost:8000/,我們會發(fā)現(xiàn)每次訪問返回的 pid 都不一樣,這說明了請求確實被分發(fā)到了各個子進程。Node.js 默認(rèn)采用的負(fù)載均衡策略是輪詢調(diào)度,可通過環(huán)境變量 NODE_CLUSTER_SCHED_POLICYcluster.schedulingPolicy 屬性來修改其負(fù)載均衡策略:

NODE_CLUSTER_SCHED_POLICY = rr // 或 none  cluster.schedulingPolicy = cluster.SCHED_RR; // 或 cluster.SCHED_NONE

另外需要注意的是,雖然每個子進程都創(chuàng)建了 HTTP server,并都監(jiān)聽了同一個端口,但并不代表由這些子進程自由競爭用戶請求,因為這樣無法保證所有子進程的負(fù)載達到均衡。所以正確的流程應(yīng)該是由主進程監(jiān)聽端口,然后將用戶請求根據(jù)分發(fā)策略轉(zhuǎn)發(fā)到具體的子進程進行處理。

由于進程之間是相互隔離的,因此進程之間一般通過共享內(nèi)存、消息傳遞、管道等機制進行通訊。Node.js 則是通過消息傳遞來完成父子進程之間的通信,比如下面的例子:

const http = require('http'); const cluster = require('cluster'); const numCPUs = require('os').cpus().length;  if (cluster.isPrimary) {   for (let i = 0; i < numCPUs; i++) {     const worker = cluster.fork();     worker.on('message', (message) => {       console.log(`I am primary(${process.pid}), I got message from worker: "${message}"`);       worker.send(`Send message to worker`)     });   } } else {   process.on('message', (message) => {     console.log(`I am worker(${process.pid}), I got message from primary: "${message}"`)   });   http.createServer((req, res) => {     res.writeHead(200);     res.end(`${process.pid}n`);     process.send('Send message to primary');   }).listen(8000); }

運行上面的例子,并訪問 http://localhost:8000/,再查看終端,我們會看到類似下面的輸出:

I am primary(44460), I got message from worker: "Send message to primary" I am worker(44461), I got message from primary: "Send message to worker" I am primary(44460), I got message from worker: "Send message to primary" I am worker(44462), I got message from primary: "Send message to worker"

利用該機制,我們可以監(jiān)聽各子進程的狀態(tài),以便在某個子進程出現(xiàn)意外后,能夠及時對其進行干預(yù),以保證服務(wù)的可用性。

cluster 模塊的接口非常簡單,為了節(jié)省篇幅,這里只對 cluster.setupPrimary 方法做一些特別聲明,其它方法請查看官方文檔:

  • cluster.setupPrimary 調(diào)用后,相關(guān)設(shè)置將同步到在 cluster.settings 屬性中,并且每次調(diào)用都基于當(dāng)前 cluster.settings 屬性的值;
  • cluster.setupPrimary 調(diào)用后,對已運行的子進程沒有影響,只影響后續(xù)的 cluster.fork 調(diào)用;
  • cluster.setupPrimary 調(diào)用后,不影響后續(xù)傳遞給 cluster.fork 調(diào)用的 env 參數(shù);
  • cluster.setupPrimary 只能在主進程中使用。

worker_threads

前文我們對 cluster 模塊進行了介紹,通過它我們可以創(chuàng)建 Node.js 進程集群以提高程序的運行效率,但 cluster 基于多進程模型,進程間高成本的切換以及進程間資源的隔離,會隨著子進程數(shù)量的增加,很容易導(dǎo)致因系統(tǒng)資源緊張而無法響應(yīng)的問題。為解決此類問題,Node.js 提供了 worker_threads,下面我們通過具體的例子對該模塊的使用進行簡單介紹:

// server.js const http = require('http'); const { Worker } = require('worker_threads');  http.createServer((req, res) => {   const httpWorker = new Worker('./http_worker.js');   httpWorker.on('message', (result) => {     res.writeHead(200);     res.end(`${result}n`);   });   httpWorker.postMessage('Tom'); }).listen(8000);  // http_worker.js const { parentPort } = require('worker_threads');  parentPort.on('message', (name) => {   parentPort.postMessage(`Welcone ${name}!`); });

上例展示了 worker_threads 的簡單使用,在使用 worker_threads 的過程中,需要注意以下幾點:

  • 通過 worker_threads.Worker 創(chuàng)建 Worker 實例,其中 Worker 腳本既可以為一個獨立的 JavaScript 文件,也可以為字符串,比如上例可修改為:

    const code = "const { parentPort } = require('worker_threads'); parentPort.on('message', (name) => {parentPort.postMessage(`Welcone ${name}!`);})"; const httpWorker = new Worker(code, { eval: true });
  • 通過 worker_threads.Worker 創(chuàng)建 Worker 實例時,可以通過指定 workerData 的值來設(shè)置 Worker 子線程的初始元數(shù)據(jù),比如:

    // server.js const { Worker } = require('worker_threads'); const httpWorker = new Worker('./http_worker.js', { workerData: { name: 'Tom'} });  // http_worker.js const { workerData } = require('worker_threads'); console.log(workerData);
  • 通過 worker_threads.Worker 創(chuàng)建 Worker 實例時,可通過設(shè)置 SHARE_ENV 以實現(xiàn)在 Worker 子線程與主線程之間共享環(huán)境變量的需求,比如:

    const { Worker, SHARE_ENV } = require('worker_threads'); const worker = new Worker('process.env.SET_IN_WORKER = "foo"', { eval: true, env: SHARE_ENV }); worker.on('exit', () => {   console.log(process.env.SET_IN_WORKER); });
  • 不同于 cluster 中進程間的通信機制,worker_threads 采用的 MessageChannel 來進行線程間的通信:

    • Worker 子線程通過 parentPort.postMessage 方法發(fā)送消息給主線程,并通過監(jiān)聽 parentPortmessage 事件來處理來自主線程的消息;
    • 主線程通過 Worker 子線程實例(此處為 httpWorker,以下均以此代替 Worker 子線程)的 postMessage 方法發(fā)送消息給 httpWorker,并通過監(jiān)聽 httpWorkermessage 事件來處理來自 Worker 子線程的消息。

在 Node.js 中,無論是 cluster 創(chuàng)建的子進程,還是 worker_threads 創(chuàng)建的 Worker 子線程,它們都擁有屬于自己的 V8 實例以及事件循環(huán),所不同的是:

  • 子進程之間的內(nèi)存空間是互相隔離的,而 Worker 子線程共享所屬進程的內(nèi)存空間;
  • 子進程之間的切換成本要遠遠高于 Worker 子線程之間的切換成本。

盡管看起來 Worker 子線程比子進程更高效,但 Worker 子線程也有不足的地方,即cluster 提供了負(fù)載均衡,而 worker_threads 則需要我們自行完成負(fù)載均衡的設(shè)計與實現(xiàn)。

總結(jié)

本文介紹了 Node.js 中 child_processclusterworker_threads 三個模塊的使用,通過這三個模塊,我們可以充分利用 CPU 多核的優(yōu)勢,并以多進(線)程的模式來高效地解決一些特殊任務(wù)(比如 AI、圖片處理等)的運行效率。每個模塊都有其適用的場景,文中僅對其基本使用進行了說明,如何結(jié)合自己的問題進行高效地運用,還需要大家自行摸索。最后,本文若有紕漏之處,還望大家能夠指正,祝大家快樂編碼每一天。

贊(0)
分享到: 更多 (0)
?
網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
亚洲欧美成人AⅤ在线专区| 无码人妻精品中文字幕不卡| 色噜噜狠狠狠狠色综合久一| 少妇粉嫩小泬喷水视频| 脱了老师内裤猛烈进入的软件| 五月丁香国产在线视频| 亚洲の无码国产の无码影院 | 漂亮人妻被中出中文字幕| 人人添人人妻人人爽频| 丝瓜草莓视频APP| 亚洲AV日韩精品一区二区三区| 亚洲色偷拍区另类无码专区| 中文字幕在线播放| 菠萝菠萝蜜在线观看| 国产成人精品午夜二三区波多野| 国产香蕉97碰碰久久人人| 久久99精品国产99久久6男男| 美女扒开裤衩让男人桶爽| 人体艺术大胆图片| 午夜亚洲精品久久久久久| 亚洲伊人精品无码一区二区| 99久久人妻无码中文字幕系列| 岛国无码AⅤ片在线观看| 国产午夜视频在线观看720P| 久久嫩草精品久久久久精品| 欧美人妖XXXX做受| 无码YY4800亚洲私人影院| 亚洲欧美另类在线视频| CHINESE农村老妓女| 国产极品视觉盛宴专区| 久久精品高清一区二区三区| 欧美性爱一区二区三区| 午夜福利理论片在线观看| 一本久久伊人热热精品中文| 波多野结衣高清一区二区三区 | 久久人人爽人人爽人人片Ⅴ| 日本丰满少妇毛茸茸| 亚洲AV永久无码一区二区三区| √天堂资源在线中文8在线最新版| 东北浪妇王梅娟偷人视频| 精品乱子伦一区二区三区| 欧洲美女与动交ZOZ0Z| 午夜无码性爽快影院6080| 最新国产成人无码久久| 国产成人综合亚洲AV| 泷泽萝拉AV种子| 天堂√最新版在线| 在线日韩日本国产亚洲| 国产白丝JK捆绑束缚调教视频| 久久久久久精品免费免费软件| 人人澡人人人妻人人人少妇| 亚洲成AV人片无码BT种子下载| JIZZJIZZ日本护士| 激情久久AV一区AV二区AV三| 欧美一级 片内射欧美A999| 亚洲大尺度专区无码| 成人AV在线播放| 久久久久人妻一区精品色| 四虎成人精品国产永久免费无码| 一区二区三区在线 | 欧洲| 国产爆乳成人AV在线播放| 蜜乳AV一区二区三区四区| 无码AV在线一区二区| 69女性XXXXⅩ丰满HD| 国产亚洲色婷婷久久99精品| 欧洲成人一区二区三区| 亚洲精品无码专区在线| 多P混交群体交乱的安全保障| 久久亚洲AV无码AV男人的天堂| 无码AV动漫精品专区| GOGO全球大胆高清人体131| 亚洲人ⅤSAⅤ国产精品| 无码一区二区三区| JAPANESE成熟丰满熟妇| 久久国产色AV免费看| 无码欧亚熟妇人妻AV在线| JAPANESE熟女熟妇多毛毛| 精品无码国产自产野外拍在线| 日日噜噜夜夜狠狠久久丁香五月| 曰批全过程免费视频观看| 国产老妇伦国产熟女老妇高清| 琪琪午夜成人理论福利片美容院| 亚洲日韩∨A无码中文字幕| 国产二级一片内射视频播放 | 在床上拔萝卜又疼又叫什么病 | 亚洲AV中文无码乱人伦在线视色| 粗大黑人巨精大战欧美成人| 男女啪啪激烈高潮喷出GIF免费| 亚洲不卡AV不卡一区二区| 国产WW久久久久久久久久| 啪啪无码人妻丰满熟妇| 正在播放老肥熟妇露脸| 加勒比一本HEYZO高清视频 | 国产精品视频一区二区三区四| 奇米第四色777ME| 中国WINDOWS野外| 精品日本一区二区三区免费 | 国产乱人伦偷精精品视频| 乳揉みま痴汉电车中文字幕| GAY2022空少被体育生暴菊| 麻花传媒剧国产MV在线观看 | 护士被医生办公室狂玩| 无码人妻久久一区二区三区APP| 插花弄玉小说荔枝很甜作者卿凌| 免费看漫画在线成人漫画| 亚洲中文字幕精品一区二区三区| 国自产精品手机在线观看视频| 婷婷97狠狠成人免费视频| 成年女人午夜毛片免费视频| 欧美日韩国产免费一区二区三区| 中文无码伦AV中文字幕在线 | 国产精品门事件AV| 丝袜灬啊灬快灬高潮了视频| 吃饭时把腿张开故意让公| 人妻18毛片A级毛片免费看| 97无码免费人妻超级碰碰夜夜| 久久亚洲中文字幕精品一区| 亚洲色成人一区二区三区小说| 国语自产偷拍精品视频偷| 亚洲AV蜜桃少妇秘 大胸| 国产乱码一区二区三区免费| 无码免费无线观看在线视频| 国产成人精选视频在线观看 | 亚洲国产精品久久久久蜜桃| 好男人WWW在线影院官网| 性国产SE╳O色欲A片免费观看 | 精品一区二区三区无码视频 | AJ四色鸳鸯真假区别| 欧美超大胆裸体XX视频| 99久久99久久精品免费看蜜桃 | 97久久久精品综合88久久| 男女裸体下面进入的免费视频| 男女无遮挡XX00动态图1| 体验区试看120秒十八禁| 公翁的粗大放进我的秘密电影 | 麻豆国产成人AV高清在线| 中文字幕久久综合伊人| 免费AV片在线观看无需播放器| 中文字幕人妻成人综合永久| 妺妺窝人体色www九色| 94久久国产乱子伦精品免费| 欧美XXXX做受性欧美88| JUX900被公每天侵犯的我| 人妖CHINESECDTS在线| 丁香婷婷激情综合俺也去| 天堂AV无码AV一区二区三区| 国产精品久久久久国产A级| 性色AV一区二区三区无码| 狠狠色综合久久久久尤物| 亚洲一区二区三区小说| 蜜桃AV抽搐高潮一区二区| AV无码专区亚洲AVL在线观看| 中国JAPANESE成熟少妇| 精品亚洲国产成人AV| 一区二区三区四区黄色网站| 男女作爱在线播放免费网站| XXXX18HD亚洲HD护士| 熟妇的荡欲BD高清| 国产亚洲精品自在久久VR| 亚洲一区二区三区毛片 | 一区二区三区无码在线观看| 欧美丰满熟妇XXXXX高潮| 丁香婷婷激情俺也去俺来也| 午夜成人性爽爽免费视频| 久久99精品久久久久久国产| 性欧美乱妇COME| 日韩欧群交P片内射中文| 国产欧美另类久久精品蜜芽| 亚洲熟妇色XXXXX欧美老妇Y| 逆徒每天都想着欺师犯上| 大帝A∨无码视频在线播放| 性色AV蜜臀AV色欲AV| 久久久久免费精品国产| AV色综合久久天堂AV色综合在| 上司侵犯部下的人妻| 怀孕挺大肚子疯狂高潮AV毛片 | 噜噜噜噜噜18禁私人影视| 不知火舞和三个小男孩| 午夜福利理论片在线观看| 久久久久免费精品国产| Z0OZO0人善之交另类| 无码中文字幕在线播放2| 久久久久亚洲AV片无码V| а√在线中文网新版地址在线| 无码人妻一区二区三区AV| 久久久无码一区二区三区| 波多野结衣AV高清一区二区三区| 性色av蜜臀av色欲av免费| 免费A级毛片无码A∨蜜芽按摩 | 韩国18禁电影风暴尺度大| 中文文字幕文字幕亚洲色| 视频无码一区二区| 久久精品人人槡人妻人人玩AV| 波多野结衣AV一区二区三区中文| 亚洲AV不卡无码国产| 免费看30分钟打扑克教程| 国产成人无码AV在线播放无广告| 亚洲综合一区无码精品| 少妇极度饥渴少妇高潮| 久久嫩草影院免费看|