成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

好玩的Sendfile---探索Node.Js中更快的數據傳輸方式

開發 前端
在nginx中,可以通過sendfile指令提供效率。Node.js的copyFile底層使用了sendfile系統調用,但是網絡IO的時候,沒有使用該API。

[[400322]]

本文轉載自微信公眾號「編程雜技」,作者theanarkh。轉載本文請聯系編程雜技公眾號。

在Node.js中,當我們給前端返回一個靜態文件的時候,我們通常會把文件先讀進內容,然后通過socket接口寫到底層,從而返回給前端。無論是一次性讀取到內存還是使用流式的方式,都不可避免地要把數據從內核復制到用戶層,再把數據復制到內核,這是一種低效的方式,因為多了無效的復制。在nginx中,可以通過sendfile指令提供效率。Node.js的copyFile底層使用了sendfile系統調用,但是網絡IO的時候,沒有使用該API。因為Node.js通過隊列的方式,控制數據的寫入。那么是否可以實現sendfile的方式來提供這網絡IO的效率。首先我們看一下sendfile的好處是什么。

  • sendfile() copies data between one file descriptor and another. Because this copying is done within the kernel, sendfile() is more efficient than the combination of read(2) and write(2), which would require transferring data to and from user space.

我們看到sendfile通過把內核完成數據的傳輸,減少了內核和用戶層的數據復制,從而提高了效率。下面我們通過napi寫一個addon來實現這個功能。

  1. #include <sys/sendfile.h>  
  2. #include <stdio.h>  
  3. #include <unistd.h> 
  4. #include <fcntl.h> 
  5. #include <node_api.h> 
  6. static napi_value copyFile(napi_env env, napi_callback_info info) { 
  7.   size_t argc = 3; 
  8.   napi_value args[3]; 
  9.   // 拿到js層的入參,這里是三個 
  10.   napi_get_cb_info(env, info, &argc, args, NULLNULL); 
  11.   int fd1; 
  12.   int fd2; 
  13.   int len; 
  14.   // js傳入的是一個數字,v8轉成了對象,這里再次把入參轉成int型 
  15.   napi_get_value_int32(env, args[0], &fd1); 
  16.   napi_get_value_int32(env, args[1], &fd2); 
  17.   napi_get_value_int32(env, args[2], &len); 
  18.   int writed = sendfile(fd2, fd1, 0,len); 
  19.   napi_value ret; 
  20.   napi_create_int32(env, writed, &ret); 
  21.   return ret; 
  22.  
  23. napi_value Init(napi_env env, napi_value exports) { 
  24.   napi_value func; 
  25.   // 創建一個函數并且設置為exports對象的getArray屬性的值 
  26.   napi_create_function(env, 
  27.                       NULL
  28.                       NAPI_AUTO_LENGTH, 
  29.                       copyFile, 
  30.                       NULL
  31.                       &func); 
  32.   napi_set_named_property(env, exports, "copyFile", func); 
  33.   return exports; 
  34. NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) 

下面我們看看怎么使用。首先用這個addon來復制文件,類似Node.js的copyyFile

  1. const fs= require('fs'); 
  2. const { copyFile } = require('./build/Release/sendfile.node'); 
  3. const { 
  4.   O_WRONLY, 
  5.   O_CREAT, 
  6. } = fs.constants; 
  7. async function test() { 
  8.   const [fd1, fd2] = await Promise.all([openFile('1.txt''r'), openFile('2.txt', O_WRONLY | O_CREAT)]); 
  9.   const { size } = await getFileInfo(fd1); 
  10.   console.log(copyFile(fd1, fd2, size)); 
  11.   fs.close(fd1, () => {}); 
  12.   fs.close(fd2, () => {}); 
  13. function openFile(filename, mode) { 
  14.   return new Promise((resolve, reject) => { 
  15.     fs.open(filename, mode, (err, fd) => { 
  16.       if (err) { 
  17.         reject(err); 
  18.       } else { 
  19.         resolve(fd); 
  20.       } 
  21.     }); 
  22.   })} 
  23.  
  24. function getFileInfo(fd) { 
  25.   return new Promise((resolve, reject) => { 
  26.     fs.fstat(fd, (err, stat) => { 
  27.       if (err) { 
  28.         reject(err) 
  29.       }else { 
  30.         resolve(stat); 
  31.       } 
  32.     }); 
  33.   }) 
  34. test(); 

執行上面代碼,我們可以看到文件會成功復制2.txt。接著我們再來試一下網絡IO的場景。

  1. const fs= require('fs'); 
  2. const http = require('http'); 
  3. const { copyFile } = require('./build/Release/sendfile.node'); 
  4. const server = http.createServer(async (req, res) => { 
  5.   const fd = await openFile('1.txt''r'); 
  6.   const { size } = await getFileInfo(fd); 
  7.   const ret = copyFile(fd, res.socket._handle.fd, size); 
  8.   res.socket.end(); 
  9. }).listen(8002); 
  10.  
  11. const { 
  12.   O_WRONLY, 
  13.   O_CREAT, 
  14. } = fs.constants; 
  15.  
  16. function openFile(filename, mode) { 
  17.   return new Promise((resolve, reject) => { 
  18.     fs.open(filename, mode, (err, fd) => { 
  19.       if (err) { 
  20.         reject(err); 
  21.       } else { 
  22.         resolve(fd); 
  23.       } 
  24.     }); 
  25.   })} 
  26.  
  27. function getFileInfo(fd) { 
  28.   return new Promise((resolve, reject) => { 
  29.     fs.fstat(fd, (err, stat) => { 
  30.       if (err) { 
  31.         reject(err) 
  32.       }else { 
  33.         resolve(stat); 
  34.       } 
  35.     }); 
  36.   })} 

以上代碼首先啟動一個http服務器,然后收到請求的時候,通過addon調用sendfile給前端返回對應的內容,最后關閉連接。結果如下。

 

sendfile似乎在網絡IO中可以應用了,但只是一個demo的思路,后續有時間繼續研究分析。

 

責任編輯:武曉燕 來源: 編程雜技
相關推薦

2021-10-08 08:37:38

數據傳輸數據調用網絡協議

2021-12-01 00:05:03

Js應用Ebpf

2025-01-13 00:00:00

2021-04-06 10:15:29

Node.jsHooks前端

2013-11-26 15:51:45

Android編程藍牙數據傳輸

2020-12-08 06:28:47

Node.js異步迭代器

2020-06-12 07:50:15

大數據

2024-05-06 10:55:39

2021-12-14 11:01:44

TCPUDP網絡協議

2010-04-07 14:54:38

2020-08-13 08:34:10

MySQL數據DTS

2011-03-04 13:22:10

FileZilla

2009-04-10 23:40:06

2009-05-19 17:05:10

2010-06-30 15:06:27

FTP數據傳輸模式

2014-08-28 09:35:32

Node.js前端開發

2010-07-13 15:55:12

FTP數據傳輸模式

2009-11-24 16:47:29

路由器基礎配置

2023-06-30 08:05:41

2023-04-12 16:20:00

同步數據異步數據傳輸
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品日韩欧美一区二区三区 | 国产一区 | 精品久久久久久久 | 亚洲欧美日韩精品久久亚洲区 | 日韩av.com| 日韩国产中文字幕 | 精品欧美一区二区三区免费观看 | 成人久久久| 日韩中文字幕一区二区 | 亚洲区中文字幕 | 一区二区三区在线免费观看视频 | 亚洲 中文 欧美 日韩 在线观看 | 国产婷婷 | 日韩av成人 | 91网视频| 成人精品鲁一区一区二区 | 成人一区在线观看 | 色本道 | 精品九九 | 91久久看片 | 91色视频在线观看 | 男女视频在线看 | 青青草原综合久久大伊人精品 | 中文字幕一区二区三区精彩视频 | 国产精品久久久久久久久久 | 久久免费观看视频 | 在线观看国产精品一区二区 | 精品麻豆剧传媒av国产九九九 | caoporn国产精品免费公开 | 欧美高清免费 | 国产精品一区二区三区在线 | 黄色av网站在线观看 | 日韩一区精品 | 国产欧美精品一区二区 | 无码日韩精品一区二区免费 | 欧美性大战久久久久久久蜜臀 | 午夜精品一区二区三区在线播放 | 一级高清 | 一区二区三区视频在线 | 久久综合激情 | 美国十次成人欧美色导视频 |