|
18 | 18 | import io.rsocket.Payload; |
19 | 19 | import io.rsocket.RSocket; |
20 | 20 | import io.rsocket.RSocketClient; |
| 21 | +import io.rsocket.core.RSocketConnector; |
21 | 22 | import java.util.List; |
22 | 23 | import org.reactivestreams.Publisher; |
23 | 24 | import reactor.core.publisher.Flux; |
24 | 25 | import reactor.core.publisher.Mono; |
| 26 | +import reactor.util.annotation.Nullable; |
25 | 27 |
|
26 | 28 | /** |
27 | | - * {@link RSocketClient} implementation that uses a pool and a {@link LoadbalanceStrategy} to select |
28 | | - * the {@code RSocket} to use for each request. |
| 29 | + * {@link RSocketClient} implementation that uses a {@link LoadbalanceStrategy} to select the {@code |
| 30 | + * RSocket} to use for a given request from a pool of possible targets. |
29 | 31 | * |
30 | 32 | * @since 1.1 |
31 | 33 | */ |
@@ -72,45 +74,109 @@ public void dispose() { |
72 | 74 | rSocketPool.dispose(); |
73 | 75 | } |
74 | 76 |
|
| 77 | + /** |
| 78 | + * Shortcut to create an {@link LoadbalanceRSocketClient} with round robin loadalancing. |
| 79 | + * Effectively a shortcut for: |
| 80 | + * |
| 81 | + * <pre class="cdoe"> |
| 82 | + * LoadbalanceRSocketClient.builder(targetPublisher) |
| 83 | + * .connector(RSocketConnector.create()) |
| 84 | + * .build(); |
| 85 | + * </pre> |
| 86 | + * |
| 87 | + * @param connector the {@link Builder#connector(RSocketConnector) to use |
| 88 | + * @param targetPublisher publisher that periodically refreshes the list of targets to loadbalance across. |
| 89 | + * @return the created client instance |
| 90 | + */ |
75 | 91 | public static LoadbalanceRSocketClient create( |
76 | | - LoadbalanceStrategy loadbalanceStrategy, |
77 | | - Publisher<List<LoadbalanceRSocketSource>> rSocketSuppliersPublisher) { |
78 | | - return new LoadbalanceRSocketClient( |
79 | | - new RSocketPool(rSocketSuppliersPublisher, loadbalanceStrategy)); |
| 92 | + RSocketConnector connector, Publisher<List<LoadbalanceTarget>> targetPublisher) { |
| 93 | + return builder(targetPublisher).connector(connector).build(); |
80 | 94 | } |
81 | 95 |
|
82 | | - public static LoadbalanceRSocketClient create( |
83 | | - Publisher<List<LoadbalanceRSocketSource>> rSocketSuppliersPublisher) { |
84 | | - return create(new RoundRobinLoadbalanceStrategy(), rSocketSuppliersPublisher); |
85 | | - } |
86 | | - |
87 | | - public static Builder builder() { |
88 | | - return new Builder(); |
| 96 | + /** |
| 97 | + * Return a builder to create an {@link LoadbalanceRSocketClient} with. |
| 98 | + * |
| 99 | + * @param targetPublisher publisher that periodically refreshes the list of targets to loadbalance |
| 100 | + * across. |
| 101 | + * @return the builder instance |
| 102 | + */ |
| 103 | + public static Builder builder(Publisher<List<LoadbalanceTarget>> targetPublisher) { |
| 104 | + return new Builder(targetPublisher); |
89 | 105 | } |
90 | 106 |
|
| 107 | + /** Builder for creating an {@link LoadbalanceRSocketClient}. */ |
91 | 108 | public static class Builder { |
92 | 109 |
|
93 | | - LoadbalanceStrategy loadbalanceStrategy; |
| 110 | + private final Publisher<List<LoadbalanceTarget>> targetPublisher; |
| 111 | + |
| 112 | + @Nullable private RSocketConnector connector; |
94 | 113 |
|
95 | | - Builder() {} |
| 114 | + @Nullable LoadbalanceStrategy loadbalanceStrategy; |
96 | 115 |
|
97 | | - public Builder withWeightedLoadbalanceStrategy() { |
98 | | - return withCustomLoadbalanceStrategy(new WeightedLoadbalanceStrategy()); |
| 116 | + Builder(Publisher<List<LoadbalanceTarget>> targetPublisher) { |
| 117 | + this.targetPublisher = targetPublisher; |
99 | 118 | } |
100 | 119 |
|
101 | | - public Builder withRoundRobinLoadbalanceStrategy() { |
102 | | - return withCustomLoadbalanceStrategy(new RoundRobinLoadbalanceStrategy()); |
| 120 | + /** |
| 121 | + * The given {@link RSocketConnector} is used as a template to produce the {@code Mono<RSocket>} |
| 122 | + * source for each {@link LoadbalanceTarget}. This is done by passing the {@code |
| 123 | + * ClientTransport} contained in every target to the {@code connect} method of the given |
| 124 | + * connector instance. |
| 125 | + * |
| 126 | + * <p>By default this is initialized with {@link RSocketConnector#create()}. |
| 127 | + * |
| 128 | + * @param connector the connector to use as a template |
| 129 | + */ |
| 130 | + public Builder connector(RSocketConnector connector) { |
| 131 | + this.connector = connector; |
| 132 | + return this; |
| 133 | + } |
| 134 | + |
| 135 | + /** |
| 136 | + * Switch to using a round-robin strategy for selecting a target. |
| 137 | + * |
| 138 | + * <p>This is the strategy used by default. |
| 139 | + */ |
| 140 | + public Builder roundRobinLoadbalanceStrategy() { |
| 141 | + this.loadbalanceStrategy = new RoundRobinLoadbalanceStrategy(); |
| 142 | + return this; |
103 | 143 | } |
104 | 144 |
|
105 | | - public Builder withCustomLoadbalanceStrategy(LoadbalanceStrategy strategy) { |
| 145 | + /** |
| 146 | + * Switch to using a strategy that assigns a weight to each pooled {@code RSocket} based on |
| 147 | + * actual usage stats, and uses that to make a choice. |
| 148 | + * |
| 149 | + * <p>By default this strategy is not used. |
| 150 | + */ |
| 151 | + public Builder weightedLoadbalanceStrategy() { |
| 152 | + this.loadbalanceStrategy = new WeightedLoadbalanceStrategy(); |
| 153 | + return this; |
| 154 | + } |
| 155 | + |
| 156 | + /** |
| 157 | + * Switch to using a custom strategy for loadbalancing. |
| 158 | + * |
| 159 | + * @see #roundRobinLoadbalanceStrategy() |
| 160 | + */ |
| 161 | + public Builder customLoadbalanceStrategy(LoadbalanceStrategy strategy) { |
106 | 162 | this.loadbalanceStrategy = strategy; |
107 | 163 | return this; |
108 | 164 | } |
109 | 165 |
|
110 | | - public LoadbalanceRSocketClient build( |
111 | | - Publisher<List<LoadbalanceRSocketSource>> rSocketSuppliersPublisher) { |
| 166 | + /** Build the {@link LoadbalanceRSocketClient} instance. */ |
| 167 | + public LoadbalanceRSocketClient build() { |
112 | 168 | return new LoadbalanceRSocketClient( |
113 | | - new RSocketPool(rSocketSuppliersPublisher, this.loadbalanceStrategy)); |
| 169 | + new RSocketPool(initConnector(), this.targetPublisher, initLoadbalanceStrategy())); |
| 170 | + } |
| 171 | + |
| 172 | + private RSocketConnector initConnector() { |
| 173 | + return (this.connector != null ? this.connector : RSocketConnector.create()); |
| 174 | + } |
| 175 | + |
| 176 | + private LoadbalanceStrategy initLoadbalanceStrategy() { |
| 177 | + return (this.loadbalanceStrategy != null |
| 178 | + ? this.loadbalanceStrategy |
| 179 | + : new RoundRobinLoadbalanceStrategy()); |
114 | 180 | } |
115 | 181 | } |
116 | 182 | } |
0 commit comments