Add LoadBalancer WebFlux sample
See gh-114
This commit is contained in:
committed by
Andy Wilkinson
parent
9ea77ab8e1
commit
9e3970e46c
@@ -29,6 +29,7 @@ groups:
|
||||
- cloud-discovery-zookeeper
|
||||
- cloud-function-web
|
||||
- cloud-function-webflux
|
||||
- cloud-loadbalancing-webflux
|
||||
- cloud-stream-kafka
|
||||
- cloud-stream-rabbit
|
||||
- cloud-task
|
||||
|
||||
39
cloud-loadbalancing-webflux/build.gradle
Normal file
39
cloud-loadbalancing-webflux/build.gradle
Normal file
@@ -0,0 +1,39 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'org.springframework.boot'
|
||||
id 'org.springframework.aot.smoke-test'
|
||||
id 'org.graalvm.buildtools.native'
|
||||
}
|
||||
|
||||
ext {
|
||||
set('springCloudVersion', "2022.0.0-SNAPSHOT")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(platform(
|
||||
org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES))
|
||||
implementation(
|
||||
platform("org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"))
|
||||
implementation("org.springframework.boot:spring-boot-starter")
|
||||
implementation("org.springframework.boot:spring-boot-starter-webflux")
|
||||
implementation("org.springframework.cloud:spring-cloud-starter-loadbalancer")
|
||||
|
||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||
|
||||
aotSmokeTestImplementation(project(":aot-smoke-test-support"))
|
||||
aotSmokeTestImplementation("org.awaitility:awaitility:4.2.0")
|
||||
}
|
||||
|
||||
aotSmokeTest {
|
||||
webApplication = true
|
||||
}
|
||||
|
||||
graalvmNative {
|
||||
binaries {
|
||||
main {
|
||||
buildArgs.add("--exclude-config")
|
||||
buildArgs.add("/netty-.*")
|
||||
buildArgs.add("META-INF/native-image/.*")
|
||||
}
|
||||
}
|
||||
}
|
||||
10
cloud-loadbalancing-webflux/docker-compose.yml
Normal file
10
cloud-loadbalancing-webflux/docker-compose.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
version: '3'
|
||||
services:
|
||||
test-service:
|
||||
image: springcloud/test-service:latest
|
||||
ports:
|
||||
- "8081"
|
||||
demo-service:
|
||||
image: springcloud/demo-service:latest
|
||||
ports:
|
||||
- "8082"
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.example.cloud.loadbalancing;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.awaitility.Awaitility;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aot.smoketest.support.assertj.AssertableOutput;
|
||||
import org.springframework.aot.smoketest.support.junit.AotSmokeTest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@AotSmokeTest
|
||||
public class CloudLoadBalancerClientWebFluxApplicationAotTests {
|
||||
|
||||
@Test
|
||||
void shouldRetrieveInstance(AssertableOutput output) {
|
||||
Awaitility.await().atMost(Duration.ofSeconds(30)).untilAsserted(() -> {
|
||||
assertThat(output).hasLineContaining("On Start: ");
|
||||
assertThat(output).hasLineContaining("On Start Request: ");
|
||||
assertThat(output).hasLineContaining("On Complete: ");
|
||||
assertThat(output).hasLineContaining("c.e.c.l.s.LoadBalancerClientTestService : demo");
|
||||
assertThat(output).hasLineContaining("c.e.c.l.s.LoadBalancerClientTestService : test");
|
||||
assertThat(output).hasNoLinesContaining("ERROR");
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.example.cloud.loadbalancing;
|
||||
|
||||
import com.example.cloud.loadbalancing.service.LoadBalancerClientTestService;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@SpringBootApplication
|
||||
public class CloudLoadBalancerClientWebFluxApplication implements CommandLineRunner {
|
||||
|
||||
@Autowired
|
||||
LoadBalancerClientTestService testService;
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(CloudLoadBalancerClientWebFluxApplication.class, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
testService.callServices();
|
||||
}
|
||||
|
||||
@RestController
|
||||
static class TestController {
|
||||
|
||||
@GetMapping("/")
|
||||
public String test() {
|
||||
return "test";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.example.cloud.loadbalancing.client;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
@Component
|
||||
public class DemoServiceClient {
|
||||
|
||||
private final WebClient webClient;
|
||||
|
||||
public DemoServiceClient(@LoadBalanced WebClient.Builder builder) {
|
||||
this.webClient = builder.build();
|
||||
}
|
||||
|
||||
public Mono<String> demo() {
|
||||
return webClient.get().uri(URI.create("http://demo-service")).retrieve().bodyToMono(String.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.example.cloud.loadbalancing.client;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
@Component
|
||||
public class TestServiceClient {
|
||||
|
||||
private final WebClient webClient;
|
||||
|
||||
public TestServiceClient(@LoadBalanced WebClient.Builder builder) {
|
||||
this.webClient = builder.build();
|
||||
}
|
||||
|
||||
public Mono<String> test() {
|
||||
return webClient.get().uri(URI.create("http://test-service")).retrieve().bodyToMono(String.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.example.cloud.loadbalancing.config;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.loadbalancer.CompletionContext;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerLifecycle;
|
||||
import org.springframework.cloud.client.loadbalancer.Request;
|
||||
import org.springframework.cloud.client.loadbalancer.Response;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
public class CustomLoadBalancerConfiguration {
|
||||
|
||||
@Bean
|
||||
LoadBalancerLifecycle<Object, Object, ServiceInstance> loadBalancerLifecycle() {
|
||||
return new TestLoadBalancerLifecycle();
|
||||
}
|
||||
|
||||
static class TestLoadBalancerLifecycle implements LoadBalancerLifecycle<Object, Object, ServiceInstance> {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(TestLoadBalancerLifecycle.class);
|
||||
|
||||
@Override
|
||||
public void onStart(Request<Object> request) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("On Start: " + request);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartRequest(Request<Object> request, Response<ServiceInstance> lbResponse) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("On Start Request: " + request + ", LB response: " + lbResponse);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete(CompletionContext<Object, ServiceInstance, Object> completionContext) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("On Complete: " + completionContext);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.example.cloud.loadbalancing.config;
|
||||
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
||||
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
@Configuration
|
||||
@LoadBalancerClient(name = "test-service", configuration = CustomLoadBalancerConfiguration.class)
|
||||
public class WebClientConfig {
|
||||
|
||||
@LoadBalanced
|
||||
@Bean
|
||||
WebClient.Builder webClientBuilder() {
|
||||
return WebClient.builder();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.example.cloud.loadbalancing.service;
|
||||
|
||||
import com.example.cloud.loadbalancing.client.DemoServiceClient;
|
||||
import com.example.cloud.loadbalancing.client.TestServiceClient;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class LoadBalancerClientTestService {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(LoadBalancerClientTestService.class);
|
||||
|
||||
private final TestServiceClient testServiceClient;
|
||||
|
||||
private final DemoServiceClient demoServiceClient;
|
||||
|
||||
public LoadBalancerClientTestService(TestServiceClient testServiceClient, DemoServiceClient demoServiceClient) {
|
||||
this.testServiceClient = testServiceClient;
|
||||
this.demoServiceClient = demoServiceClient;
|
||||
|
||||
}
|
||||
|
||||
public void callServices() {
|
||||
testServiceClient.test().subscribe(responseBody -> {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info(responseBody);
|
||||
}
|
||||
});
|
||||
demoServiceClient.demo().subscribe(responseBody -> {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info(responseBody);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
spring:
|
||||
application:
|
||||
name: loadbalancer-client
|
||||
cloud:
|
||||
loadbalancer:
|
||||
eager-load:
|
||||
clients:
|
||||
- demo-service
|
||||
discovery:
|
||||
client:
|
||||
simple:
|
||||
instances:
|
||||
test-service:
|
||||
- uri: http://${TEST-SERVICE_HOST:localhost}:${TEST-SERVICE_PORT_8081:8081}
|
||||
demo-service:
|
||||
- uri: http://${DEMO-SERVICE_HOST:localhost}:${DEMO-SERVICE_PORT_8082:8082}
|
||||
@@ -44,6 +44,7 @@ include "cloud-discovery-consul"
|
||||
include "cloud-discovery-zookeeper"
|
||||
include "cloud-function-web"
|
||||
include "cloud-function-webflux"
|
||||
include 'cloud-loadbalancing-webflux'
|
||||
include "cloud-stream-kafka"
|
||||
include "cloud-stream-rabbit"
|
||||
include "cloud-task"
|
||||
|
||||
Reference in New Issue
Block a user