From 1dbe4629aa296140118a4cbec328b111db6c981f Mon Sep 17 00:00:00 2001 From: Andy Pan Date: Tue, 21 Nov 2023 18:16:18 +0800 Subject: [PATCH 1/9] chore: add new benchmark tests (#309) --- ants_benchmark_test.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/ants_benchmark_test.go b/ants_benchmark_test.go index 83cd920..f39b0e6 100644 --- a/ants_benchmark_test.go +++ b/ants_benchmark_test.go @@ -200,3 +200,27 @@ func BenchmarkAntsMultiPoolThroughput(b *testing.B) { } } } + +func BenchmarkParallelAntsPoolThroughput(b *testing.B) { + p, _ := NewPool(PoolCap, WithExpiryDuration(DefaultExpiredTime)) + defer p.Release() + + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + _ = p.Submit(demoFunc) + } + }) +} + +func BenchmarkParallelAntsMultiPoolThroughput(b *testing.B) { + p, _ := NewMultiPool(10, PoolCap/10, RoundRobin, WithExpiryDuration(DefaultExpiredTime)) + defer p.ReleaseTimeout(DefaultExpiredTime) //nolint:errcheck + + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + _ = p.Submit(demoFunc) + } + }) +} From 8b0eb06e608c2903fcc8c5b714234333ab452890 Mon Sep 17 00:00:00 2001 From: POABOB Date: Mon, 27 Nov 2023 10:56:56 +0800 Subject: [PATCH 2/9] doc: add MultiPool & MultiPoolFunc example code and update READMEs. (#311) --- README.md | 33 +++++++++++++++++++++++++++++++++ README_ZH.md | 33 +++++++++++++++++++++++++++++++++ examples/main.go | 32 +++++++++++++++++++++++++++++++- 3 files changed, 97 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bacefbd..855359c 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,39 @@ func main() { wg.Wait() fmt.Printf("running goroutines: %d\n", p.Running()) fmt.Printf("finish all tasks, result is %d\n", sum) + if sum != 499500 { + panic("the final result is wrong!!!") + } + + // Use the MultiPool and set the capacity of the 10 goroutine pools to unlimited. + // If you use -1 as the pool size parameter, the size will be unlimited. + // There are two load-balancing algorithms for pools: ants.RoundRobin and ants.LeastTasks. + mp, _ := ants.NewMultiPool(10, -1, ants.RoundRobin) + defer mp.ReleaseTimeout(5 * time.Second) + for i := 0; i < runTimes; i++ { + wg.Add(1) + _ = mp.Submit(syncCalculateSum) + } + wg.Wait() + fmt.Printf("running goroutines: %d\n", mp.Running()) + fmt.Printf("finish all tasks.\n") + + // Use the MultiPoolFunc and set the capacity of 10 goroutine pools to (runTimes/10). + mpf, _ := ants.NewMultiPoolWithFunc(10, runTimes/10, func(i interface{}) { + myFunc(i) + wg.Done() + }, ants.LeastTasks) + defer mpf.ReleaseTimeout(5 * time.Second) + for i := 0; i < runTimes; i++ { + wg.Add(1) + _ = mpf.Invoke(int32(i)) + } + wg.Wait() + fmt.Printf("running goroutines: %d\n", mpf.Running()) + fmt.Printf("finish all tasks, result is %d\n", sum) + if sum != 499500*2 { + panic("the final result is wrong!!!") + } } ``` diff --git a/README_ZH.md b/README_ZH.md index d3bb007..faa2095 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -122,6 +122,39 @@ func main() { wg.Wait() fmt.Printf("running goroutines: %d\n", p.Running()) fmt.Printf("finish all tasks, result is %d\n", sum) + if sum != 499500 { + panic("the final result is wrong!!!") + } + + // Use the MultiPool and set the capacity of the 10 goroutine pools to unlimited. + // If you use -1 as the pool size parameter, the size will be unlimited. + // There are two load-balancing algorithms for pools: ants.RoundRobin and ants.LeastTasks. + mp, _ := ants.NewMultiPool(10, -1, ants.RoundRobin) + defer mp.ReleaseTimeout(5 * time.Second) + for i := 0; i < runTimes; i++ { + wg.Add(1) + _ = mp.Submit(syncCalculateSum) + } + wg.Wait() + fmt.Printf("running goroutines: %d\n", mp.Running()) + fmt.Printf("finish all tasks.\n") + + // Use the MultiPoolFunc and set the capacity of 10 goroutine pools to (runTimes/10). + mpf, _ := ants.NewMultiPoolWithFunc(10, runTimes/10, func(i interface{}) { + myFunc(i) + wg.Done() + }, ants.LeastTasks) + defer mpf.ReleaseTimeout(5 * time.Second) + for i := 0; i < runTimes; i++ { + wg.Add(1) + _ = mpf.Invoke(int32(i)) + } + wg.Wait() + fmt.Printf("running goroutines: %d\n", mpf.Running()) + fmt.Printf("finish all tasks, result is %d\n", sum) + if sum != 499500*2 { + panic("the final result is wrong!!!") + } } ``` diff --git a/examples/main.go b/examples/main.go index 3e1d9e5..b967098 100644 --- a/examples/main.go +++ b/examples/main.go @@ -63,7 +63,7 @@ func main() { fmt.Printf("running goroutines: %d\n", ants.Running()) fmt.Printf("finish all tasks.\n") - // Use the pool with a method, + // Use the pool with a function, // set 10 to the capacity of goroutine pool and 1 second for expired duration. p, _ := ants.NewPoolWithFunc(10, func(i interface{}) { myFunc(i) @@ -81,4 +81,34 @@ func main() { if sum != 499500 { panic("the final result is wrong!!!") } + + // Use the MultiPool and set the capacity of the 10 goroutine pools to unlimited. + // If you use -1 as the pool size parameter, the size will be unlimited. + // There are two load-balancing algorithms for pools: ants.RoundRobin and ants.LeastTasks. + mp, _ := ants.NewMultiPool(10, -1, ants.RoundRobin) + defer mp.ReleaseTimeout(5 * time.Second) + for i := 0; i < runTimes; i++ { + wg.Add(1) + _ = mp.Submit(syncCalculateSum) + } + wg.Wait() + fmt.Printf("running goroutines: %d\n", mp.Running()) + fmt.Printf("finish all tasks.\n") + + // Use the MultiPoolFunc and set the capacity of 10 goroutine pools to (runTimes/10). + mpf, _ := ants.NewMultiPoolWithFunc(10, runTimes/10, func(i interface{}) { + myFunc(i) + wg.Done() + }, ants.LeastTasks) + defer mpf.ReleaseTimeout(5 * time.Second) + for i := 0; i < runTimes; i++ { + wg.Add(1) + _ = mpf.Invoke(int32(i)) + } + wg.Wait() + fmt.Printf("running goroutines: %d\n", mpf.Running()) + fmt.Printf("finish all tasks, result is %d\n", sum) + if sum != 499500*2 { + panic("the final result is wrong!!!") + } } From 306f027948e75ce33eb4faee73f67e024095d6be Mon Sep 17 00:00:00 2001 From: Andy Pan Date: Wed, 13 Dec 2023 13:25:15 +0800 Subject: [PATCH 3/9] chore: fix some broken image links --- README.md | 2 +- README_ZH.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 855359c..0b94c77 100644 --- a/README.md +++ b/README.md @@ -360,7 +360,7 @@ The source code in `ants` is available under the [MIT License](/LICENSE). The following companies/organizations use `ants` in production. -                         +                         ### open-source software diff --git a/README_ZH.md b/README_ZH.md index faa2095..03cbc3e 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -361,7 +361,7 @@ pool.Reboot() 以下公司/组织在生产环境上使用了 `ants`。 -                         +                         ### 开源软件 From 74f5b2d3300a11d3f49abcd2582077d51c3b419f Mon Sep 17 00:00:00 2001 From: Andy Pan Date: Fri, 26 Jan 2024 22:52:50 +0800 Subject: [PATCH 4/9] chore: add more use cases --- README.md | 3 ++- README_ZH.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0b94c77..b89aad1 100644 --- a/README.md +++ b/README.md @@ -360,7 +360,7 @@ The source code in `ants` is available under the [MIT License](/LICENSE). The following companies/organizations use `ants` in production. -                         +                           ### open-source software @@ -384,6 +384,7 @@ The open-source projects below do concurrent programming with the help of `ants` - [AdGuardDNS](https://github.com/AdguardTeam/AdGuardDNS): AdGuard DNS is an alternative solution for tracker blocking, privacy protection, and parental control. - [WatchAD2.0](https://github.com/Qihoo360/WatchAD2.0): WatchAD2.0 是 360 信息安全中心开发的一款针对域安全的日志分析与监控系统,它可以收集所有域控上的事件日志、网络流量,通过特征匹配、协议分析、历史行为、敏感操作和蜜罐账户等方式来检测各种已知与未知威胁,功能覆盖了大部分目前的常见内网域渗透手法。 - [vanus](https://github.com/vanus-labs/vanus): Vanus is a Serverless, event streaming system with processing capabilities. It easily connects SaaS, Cloud Services, and Databases to help users build next-gen Event-driven Applications. +- [trpc-go](https://github.com/trpc-group/trpc-go): A pluggable, high-performance RPC framework written in Golang. #### All use cases: diff --git a/README_ZH.md b/README_ZH.md index 03cbc3e..65e7a49 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -361,7 +361,7 @@ pool.Reboot() 以下公司/组织在生产环境上使用了 `ants`。 -                         +                           ### 开源软件 @@ -385,6 +385,7 @@ pool.Reboot() - [AdGuardDNS](https://github.com/AdguardTeam/AdGuardDNS): AdGuard DNS is an alternative solution for tracker blocking, privacy protection, and parental control. - [WatchAD2.0](https://github.com/Qihoo360/WatchAD2.0): WatchAD2.0 是 360 信息安全中心开发的一款针对域安全的日志分析与监控系统,它可以收集所有域控上的事件日志、网络流量,通过特征匹配、协议分析、历史行为、敏感操作和蜜罐账户等方式来检测各种已知与未知威胁,功能覆盖了大部分目前的常见内网域渗透手法。 - [vanus](https://github.com/vanus-labs/vanus): Vanus is a Serverless, event streaming system with processing capabilities. It easily connects SaaS, Cloud Services, and Databases to help users build next-gen Event-driven Applications. +- [trpc-go](https://github.com/trpc-group/trpc-go): 一个 Go 实现的可插拔的高性能 RPC 框架。 #### 所有案例: From 5c07bca122f2ac7e9e7bd52c4c653112eeeff38a Mon Sep 17 00:00:00 2001 From: Andy Pan Date: Mon, 5 Feb 2024 18:59:34 +0800 Subject: [PATCH 5/9] chore: bump up some GitHub actions --- .github/workflows/codeql.yml | 8 ++++---- .github/workflows/test.yml | 17 +++++++++-------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 56a7542..c1df467 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -42,20 +42,20 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 2 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: go # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). # If this step fails, then you should remove it and run the build manually (see below). - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -69,4 +69,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 \ No newline at end of file + uses: github/codeql-action/analyze@v3 \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 33ff07a..d304abe 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,17 +37,17 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Setup Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v5 with: go-version: '^1.16' - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup and run golangci-lint uses: golangci/golangci-lint-action@v3 with: - version: v1.51.2 + version: v1.55.2 args: --timeout 5m -v -E gofumpt -E gocritic -E misspell -E revive -E godot test: needs: lint @@ -60,12 +60,12 @@ jobs: runs-on: ${{ matrix.os}} steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.ref }} - name: Setup Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v5 with: go-version: ${{ matrix.go }} @@ -83,7 +83,7 @@ jobs: echo "GO_CACHE=$(go env GOCACHE)" >> $GITHUB_OUTPUT - name: Cache go modules - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ${{ steps.go-env.outputs.GO_CACHE }} @@ -96,11 +96,12 @@ jobs: run: go test -v -race -coverprofile="codecov.report" -covermode=atomic - name: Upload code coverage report to Codecov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: file: ./codecov.report flags: unittests name: codecov-ants fail_ci_if_error: true verbose: true - + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} From 1eb46544fba520d1ddd942ecb6887c32fb528955 Mon Sep 17 00:00:00 2001 From: Andy Pan Date: Tue, 27 Feb 2024 16:12:57 +0800 Subject: [PATCH 6/9] chore: update READMEs --- README.md | 3 ++- README_ZH.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b89aad1..5ed627d 100644 --- a/README.md +++ b/README.md @@ -360,7 +360,7 @@ The source code in `ants` is available under the [MIT License](/LICENSE). The following companies/organizations use `ants` in production. -                           +                         ### open-source software @@ -385,6 +385,7 @@ The open-source projects below do concurrent programming with the help of `ants` - [WatchAD2.0](https://github.com/Qihoo360/WatchAD2.0): WatchAD2.0 是 360 信息安全中心开发的一款针对域安全的日志分析与监控系统,它可以收集所有域控上的事件日志、网络流量,通过特征匹配、协议分析、历史行为、敏感操作和蜜罐账户等方式来检测各种已知与未知威胁,功能覆盖了大部分目前的常见内网域渗透手法。 - [vanus](https://github.com/vanus-labs/vanus): Vanus is a Serverless, event streaming system with processing capabilities. It easily connects SaaS, Cloud Services, and Databases to help users build next-gen Event-driven Applications. - [trpc-go](https://github.com/trpc-group/trpc-go): A pluggable, high-performance RPC framework written in Golang. +- [motan-go](https://github.com/weibocom/motan-go): a remote procedure call (RPC) framework for the rapid development of high-performance distributed services. #### All use cases: diff --git a/README_ZH.md b/README_ZH.md index 65e7a49..4b86013 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -361,7 +361,7 @@ pool.Reboot() 以下公司/组织在生产环境上使用了 `ants`。 -                           +                         ### 开源软件 @@ -386,6 +386,7 @@ pool.Reboot() - [WatchAD2.0](https://github.com/Qihoo360/WatchAD2.0): WatchAD2.0 是 360 信息安全中心开发的一款针对域安全的日志分析与监控系统,它可以收集所有域控上的事件日志、网络流量,通过特征匹配、协议分析、历史行为、敏感操作和蜜罐账户等方式来检测各种已知与未知威胁,功能覆盖了大部分目前的常见内网域渗透手法。 - [vanus](https://github.com/vanus-labs/vanus): Vanus is a Serverless, event streaming system with processing capabilities. It easily connects SaaS, Cloud Services, and Databases to help users build next-gen Event-driven Applications. - [trpc-go](https://github.com/trpc-group/trpc-go): 一个 Go 实现的可插拔的高性能 RPC 框架。 +- [motan-go](https://github.com/weibocom/motan-go): 一套高性能、易于使用的分布式远程服务调用(RPC)框架。motan-go 是 motan 的 Go 语言实现。 #### 所有案例: From 0454cab594d58c42b7432bb5ba2421262632462a Mon Sep 17 00:00:00 2001 From: Andy Pan Date: Sun, 10 Mar 2024 14:41:31 +0800 Subject: [PATCH 7/9] chore: switch from Gitter to Discord --- .github/ISSUE_TEMPLATE/bug-report.yaml | 2 +- .github/ISSUE_TEMPLATE/feature-request.yaml | 2 +- .github/ISSUE_TEMPLATE/question.yaml | 2 +- README.md | 1 - README_ZH.md | 1 - 5 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug-report.yaml b/.github/ISSUE_TEMPLATE/bug-report.yaml index 89b75ae..2a4a59c 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yaml +++ b/.github/ISSUE_TEMPLATE/bug-report.yaml @@ -11,7 +11,7 @@ body: value: | ## Before you go any further - Please read [*How To Ask Questions The Smart Way*](http://www.catb.org/~esr/faqs/smart-questions.html) ( Chinese translation: [《提问的智慧》](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md)) before you file an issue formally. - - Keep in mind that there is always welcome to ask questions on [Gitter](https://gitter.im/ants-pool/ants). + - Keep in mind that there is always welcome to ask questions on [Discord](https://discord.gg/Cuy7KPaWQc). - type: checkboxes id: checklist attributes: diff --git a/.github/ISSUE_TEMPLATE/feature-request.yaml b/.github/ISSUE_TEMPLATE/feature-request.yaml index eadc2d5..0d92e4d 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.yaml +++ b/.github/ISSUE_TEMPLATE/feature-request.yaml @@ -11,7 +11,7 @@ body: value: | ## Before you go any further - Please read [*How To Ask Questions The Smart Way*](http://www.catb.org/~esr/faqs/smart-questions.html) ( Chinese translation: [《提问的智慧》](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md)) before you file an issue formally. - - Keep in mind that there is always welcome to ask questions on [Gitter](https://gitter.im/ants-pool/ants). + - Keep in mind that there is always welcome to ask questions on [Discord](https://discord.gg/Cuy7KPaWQc). - type: textarea id: feature-request attributes: diff --git a/.github/ISSUE_TEMPLATE/question.yaml b/.github/ISSUE_TEMPLATE/question.yaml index ed605e3..df18ea7 100644 --- a/.github/ISSUE_TEMPLATE/question.yaml +++ b/.github/ISSUE_TEMPLATE/question.yaml @@ -9,7 +9,7 @@ body: value: | ## Before you go any further - Please read [*How To Ask Questions The Smart Way*](http://www.catb.org/~esr/faqs/smart-questions.html) ( Chinese translation: [《提问的智慧》](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md)) before you file an issue formally. - - Keep in mind that there is always welcome to ask questions on [Gitter](https://gitter.im/ants-pool/ants). + - Keep in mind that there is always welcome to ask questions on [Discord](https://discord.gg/Cuy7KPaWQc). - type: textarea id: question attributes: diff --git a/README.md b/README.md index 5ed627d..cf54eea 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@
- diff --git a/README_ZH.md b/README_ZH.md index 4b86013..a888295 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -7,7 +7,6 @@
- From 10d9975f1099e104c261078d59181477ae4c9c03 Mon Sep 17 00:00:00 2001 From: Andy Pan Date: Sun, 17 Mar 2024 13:51:25 +0800 Subject: [PATCH 8/9] chore: update READMEs --- README.md | 2 +- README_ZH.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cf54eea..b06a61e 100644 --- a/README.md +++ b/README.md @@ -359,7 +359,7 @@ The source code in `ants` is available under the [MIT License](/LICENSE). The following companies/organizations use `ants` in production. -                         +                           ### open-source software diff --git a/README_ZH.md b/README_ZH.md index a888295..cefcd87 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -360,7 +360,7 @@ pool.Reboot() 以下公司/组织在生产环境上使用了 `ants`。 -                         +                           ### 开源软件 From ce28ca17d1bfa3f43d05a27d6064c4f2118071de Mon Sep 17 00:00:00 2001 From: Akshay Nanavare <43538145+akshaynanavare@users.noreply.github.com> Date: Tue, 26 Mar 2024 17:05:40 +0530 Subject: [PATCH 9/9] bug: return error before creating multi pools if lbs is invalid to avoid leaks (#317) --- multipool.go | 6 +++--- multipool_func.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/multipool.go b/multipool.go index 1e8b27b..1de75ae 100644 --- a/multipool.go +++ b/multipool.go @@ -56,6 +56,9 @@ type MultiPool struct { // NewMultiPool instantiates a MultiPool with a size of the pool list and a size // per pool, and the load-balancing strategy. func NewMultiPool(size, sizePerPool int, lbs LoadBalancingStrategy, options ...Option) (*MultiPool, error) { + if lbs != RoundRobin && lbs != LeastTasks { + return nil, ErrInvalidLoadBalancingStrategy + } pools := make([]*Pool, size) for i := 0; i < size; i++ { pool, err := NewPool(sizePerPool, options...) @@ -64,9 +67,6 @@ func NewMultiPool(size, sizePerPool int, lbs LoadBalancingStrategy, options ...O } pools[i] = pool } - if lbs != RoundRobin && lbs != LeastTasks { - return nil, ErrInvalidLoadBalancingStrategy - } return &MultiPool{pools: pools, lbs: lbs}, nil } diff --git a/multipool_func.go b/multipool_func.go index 8101d31..c7d31ff 100644 --- a/multipool_func.go +++ b/multipool_func.go @@ -45,6 +45,9 @@ type MultiPoolWithFunc struct { // NewMultiPoolWithFunc instantiates a MultiPoolWithFunc with a size of the pool list and a size // per pool, and the load-balancing strategy. func NewMultiPoolWithFunc(size, sizePerPool int, fn func(interface{}), lbs LoadBalancingStrategy, options ...Option) (*MultiPoolWithFunc, error) { + if lbs != RoundRobin && lbs != LeastTasks { + return nil, ErrInvalidLoadBalancingStrategy + } pools := make([]*PoolWithFunc, size) for i := 0; i < size; i++ { pool, err := NewPoolWithFunc(sizePerPool, fn, options...) @@ -53,9 +56,6 @@ func NewMultiPoolWithFunc(size, sizePerPool int, fn func(interface{}), lbs LoadB } pools[i] = pool } - if lbs != RoundRobin && lbs != LeastTasks { - return nil, ErrInvalidLoadBalancingStrategy - } return &MultiPoolWithFunc{pools: pools, lbs: lbs}, nil }