成人免费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

2011-03-04 13:22:10

FileZilla

2020-08-13 08:34:10

MySQL數據DTS

2010-06-30 15:06:27

FTP數據傳輸模式

2009-04-10 23:40:06

2009-05-19 17:05:10

2014-08-28 09:35:32

Node.js前端開發

2009-11-24 16:47:29

路由器基礎配置

2023-06-30 08:05:41

2010-07-13 15:55:12

FTP數據傳輸模式

2015-10-14 09:44:55

TCP網絡協議數據傳輸
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 九九久久免费视频 | 波多野结衣中文视频 | 亚洲精品在线国产 | 精精国产xxxx视频在线野外 | 亚洲欧美久久 | 狠狠干天天干 | 欧美日韩一 | 亚洲欧美日韩一区二区 | 亚洲综合无码一区二区 | 免费观看日韩av | 欧美专区在线 | 亚洲欧美在线观看 | 国产精品免费观看视频 | 久久亚洲免费 | 在线观看国产视频 | 国产精品久久久久久妇女6080 | 国产原创在线观看 | 99精彩视频| 国产高清一区二区 | 欧美黄色精品 | 欧美精品一区在线 | 亚洲国产精品一区二区第一页 | 国产精品视频在线免费观看 | 精品一区二区久久久久久久网站 | 毛片a级毛片免费播放100 | 欧美综合久久 | 日韩精品视频一区二区三区 | 一区精品在线观看 | 欧美阿v| 一区二区三区免费 | 免费在线一区二区三区 | 午夜av电影 | jlzzjlzz欧美大全 | 美女国内精品自产拍在线播放 | 国产又爽又黄的视频 | 黄色网址免费在线观看 | 羞羞的视频在线观看 | 亚洲视屏| 亚洲精品久久久久久久久久久 | 免费a级毛片在线播放 | 日韩一区二区在线视频 |