Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.
Get started with mocking and improve your application tests using our Mockito guide:
Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.
Get started with understanding multi-threaded applications with our Java Concurrency guide:
Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:
Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.
But these can also be overused and fall into some common pitfalls.
To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:
Get started with Spring and Spring Boot, through the Learn Spring course:
>> LEARN SPRINGExplore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:
Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.
I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.
You can explore the course here:
Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.
Get started with Spring Data JPA through the guided reference course:
Refactor Java code safely β and automatically β with OpenRewrite.
Refactoring big codebases by hand is slow, risky, and easy to put off. Thatβs where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.
Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions β one for newcomers and one for experienced users. Youβll see how recipes work, how to apply them across projects, and how to modernize code with confidence.
Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.
1. Introduction
Netflix Ribbon is an Inter Process Communication (IPC) cloud library. Ribbon primarily provides client-side load balancing algorithms.
Apart from the client-side load balancing algorithms, Ribbon provides also other features:
- Service Discovery Integration β Ribbon load balancers provide service discovery in dynamic environments like a cloud. Integration with Eureka and Netflix service discovery component is included in the ribbon library
- Fault Tolerance β the Ribbon API can dynamically determine whether the servers are up and running in a live environment and can detect those servers that are down
- Configurable load-balancing rules β Ribbon supports RoundRobinRule, AvailabilityFilteringRule, WeightedResponseTimeRule out of the box and also supports defining custom rules
Ribbon API works based on the concept called βNamed Clientβ. While configuring Ribbon in our application configuration file we provide a name for the list of servers included for the load balancing.
Letβs take it for a spin.
2. Dependency Management
The Netflix Ribbon API can be added to our project by adding the below dependency to our pom.xml:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
The latest libraries can be found here.
3. Example Application
In order to see the working of Ribbon API, we build a sample microservice application with Spring RestTemplate and we enhance it with Netflix Ribbon API along with Spring Cloud Netflix API.
Weβll use one of Ribbonβs load-balancing strategies, WeightedResponseTimeRule, to enable the client side load balancing between 2 servers, which are defined under a named client in the configuration file, in our application.
4. Ribbon Configuration
Ribbon API enables us to configure the following components of the load balancer:
- Rule β Logic component which specifies the load balancing rule we are using in our application
- Ping β A Component which specifies the mechanism we use to determine the serverβs availability in real-time
- ServerList β can be dynamic or static. In our case, we are using a static list of servers and hence we are defining them in the application configuration file directly
Let write a simple configuration for the library:
public class RibbonConfiguration {
@Autowired
IClientConfig ribbonClientConfig;
@Bean
public IPing ribbonPing(IClientConfig config) {
return new PingUrl();
}
@Bean
public IRule ribbonRule(IClientConfig config) {
return new WeightedResponseTimeRule();
}
}
Notice how we used the WeightedResponseTimeRule rule to determine the server and PingUrl mechanism to determine the serverβs availability in real-time.
According to this rule, each server is given a weight according to its average response time, lesser the response time gives lesser the weight. This rule randomly selects a server where the possibility is determined by serverβs weight.
And the PingUrl will ping every URL to determine the serverβs availability.
5. application.yml
Below is the application.yml configuration file we created for this sample application:
spring:
application:
name: spring-cloud-ribbon
server:
port: 8888
ping-server:
ribbon:
eureka:
enabled: false
listOfServers: localhost:9092,localhost:9999
ServerListRefreshInterval: 15000
In the above file, we specified:
- Application name
- Port number of the application
- Named client for the list of servers: βping-serverβ
- Disabled Eureka service discovery component, by setting eureka: enabled to false
- Defined the list of servers available for load balancing, in this case, 2 servers
- Configured the server refresh rate with ServerListRefreshInterval
6. RibbonClient
Letβs now set up the main application component snippet β where we use the RibbonClient to enable the load balancing instead of the plain RestTemplate:
@SpringBootApplication
@RestController
@RibbonClient(
name = "ping-a-server",
configuration = RibbonConfiguration.class)
public class ServerLocationApp {
@Autowired
RestTemplate restTemplate;
@RequestMapping("/server-location")
public String serverLocation() {
return this.restTemplate.getForObject(
"http://ping-server/locaus", String.class);
}
public static void main(String[] args) {
SpringApplication.run(ServerLocationApp.class, args);
}
}
And hereβs the RestTemplate configuration:
@Configuration
public class RestTemplateConfiguration{
@LoadBalanced
@Bean
RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
We defined a controller class with the annotation @RestController; we also annotated the class with @RibbonClient with a name and a configuration class.
The configuration class we defined here is the same class that we defined before in which we provided the desired Ribbon API configuration for this application.
Notice we annotated the RestTemplate with @LoadBalanced which suggests that we want this to be load balanced and in this case with Ribbon.
7. Failure Resiliency in Ribbon
As we discussed earlier in this article, Ribbon API not only provides client side load balancing algorithms but also it has built in failure resiliency.
As stated before, Ribbon API can determine the serverβs availability through the constant pinging of servers at regular intervals and has a capability of skipping the servers which are not live.
In addition to that, it also implements Circuit Breaker pattern to filter out the servers based on specified criteria.
The Circuit Breaker pattern minimizes the impact of a server failure on performance by swiftly rejecting a request to that server that is failing without waiting for a time-out. We can disable this Circuit Breaker feature by setting the property niws.loadbalancer.availabilityFilteringRule.filterCircuitTripped to false.
When all servers are down, thus no server is available to serve the request, the pingUrl() will fail and we receive an exception java.lang.IllegalStateException with a message βNo instances are available to serve the requestβ.
8. Conclusion
In this article, we discussed Netflix Ribbon API and its implementation in a simple sample application.
