自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Node.js中關(guān)于Accept時Emfile的處理

開發(fā) 前端
EMFILE表示進(jìn)程打開的文件描述符達(dá)到了上限,比如建立了一個TCP連接后,調(diào)用accept函數(shù)的時候就可能觸發(fā)這個錯誤。那么這個會導(dǎo)致什么問題呢?首先我們看看Node.js是如何處理連接的。

[[403078]]

本文轉(zhuǎn)載自微信公眾號「編程雜技」,作者theanarkh。轉(zhuǎn)載本文請聯(lián)系編程雜技公眾號。

EMFILE表示進(jìn)程打開的文件描述符達(dá)到了上限,比如建立了一個TCP連接后,調(diào)用accept函數(shù)的時候就可能觸發(fā)這個錯誤。那么這個會導(dǎo)致什么問題呢?首先我們看看Node.js是如何處理連接的。

void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {

uv_stream_t* stream;

int err;

stream = container_of(w, uv_stream_t, io_watcher);

while (uv__stream_fd(stream) != -1) {

// 摘取一個TCP連接

err = uv__accept(uv__stream_fd(stream));

// 記錄下來

stream->accepted_fd = err;

// 執(zhí)行上層回調(diào),回調(diào)里消費accepted_fd

stream->connection_cb(stream, 0);

// 下一個循環(huán)

}

}

當(dāng)監(jiān)聽socket上可讀事件觸發(fā)的時候,Node.js就會執(zhí)行uv__server_io進(jìn)行處理。在uv__server_io中Node.js就會不斷地調(diào)用accept摘取連接,然后執(zhí)行回調(diào)處理該連接。這是正常的流程,那么如果accept出錯了,那會怎么樣?比如返回了EMFILE錯誤。

因為Node.js中,epoll的工作模式是水平觸發(fā),所以每輪事件循環(huán)中,uv__server_io都會被觸發(fā),然后執(zhí)行accept,接著觸發(fā)錯誤(如果還沒有可用的文件描述符的話)。然而底層已完成三次握手的TCP連接無法得到處理,客戶端也只能默默地在等待。Node.js選擇的處理策略是關(guān)閉連接來通知客戶端,服務(wù)器已經(jīng)過載。我們看看Node.js具體是怎么做的。在初始化第一個Libuv stream的時候會首先預(yù)留一個文件描述符。

if (loop->emfile_fd == -1) {

err = uv__open_cloexec("/dev/null", O_RDONLY);

if (err < 0)

/* In the rare case that "/dev/null" isn't mounted open "/"

* instead.

*/

err = uv__open_cloexec("/", O_RDONLY);

if (err >= 0)

loop->emfile_fd = err;

}

我們看到Node.js打開了一個資源,然后拿到了一個文件描述符保存到emfile_fd。當(dāng)Node.js處理TCP連接的時候,這個emfile_fd可能就會被用上。

// 摘取TCP連接

err = uv__accept(uv__stream_fd(stream));

if (err < 0) {

// 文件描述符過載

if (err == UV_EMFILE || err == UV_ENFILE) {

err = uv__emfile_trick(loop, uv__stream_fd(stream));

if (err == UV_EAGAIN || err == UV__ERR(EWOULDBLOCK))

break;

}

stream->connection_cb(stream, err);

continue;

}

我們看到當(dāng)uv_accept返回UV_EMFILE錯誤的時候,會執(zhí)行uv__emfile_trick。

static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) {

int err;

int emfile_fd;

if (loop->emfile_fd == -1)

return UV_EMFILE;

// 關(guān)閉預(yù)留的文件描述符,下面的uv_accept才能執(zhí)行成果

uv__close(loop->emfile_fd);

loop->emfile_fd = -1;

// 循環(huán)關(guān)閉無法處理的TCP連接

do {

// 摘取TCP連接

err = uv__accept(accept_fd);

if (err >= 0)

// 關(guān)閉TCP連接,通知客戶端服務(wù)器過載

uv__close(err);

} while (err >= 0 || err == UV_EINTR);

// 重新獲取一個預(yù)留的文件描述符

emfile_fd = uv__open_cloexec("/", O_RDONLY);

if (emfile_fd >= 0)

loop->emfile_fd = emfile_fd;

return err;

}

我們看到uv__emfile_trick中關(guān)閉了所有無法處理的TCP連接,然后重新補充預(yù)留的文件描述符。正常來說uv_accept最后會返回UV_EAGAIN表示沒有連接需要處理了,從而結(jié)束處理連接的整個邏輯。

 

責(zé)任編輯:武曉燕 來源: 編程雜技
相關(guān)推薦

2021-04-19 07:41:37

AcceptEmfile問題

2021-03-04 23:12:57

Node.js異步迭代器開發(fā)

2011-11-02 09:04:15

Node.js

2021-12-25 22:29:57

Node.js 微任務(wù)處理事件循環(huán)

2020-10-26 08:34:13

Node.jsCORS前端

2021-12-28 20:04:23

Node.js開發(fā)JavaScript

2023-10-04 07:35:03

2024-01-05 08:49:15

Node.js異步編程

2016-08-11 14:02:02

NodeJS前端

2020-04-15 15:48:03

Node.jsstream前端

2021-05-21 09:36:42

開發(fā)技能代碼

2013-11-01 09:34:56

Node.js技術(shù)

2015-03-10 10:59:18

Node.js開發(fā)指南基礎(chǔ)介紹

2017-03-19 16:40:28

漏洞Node.js內(nèi)存泄漏

2017-03-20 13:43:51

Node.js內(nèi)存泄漏

2020-05-29 15:33:28

Node.js框架JavaScript

2012-02-03 09:25:39

Node.js

2020-11-02 11:40:24

Node.jsRequire前端

2011-09-08 14:16:12

Node.js

2011-09-08 13:53:31

Node.js
點贊
收藏

51CTO技術(shù)棧公眾號