omnip620 / node-zookeeper-dubbo

A middleware helps node to communicate dubbo by using its default protocol, which is registered in zookeeper
300 stars 80 forks source link

socket长连接的负载均衡管理代码有问题 #100

Closed wunqiaoseven closed 5 years ago

wunqiaoseven commented 5 years ago

retrieveServices(event) { for (const [key, val] of Object.entries(this.dependencies)) { const path = /${this.root}/${val.interface}/providers; if (!event || path === event.path) this.client.getChildren(path, this.watchService.bind(this), this.resolveService(path, key, val)); } }

watchService(event) { appDebug([file_name, 'watchService', event]); this.retrieveServices(event); }

当zookeeper新增服务,或者服务退出时收到childChange事件,此时重新调用determineService,目前的代码会直接忽略之前的socket连接,重新再建立tcp。这里会导致内存泄露。建议determineService修改一下,下面是我修改后的代码。 每当serverChange的时候,先检查之前的socket连接是否有效,过滤掉已连接的server。只对新增的那台Ip创建新连接

determineService(depKey, depVal, providers) { if (providers.length > serverMaxTcp) providers = providers.splice(0, serverMaxTcp); if (!this[depKey]) { //初始化 appDebug([file_name, 'determineService', 初始化${depKey}服务Ip集:${JSON.stringify(providers.map(i => i.host))}]); this[depKey] = new Service(depVal, providers, this.dver); } else { const socketIps = this[depKey].dispatcher.getSocketIp(); // console.log(providers.map(i => i.host)); // console.log(this[depKey].dispatcher.getSocketIp()); providers.forEach(i => { if (socketIps.indexOf(i.host) === -1) { appDebug([file_name, 'determineService', ${depKey}服务 新增服务器${i.host}]); this[depKey].initSockets(i.host.split(':')[0], i.host.split(':')[1]); } }); } }

omnip620 commented 5 years ago

大哥 代码格式化一下 😃

wunqiaoseven commented 5 years ago

determineService(depKey, depVal, providers) { this[depKey] = new Service(depVal, providers, this.dver); } 目前3.0的版本每次服务端在zk上新注册一台服务,触发client的server childNode change事件。然后你这边就会重新初始化server下的socket。但是这行代码并没有维护之前建立的socket,就会导致内存溢出,出现noavaliable并且最终崩溃。是否应该在这个地方判断,只建立新增服务的tcp之前已存在的不处理。