dubbo-go icon indicating copy to clipboard operation
dubbo-go copied to clipboard

feat(triple): Implement TriClientPool and Delay triple client Method Binding

Open Aetherance opened this issue 1 month ago • 14 comments

About this PR and draft status

This PR introduces TriClientPool, which is used to reuse tri.Client in the Triple scenario, reducing the overhead of client creation and initialization, and helping improve throughput in high-concurrency situations.

During the implementation of the pool, in order to better support client reuse, we made some adjustments to the timing of tri.Client usage.
Previously, tri.Client would bind methods at creation, and this binding was permanent and at the method level, making it impossible to reuse the client across different calls. Now it has been changed to bind at the service level: each client only knows which service it corresponds to, while method-related logic (such as parsing and binding) is deferred until the actual RPC call is made. In this way, tri.Client only handles connection and communication initialization at creation, and call-specific information exists only in the execution path of a single request.

This adjustment prevents the client instance from holding method state permanently, making it easier to reuse across different calls, while reducing unnecessary initialization and potential contention, thereby better supporting the pool.

Since this change was introduced during the implementation of TriClientPool and affects how tri.Client is used, the PR is marked as draft to first confirm that this adjustment aligns with expectations. Once the semantics are agreed upon, the implementation and related tests can be further completed.

This PR introduces changes to tri.Client and ClientManager, mainly focusing on:

Unified TriClientPool

  • Previously, ClientManager maintained a map[string]*TriClientPool, one pool per method.
  • Now the entire ClientManager shares a single TriClientPool, simplifying management and reducing memory overhead.
  • The pool supports auto-scaling, non-blocking Put(), safe Close(), and other enhancements.

Delayed tri.Client Method Binding

  • Method binding is moved from client construction to actual RPC call time.
  • Avoids unnecessary pre-binding for unused methods and improves flexibility.
  • Fully compatible with the unified TriClientPool architecture.

Other Changes

  • Added optional per-client transport mode (tri.per_client_transport URL parameter)
  • Unit tests and performance benchmarks included to validate pool behavior and throughput

Benefits

  • Pooling improves resource reuse and high-concurrency throughput
  • Delayed method binding reduces overhead and increases flexibility
  • Simplifies ClientManager maintenance and future extensibility

TriClientPool API

  • NewTriClientPool(warmUpSize int, maxSize int, factory func() *tri.Client) *TriClientPool
    Create a new pool with initial warm-up size, maximum size, and a client factory function.

  • Get(timeout time.Duration) (*tri.Client, error)
    Retrieves a client from the pool.

    • Tries non-blocking receive first.
    • Expands the pool if allowed.
    • If timeout occurs, returns a fallback client to ensure at least one usable client.
  • Put(client *tri.Client)
    Returns a client to the pool. Non-blocking; drops the client if the pool is full (part of shrinking).

  • Close()
    Safely closes the pool.

  • MaxSize() int
    Returns the maximum allowed pool size.

  • Closed() bool
    Returns whether the pool has been closed.

Per-Client Transport Option

Added a URL parameter: tri.per_client_transport

  • true: each client gets a dedicated transport connection

  • false (default): all clients share a common transport

Benchmark Results

run go test -bench . at protocol/triple you will see the result of benchmark like

BenchmarkThroughputComparisonDelay/delay_1ms/SingleClient-24               28291             44420 ns/op
BenchmarkThroughputComparisonDelay/delay_1ms/TriClientPool-24              80985             15073 ns/op
BenchmarkThroughputComparisonDelay/delay_100ms/SingleClient-24               547           2056883 ns/op
BenchmarkThroughputComparisonDelay/delay_100ms/TriClientPool-24             1530            699295 ns/op

Integration Tests

Integration tests have been implemented to validate the correctness and stability of TriClientPool and delayed method binding.

TriClientPool Usage

pool := triple.NewTriClientPool(2, 10, func() *triple.Client {
    // Create a new tri.Client
    return /* tri.Client instance */
})
defer pool.Close()

ctx := context.Background()
client, _ := pool.Get(50 * time.Millisecond)

// Use the client to make an RPC call

pool.Put(client)

Aetherance avatar Nov 23 '25 11:11 Aetherance

issue #3087

Aetherance avatar Nov 24 '25 04:11 Aetherance

please fix the code format

CAICAIIs avatar Nov 24 '25 04:11 CAICAIIs

Maybe it would be better to put TriClientPool in a separate new file instead of cramming it into the existing client.go?

CAICAIIs avatar Nov 24 '25 05:11 CAICAIIs

This PR is still in progress. I’ll update it once it's ready for review.

Aetherance avatar Nov 24 '25 07:11 Aetherance

Fix ci error.

marsevilspirit avatar Nov 26 '25 10:11 marsevilspirit

Codecov Report

:x: Patch coverage is 48.38710% with 96 lines in your changes missing coverage. Please review. :white_check_mark: Project coverage is 37.12%. Comparing base (60d1c2a) to head (3e6d54a). :warning: Report is 660 commits behind head on develop.

Files with missing lines Patch % Lines
protocol/triple/client_pool.go 61.22% 46 Missing and 11 partials :warning:
protocol/triple/client.go 0.00% 39 Missing :warning:
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #3086      +/-   ##
===========================================
- Coverage    46.76%   37.12%   -9.65%     
===========================================
  Files          295      461     +166     
  Lines        17172    33143   +15971     
===========================================
+ Hits          8031    12305    +4274     
- Misses        8287    19603   +11316     
- Partials       854     1235     +381     

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

:rocket: New features to boost your workflow:
  • :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

codecov-commenter avatar Nov 27 '25 05:11 codecov-commenter

@marsevilspirit review

Aetherance avatar Nov 28 '25 05:11 Aetherance

@marsevilspirit done

Aetherance avatar Nov 28 '25 13:11 Aetherance

Write a performance test to demonstrate that your change can improve the throughput of triple.

marsevilspirit avatar Nov 28 '25 14:11 marsevilspirit

Thanks for reviewing. I will fix later

Aetherance avatar Nov 29 '25 17:11 Aetherance

protocol/triple/client_pool.go needs sound unit tests, please write a test file for it

done @Alanxtl

Aetherance avatar Dec 06 '25 08:12 Aetherance

Do you have test results? If so, please post them on this thread.

marsevilspirit avatar Dec 12 '25 05:12 marsevilspirit

Enhance the PR description by detailing the implementation approach, making it easier for future reference.

Refer to this link: https://github.com/apache/dubbo-go/pull/3090#issue-3666897313

marsevilspirit avatar Dec 12 '25 05:12 marsevilspirit