1. Introduction to Ribbon:
Ribbon is a service that provides load balancing functions for clients. It internally provides an interface called ILoadBalance to represent the operations of the load balancer, such as adding server operations, selecting server operations, obtaining all server lists, and obtaining available server lists. and many more.
issues that need resolving:
- ① How to not hard-code the address of Eureka Server when configuring Eureka Client registration center?
- ② When communicating between different modules of a microservice, how do you not hard-code the address of the service provider?
- ③ When deploying multiple same microservices, how to achieve load balancing at request?
What is Ribbon?
Second, SpringCloud's Ribbon entry case
<!-- eureka包含Ribbon依赖jar包 spring-cloud-netflix-ribbon--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
② How to use Ribbon
@Bean @LoadBalanced public RestTemplate restTemplate () { return new RestTemplate (); }
③ How to solve hard coding
When using RestTemplate with the @LoadBalanced annotation to call the service provider's interface, you can use the virtual IP instead of the real IP address . The so-called virtual IP is the value of the spring.application.name property configured by the service provider in the application.properties or yml file . Examples are as follows:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import com.qxj.cloud.entity.User; @RestController public class MovieController { @Autowired private RestTemplate restTemplate; @RequestMapping(value="/movie/{id}",method = RequestMethod.GET,produces="application/json;charset=UTF-8") public User findById(@PathVariable Long id) {
//微服务的虚拟id http://provider-user User user = this.restTemplate.getForObject("http://provider-user:7900/simple/" + id, User.class); return user; } }
Small summary: After the integration of Ribbon and Eureka, Consumer can directly call the service without caring about the ip address and port number
Microservice (service provider) cluster construction:Machine 1
server:
port: 7900
spring:
application:
name: provider-user
#eureka client connection configuration
eureka:
client:
service-url:
#Registration
center address defaultZone: http: // user: password123 @ localhost: 8761 / eureka
instance :
#Register ip to eureka
prefer-ip-address: true
#Microservice registers eureka with instance name $ {spring.cloud.client.ip-address} means ip address
instance-id: $ {spring.application.name} : $ {spring.cloud.client.ip-address}: $ {spring.application.instance_id: $ {server.port}}
Machine 2
server:
port: 7901
spring:
application:
name: provider-user
#eurekaClient connection configuration
eureka:
client:
service-url:
#Registration
center address defaultZone: http: // user: password123 @ localhost: 8761 / eureka
instance: #Register
ip to eureka
prefer-ip-address: true
#Micro service registers instance name with eureka $ {spring.cloud.client.ip-address} indicates the ip address
instance-id: $ {spring.application.name}: $ {spring.cloud.client.ip-address}: $ {spring.application.instance_id: $ { server.port))
Machine 3
server:
port: 7902
spring:
application:
name: provider-user
#eureka client connection configuration
eureka:
client:
service-url:
instance:
center address
defaultZone: http: // user: password123 @ localhost: 8761 / eureka #Register
#Register ip to eureka
prefer-ip-address: true
#Microservice registers eureka with instance name $ {spring.cloud.client.ip-address} means ip address
instance-id: $ {spring.application.name}: $ {spring.cloud.client.ip-address}: $ {spring.application.instance_id: $ {server.port}}
The {Spring.application.name} is the same and cannot be changed.
Three, Ribbon component IRule
The default is RoundBobinRule (Poll)
Four, custom load balancing algorithm:
The main function of the so-called custom Ribbon Client is to use a custom configuration to replace the Ribbon's default load balancing strategy. Note: The custom Ribbon Client is targeted. Generally, a custom Ribbon Client is for a service provider (including A series of copies with the same service name). A Ribbon Client has been customized. The load balancing strategy set by it is only valid for the service provider of a specific service name, but it cannot affect the strategy used by the service consumer to communicate with other service providers. According to the meaning of the official documentation, it is recommended to customize the configuration class outside the scope of the package scanned by the springboot main program . In fact, there are two ways to customize RibbonClient with pure code:
Method 1: Define the configuration class outside the package scanned by the springboot main program, and then add the @RibbonClient annotation to the springboot main program to introduce the configuration class .import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework .cloud.netflix.ribbon.RibbonClient; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; import com.qxj.configuration.MySelfRule; @SpringBootApplication // This annotation indicates that the application is both The eureka instance is the eureka client and can discover the registered service @EnableEurekaClient //When starting the microservice , we can load our custom Ribbon configuration class, so that the configuration takes effect @RibbonClient (name = "provider-user", configuration = MySelfRule. Class ) public class ConsumerMovieRibbonApplication { @Bean @LoadBalanced public RestTemplate restTemplate () { return new RestTemplate (); } public static void main (String [] args) { SpringApplication.run (ConsumerMovieRibbonApplication. class , args); } }
Rule configuration file, configuration, and should not be in the package path SpringBoot , by @RibbonClient comment Load:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.netflix.loadbalancer.IRule; @Configuration public class MySelfRule { @Bean public IRule MyRule() { return new RandomRule_QXJ(); } }
Custom LoadBalance:
import java.util.List; import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.AbstractLoadBalancerRule; import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.Server; public class RandomRule_QXJ extends AbstractLoadBalancerRule { private int total = 0; // The total number of calls, currently requires each call 5 times private int currentIndex = 0; // Currently provided service machine number / ** * Service selection algorithm, requires each call 5 times * @param lb * @paramkey * @return * / public Server choose (ILoadBalancer lb, Object key) { if (lb == null ) { return null ; } Server server = null ; while (server == null ) { // Determine whether the current thread is interrupted / / interrupted () is a static method: the internal implementation is called isInterrupted () of the current thread, and will reset the interruption status of the current thread if (Thread.interrupted ()) { return null ; } // Activate available services List <Server> upList = lb.getReachableServers (); // All services List <Server> allList = lb.getAllServers (); int serverCount = allList.size (); if (serverCount == 0 ) { return null ; } if (total <5 ) { server = upList.get (currentIndex); total ++ ; } else { total = 0 ; // Use the next machine service currentIndex ++ ; // If the current service machine is the last one in the upList collection, reuse the first machine service if (currentIndex> = upList.size ()) { currentIndex = 0 ; } } System.out.println ( "currentIndex: "+ currentIndex +" --- total: "+ total); // When looping to the first service, server == null, you need to reacquire server if (server == null ) { Thread.yield (); continue ; } if (server.isAlive ()) { return server; } // This code will not actually execute server = null ; Thread.yield (); } return server; } @Override public Server choose (Object key) { return choose (getLoadBalancer (), key); } @Override public void initWithNiwsConfig (IClientConfig clientConfig) { } }
Method 2: Application.yml file configuration method
# @ RibbonClient (name = "provider-user") Same as name, it means to use custom load balancing rules for this
microservice
provider-user:
ribbon: NFLoadBalancerRuleClassName: com.qxj.configuration.RandomRule_QXJ
Configured priority
Priority of configuration file> Java code configuration method> netflix custom configuration method
Copyright Statement: This article is an original article of CSDN blogger "An Xiaoyan said he is busy", following the CC 4.0 BY-SA copyright agreement, please attach the original text for reprint Source link and this statement.
Original link: https://blog.csdn.net/JinXYan/java/article/details/90726707