이벤트 이미터 메모리 누출이 감지됨
다음 경고가 표시됩니다.
(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.
Trace:
at EventEmitter.<anonymous> (events.js:139:15)
at EventEmitter.<anonymous> (node.js:385:29)
at Server.<anonymous> (server.js:20:17)
at Server.emit (events.js:70:17)
at HTTPParser.onIncoming (http.js:1514:12)
at HTTPParser.onHeadersComplete (http.js:102:31)
at Socket.ondata (http.js:1410:22)
at TCP.onread (net.js:354:27)
server.js:에 다음과 같은 코드를 작성했습니다.
http.createServer(
function (req, res) { ... }).listen(3013);
이것을 어떻게 고칩니까?
저는 여기서 경고가 존재하는 데는 이유가 있으며 올바른 해결책은 제한을 늘리는 것이 아니라 동일한 이벤트에 많은 청취자를 추가하는 이유를 파악하는 것일 가능성이 높다는 것을 지적하고 싶습니다.왜 그렇게 많은 청취자가 추가되는지 알고 그것이 당신이 진정으로 원하는 것이라고 확신하는 경우에만 제한을 늘립니다.
이 페이지를 찾은 이유는 이 경고를 받고 사용 중인 코드에 버그가 있어서 글로벌 개체를 이벤트 이미터로 전환했기 때문입니다!이러한 일들이 눈에 띄지 않게 되는 것을 원치 않기 때문에 저는 분명히 전 세계적으로 한도를 늘리는 것에 대해 조언하고 싶습니다.
노드의 버전은 무엇입니까?또 어떤 코드가 있습니까?그것은 정상적인 행동이 아닙니다.
간단히 말해, 다음과 같습니다.process.setMaxListeners(0);
node.js - request - "발신하는 방법"도 참조하십시오.setMaxListeners()?"
허용된 답변은 제한을 늘리는 방법에 대한 의미를 제공하지만, @voltrevo가 지적했듯이 경고는 이유가 있고 코드에 버그가 있을 수 있습니다.
다음 버그 코드를 고려하십시오.
//Assume Logger is a module that emits errors
var Logger = require('./Logger.js');
for (var i = 0; i < 11; i++) {
//BUG: This will cause the warning
//As the event listener is added in a loop
Logger.on('error', function (err) {
console.log('error writing log: ' + err)
});
Logger.writeLog('Hello');
}
이제 수신기를 추가하는 올바른 방법을 확인합니다.
//Good: event listener is not in a loop
Logger.on('error', function (err) {
console.log('error writing log: ' + err)
});
for (var i = 0; i < 11; i++) {
Logger.writeLog('Hello');
}
maxListeners를 변경하기 전에 코드에서 유사한 문제를 검색합니다(다른 답변에서 설명됨).
기본적으로 단일 이벤트에 대해 최대 10명의 수신기를 등록할 수 있습니다.
코드인 경우 다음을 통해 maxListeners를 지정할 수 있습니다.
const emitter = new EventEmitter()
emitter.setMaxListeners(100)
// or 0 to turn off the limit
emitter.setMaxListeners(0)
그러나 코드가 아닌 경우 이 방법을 사용하여 기본 제한을 전체적으로 늘릴 수 있습니다.
require('events').EventEmitter.prototype._maxListeners = 100;
물론 제한을 해제할 수는 있지만 주의해야 합니다.
// turn off limits by default (BE CAREFUL)
require('events').EventEmitter.prototype._maxListeners = 0;
참고로 코드는 앱의 맨 처음에 있어야 합니다.
ADD: 노드 0.11 이후 이 코드는 기본 제한을 변경하는 데도 사용됩니다.
require('events').EventEmitter.defaultMaxListeners = 0
를 바꿉니다..on()와 함께once().사용.once()에서는 이벤트가 동일한 기능으로 처리되는 경우 이벤트 수신기를 제거합니다.
이렇게 해도 문제가 해결되지 않으면 패키지에 있는 리슬러를 다시 설치합니다.json "restler": "git://github.com/danwrong/restler.git#9d455ff14c57ddbe263dbbcd0289d76413bfe07d "
이것은 노드에서 restler 0.10의 잘못된 동작과 관련이 있습니다.여기에서 문제가 종결된 것을 볼 수 있습니다: https://github.com/danwrong/restler/issues/112 하지만, npm은 아직 이것을 업데이트하지 않았기 때문에 당신이 githead를 참조해야 합니다.
노드 버전: v11.10.1
스택 추적의 경고 메시지:
process.on('warning', e => console.warn(e.stack));
(node:17905) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 wakeup listeners added. Use emitter.setMaxListeners() to increase limit
MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 wakeup listeners added. Use emitter.setMaxListeners() to increase limit
at _addListener (events.js:255:17)
at Connection.addListener (events.js:271:10)
at Connection.Readable.on (_stream_readable.js:826:35)
at Connection.once (events.js:300:8)
at Connection._send (/var/www/html/fleet-node-api/node_modules/http2/lib/protocol/connection.js:355:10)
at processImmediate (timers.js:637:19)
at process.topLevelDomainCallback (domain.js:126:23)
github 문제 검색, 문서화 및 유사한 이벤트 이미터 메모리 누수 생성 후 iOS 푸시 알림에 사용된 노드-apn 모듈로 인해 이 문제가 발견되었습니다.
이를 통해 다음 문제가 해결되었습니다.
각 인증서/키 쌍에 대해 프로세스당 하나의 공급자만 생성해야 합니다.각 통지에 대해 새 공급자를 생성할 필요가 없습니다.하나의 앱에만 알림을 보내는 경우 둘 이상의 공급자가 필요하지 않습니다.
앱에서 계속 공급자 인스턴스를 만드는 경우 공급자에게 문의해야 합니다.종료(shutdown)는 리소스 및 메모리를 해제하기 위해 각 공급자와 함께 작업을 마치면 실행됩니다.
알림이 전송될 때마다 제공자 개체를 생성하고 있었고 GC가 이 개체를 삭제할 것으로 예상했습니다.
내 macosx에 glio를 설치할 때도 이 경고가 발생합니다.
cmd fix를 사용합니다.
sudo npm install -g npm@next
https://github.com/npm/npm/issues/13806
저는 가능할 때마다 로그를 억제하는 대신 문제를 찾아 해결하는 것을 선호합니다.이한 후, 저는 것을 .req.socketExpress 미들웨어에서 계속해서 발생하는 소켓 IO 오류를 감지합니다.어느 순간, 저는 그것이 필요하지 않다는 것을 알았지만, 어쨌든 저는 듣는 사람들을 곁에 두었습니다.저는 방금 그것들을 제거했고 당신이 겪고 있는 오류는 사라졌습니다.다음 미들웨어를 사용하거나 사용하지 않고 서버에 대한 요청을 실행하여 원인임을 확인했습니다.
socketEventsHandler(req, res, next) {
req.socket.on("error", function(err) {
console.error('------REQ ERROR')
console.error(err.stack)
});
res.socket.on("error", function(err) {
console.error('------RES ERROR')
console.error(err.stack)
});
next();
}
해당 미들웨어를 제거하면 표시되는 경고가 중지됩니다.코드를 살펴보고 필요 없는 청취자를 설정할 수 있는 곳을 찾아보겠습니다.
다른 사람들이 지적했듯이, 한도를 늘리는 것은 최선의 답이 아닙니다.저는 같은 문제에 직면했지만, 제 코드에서는 이벤트 청취자를 사용하지 않았습니다.코드를 자세히 들여다보니, 저는 가끔 많은 약속들을 만들어내고 있었습니다.각 약속에는 제공된 URL을 스크랩하는 코드가 있습니다(일부 타사 라이브러리 사용).만약 당신이 그런 일을 하고 있다면, 그것이 원인일 수도 있습니다.
이를 방지하는 방법은 이 스레드를 참조하십시오.ES6의 Promise.all()을 사용할 때 동시성을 제한하는 가장 좋은 방법은 무엇입니까?
내 경우에는, 그것은.child.stderr.pipe(process.stderr)제가 아이의 10개 정도의 사례를 시작할 때 불려지고 있었습니다.따라서 이벤트 핸들러를 LOOP의 동일한 EventEmitter Object에 연결하게 되면 nodejs가 이 오류를 발생시킵니다.
때때로 이러한 경고는 우리가 한 것이 아니라 우리가 잊어버린 것일 때 발생합니다!
npm으로 dotenv 패키지를 설치할 때 이 경고가 발생했지만 앱 시작 부분에 require('dotenv').load() 문을 추가하기 전에 중단되었습니다.프로젝트로 돌아왔을 때 "Possible Event Emitter 메모리 누수가 감지됨" 경고가 표시되기 시작했습니다.
저는 그 문제가 제가 하지 않은 것이 아니라 제가 한 일 때문이라고 생각했습니다!
일단 제가 실수를 발견하고 요청서를 추가하자 메모리 누수 경고가 사라졌습니다.
경고의 실제 문제/근본 원인을 해결하는 방법을 알려준 RLaaa에게 감사드립니다.제 경우에는 MySQL 버그 코드였습니다.
다음과 같은 코드가 포함된 약속을 작성했다고 가정할 때:
pool.getConnection((err, conn) => {
if(err) reject(err)
const q = 'SELECT * from `a_table`'
conn.query(q, [], (err, rows) => {
conn.release()
if(err) reject(err)
// do something
})
conn.on('error', (err) => {
reject(err)
})
})
다음이 있습니다.conn.on('error')코드의 청취자입니다.문자 그대로 수신기를 계속해서 추가하는 코드는 쿼리를 호출하는 횟수에 따라 달라집니다.한편.if(err) reject(err)같은 일을 합니다.
그래서 저는 그것을 제거했습니다.conn.on('error')청취자와 voila...해결되었습니다!이것이 도움이 되길 바랍니다.
나의 경우 setInterval로 불리는 비동기 함수 내부에서 데이터베이스에 대한 Sequetize 연결을 만드는 동안 연결을 닫지 않았기 때문입니다.
저도 같은 문제를 겪고 있었습니다.그리고 문제는 포트 8080을 청취자 2명에게 듣고 있었기 때문에 발생했습니다.
setMaxListeners()잘 작동하지만, 저는 그것을 추천하지 않습니다.
올바른 방법은 코드에서 추가 청취자를 확인하고 청취자를 제거하거나 청취 중인 포트 번호를 변경하는 것입니다. 이것으로 문제가 해결되었습니다.
저는 오늘 시작할 때까지 이것을 먹고 있었습니다.grunt watch최종 해결자
watch: {
options: {
maxListeners: 99,
livereload: true
},
}
짜증나는 메시지가 사라졌습니다.
다음을 사용하여 새 수신기를 만들기 전에 모든 수신기를 지워야 합니다.
클라이언트/서버
socket.removeAllListeners();
소켓이 클라이언트 소켓 또는 생성된 서버 소켓이라고 가정합니다.
또한 특정 이벤트 수신기에서 구독할 수 있습니다. 예를 들어, 이벤트 수신기를 제거합니다.connect다음과 같은 청취자:
this.socket.removeAllListeners("connect");
저는 같은 문제에 직면했지만 비동기 대기로 성공적으로 처리했습니다.
도움이 되는지 확인 부탁드립니다.
25, dataLength = 25,
예:
i = < {(let i = 0; i < dataLength; i++) {message
sftp.get(remotePath, fs.createWriteStream())xyzProject/${data[i].name}));
}
시작:
i = < {(let i = 0; i < dataLength; i++) {message
wait sftp.get(remotePath, fs.createWriteStream())xyzProject/${data[i].name}));
}
사용 중이라고 말씀하셨습니다.process.on('uncaughtException', callback);
이 진술서를 어디서 실행하고 있습니까?다음으로 전달된 콜백 내에 있습니까?http.createServer?
만약 그렇다면, 동일한 콜백의 다른 복사본이 각각의 새로운 요청에 따라 포착되지 않은 예외 이벤트에 첨부될 것입니다. 왜냐하면function (req, res) { ... }새되며 문 됩니다.process.on('uncaughtException', callback);
프로세스 개체는 모든 요청에 대해 전역적이며 새 요청이 들어올 때마다 수신기를 이벤트에 추가하는 것은 의미가 없습니다.당신은 그런 종류의 행동을 원하지 않을지도 모릅니다.
새 새 수신기는 더 다음을 사용할 필요가 없습니다.
process.removeAllListeners('uncaughtException');
이 문제에 대한 우리 팀의 해결책은 .npmrc에서 레지스트리 경로를 제거하는 것이었습니다.rc 파일에 두 개의 경로 별칭이 있었고, 하나는 더 이상 사용되지 않는 아티팩트리 인스턴스를 가리키고 있었습니다.
이 오류는 우리 앱의 실제 코드와는 아무런 관련이 없으며 개발 환경과 모든 관련이 있습니다.
추가하기EventEmitter.defaultMaxListeners = <MaxNumberOfClients>node_modules\loopback-datasource-juggler\lib\datasource.js수정된 문제일 수 있습니다 :)
server.js(또는 메인 Node.js 앱이 포함된 모든 것)의 첫 줄에 다음을 입력합니다.
require('events').EventEmitter.prototype._maxListeners = 0;
그러면 오류가 사라집니다 :)
언급URL : https://stackoverflow.com/questions/9768444/possible-eventemitter-memory-leak-detected
'codememo' 카테고리의 다른 글
| Mac OS에서 Node.js를 최신 버전으로 업그레이드합니다. (0) | 2023.05.28 |
|---|---|
| Swift: iOS 화면 크기 결정 (0) | 2023.05.28 |
| 가시성 간의 차이입니다.축소 및 가시성.히든 (0) | 2023.05.28 |
| 줄 끝 변환이 깃 코어에서 작동하는 방식입니다.서로 다른 운영 체제 간의 자동 제어 (0) | 2023.05.28 |
| 내용을 기준으로 문자열 목록 필터링 (0) | 2023.05.28 |