Spring Cloud step-by-step (part 5)
Marcin Piczkowski
Posted on June 28, 2018
This is a continuation of previous blog posts:
This is a continuation of previous blog posts:
- Spring Cloud step-by-step (part 1)
- Spring Cloud step-by-step (part 2)
- Spring Cloud step-by-step (part 3)
- Spring Cloud step-by-step (part 4)
In previous blog post I showed you how to invoke other services using EurekaClient
, but there is a simpler way.
RestTemplate
is smart enough to resolve service URI from Eureka server itself.
Ribbon is a client-side load balancer and SpringTemplate
supports it by simply adding one annotation: @LoadBalanced
.
Let's create version 2 of Rental Service controller which will look this way:
@RestController
@RequestMapping(path = "/v2")
public class RentalControllerV2 {
protected String serviceUrl = "http://PRICING-SERVICE";
private final RestTemplate restTemplate;
public RentalControllerV2(@Qualifier("ribbon-template") RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@RequestMapping(path = "/rentals/{id}/charges", method = RequestMethod.GET)
public ResponseEntity getPossibleCharges(@PathVariable("id") String id) {
ZonedDateTime startTime = ZonedDateTime.now();
ZonedDateTime endTime = startTime.plus(2, ChronoUnit.DAYS);
HttpEntity<PriceRequest> request = new HttpEntity<>(
new PriceRequest("vip", startTime, endTime)
);
PriceResponse response = restTemplate.postForObject(serviceUrl + "/v1/prices", request, PriceResponse.class);
return new ResponseEntity<>(new RentalChargesResponse(response.getPrice()), HttpStatus.OK);
}
}
To enable Ribbon we have to add this property in bootstrap.yaml
or application.yaml
ribbon:
http:
client:
enabled: true
In the controller above I am injecting RestTemplate
as a bean named ribbon-template
.
This is because I wanted to leave two RestTemplate
beans in the application: one which we use in version 1 controller with native EurekaClient API and another in version 2 controller which is load-balanced RestTemplate
.
This is how my beans configuration looks like in main class:
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean("ribbon-template")
@LoadBalanced
public RestTemplate restTemplateWithRibbon() {
return new RestTemplate();
}
And that's it. Start the application and invoke endpoint:
curl localhost:8080/v2/rentals/1/charges
You will see in logs how Spring is resolving Rental Service URL from service name:
2018-06-29 01:11:58.027 INFO 18934 --- [nio-8080-exec-1] c.netflix.config.ChainedDynamicProperty : Flipping property: PRICING-SERVICE.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2018-06-29 01:11:58.048 INFO 18934 --- [nio-8080-exec-1] c.n.u.concurrent.ShutdownEnabledTimer : Shutdown hook installed for: NFLoadBalancer-PingTimer-PRICING-SERVICE
2018-06-29 01:11:58.067 INFO 18934 --- [nio-8080-exec-1] c.netflix.loadbalancer.BaseLoadBalancer : Client: PRICING-SERVICE instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=PRICING-SERVICE,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null
2018-06-29 01:11:58.072 INFO 18934 --- [nio-8080-exec-1] c.n.l.DynamicServerListLoadBalancer : Using serverListUpdater PollingServerListUpdater
2018-06-29 01:11:58.089 INFO 18934 --- [nio-8080-exec-1] c.netflix.config.ChainedDynamicProperty : Flipping property: PRICING-SERVICE.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2018-06-29 01:11:58.090 INFO 18934 --- [nio-8080-exec-1] c.n.l.DynamicServerListLoadBalancer : DynamicServerListLoadBalancer for client PRICING-SERVICE initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=PRICING-SERVICE,current list of Servers=[192.168.43.107:46579],Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone; Instance count:1; Active connections count: 0; Circuit breaker tripped count: 0; Active connections per server: 0.0;]
},Server stats: [[Server:192.168.43.107:46579; Zone:defaultZone; Total Requests:0; Successive connection failure:0; Total blackout seconds:0; Last connection made:Thu Jan 01 01:00:00 CET 1970; First connection made: Thu Jan 01 01:00:00 CET 1970; Active Connections:0; total failure count in last (1000) msecs:0; average resp time:0.0; 90 percentile resp time:0.0; 95 percentile resp time:0.0; min resp time:0.0; max resp time:0.0; stddev resp time:0.0]
]}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@fcc5a3d
2018-06-29 01:11:58.131 INFO 18934 --- [nio-8080-exec-1] com.netflix.http4.ConnectionPoolCleaner : Initializing ConnectionPoolCleaner for NFHttpClient:PRICING-SERVICE
2018-06-29 01:11:59.075 INFO 18934 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty : Flipping property: PRICING-SERVICE.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
As usual, source code for this example is on Github spring-cloud-5 branch.
Posted on June 28, 2018
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.