Using the Ribbon
Simple to use
Write a production terminal and a consumer terminal. Start the two production terminals. Then the consumer terminal accesses the production terminal through the load balancing function of the Ribbon.
The production end
- Introduction of depend on
- Writing configuration files
- Start the class
- The controller class
The project structure
The overall project structure is shown below
Introduction of depend on
To introduce dependencies in the parent project, refer to the previous Nacos usage tips, and the subproject POM.xml file is
<? The XML version = "1.0" encoding = "utf-8"? > < project XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" Xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > < the parent > < artifactId > Learn < / artifactId > < groupId > zyz. SpringCloudAlibaba < / groupId > < version > 1.0 - the SNAPSHOT < / version > < / parent > The < modelVersion > 4.0.0 < / modelVersion > < artifactId > ribbon - produce < / artifactId > < dependencies > < the dependency > <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>Copy the code
Writing configuration files
Write the configuration file application.yml
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
application:
name: ribbon-provider
server:
port: 8081
Copy the code
Creating a Startup Class
Create the RibbonProvider startup class
package com.zyz; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class RibbonProvider { public static void main(String[] args) { SpringApplication.run(RibbonProvider.class, args); }}Copy the code
A new Controller class
package com.zyz.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @Slf4j @RestController public class ProviderController { @GetMapping(value = "/ribbon/provider/{string}") public String echo(@PathVariable String string){ log.info("Receive this request"); return "Hello Ribbon provider Discovery " + string; }}Copy the code
Introduce the logging annotation @slf4j
reference
The consumer end
- Introduction of depend on
- Writing configuration files
- Start the class
- The configuration class
- The controller class
Overall project structure
The overall project structure is shown below
Introduction of depend on
<? The XML version = "1.0" encoding = "utf-8"? > < project XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" Xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > < the parent > < artifactId > Learn < / artifactId > < groupId > zyz. SpringCloudAlibaba < / groupId > < version > 1.0 - the SNAPSHOT < / version > < / parent > The < modelVersion > 4.0.0 < / modelVersion > < artifactId > ribbon - consumer < / artifactId > < dependencies > < the dependency > <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> </dependencies> </project>Copy the code
Writing configuration files
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
application:
name: ribbon-consumer
server:
port: 8083
Copy the code
Start the class
package com.zyz; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class RibbonConsumer { public static void main(String[] args) { SpringApplication.run(RibbonConsumer.class,args); }}Copy the code
The configuration class
package com.zyz.config; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class WebConfig { @LoadBalanced @Bean public RestTemplate restTemplate(){ return new RestTemplate(); }}Copy the code
The controller class
package com.zyz.contorller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController public class ConsumerController { @Autowired private RestTemplate restTemplate; @GetMapping(value = "/ribbon/consumer/{str}") public String rest(@PathVariable String str){ return restTemplate.getForObject("http://ribbon-provider/ribbon/provider/" + str, String.class); }}Copy the code
Start the project
Start the two production ends and use the consumer side for access to verify the results
Start the skills
The production port is 8081. After starting a service with 8081, we can change the port to 8082 and modify the following figure. Then we can start two instances of the same project
Mac: Select Allow Parallel Run
Authentication is successful
The Ribbon’s built-in load balancing algorithm
RandomRule
Select a Server at random
RetryRule
The retry mechanism is added to the load balancing policy. If the Server selection fails during the configuration period, the system tries to use subRule to select an available Server
RoundRobinRule
Poll Select, poll index, and select the Server corresponding to index
AvailabilityFilteringRule
Filter out back-end servers tagged with circuit tripped that repeatedly failed to connect and filter out those with high concurrency or use an AvailabilityPredicate that includes the logic to filter servers, Check the running status of each Server recorded in status
BestAvailableRule
Pick a Server with minimal concurrent requests, inspect servers one by one, and skip them if they tripped.
WeightedResponseTimeRule
Based on response time weighting, the longer the response time, the smaller the weight and the lower the probability of being selected
ZoneAvoidanceRule (default is this)
Compound judge the performance of the Zone where the Server resides and the availability of the Server select the Server. In the case of no Zone, the class is polling.
Ribbon custom load balancing policies
The Ribbon also supports custom configuration load balancing policies, such as random order centers and polling inventory centers.
Three services are set up, the first an order center, the second an inventory center, and the third a caller.
The order center
- Introduction of depend on
- Writing configuration files
- Start the class
- The controller class
The overall structure
Introduction of depend on
<? The XML version = "1.0" encoding = "utf-8"? > < project XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" Xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > < the parent > < artifactId > Learn < / artifactId > < groupId > zyz. SpringCloudAlibaba < / groupId > < version > 1.0 - the SNAPSHOT < / version > < / parent > The < modelVersion > 4.0.0 < / modelVersion > < artifactId > ribbon - product < / artifactId > < dependencies > < the dependency > <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>Copy the code
Writing configuration files
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
application:
name: ribbon-product
server:
port: 8081
Copy the code
Start the class
package com.zyz; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class RibbonProduct { public static void main(String[] args) { SpringApplication.run(RibbonProduct.class, args); }}Copy the code
Controlelr class
package com.zyz.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController @Slf4j public class ProductController { @GetMapping(value = "/ribbon/product/{string}") public String echo(@PathVariable String string){ log.info("Receive this request"); return "Hello Ribbon product Discovery " + string; }}Copy the code
Inventory center
- Introduction of depend on
- Writing configuration files
- Start the class
- The controller class
Introduction of depend on
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Copy the code
Writing configuration files
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
application:
name: ribbon-order
server:
port: 8083
Copy the code
Start the class
package com.zyz; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class RibbonOrder { public static void main(String[] args) { SpringApplication.run(RibbonOrder.class, args); }}Copy the code
The controller class
package com.zyz.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController @Slf4j public class OrderController { @GetMapping(value = "/ribbon/order/{str}") public String order(@PathVariable String string){ log.info("Receive this request"); return "Hello Ribbon order Discovery " + string; }}Copy the code
The client
- Introduction of depend on
- Write configuration files (including load balancing configuration policies)
- Start the class
- The controller class
- The configuration class
The overall structure
Introduction of depend on
<? The XML version = "1.0" encoding = "utf-8"? > < project XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" Xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > < the parent > < artifactId > Learn < / artifactId > < groupId > zyz. SpringCloudAlibaba < / groupId > < version > 1.0 - the SNAPSHOT < / version > < / parent > The < modelVersion > 4.0.0 < / modelVersion > < artifactId > ribbon - app < / artifactId > < dependencies > < the dependency > <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>Copy the code
Writing configuration files
spring: cloud: nacos: discovery: server-addr: localhost:8848 application: name: ribbon-app server: port: 8088 ribbon-order: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule ribbon-product: ribbon: NFLoadBalancerRuleClassName: com.net flix. Loadbalancer. RoundRobinRule # open ribbon hunger load, solve the service call for the first time under the condition of slow ribbon: eager - load: Clients: ribbon-order,ribbon-productCopy the code
Start the class
package com.zyz; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class RibbonApp { public static void main(String[] args) { SpringApplication.run(RibbonApp.class, args); }}Copy the code
The controller class
package com.zyz.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @Slf4j @RestController public class RibbonController { @Autowired private RestTemplate restTemplate; @GetMapping(value = "/ribbon/app/product/{str}") public String product(@PathVariable String str){ return restTemplate.getForObject("http://ribbon-product/ribbon/product/" + str, String.class); } @GetMapping(value = "/ribbon/app/order/{str}") public String order(@PathVariable String str){ return restTemplate.getForObject("http://ribbon-order/ribbon/order/" + str, String.class); }}Copy the code
The configuration class
package com.zyz.config; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class WebConfig { @LoadBalanced @Bean public RestTemplate restTemplate(){ return new RestTemplate(); }}Copy the code
Ribbon common parameter description
Commonly used parameters
The Ribbon customizes load balancing policies
Nacos supports weight configuration, which is a useful feature, such as:
- Set low weights for poor machines and high weights for good machines, so that requests are sent to high machines first
- When an instance is abnormal, set the weight low, troubleshoot the problem, and then restore the weight after troubleshooting
- When you want to take an instance offline, set the weight of the instance to 0 so that traffic does not flow to it — then take it offline gracefully
Let’s extend the Ribbon to support Nacos weight configuration
Custom weight rule class
package com.zyz.rule; import com.alibaba.cloud.nacos.NacosDiscoveryProperties; import com.alibaba.cloud.nacos.ribbon.NacosServer; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.naming.NamingService; import com.alibaba.nacos.api.naming.pojo.Instance; import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.AbstractLoadBalancerRule; import com.netflix.loadbalancer.BaseLoadBalancer; import com.netflix.loadbalancer.Server; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @Slf4j public class WeightRule extends AbstractLoadBalancerRule { @Autowired private NacosDiscoveryProperties discoveryProperties; } @override public void initWithNiwsConfig(IClientConfig IClientConfig) Server choose(Object key) { try { log.info("key:{}",key); BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer) this.getLoadBalancer(); log.info("baseLoadBalancer--->:{}",baseLoadBalancer); String serviceName = baseloadbalancer.getName (); / / for Nacos service discovery related component API NamingService NamingService = discoveryProperties. NamingServiceInstance (); / / get a nacos based client achieve weight load balancing algorithm Instance Instance. = namingService selectOneHealthyInstance (serviceName); Return new NacosServer(instance); }catch (NacosException e){log.error(" error "); } return null; }}Copy the code
Add the configuration
ribbon-product:
ribbon:
NFLoadBalancerRuleClassName: com.zyz.rule.WeightRule
Copy the code