- Ribbon负载均衡(客户端)
书签:
(1)@LoadBalanced 负载均衡
(2)Ribbon自带的负载规则
(3)Ribbon自定义负载规则
- @LoadBalanced 负载均衡
复制项目eureka-provider,生成eureka-provider-2,修改eureka-provider-2的端口成8091即可,请求返回的信息改变一下:
@GetMapping("/t") public Object t(){ return "msg from provider-2";// 后面加个2,方便对比 } |
修改eureka-consumer项目启动类:主要是加上注解@LoadBalanced;请求服务提供者用服务名
package cn.ywj.eurekaconsumer;
import com.netflix.appinfo.InstanceInfo; import com.netflix.discovery.EurekaClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.ribbon.RibbonClient; import org.springframework.context.annotation.Bean; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate;
@SpringBootApplication @RestController public class EurekaConsumerApplication {
@Bean @LoadBalanced public RestTemplate getRestTemplate () {// 注入一个RestTemplate return new RestTemplate() ; }
@Autowired private RestTemplate restTemplate;
//@Autowired //private EurekaClient eurekaClient;
@RequestMapping("/t") public Object t(){
//InstanceInfo instanceInfo = eurekaClient.getNextServerFromEureka("EUREKA-PROVIDER", false);// 通过服务名可以拿到地址 String str = restTemplate.getForObject("http://EUREKA-PROVIDER/t", String.class);// 直接用服务名请求 return str; }
public static void main(String[] args) { SpringApplication.run(EurekaConsumerApplication.class, args); } } |
启动eureka-consumer项目,访问:http://localhost:8082/t 返回的结果有时是:msg from provider,有时是:msg from provider-2,轮来轮去。
- Ribbon自带的负载规则
package cn.ywj.eurekaconsumer;
import com.netflix.loadbalancer.*; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
@Configuration public class RibbonConfiguration {
@Bean public IRule ribbonRule() { return new RoundRobinRule();// 轮循算法
/* 相关算法
一、RoundRobinRule :系统默认的规则,通过简单地轮询服务列表来选择服务器
二、AvailabilityFilteringRule 该规则会忽略以下服务器
1、无法连接的服务器 在默认情况下,如果 次连接失败,该服务器将会被置为“路”的状态,该状态将持续 30 秒;如果再次连接失败, “短路”状态的持续时间 将会以几何级数增加。可以通过修改 niws.loadbalancer. <clientName>.connectionFailureCountThreshold 属性,来配置连接失败的次数
2、并发数过高的服务器:如果连接到该服务器的并发数过高,也会被这个规则忽略,可以通过修改< lientName> .ribbon.ActiveConnectionsLirnit 属性 来设最高并发数
三、WeightedResponseTimeRule :为每个服务器赋予一个权重值 服务器的响应时间越长,该权重值就越少,这个规则会随机选择服务器,权重值有可能会决定服务器选择
四、ZoneAvoidanceRule :该规则以区域、可用服务器为基础进行服务器选择。使用 Zone对服务器进行分类,可以理解为机架或者机房
五、BestAvailableRule :忽略“短路”的服务器,并选择并发数较低的服务器。
六、RandomRule :顾名思义,随机选择可用的服务器。
七、RerRule 含有重试的选择逻辑,如果使用 RoundRobinRule 选择的服务器无法连接,那么将会重新选择服务器。*/ } } |
- Ribbon自定义负载规则
参考RandomRule.java类,简单自定义一个规则 -- 只访问第一个服务
创建DiyRibbon.java
DiyRibbon.java不能被@ComponentScan扫到!
DiyRibbon.java不能被@ComponentScan扫到!
DiyRibbon.java不能被@ComponentScan扫到!
package diy.ribbon;
import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.AbstractLoadBalancerRule; import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.Server;
import java.util.List; import java.util.concurrent.ThreadLocalRandom;
/** * 此类不能被@ComponentScan扫到 */ public class DiyRibbon extends AbstractLoadBalancerRule {
@Override public void initWithNiwsConfig(IClientConfig iClientConfig) {
}
@Override public Server choose(Object o) { return choose(getLoadBalancer(), o); }
protected int chooseRandomInt(int serverCount) { return ThreadLocalRandom.current().nextInt(serverCount); } public Server choose(ILoadBalancer lb, Object key) { if (lb == null) { return null; } List<Server> upList = lb.getReachableServers(); System.out.println("--->"+upList.size()); if(upList != null && upList.size() > 0){ return upList.get(0);// 拿第一个 } return null; } } |
创建配置类:RibbonConfiguration.java
package cn.ywj.eurekaconsumer;
import com.netflix.loadbalancer.*; import diy.ribbon.DiyRibbon; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
@Configuration public class RibbonConfiguration {
@Bean public IRule ribbonRule() {
return new DiyRibbon();// 自定义负载规则
//return new RoundRobinRule();// 轮循算法
/* 相关算法
一、RoundRobinRule :系统默认的规则,通过简单地轮询服务列表来选择服务器
二、AvailabilityFilteringRule 该规则会忽略以下服务器
1、无法连接的服务器 在默认情况下,如果 次连接失败,该服务器将会被置为“路”的状态,该状态将持续 30 秒;如果再次连接失败, “短路”状态的持续时间 将会以几何级数增加。可以通过修改 niws.loadbalancer. <clientName>.connectionFailureCountThreshold 属性,来配置连接失败的次数
2、并发数过高的服务器:如果连接到该服务器的并发数过高,也会被这个规则忽略,可以通过修改< lientName> .ribbon.ActiveConnectionsLirnit 属性 来设最高并发数
三、WeightedResponseTimeRule :为每个服务器赋予一个权重值 服务器的响应时间越长,该权重值就越少,这个规则会随机选择服务器,权重值有可能会决定服务器选择
四、ZoneAvoidanceRule :该规则以区域、可用服务器为基础进行服务器选择。使用 Zone对服务器进行分类,可以理解为机架或者机房
五、BestAvailableRule :忽略“短路”的服务器,并选择并发数较低的服务器。
六、RandomRule :顾名思义,随机选择可用的服务器。
七、RerRule 含有重试的选择逻辑,如果使用 RoundRobinRule 选择的服务器无法连接,那么将会重新选择服务器。*/ } } |
启动类加入注解:@RibbonClient
package cn.ywj.eurekaconsumer;
import com.netflix.appinfo.InstanceInfo; import com.netflix.discovery.EurekaClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.cloud.netflix.ribbon.RibbonClient; import org.springframework.context.annotation.Bean; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate;
import java.net.MalformedURLException; import java.net.URI;
@SpringBootApplication @RestController @RibbonClient(name = "eureka-provider", configuration = RibbonConfiguration.class)// name是服务注册者 public class EurekaConsumerApplication {
@Bean @LoadBalanced public RestTemplate getRestTemplate () {// 注入一个RestTemplate return new RestTemplate() ; }
@Autowired private RestTemplate restTemplate;
//@Autowired //private EurekaClient eurekaClient;
@RequestMapping("/t") public Object t(){
//InstanceInfo instanceInfo = eurekaClient.getNextServerFromEureka("EUREKA-PROVIDER", false);// 通过服务名可以拿到地址 String str = restTemplate.getForObject("http://EUREKA-PROVIDER/t", String.class);// 直接用服务名请求 return str; }
public static void main(String[] args) { SpringApplication.run(EurekaConsumerApplication.class, args); } } |
测试结果:怎么刷新都只是返回第一个provider返回的信息。。。OK