or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

circuit-breakers.mdhttp-clients.mdindex.mdload-balancing.mdreactive-support.mdservice-discovery.mdservice-registration.md

load-balancing.mddocs/

0

# Load Balancing

1

2

Client-side load balancing enables applications to distribute requests across multiple service instances with support for multiple algorithms, health checking, retry mechanisms, and both blocking and reactive programming models.

3

4

## Capabilities

5

6

### Load Balanced Annotation

7

8

Marks RestTemplate or WebClient beans for automatic load balancing.

9

10

```java { .api }

11

/**

12

* Marks RestTemplate or WebClient beans for load balancing

13

*/

14

@LoadBalanced

15

public @interface LoadBalanced {}

16

```

17

18

**Usage Examples:**

19

20

```java

21

@Configuration

22

public class LoadBalancerConfig {

23

24

@Bean

25

@LoadBalanced

26

public RestTemplate restTemplate() {

27

return new RestTemplate();

28

}

29

30

@Bean

31

@LoadBalanced

32

public WebClient.Builder webClientBuilder() {

33

return WebClient.builder();

34

}

35

}

36

37

@Service

38

public class UserService {

39

40

@Autowired

41

@LoadBalanced

42

private RestTemplate restTemplate;

43

44

public String getUser(String userId) {

45

// This will be load balanced across user-service instances

46

return restTemplate.getForObject("http://user-service/users/" + userId, String.class);

47

}

48

}

49

```

50

51

### Load Balancer Client

52

53

Main interface for client-side load balancing operations.

54

55

```java { .api }

56

/**

57

* Main interface for client-side load balancing

58

*/

59

public interface LoadBalancerClient extends ServiceInstanceChooser {

60

/**

61

* Execute a request using load balancing

62

* @param serviceId The service ID to load balance across

63

* @param request The request to execute

64

* @return The result from the request execution

65

* @throws IOException If request execution fails

66

*/

67

<T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;

68

69

/**

70

* Execute a request using load balancing with a specific service instance

71

* @param serviceId The service ID

72

* @param serviceInstance The service instance to use

73

* @param request The request to execute

74

* @return The result from the request execution

75

* @throws IOException If request execution fails

76

*/

77

<T> T execute(String serviceId, ServiceInstance serviceInstance,

78

LoadBalancerRequest<T> request) throws IOException;

79

80

/**

81

* Create a proper URI with a real host and port for systems to utilize

82

* @param instance The service instance

83

* @param original The original URI

84

* @return A reconstructed URI

85

*/

86

URI reconstructURI(ServiceInstance instance, URI original);

87

}

88

```

89

90

### Service Instance Chooser

91

92

Interface for selecting service instances.

93

94

```java { .api }

95

/**

96

* Interface for selecting service instances

97

*/

98

public interface ServiceInstanceChooser {

99

/**

100

* Choose a ServiceInstance from the LoadBalancer for the specified service

101

* @param serviceId The service ID to choose an instance for

102

* @return A ServiceInstance that matches the serviceId

103

*/

104

ServiceInstance choose(String serviceId);

105

106

/**

107

* Choose a ServiceInstance from the LoadBalancer for the specified service and request

108

* @param serviceId The service ID to choose an instance for

109

* @param request The request context

110

* @return A ServiceInstance that matches the serviceId

111

*/

112

<T> ServiceInstance choose(String serviceId, Request<T> request);

113

}

114

```

115

116

### Load Balancer Request

117

118

Interface for wrapping requests in load balancing context.

119

120

```java { .api }

121

/**

122

* Interface for wrapping requests in load balancing context

123

*/

124

public interface LoadBalancerRequest<T> {

125

/**

126

* Apply the request to the given ServiceInstance

127

* @param instance The service instance to apply the request to

128

* @return The result of applying the request

129

* @throws Exception If the request fails

130

*/

131

T apply(ServiceInstance instance) throws Exception;

132

}

133

```

134

135

**Usage Example:**

136

137

```java

138

@Autowired

139

private LoadBalancerClient loadBalancerClient;

140

141

public String callService() {

142

return loadBalancerClient.execute("user-service",

143

instance -> {

144

String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/users";

145

// Make HTTP call using the selected instance

146

return restTemplate.getForObject(url, String.class);

147

});

148

}

149

```

150

151

### Request and Response Framework

152

153

Framework for handling load balancer requests and responses.

154

155

```java { .api }

156

/**

157

* Interface for load balancer requests

158

*/

159

public interface Request<C> {

160

/**

161

* @return The request context

162

*/

163

C getContext();

164

}

165

166

/**

167

* Interface for load balancer responses

168

*/

169

public interface Response<T> {

170

/**

171

* @return Whether the response has a server

172

*/

173

boolean hasServer();

174

175

/**

176

* @return The selected server

177

*/

178

T getServer();

179

}

180

181

/**

182

* Default implementation of Request

183

*/

184

public class DefaultRequest<T> implements Request<T> {

185

public DefaultRequest(T context);

186

}

187

188

/**

189

* Default implementation of Response with selected ServiceInstance

190

*/

191

public class DefaultResponse implements Response<ServiceInstance> {

192

public DefaultResponse(ServiceInstance serviceInstance);

193

}

194

195

/**

196

* Response implementation for no available instances

197

*/

198

public class EmptyResponse implements Response<ServiceInstance> {

199

public EmptyResponse();

200

}

201

```

202

203

### Context Classes

204

205

Context objects for carrying request information through the load balancing process.

206

207

```java { .api }

208

/**

209

* Default request context implementation

210

*/

211

public class DefaultRequestContext implements RequestDataContext {

212

public DefaultRequestContext(RequestData requestData, String hint);

213

}

214

215

/**

216

* Request context containing request data

217

*/

218

public interface RequestDataContext {

219

/**

220

* @return The request data

221

*/

222

RequestData getClientRequest();

223

}

224

225

/**

226

* Request context with load balancer hints

227

*/

228

public class HintRequestContext implements RequestDataContext {

229

public HintRequestContext(RequestData requestData, String hint);

230

public String getHint();

231

}

232

233

/**

234

* Context for retryable requests

235

*/

236

public class RetryableRequestContext implements RequestDataContext {

237

public RetryableRequestContext(RequestData requestData, int retryCount);

238

public int getRetryCount();

239

}

240

241

/**

242

* HTTP request data holder

243

*/

244

public class RequestData {

245

public RequestData(HttpRequest httpRequest);

246

public HttpRequest getHttpRequest();

247

public HttpHeaders getHeaders();

248

public String getUrl();

249

}

250

251

/**

252

* HTTP response data holder

253

*/

254

public class ResponseData {

255

public ResponseData(HttpHeaders headers, Object requestData);

256

public HttpHeaders getHeaders();

257

public Object getRequestData();

258

}

259

```

260

261

### Load Balancer Properties

262

263

Configuration properties for load balancer behavior.

264

265

```java { .api }

266

/**

267

* Base load balancer configuration properties

268

*/

269

@ConfigurationProperties("spring.cloud.loadbalancer")

270

public class LoadBalancerProperties {

271

private HealthCheck healthCheck = new HealthCheck();

272

private Retry retry = new Retry();

273

private StickySession stickySession = new StickySession();

274

private XForwarded xForwarded = new XForwarded();

275

276

/**

277

* Health check configuration

278

*/

279

public static class HealthCheck {

280

private boolean enabled = true;

281

private Duration interval = Duration.ofSeconds(25);

282

private String path = "/actuator/health";

283

// getters and setters

284

}

285

286

/**

287

* Retry configuration

288

*/

289

public static class Retry {

290

private boolean enabled = true;

291

private int maxRetriesOnSameServiceInstance = 0;

292

private int maxRetriesOnNextServiceInstance = 1;

293

private Set<Class<? extends Throwable>> retryableExceptions = new HashSet<>();

294

// getters and setters

295

}

296

297

/**

298

* Sticky session configuration

299

*/

300

public static class StickySession {

301

private boolean enabled = false;

302

private String instanceIdCookieName = "sc-lb-instance-id";

303

// getters and setters

304

}

305

}

306

307

/**

308

* Client-specific load balancer properties

309

*/

310

@ConfigurationProperties("spring.cloud.loadbalancer")

311

public class LoadBalancerClientsProperties {

312

private Map<String, LoadBalancerProperties> clients = new HashMap<>();

313

// getters and setters

314

}

315

```

316

317

### HTTP Client Interceptors

318

319

Interceptors for adding load balancing to HTTP clients.

320

321

```java { .api }

322

/**

323

* HTTP client interceptor for load balancing

324

*/

325

public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {

326

public LoadBalancerInterceptor(LoadBalancerClient loadBalancer);

327

public LoadBalancerInterceptor(LoadBalancerClient loadBalancer,

328

LoadBalancerRequestFactory requestFactory);

329

}

330

331

/**

332

* Load balancer interceptor with retry support

333

*/

334

public class RetryLoadBalancerInterceptor implements ClientHttpRequestInterceptor {

335

public RetryLoadBalancerInterceptor(LoadBalancerClient loadBalancer,

336

LoadBalancerProperties properties);

337

}

338

339

/**

340

* Async HTTP client interceptor

341

*/

342

public class AsyncLoadBalancerInterceptor implements AsyncClientHttpRequestInterceptor {

343

public AsyncLoadBalancerInterceptor(LoadBalancerClient loadBalancer);

344

}

345

```

346

347

### Customization Interfaces

348

349

Interfaces for customizing HTTP clients.

350

351

```java { .api }

352

/**

353

* Interface for customizing RestTemplate

354

*/

355

public interface RestTemplateCustomizer {

356

/**

357

* Customize the RestTemplate

358

* @param restTemplate The RestTemplate to customize

359

*/

360

void customize(RestTemplate restTemplate);

361

}

362

363

/**

364

* Interface for customizing AsyncRestTemplate

365

*/

366

public interface AsyncRestTemplateCustomizer {

367

/**

368

* Customize the AsyncRestTemplate

369

* @param restTemplate The AsyncRestTemplate to customize

370

*/

371

void customize(AsyncRestTemplate restTemplate);

372

}

373

```

374

375

### Retry Support

376

377

Support for retrying failed load balanced requests.

378

379

```java { .api }

380

/**

381

* Factory for creating retry policies

382

*/

383

public interface LoadBalancedRetryFactory {

384

/**

385

* Create a retry policy for the given service

386

* @param service The service ID

387

* @param loadBalancerProperties The load balancer properties

388

* @return A retry policy

389

*/

390

LoadBalancedRetryPolicy createRetryPolicy(String service,

391

LoadBalancerProperties loadBalancerProperties);

392

}

393

394

/**

395

* Retry policy interface for load balanced requests

396

*/

397

public interface LoadBalancedRetryPolicy extends RetryPolicy {

398

/**

399

* Check if retry is possible

400

* @param retryContext The retry context

401

* @return true if retry is possible

402

*/

403

boolean canRetry(LoadBalancedRetryContext retryContext);

404

405

/**

406

* Register a throwable with the retry policy

407

* @param retryContext The retry context

408

* @param throwable The throwable that occurred

409

*/

410

void registerThrowable(LoadBalancedRetryContext retryContext, Throwable throwable);

411

}

412

413

/**

414

* Recovery callback for retry scenarios

415

*/

416

public abstract class LoadBalancedRecoveryCallback<T, R> implements RecoveryCallback<R> {

417

/**

418

* Create a recovery callback

419

* @param request The original request

420

* @param originalUri The original URI

421

* @param loadBalancerClient The load balancer client

422

*/

423

protected LoadBalancedRecoveryCallback(LoadBalancerRequest<T> request,

424

URI originalUri,

425

LoadBalancerClient loadBalancerClient);

426

}

427

428

/**

429

* Exception for HTTP status codes that should trigger retries

430

*/

431

public class RetryableStatusCodeException extends Exception {

432

public RetryableStatusCodeException(String serviceId, int statusCode, HttpResponse response);

433

public int getStatusCode();

434

public HttpResponse getResponse();

435

}

436

```

437

438

### Reactive Load Balancing

439

440

Reactive load balancing support for WebClient.

441

442

```java { .api }

443

/**

444

* Reactive load balancer interface

445

*/

446

public interface ReactiveLoadBalancer<T> {

447

/**

448

* Choose a server instance

449

* @param request The request context

450

* @return A Mono containing the response

451

*/

452

Mono<Response<T>> choose(Request request);

453

454

/**

455

* Choose a server instance with default request

456

* @return A Mono containing the response

457

*/

458

default Mono<Response<T>> choose() {

459

return choose(REQUEST);

460

}

461

462

Request REQUEST = new DefaultRequest<>();

463

464

/**

465

* Factory interface for creating reactive load balancers

466

*/

467

interface Factory<T> {

468

ReactiveLoadBalancer<T> getInstance(String serviceId);

469

}

470

}

471

472

/**

473

* WebClient exchange filter function for load balancing

474

*/

475

public class ReactorLoadBalancerExchangeFilterFunction implements ExchangeFilterFunction {

476

public ReactorLoadBalancerExchangeFilterFunction(ReactiveLoadBalancer.Factory<ServiceInstance> loadBalancerFactory);

477

}

478

479

/**

480

* WebClient filter with retry support

481

*/

482

public class RetryableLoadBalancerExchangeFilterFunction implements ExchangeFilterFunction {

483

public RetryableLoadBalancerExchangeFilterFunction(RetrySpec retrySpec,

484

ReactiveLoadBalancer.Factory<ServiceInstance> loadBalancerFactory);

485

}

486

```

487

488

## Configuration Properties

489

490

```properties

491

# Enable/disable load balancer

492

spring.cloud.loadbalancer.enabled=true

493

494

# Health check configuration

495

spring.cloud.loadbalancer.health-check.enabled=true

496

spring.cloud.loadbalancer.health-check.interval=25s

497

spring.cloud.loadbalancer.health-check.path=/actuator/health

498

499

# Retry configuration

500

spring.cloud.loadbalancer.retry.enabled=true

501

spring.cloud.loadbalancer.retry.max-retries-on-same-service-instance=0

502

spring.cloud.loadbalancer.retry.max-retries-on-next-service-instance=1

503

504

# Sticky session configuration

505

spring.cloud.loadbalancer.sticky-session.enabled=false

506

spring.cloud.loadbalancer.sticky-session.instance-id-cookie-name=sc-lb-instance-id

507

508

# Client-specific configuration

509

spring.cloud.loadbalancer.clients.user-service.health-check.enabled=false

510

spring.cloud.loadbalancer.clients.user-service.retry.max-retries-on-next-service-instance=2

511

```

512

513

**Usage Examples:**

514

515

```java

516

// Basic load balancing with RestTemplate

517

@RestController

518

public class UserController {

519

520

@Autowired

521

@LoadBalanced

522

private RestTemplate restTemplate;

523

524

@GetMapping("/users/{id}")

525

public String getUser(@PathVariable String id) {

526

return restTemplate.getForObject("http://user-service/users/" + id, String.class);

527

}

528

}

529

530

// Reactive load balancing with WebClient

531

@Service

532

public class ReactiveUserService {

533

534

private final WebClient webClient;

535

536

public ReactiveUserService(@LoadBalanced WebClient.Builder webClientBuilder) {

537

this.webClient = webClientBuilder.build();

538

}

539

540

public Mono<String> getUser(String id) {

541

return webClient.get()

542

.uri("http://user-service/users/{id}", id)

543

.retrieve()

544

.bodyToMono(String.class);

545

}

546

}

547

548

// Manual load balancing

549

@Service

550

public class ManualLoadBalancingService {

551

552

@Autowired

553

private LoadBalancerClient loadBalancerClient;

554

555

public String callService() {

556

return loadBalancerClient.execute("user-service", instance -> {

557

String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/users";

558

RestTemplate restTemplate = new RestTemplate();

559

return restTemplate.getForObject(url, String.class);

560

});

561

}

562

}

563

```