최대 청취자경고 초과: EventEmitter 메모리 누출 가능성이 감지되었습니다. 11개의 메시지 수신기가 추가되었습니다.이미터를 사용합니다.최대 청취자()를 설정하여 제한을 늘립니다.
중복 솔루션으로 플래그가 지정될 수 있다는 것을 알고 있지만 스택 오버플로에 대한 솔루션이 제게 적합하지 않습니다.
문제
(node:5716) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 message lis
teners added. Use emitter.setMaxListeners() to increase limit.
제 코드베이스가 커서 가끔 이런 오류가 발생하는 이유를 모르겠습니다.청취자 제한을 늘리려고 했는데 아쉽게도 안 되네요.
const EventEmitter = require('events');
const emitter = new EventEmitter()
emitter.setMaxListeners(50)
갱신하다
일부 검색 후 이 명령을 실행하여 경고 추적
node --trace-warnings index.babel.js
알고 보니 제 socket.io 코드가 Redis에서 socket.io 을 사용하고 있는 문제인 것 같습니다.이것은 오류입니다.
node:14212) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 message li
steners added. Use emitter.setMaxListeners() to increase limit
at _addListener (events.js:281:19)
at RedisClient.addListener (events.js:298:10)
at Namespace.<anonymous> (D:/newProject/services/socket.js:21:17)
at emitOne (events.js:115:13)
at Namespace.emit (events.js:210:7)
at Namespace.emit (D:\newProject\node_modules\socket.io\lib\namespace.js:213:10)
at D:\newProject\node_modules\socket.io\lib\namespace.js:181:14
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)
이 코드는 코드입니다(그러나 이 코드는 더 구체적인 작업을 위해 항상 실행되는 것은 아닙니다).
const redis = require('redis');
const config = require('../config');
const sub = redis.createClient(config.REDIS.port, config.REDIS.host);
const pub = redis.createClient(config.REDIS.port, config.REDIS.host);
sub.subscribe('spread');
module.exports = io => {
io.on('connection', socket => {
/* To find the User Login */
let passport = socket.handshake.session.passport;
if (typeof passport !== 'undefined') {
socket.on('typing:send', data => {
pub.publish('spread', JSON.stringify(data));
});
sub.on('message', (ch, msg) => {
// This is the Exact line where I am getting this error
io.emit(`${JSON.parse(msg).commonID}:receive`, { ...JSON.parse(msg) });
});
}
});
};
의 내장 모듈(또는 로 컴파일한 경우 프론트엔드 앱에 번들된 버전)은 코드에 대한 몇 가지 가정을 합니다.언젠가, 어딘가에서, 누군가가 당신이 만약X
청취자 수가 등록된 경우, 확실히 메모리 누수가 발생했습니다.그리고 때로는 옳을 때도 있고, 누수된 부분을 찾으러 가라는 것을 정확하게 알려줍니다.
이 경고는 여러 번 받았지만, 일반적으로 두 가지 특정한 이유 때문에 받은 것이며, 두 가지 모두 간단한 해결책이 있습니다.
문제 1: 바운드 이벤트 수신기 함수가 일치하지 않음
구성 요소는 이벤트 수신기로 구성 요소 메서드를 사용하고 있으며 등록할 때 구성 요소를 바인딩하고 있습니다.
import events from '../lib/events' // some singleton event emitter
class MyComponent extends React.Component {
componentDidMount() {
events.addEventListener('some-event', this.myMethod.bind(this))
}
componentWillUnmount() {
events.removeEventListener('some-event', this.myMethod.bind(this))
}
myMethod() {
// does something
}
render() {
// gotta have this too
}
}
여기서 문제는 제거하려는 기능이 추가한 기능과 동일하지 않도록 매번 새로운 기능을 생성한다는 것입니다.결과적으로 추가된 기능은 계속 추가되고(나쁜 말장난), 실제로 메모리가 제대로 유출됩니다.
해결책 1: 방법을 조기에 바인딩
에 바인딩합니다. 일반적으로constructor()
한지 확인할 수 그러면 매번 바운드 버전을 참조하여 제거된 기능이 추가된 기능과 동일한지 확인할 수 있습니다.
import events from '../lib/events' // some singleton event emitter
class MyComponent extends React.Component {
constructor() {
// bind your method early so the function removed
// is the same as the function added
this.myMethod = this.myMethod.bind(this)
}
componentDidMount() {
events.addEventListener('some-event', this.myMethod)
}
componentWillUnmount() {
events.removeEventListener('some-event', this.myMethod)
}
myMethod() {
// does something
}
render() {
// gotta have this too
}
}
문제 2: 이벤트 청취자가 많고 많습니다.
때때로 여러분은 정말로 숙제를 다 하고 청취자를 필요에 따라 일찍 묶은 것을 다시 확인한 다음 적절한 장소에서 모두 제거했습니다.그런 다음 자세히 들여다보면 다음과 같은 일을 하고 있음을 알 수 있습니다.
import MyComponent from './MyComponent' // same component above
class Parent extends React.Component {
render() {
return (
<div>
{ this.props.largeArray.map(MyComponent) }
</div>
)
}
}
를 들어,this.props.largeArray
50개, 100개, 또는 250개의 원소를 가지고 있었습니다.는) 250합니다 를 (입니다.MyComponent
은 또 고유 를 .
겁내지 마!이것은 완전히 유효한 코드이며, 메모리 누수가 없습니다.하지만 그건 최대 청취자 제한을 뚫고서 누군가가, 언젠가, 당신을 보호하기 위해 임의적으로 결정한 것입니다.
솔루션 2: 사용으로 전환
만약 여러분이 숙제를 다 했다고 결정하고, 모든 것들을 다시 확인했고, 많은 이벤트 청취자들을 (설계상으로!) 등록하고 있다면, 가장 간단한 해결책은 노드의 드롭인 대체물인 을 사용하는 것으로 전환하는 것입니다.events
모듈, 더 빠르고 브라우저 compat이 가능하며 최대 listeners 제한을 설정하지 않습니다.
된 와 .events
모듈:
const EventEmitter = require('eventemitter3')
const emitter = new EventEmitter()
Event Emitter의 기본 제한은 10입니다.이미터로 늘릴 수 있습니다.최대 청취자를 설정합니다.제 제안은 독자 분이 구독을 취소하지 않았기 때문에 청취자가 증가하지 않는 한 그리고 명시적으로 요구될 때까지 그것을 변경하지 않는 것입니다.이제 코드대로 하겠습니다.
const redis = require('redis');
const config = require('../config');
const sub = redis.createClient(config.REDIS.port, config.REDIS.host);
const pub = redis.createClient(config.REDIS.port, config.REDIS.host);
sub.subscribe('spread');
module.exports = (io) => {
io.on('connection', (socket) => {
// this callback will be executed for all the socket connections.
let passport =
socket.handshake.session.passport; /* To find the User Login */
if (typeof passport !== 'undefined') {
socket.on('typing:send', (data) => {
pub.publish('spread', JSON.stringify(data));
});
// this is where you are subscribing for each and every socket connected to your server
sub.on('message', (ch, msg) => {
// this is the Exact line where I am getting this error
// whereas you are emitting messages on socket manager, not on the socket.
io.emit(`${JSON.parse(msg).commonID}:receive`, { ...JSON.parse(msg) });
});
}
});
};
위의 코드를 분석하면 서버에 대한 20개의 소켓 연결을 열면 20개가 가입됩니다. 여기서 잘못된 것입니다.만약 당신의 요구사항이 서버 레벨에서 Redis에 게시된 메시지를 듣고 io에 전송하는 것이라면 당신의 코드는 아래와 같습니다.
const redis = require('redis');
const config = require('../config');
const sub = redis.createClient(config.REDIS.port, config.REDIS.host);
const pub = redis.createClient(config.REDIS.port, config.REDIS.host);
sub.subscribe('spread');
module.exports = (io) => {
sub.on('message', (ch, msg) => {
// this is the Exact line where I am getting this error
io.emit(`${JSON.parse(msg).commonID}:receive`, { ...JSON.parse(msg) });
});
io.on('connection', (socket) => {
let passport =
socket.handshake.session.passport; /* To find the User Login */
if (typeof passport !== 'undefined') {
socket.on('typing:send', (data) => {
pub.publish('spread', JSON.stringify(data));
});
}
});
};
최대 청취자경고 초과: EventEmitter 메모리 누출 가능성이 감지되었습니다. 11개의 메시지 수신기가 추가되었습니다.이미터를 사용합니다.최대 청취자()를 설정하여 제한을 늘립니다.
기본적으로 단일 이벤트에 최대 10명까지 청취자를 등록할 수 있으며, 11명을 받았습니다.
// Change to 80 or 150 whatever and see what happens
require('events').EventEmitter.prototype._maxListeners = 70;
require('events').defaultMaxListeners = 70;
process.on('warning', function (err) {
if ( 'MaxListenersExceededWarning' == err.name ) {
console.log('o kurwa');
// write to log function
process.exit(1); // its up to you what then in my case script was hang
}
});
이 방법은 LifeCycle 방법을 사용하여 React Components 내의 이벤트 수신기를 추가하고 제거하는 권장 방법입니다.
import { Component } from 'react';
class Example extends Component {
constructor(props) {
super(props);
this.state = {
windowWidth: window.innderWidth,
};
}
componentDidMount() {
window.addEventListener('resize', this.handleResize);
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize);
}
handleResize = () => {
this.setState({ windowWidth: window.innerWidth });
}
render() {
return (
<div>
Current window width: {this.state.windowWidth}
</div>
);
}
}
window
는 글로벌 실행 컨텍스트 내에 있습니다.
- 귀를 쫑긋 세우게 하다
- 이 합니다()).
resize
- 수신자를 추적하지 말라는 지시가 있을 때까지 계속합니다.
수신기를 제거하도록 전역 범위에 지시하지 않으면 브라우저 설정에 의해 할당된 전역 메모리가 서서히 증발하여 브라우저 및 응용 프로그램이나 이미 운영 중인 경우 클라이언트의 브라우저가 손상됩니다.그들이 글로벌 메모리를 조작할 때는 매우 조심해야 하고 매우 의식해야 합니다.
React Component의 작업에서 라이프사이클 방법을 사용하는 이유를 이해하고 싶다면 여기에서 React의 Reconiation 라이프사이클을 살펴보시기를 강력히 권장합니다.스스로를 '반응 개발자'라고 정확히 부를 수도 없고 '화해'에 대해 잘 알지도 못합니다.
참고 이 구성요소는 바벨을 사용하여 코드의 일부를 변환합니다.import
, 할당된 사용자 지정 방법handleResize
화살표 기능만 사용합니다.환경 설정에 도움이 필요한 경우, 제가 작성한 블로그 게시물을 참조하여 이해할 수 있습니다.
행운을 빌어요.
언급URL : https://stackoverflow.com/questions/50709059/maxlistenersexceededwarning-possible-eventemitter-memory-leak-detected-11-mess
'sourcecode' 카테고리의 다른 글
워드프레스 SQL은 X 제품에 대한 사용자의 이름과 성을 쿼리합니까? (0) | 2023.09.26 |
---|---|
각2 사용자 정의 양식 입력 (0) | 2023.09.26 |
OSX Swift 기본 브라우저에서 URL 열기 (0) | 2023.09.26 |
피카소 v/s 이미지로더 v/s 프레스코 vs 글라이드 vs 코일 (0) | 2023.09.21 |
Importing CSV data using PHP/MySQL (0) | 2023.09.21 |