From 0df4859e52cfe918dfc63c4277e629af7ddb6edc Mon Sep 17 00:00:00 2001 From: zhangrui11 Date: Fri, 22 Apr 2022 17:21:06 +0800 Subject: [PATCH 1/9] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0balancerFilter?= =?UTF-8?q?=E4=BC=98=E5=85=88=E5=8C=B9=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/client/address_group.js | 23 ++++++++++++++++++- lib/client/loadbalancer/base.js | 16 +++++++++++++- lib/client/loadbalancer/weight_rr.js | 4 ++-- test/client/address_group.test.js | 33 ++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 4 deletions(-) diff --git a/lib/client/address_group.js b/lib/client/address_group.js index 6e9d56f..ea20917 100644 --- a/lib/client/address_group.js +++ b/lib/client/address_group.js @@ -340,11 +340,32 @@ class AddressGroup extends Base { return weight; } + async getFilterConnection(req) { + try { + return await this.getConnectionDefault(req, true); + } catch (error) { + // 兜底,connect异常,说明host不可用 + if (error.message === "Cannot read property 'host' of undefined" && error.name === 'TypeError') { + this.logger.info('[AddressGroup] getFilterConnection error, will retry getConnectionDefault', error); + return null; + } + throw error; + } + } + async getConnection(req) { + const hasFilter = typeof this.options.balancerFilter === 'function'; + // 增加一层filter判断,若正常则直接返回,否则走原 getConnection 逻辑 + const filterConnection = await hasFilter ? await this.getFilterConnection(req) : null; + if (filterConnection) return filterConnection; + return this.getConnectionDefault(req); + } + + async getConnectionDefault(req, needFilter) { const meta = req.meta; meta.connectionGroup = this.key; - const address = this._loadbalancer.select(req); + const address = this._loadbalancer.select(req, needFilter); if (!address) return null; const { connectionOpts, connectionClass } = this.options; diff --git a/lib/client/loadbalancer/base.js b/lib/client/loadbalancer/base.js index a99fea0..ef7c3be 100644 --- a/lib/client/loadbalancer/base.js +++ b/lib/client/loadbalancer/base.js @@ -23,7 +23,21 @@ class LoadBalancer extends Base { return this.addressGroup.logger; } - select(request) { + select(request, needFilter) { + // 需要时才需要过滤 + const hasFilter = needFilter && typeof this.addressGroup.options.balancerFilter === 'function'; + // 透出addressList,供外部进行一次优先筛选 + if (hasFilter) { + const list = this.addressGroup.options.balancerFilter( + this.addressList + ); + if (Array.isArray(list)) { + // 若优先筛选后无可用,重新尝试全部地址 + if (list.length === 0) return this._doSelect(request, this.addressList); + // list.length === 1 也进行一次 doSelect,有可能getWeight异常 + return this._doSelect(request, list); + } + } if (this.size === 0) return null; if (this.size === 1) return this.addressList[0]; diff --git a/lib/client/loadbalancer/weight_rr.js b/lib/client/loadbalancer/weight_rr.js index fe4f7a9..05fbd60 100644 --- a/lib/client/loadbalancer/weight_rr.js +++ b/lib/client/loadbalancer/weight_rr.js @@ -17,7 +17,7 @@ class WeightRoundRobinLoadBalancer extends LoadBalancer { _rr(request, addressList) { const address = addressList[this._offset]; - this._offset = (this._offset + 1) % this.size; + this._offset = (this._offset + 1) % addressList.length; const weight = this.getWeight(address); if (weight === DEFAULT_WEIGHT) return address; @@ -29,7 +29,7 @@ class WeightRoundRobinLoadBalancer extends LoadBalancer { _doSelect(request, addressList) { let address; - let count = this.size; + let count = addressList.length; while (count--) { address = this._rr(request, addressList); if (address) return address; diff --git a/test/client/address_group.test.js b/test/client/address_group.test.js index 003d36d..ffc0432 100644 --- a/test/client/address_group.test.js +++ b/test/client/address_group.test.js @@ -203,6 +203,39 @@ describe('test/client/address_group.test.js', () => { await utils.closeAll(); }); + it('balancerFilter 优先匹配', async function() { + await Promise.all([ + utils.startServer(13201), + utils.startServer(13202), + ]); + + const addressGroup = new AddressGroup({ + key: 'xxx', + logger, + connectionManager, + balancerFilter: addressList => { + return addressList.filter(v => { + return v.host === '127.0.0.1:13202'; + }); + }, + }); + addressGroup.addressList = [ + urlparse('bolt://127.0.0.1:13201', true), + urlparse('bolt://127.0.0.1:13202', true), + ]; + let count = 10; + while (count--) { + const connection = await addressGroup.getConnection(req); + assert(connection && connection.isConnected); + // 优先匹配 + assert(connection.url === 'bolt://127.0.0.1:13202'); + } + + addressGroup.close(); + await connectionManager.closeAllConnections(); + await utils.closeAll(); + }); + describe('对于连不上地址的处理', () => { const mod = 2; const count = 10; From e851387cf379e8e9c7679d311f76e19a6ad2a713 Mon Sep 17 00:00:00 2001 From: zhangrui11 Date: Fri, 22 Apr 2022 21:54:05 +0800 Subject: [PATCH 2/9] =?UTF-8?q?feat:=20=20=E4=BC=98=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=EF=BC=8C=E5=A2=9E=E5=8A=A0=E6=B5=8B=E8=AF=95=E7=94=A8?= =?UTF-8?q?=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/client/address_group.js | 8 +++--- lib/client/loadbalancer/weight_rr.js | 4 +-- test/client/address_group.test.js | 38 ++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/lib/client/address_group.js b/lib/client/address_group.js index ea20917..548971c 100644 --- a/lib/client/address_group.js +++ b/lib/client/address_group.js @@ -356,9 +356,11 @@ class AddressGroup extends Base { async getConnection(req) { const hasFilter = typeof this.options.balancerFilter === 'function'; // 增加一层filter判断,若正常则直接返回,否则走原 getConnection 逻辑 - const filterConnection = await hasFilter ? await this.getFilterConnection(req) : null; - if (filterConnection) return filterConnection; - return this.getConnectionDefault(req); + if (hasFilter) { + const filterConnection = await this.getFilterConnection(req); + if (filterConnection) return filterConnection; + } + return await this.getConnectionDefault(req); } async getConnectionDefault(req, needFilter) { diff --git a/lib/client/loadbalancer/weight_rr.js b/lib/client/loadbalancer/weight_rr.js index 05fbd60..fe4f7a9 100644 --- a/lib/client/loadbalancer/weight_rr.js +++ b/lib/client/loadbalancer/weight_rr.js @@ -17,7 +17,7 @@ class WeightRoundRobinLoadBalancer extends LoadBalancer { _rr(request, addressList) { const address = addressList[this._offset]; - this._offset = (this._offset + 1) % addressList.length; + this._offset = (this._offset + 1) % this.size; const weight = this.getWeight(address); if (weight === DEFAULT_WEIGHT) return address; @@ -29,7 +29,7 @@ class WeightRoundRobinLoadBalancer extends LoadBalancer { _doSelect(request, addressList) { let address; - let count = addressList.length; + let count = this.size; while (count--) { address = this._rr(request, addressList); if (address) return address; diff --git a/test/client/address_group.test.js b/test/client/address_group.test.js index ffc0432..d8b1f2d 100644 --- a/test/client/address_group.test.js +++ b/test/client/address_group.test.js @@ -230,7 +230,45 @@ describe('test/client/address_group.test.js', () => { // 优先匹配 assert(connection.url === 'bolt://127.0.0.1:13202'); } + addressGroup.addressList = [ + urlparse('bolt://127.0.0.1:13201', true), + ]; + count = 3; + while (count--) { + const connection = await addressGroup.getConnection(req); + assert(connection && connection.isConnected); + // 优先匹配 + assert(connection.url === 'bolt://127.0.0.1:13201'); + } + addressGroup.close(); + await connectionManager.closeAllConnections(); + await utils.closeAll(); + }); + + it('balancerFilter 优先匹配 异常', async function() { + await Promise.all([ + utils.startServer(13201), + utils.startServer(13202), + ]); + const addressGroup = new AddressGroup({ + key: 'xxx', + logger, + connectionManager, + balancerFilter: addressList => { + return addressList.map(() => [ 1 ]); + }, + }); + // 使用错误地址 + addressGroup.addressList = [ + urlparse('bolt://127.0.0.1:132011', true), + urlparse('bolt://127.0.0.1:132022', true), + ]; + try { + await addressGroup.getConnection(req); + } catch (error) { + assert(error.code === 'ERR_SOCKET_BAD_PORT'); + } addressGroup.close(); await connectionManager.closeAllConnections(); await utils.closeAll(); From 83045b7ffb049d21610351f33f92825484415513 Mon Sep 17 00:00:00 2001 From: zhangrui11 Date: Fri, 22 Apr 2022 22:04:13 +0800 Subject: [PATCH 3/9] =?UTF-8?q?style:=20=E5=A2=9E=E5=8A=A0=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/client/address_group.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/client/address_group.test.js b/test/client/address_group.test.js index d8b1f2d..3e77263 100644 --- a/test/client/address_group.test.js +++ b/test/client/address_group.test.js @@ -230,6 +230,7 @@ describe('test/client/address_group.test.js', () => { // 优先匹配 assert(connection.url === 'bolt://127.0.0.1:13202'); } + // 匹配到的数据不可用时,会调用其他地址 addressGroup.addressList = [ urlparse('bolt://127.0.0.1:13201', true), ]; From edef816c42a59ec57e18593500b76dcada88cb01 Mon Sep 17 00:00:00 2001 From: zhangrui11 Date: Sat, 23 Apr 2022 01:09:37 +0800 Subject: [PATCH 4/9] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96weight=5Frr?= =?UTF-8?q?=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/client/address_group.js | 22 +++++++--------------- lib/client/loadbalancer/base.js | 4 ++-- lib/client/loadbalancer/weight_rr.js | 25 +++++++++++++++++++++++++ test/client/address_group.test.js | 7 +++++-- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/lib/client/address_group.js b/lib/client/address_group.js index 548971c..f6e1ab9 100644 --- a/lib/client/address_group.js +++ b/lib/client/address_group.js @@ -340,25 +340,17 @@ class AddressGroup extends Base { return weight; } - async getFilterConnection(req) { - try { - return await this.getConnectionDefault(req, true); - } catch (error) { - // 兜底,connect异常,说明host不可用 - if (error.message === "Cannot read property 'host' of undefined" && error.name === 'TypeError') { - this.logger.info('[AddressGroup] getFilterConnection error, will retry getConnectionDefault', error); - return null; - } - throw error; - } - } - async getConnection(req) { const hasFilter = typeof this.options.balancerFilter === 'function'; // 增加一层filter判断,若正常则直接返回,否则走原 getConnection 逻辑 if (hasFilter) { - const filterConnection = await this.getFilterConnection(req); - if (filterConnection) return filterConnection; + try { + const filterConnection = await this.getConnectionDefault(req, true); + if (filterConnection) return filterConnection; + } catch (error) { + // filter 地址都失败后,多走一次原 getConnection 逻辑 + this.logger.info('[AddressGroup] filterConnection error', error); + } } return await this.getConnectionDefault(req); } diff --git a/lib/client/loadbalancer/base.js b/lib/client/loadbalancer/base.js index ef7c3be..3aa37aa 100644 --- a/lib/client/loadbalancer/base.js +++ b/lib/client/loadbalancer/base.js @@ -34,8 +34,8 @@ class LoadBalancer extends Base { if (Array.isArray(list)) { // 若优先筛选后无可用,重新尝试全部地址 if (list.length === 0) return this._doSelect(request, this.addressList); - // list.length === 1 也进行一次 doSelect,有可能getWeight异常 - return this._doSelect(request, list); + // weight_rr 使用了this.addressList,增加了一个使用传参的filter_rr_doSelect方法 + return this.filter_rr_doSelect(request, list); } } if (this.size === 0) return null; diff --git a/lib/client/loadbalancer/weight_rr.js b/lib/client/loadbalancer/weight_rr.js index fe4f7a9..55b4d89 100644 --- a/lib/client/loadbalancer/weight_rr.js +++ b/lib/client/loadbalancer/weight_rr.js @@ -37,6 +37,31 @@ class WeightRoundRobinLoadBalancer extends LoadBalancer { // 直接返回兜底 return addressList[this._offset]; } + + // 有balancerFilter时使用外部传入的addressList + filter_rr_doSelect(request, addressList) { + let address; + let count = addressList.length; + this.filter_offset = utility.random(addressList.length); + while (count--) { + address = this.filter_rr(request, addressList); + if (address) return address; + } + // 直接返回兜底 + return addressList[this.filter_offset]; + } + + filter_rr(request, addressList) { + const address = addressList[this.filter_offset]; + this._offset = (this.filter_offset + 1) % addressList.length; + + const weight = this.getWeight(address); + if (weight === DEFAULT_WEIGHT) return address; + if (weight === 0) return null; + + const randNum = utility.random(DEFAULT_WEIGHT); + return weight >= randNum ? address : null; + } } module.exports = WeightRoundRobinLoadBalancer; diff --git a/test/client/address_group.test.js b/test/client/address_group.test.js index 3e77263..2f56f29 100644 --- a/test/client/address_group.test.js +++ b/test/client/address_group.test.js @@ -207,6 +207,8 @@ describe('test/client/address_group.test.js', () => { await Promise.all([ utils.startServer(13201), utils.startServer(13202), + utils.startServer(13203), + utils.startServer(13204), ]); const addressGroup = new AddressGroup({ @@ -222,8 +224,10 @@ describe('test/client/address_group.test.js', () => { addressGroup.addressList = [ urlparse('bolt://127.0.0.1:13201', true), urlparse('bolt://127.0.0.1:13202', true), + urlparse('bolt://127.0.0.1:13203', true), + urlparse('bolt://127.0.0.1:13204', true), ]; - let count = 10; + let count = 3; while (count--) { const connection = await addressGroup.getConnection(req); assert(connection && connection.isConnected); @@ -238,7 +242,6 @@ describe('test/client/address_group.test.js', () => { while (count--) { const connection = await addressGroup.getConnection(req); assert(connection && connection.isConnected); - // 优先匹配 assert(connection.url === 'bolt://127.0.0.1:13201'); } addressGroup.close(); From c43f1be7b36ebc33c328ed78b62ffffb7b5614d8 Mon Sep 17 00:00:00 2001 From: zhangrui11 Date: Sat, 23 Apr 2022 02:03:29 +0800 Subject: [PATCH 5/9] =?UTF-8?q?feat:=20=E8=A7=A6=E5=8F=91cov?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/client/address_group.test.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/client/address_group.test.js b/test/client/address_group.test.js index 2f56f29..1c97bd8 100644 --- a/test/client/address_group.test.js +++ b/test/client/address_group.test.js @@ -244,6 +244,14 @@ describe('test/client/address_group.test.js', () => { assert(connection && connection.isConnected); assert(connection.url === 'bolt://127.0.0.1:13201'); } + addressGroup.addressList = [ + urlparse('bolt://127.0.0.1:13202', true), + ]; + addressGroup._weightMap.set('127.0.0.1:13202', 20); + addressGroup._maxIdleWindow = addressGroup._maxIdleWindow + Date.now(); + const connection = await addressGroup.getConnection(req); + assert(connection && connection.isConnected); + assert(connection.url === 'bolt://127.0.0.1:13202'); addressGroup.close(); await connectionManager.closeAllConnections(); await utils.closeAll(); From defdd7ff54e6899be46dee8d4becdce9122c762b Mon Sep 17 00:00:00 2001 From: zhangrui11 Date: Sat, 23 Apr 2022 16:05:24 +0800 Subject: [PATCH 6/9] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0weight=20rr?= =?UTF-8?q?=E7=9A=84filter=5FdoSelect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/client/loadbalancer/base.js | 3 ++- lib/client/loadbalancer/weight_rr.js | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/client/loadbalancer/base.js b/lib/client/loadbalancer/base.js index 3aa37aa..2f615fc 100644 --- a/lib/client/loadbalancer/base.js +++ b/lib/client/loadbalancer/base.js @@ -35,7 +35,8 @@ class LoadBalancer extends Base { // 若优先筛选后无可用,重新尝试全部地址 if (list.length === 0) return this._doSelect(request, this.addressList); // weight_rr 使用了this.addressList,增加了一个使用传参的filter_rr_doSelect方法 - return this.filter_rr_doSelect(request, list); + this.inBalancerFilterFilter = true; + return this._doSelect(request, list); } } if (this.size === 0) return null; diff --git a/lib/client/loadbalancer/weight_rr.js b/lib/client/loadbalancer/weight_rr.js index 55b4d89..ead90ce 100644 --- a/lib/client/loadbalancer/weight_rr.js +++ b/lib/client/loadbalancer/weight_rr.js @@ -28,6 +28,8 @@ class WeightRoundRobinLoadBalancer extends LoadBalancer { } _doSelect(request, addressList) { + // 存在balancerFilterFilter标识使用filter_doSelect + if (this.inBalancerFilterFilter) return this.filter_doSelect(request, addressList); let address; let count = this.size; while (count--) { @@ -39,7 +41,9 @@ class WeightRoundRobinLoadBalancer extends LoadBalancer { } // 有balancerFilter时使用外部传入的addressList - filter_rr_doSelect(request, addressList) { + filter_doSelect(request, addressList) { + // 关闭balancerFilterFilter标识 + this.inBalancerFilterFilter = false; let address; let count = addressList.length; this.filter_offset = utility.random(addressList.length); From 1c8d540681a607ecbd0aaee3d26873f91bdf1c2c Mon Sep 17 00:00:00 2001 From: zhangrui11 Date: Sat, 23 Apr 2022 16:40:53 +0800 Subject: [PATCH 7/9] =?UTF-8?q?feat:=20inBalancerFilterFilter=E6=A0=87?= =?UTF-8?q?=E8=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/client/loadbalancer/base.js | 1 + lib/client/loadbalancer/weight_rr.js | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/client/loadbalancer/base.js b/lib/client/loadbalancer/base.js index 2f615fc..bf1f21d 100644 --- a/lib/client/loadbalancer/base.js +++ b/lib/client/loadbalancer/base.js @@ -26,6 +26,7 @@ class LoadBalancer extends Base { select(request, needFilter) { // 需要时才需要过滤 const hasFilter = needFilter && typeof this.addressGroup.options.balancerFilter === 'function'; + this.inBalancerFilterFilter = false; // 透出addressList,供外部进行一次优先筛选 if (hasFilter) { const list = this.addressGroup.options.balancerFilter( diff --git a/lib/client/loadbalancer/weight_rr.js b/lib/client/loadbalancer/weight_rr.js index ead90ce..62004af 100644 --- a/lib/client/loadbalancer/weight_rr.js +++ b/lib/client/loadbalancer/weight_rr.js @@ -42,8 +42,6 @@ class WeightRoundRobinLoadBalancer extends LoadBalancer { // 有balancerFilter时使用外部传入的addressList filter_doSelect(request, addressList) { - // 关闭balancerFilterFilter标识 - this.inBalancerFilterFilter = false; let address; let count = addressList.length; this.filter_offset = utility.random(addressList.length); From 5bba4e0d8d3353f176263b1d4ff55c4fd64a0341 Mon Sep 17 00:00:00 2001 From: zhangrui11 Date: Sun, 24 Apr 2022 11:05:02 +0800 Subject: [PATCH 8/9] feat: inBalancerFilterFilter reset --- lib/client/loadbalancer/base.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/client/loadbalancer/base.js b/lib/client/loadbalancer/base.js index bf1f21d..1ceeac5 100644 --- a/lib/client/loadbalancer/base.js +++ b/lib/client/loadbalancer/base.js @@ -40,6 +40,7 @@ class LoadBalancer extends Base { return this._doSelect(request, list); } } + this.inBalancerFilterFilter = false; if (this.size === 0) return null; if (this.size === 1) return this.addressList[0]; From 55d857d9fbafe47caca1dbb9b67e6f54bfdab4dd Mon Sep 17 00:00:00 2001 From: zhangrui11 Date: Sun, 24 Apr 2022 17:15:05 +0800 Subject: [PATCH 9/9] =?UTF-8?q?feat:=20=E9=80=BB=E8=BE=91=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/client/loadbalancer/base.js | 11 +++++------ lib/client/loadbalancer/weight_rr.js | 6 +++--- test/client/address_group.test.js | 1 + 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/client/loadbalancer/base.js b/lib/client/loadbalancer/base.js index 1ceeac5..c8600a4 100644 --- a/lib/client/loadbalancer/base.js +++ b/lib/client/loadbalancer/base.js @@ -32,15 +32,14 @@ class LoadBalancer extends Base { const list = this.addressGroup.options.balancerFilter( this.addressList ); - if (Array.isArray(list)) { - // 若优先筛选后无可用,重新尝试全部地址 - if (list.length === 0) return this._doSelect(request, this.addressList); - // weight_rr 使用了this.addressList,增加了一个使用传参的filter_rr_doSelect方法 + if (Array.isArray(list) && list.length > 0) { this.inBalancerFilterFilter = true; - return this._doSelect(request, list); + const address = this._doSelect(request, list); + this.inBalancerFilterFilter = false; + // 没有数据使用this.addressList重试 + if (address) return address; } } - this.inBalancerFilterFilter = false; if (this.size === 0) return null; if (this.size === 1) return this.addressList[0]; diff --git a/lib/client/loadbalancer/weight_rr.js b/lib/client/loadbalancer/weight_rr.js index 62004af..5f6ecc2 100644 --- a/lib/client/loadbalancer/weight_rr.js +++ b/lib/client/loadbalancer/weight_rr.js @@ -40,7 +40,7 @@ class WeightRoundRobinLoadBalancer extends LoadBalancer { return addressList[this._offset]; } - // 有balancerFilter时使用外部传入的addressList + // 原逻辑this.size this.offset使用了this.addressList, 在这里新增一个使用内部addressList的方法 filter_doSelect(request, addressList) { let address; let count = addressList.length; @@ -49,8 +49,8 @@ class WeightRoundRobinLoadBalancer extends LoadBalancer { address = this.filter_rr(request, addressList); if (address) return address; } - // 直接返回兜底 - return addressList[this.filter_offset]; + // 全失败 + return null; } filter_rr(request, addressList) { diff --git a/test/client/address_group.test.js b/test/client/address_group.test.js index 1c97bd8..f05bb25 100644 --- a/test/client/address_group.test.js +++ b/test/client/address_group.test.js @@ -227,6 +227,7 @@ describe('test/client/address_group.test.js', () => { urlparse('bolt://127.0.0.1:13203', true), urlparse('bolt://127.0.0.1:13204', true), ]; + await addressGroup.ready(); let count = 3; while (count--) { const connection = await addressGroup.getConnection(req);