"It takes about 4 minutes to read this article"
In the previous five-minute guides to Spring Cloud, we have introduced several core components of Spring Cloud in turn, covering the fundamental functions required in a microservice architecture, such as service discovery, melting, centralized configuration.The protagonist presented today is also Ribbon by Netflix, which officially defines Ribbon as a library for remote calls and is better known for its ability to make client-side Load Balance s.
Load Balance is a necessary basic function for any distributed system and can be divided into client-side and server-side LBs from an implementation perspective.Server-based LB solutions, such as reverse proxy through nginx or commercial F5, are the most frequently touched solutions in your daily work.But today's example demonstrates how to build a client application with LB using Ribbon.Let's get started.
Basic concepts
Still in use https://start.spring.io/ To quickly build a Spring Boot project and add Ribbon dependencies as follows:
Before writing specific code, let's introduce the core concepts in Ribbon.
- Rule - This component determines the operation of returning that server address from a stack of candidate servers for remote calls.
- Ping - A component that runs in the background to confirm which servers are available for survival.
- ServerList - A list of servers currently available as LB that can be either static or dynamic.If the list is dynamic (for example, obtained from the Eurka server), a background thread refreshes the list at intervals.
Ribbon provides 3 Rule s built in for us to use:
- RoundRobinRule: The simplest rule, called in turn in the ServerList.
- AvailabilityFilteringRule: Under this rule, Ribbon integrates Hystrix functionality. By default, when a remote method is invoked three times and fails, the breaker switch is turned on, and Ribbon skips the server address in subsequent requests until the breaker is closed after 30 seconds before rejoining the call list.
- WeightedResponseTimeRule: A load rule that uses response time as a weight, and the longer a server responds, the lower its weight.When selecting a server, the server is selected randomly with weights.
To configure
Spring Cloud Ribbon supports a variety of configurations, most commonly configured in application.yml and other configuration files and programmatically.Let's first familiarize ourselves with the format of the configuration.The format <clientName>. <nameSpace>. <propertyName>=<value> describes the parameters, where clientName represents the Ribbon client-based name, while nameSpace is a similar configuration group concept and represents a set of configuration parameters.
Let's first look at the configuration of the official sample:
# Max number of retries on the same server (excluding the first try) sample-client.ribbon.MaxAutoRetries=1 # Max number of next servers to retry (excluding the first server) sample-client.ribbon.MaxAutoRetriesNextServer=1 # Whether all operations can be retried for this client sample-client.ribbon.OkToRetryOnAllOperations=true # Interval to refresh the server list from the source sample-client.ribbon.ServerListRefreshInterval=2000 # Connect timeout used by Apache HttpClient sample-client.ribbon.ConnectTimeout=3000 # Read timeout used by Apache HttpClient sample-client.ribbon.ReadTimeout=3000 # Initial list of servers, can be changed via Archaius dynamic property at runtime sample-client.ribbon.listOfServers=www.microsoft.com:80,www.yahoo.com:80,www.google.com:80
Then take a look at the official sample code:
public static void main(String[] args) throws Exception { ConfigurationManager.loadPropertiesFromResources("sample-client.properties"); // 1 System.out.println(ConfigurationManager.getConfigInstance().getProperty("sample-client.ribbon.listOfServers")); RestClient client = (RestClient) ClientFactory.getNamedClient("sample-client"); // 2 HttpClientRequest request = HttpClientRequest.newBuilder().setUri(new URI("/")).build(); // 3 for (int I = 0; I < 20; I++) { HttpClientResponse response = client.executeWithLoadBalancer(request); // 4 System.out.println("Status code for " + response.getRequestedURI() + " :" + response.getStatus()); } ZoneAwareLoadBalancer lb = (ZoneAwareLoadBalancer) client.getLoadBalancer(); System.out.println(lb.getLoadBalancerStats()); ConfigurationManager.getConfigInstance().setProperty( "sample-client.ribbon.listOfServers", "www.linkedin.com:80,www.google.com:80"); // 5 System.out.println("changing servers ..."); Thread.sleep(3000); // 6 for (int I = 0; I < 20; I++) { HttpClientResponse response = client.executeWithLoadBalancer(request); System.out.println("Status code for " + response.getRequestedURI() + " : " + response.getStatus()); response.releaseResources(); } System.out.println(lb.getLoadBalancerStats()); // 7 }
- Load configuration information from sample-client.properties.
- Initialize a client named sample-client through ClientFactory.
- Build an http request object that contains information about calling a remote endpoint.
- Perform remote calls.
- Modify the list of available servers.
- Re-invoke the remote method after the thread has been dormant for 3 seconds.
- Output LB execution information.
From the output of the run, we can see that in the first call, we output the server information in the configuration file in turn, microsoft, yahoo, and google.After we modify the configuration, the second call will see the list of servers change to linkedin and google.
Integration with Spring Cloud
Remote calls are common in the microservice architecture, so Spring Cloud integrates Ribbon to allow developers to optimize the process of remote calls.During the integration process with Spring Cloud, we first wrote the following configuration files:
spring: application: name: spring-cloud-ribbon server: port: 8888 ping-server: ribbon: eureka: enabled: false listOfServers: localhost:9092,localhost:9999 ServerListRefreshInterval: 15000
As mentioned earlier, we configure clientName as ping-server, namespace as ribbon, the optional list of servers is local localhost:9092 and localhost:9999, and the others are the default configurations.
Spring Cloud has already fully configured Ribbon for use with just a few comments.In the following example, we use the RestTemplate provided by Spring to make remote calls, and with a few simple annotations we can make the original normal RestTemplate load balancing and breaking. See the code below:
@SpringBootApplication @RestController @RibbonClient( name = "ping-a-server", configuration = RibbonConfiguration.class) public class ServerLocationApp { @LoadBalanced @Bean RestTemplate getRestTemplate() { return new RestTemplate(); } @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); } }
Where @RibbonClient will return Ribbon's wrapper object according to our previous configuration information, and the @LoadBalanced annotation will proxy the created ReestTemplate object to an object with Ribbon functionality that the user cannot perceive as different.
epilogue
With a few simple configurations and codes, load balancing and fusing can be incorporated into remote calls to our system. We'll show you how to integrate with Eureka, get a dynamic list of available servers from Eureka Server, and focus on my Public Number if you want to learn more about Ribbon and Micro Services.