We need two modules
module name | role | port |
---|---|---|
Client | Load-balancing client | 8888 |
Server | Load-balancing server | 8090, 8092, 8093 |
Run the app on specified port
SERVER_PORT=9999 mvn spring-boot:run
Module Server
dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
application.properties
server.port= 8090
spring.application.name = server
ServerApplication.java
@RestController
@SpringBootApplication
public class ServerApplication {
@Autowired
private ServerProperties serverProperties;
private static Logger log = LoggerFactory.getLogger(ServerApplication.class);
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
@GetMapping("/greeting")
public String greet() {
log.info("Access /greeting");
List<String> greetings = Arrays.asList("Hi there", "Greetings", "Salutations");
Random rand = new Random();
int randomNum = rand.nextInt(greetings.size());
return greetings.get(randomNum) + serverProperties.getPort();
}
@GetMapping("/")
public String home() {
log.info("Access /");
return "Hi!";
}
}
Module Client
Dependencies
Spring Boot Starter Load Balancing + Spring Reactive Web
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
application.properties
server.port= 8888
spring.application.name = client
ClientApplication.java
@SpringBootApplication
@RestController
public class ClientApplication {
private final WebClient.Builder loadBalancedWebClientBuilder;
private final ReactorLoadBalancerExchangeFilterFunction lbFunction;
public ClientApplication(WebClient.Builder webClientBuilder,
ReactorLoadBalancerExchangeFilterFunction lbFunction) {
this.loadBalancedWebClientBuilder = webClientBuilder;
this.lbFunction = lbFunction;
}
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
private String serverName = "server";
@RequestMapping("/hi")
public Mono<String> hi(@RequestParam(value = "name", defaultValue = "Mary") String name) {
return loadBalancedWebClientBuilder.build().get().uri("http://"+serverName+"/greeting")
.retrieve().bodyToMono(String.class)
.map(greeting -> String.format("%s, %s!", greeting, name));
}
@RequestMapping("/hello")
public Mono<String> hello(@RequestParam(value = "name", defaultValue = "John") String name) {
return WebClient.builder()
.filter(lbFunction)
.build().get().uri("http://"+serverName+"/greeting")
.retrieve().bodyToMono(String.class)
.map(greeting -> String.format("%s, %s!", greeting, name));
}
}
ClientConfig.java
@Configuration
public class ClientConfig {
@Bean
@Primary
ServiceInstanceListSupplier serviceInstanceListSupplier() {
return new DemoServiceInstanceListSuppler("server");
}
}
WebClientConfig.java
@Configuration
@LoadBalancerClient(name = "client", configuration = ClientConfig.class)
public class WebClientConfig {
@LoadBalanced
@Bean
WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
}
DemoServiceInstanceListSuppler.java
lass DemoServiceInstanceListSuppler implements ServiceInstanceListSupplier {
private final String serviceId;
DemoServiceInstanceListSuppler(String serviceId) {
this.serviceId = serviceId;
}
@Override
public String getServiceId() {
return serviceId;
}
@Override
public Flux<List<ServiceInstance>> get() {
return Flux.just(Arrays
.asList(new DefaultServiceInstance(serviceId + "1", serviceId, "localhost", 8090, false),
new DefaultServiceInstance(serviceId + "2", serviceId, "localhost", 8092, false),
new DefaultServiceInstance(serviceId + "3", serviceId, "localhost", 8093, false))
);
}
}
Reference: