2016-05-09 161 views
3

基礎上應對this question網口,我試圖找出原因有多個工人在同一端口上調用server.listen() /地址不會引起任何問題,但有一個老工人呼叫server.close()隨後在同一端口上的server.listen()將反覆給出錯誤EADDRINUSE共享與羣集模塊

這聽起來好像不是正確關閉的情況,因爲發出了close事件,這是我嘗試設置新偵聽器時的情況。當這名工人得到EADDRINUSE時,新產生的工人可以撥打server.listen(),沒有問題。

這是一個簡單的測試,將證明問題。由於工作人員每隔100ms分叉一次,他們將在端口16000上建立一個監聽器。當工作人員10分叉時,它將建立一個超時以在1秒後拆除其監聽者。一旦發生close事件,它將嘗試再次在端口16000上調用server.listen(),並獲取EADDRINUSE錯誤。爲了保持一致性,該測試在綁定過程中明確提供了相同的地址,以避免核心模塊處理null地址的任何潛在問題。

這個特定的實現將導致工作人員10在綁定過程中遇到錯誤後會佔用所有的週期,從而避免主進程分派新的工作人員。如果在致電server.listen()之前添加延遲,則工作人員10仍將繼續擊中EADDRINUSE,同時主人不斷分派能夠建立聽衆的新工作人員。

var cluster = require('cluster'); 
var net  = require('net'); 

if (cluster.isMaster) { 
    setInterval(function(){cluster.fork()},100); 
} else { 
    var workerID = cluster.worker.id; 
    var server; 
    var setup = function() { 
     console.log('Worker ' + workerID + ' setting up listener'); 
     server = net.createServer(function(stream) {}); 
     server.on('error', function(err) { 
      console.log('Error on worker ' + workerID, err); 
      teardown(); 
     }); 
     if (workerID == 10) { 
      server.listen(16000, '127.0.0.1', function() { 
       console.log('Worker ' + workerID + ' listener established'); 
       setTimeout(teardown, 1000); 
      }); 
     } else { 
      server.listen(16000, '127.0.0.1', function() { 
       console.log('Worker ' + workerID + ' listener established'); 
      }); 
     } 
    } 
    var teardown = function() { 
     console.log('Worker ' + workerID + ' closing listener'); 
     server.close(setup); 
    } 
    setup(); 
} 

從這個測試用例初始輸出:

Worker 1 setting up listener 
Worker 1 listener established 
Worker 2 setting up listener 
Worker 2 listener established 
Worker 3 setting up listener 
Worker 3 listener established 
Worker 4 setting up listener 
Worker 4 listener established 
Worker 5 setting up listener 
Worker 5 listener established 
Worker 6 setting up listener 
Worker 6 listener established 
Worker 7 setting up listener 
Worker 7 listener established 
Worker 8 setting up listener 
Worker 8 listener established 
Worker 9 setting up listener 
Worker 9 listener established 
Worker 10 setting up listener 
Worker 10 listener established 
Worker 11 setting up listener 
Worker 11 listener established 
Worker 12 setting up listener 
Worker 12 listener established 
Worker 13 setting up listener 
Worker 13 listener established 
Worker 14 setting up listener 
Worker 14 listener established 
Worker 15 setting up listener 
Worker 15 listener established 
Worker 16 setting up listener 
Worker 16 listener established 
Worker 17 setting up listener 
Worker 17 listener established 
Worker 18 setting up listener 
Worker 18 listener established 
Worker 19 setting up listener 
Worker 19 listener established 
Worker 10 closing listener 
Worker 10 setting up listener 
Error on worker 10 { [Error: bind EADDRINUSE 127.0.0.1:16000] 
    code: 'EADDRINUSE', 
    errno: 'EADDRINUSE', 
    syscall: 'bind', 
    address: '127.0.0.1', 
    port: 16000 } 
Worker 10 closing listener 
Worker 10 setting up listener 
Error on worker 10 { [Error: bind EADDRINUSE 127.0.0.1:16000] 
    code: 'EADDRINUSE', 
    errno: 'EADDRINUSE', 
    syscall: 'bind', 
    address: '127.0.0.1', 
    port: 16000 } 
Worker 10 closing listener 
+0

可如果你聽端口0,而不是16000(意思是監聽端口將是隨機的,但所有工人將使用相同的隨機端口),錯誤沒有被拋出,所以我不知道如果[此代碼](https://github.com/nodejs/node/blob/cee4c25c9281d106f80b20ba7854bf9003f9357a/lib/net.js#L1310-L1315)可能會導致錯誤(雖然它doesn由於AFAICS這意味着端口不匹配,所以不應該有太多的意義)。 – robertklep

+0

通過使用端口0而不是16000,所有的初始偵聽器都建立在同一個端口上(在我的情況下是53230),但是當工作人員10啓動另一個端口爲0的偵聽器時,它似乎增加了正在偵聽的端口(第一次收聽53230,第二次收聽53231等)。 –

+0

呃,我沒有意識到這一點。這聽起來像是在第二次調用worker.listen()時充滿了問題。 – robertklep

回答

3

問題似乎是內部到羣集模塊和正在通過this issue跟蹤節點Github上上。

問題現在已經更新並且已修復。

更新:此修復程序是V6.2.1