前面已经使用Ribbon实现了路由,通过测试,也不难发现默认Ribbon使用的路由策略是轮询,可以看下源代码BaseLoadBalancer
04.自定义Ribbon路由 - 图1

1.全局路由配置

这种负载均衡的策略其实也是可以由用户来修改的,如果想要去修改,可以使用自定义的LoadBalance

【microcloud-consumer】 修改RestConfig
package cn.enjoy.config;


import com.netflix.loadbalancer.IRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.Charset;
import java.util.Base64;

@Configuration
public class RestConfig {

@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}

@Bean
public HttpHeaders getHeaders() { // 要进行一个Http头信息配置
HttpHeaders headers = new HttpHeaders(); // 定义一个HTTP的头信息
String auth = “root:enjoy”; // 认证的原始信息
byte[] encodedAuth = Base64.getEncoder()
.encode(auth.getBytes(Charset.forName(“US-ASCII”))); // 进行一个加密的处理
String authHeader = “Basic “ + new String(encodedAuth);
headers.set(“Authorization”, authHeader);
return headers;
}

@Bean
public IRule ribbonRule() { // 其中IRule就是所有规则的标准
return new com.netflix.loadbalancer.RandomRule(); // 随机的访问策略
}

}


这个时候重启测试发现,默认的路由规则已经变成了随机

2.单独设置某个Ribbon的路由

有时候,某个消费者可能需要访问多个多个服务提供方,而希望每个服务提供方提供的路由规则并不相同,这个时候就不能让Spring扫描到IRULE,需要通过@RibbonClient 来指定服务于配置的关系
【microcloud-consumer】 修改RestConfig,删除IRULE
package cn.enjoy.config;


import com.netflix.loadbalancer.IRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.Charset;
import java.util.Base64;

@Configuration
public class RestConfig {

@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}

@Bean
public HttpHeaders getHeaders() { // 要进行一个Http头信息配置
HttpHeaders headers = new HttpHeaders(); // 定义一个HTTP的头信息
String auth = “root:enjoy”; // 认证的原始信息
byte[] encodedAuth = Base64.getEncoder()
.encode(auth.getBytes(Charset.forName(“US-ASCII”))); // 进行一个加密的处理
String authHeader = “Basic “ + new String(encodedAuth);
headers.set(“Authorization”, authHeader);
return headers;
}

~~ @Bean
public IRule ribbonRule() { // 其中IRule就是所有规则的标准
return new com.netflix.loadbalancer.RandomRule(); // 随机的访问策略
}~~

}


【microcloud-consumer】新增一个路由规则的配置类,注意这个类不应该放到SpringCloud扫描不到的位置,否则又回变成全局的IRULE,所以这个时候应该单独使用一个新的包,着个包和启动并不在同一个包下
package cn.xiangxue.config;
import com.netflix.loadbalancer.IRule;
import org.springframework.context.annotation.Bean;

public class RibbonConfig {
@Bean
public IRule ribbonRule() { // 其中IRule就是所有规则的标准
return new com.netflix.loadbalancer.RandomRule(); // 随机的访问策略
}
}


【microcloud-consumer】 修改启动类,使用@RibbonClient指定配置类
package cn.enjoy;
import cn.xiangxue.config.RibbonConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.RibbonClients;

@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name =”MICROCLOUD-PROVIDER-PRODUCT” ,configuration = RibbonConfig.class)
public class ConsumerApp {
public static void main(String[] args) {
SpringApplication.run(ConsumerApp.class,args);
}
}


这里的name 只服务的名称,如果需要有多个服务提供方,这个时候可以使用@RibbonClients进行配置

3.服务提供方的信息获取

在服务的消费方,也是可以获取到服务提供方的具体信息

【microcloud-consumer】修改ConsumerProductController
package cn.enjoy.controller;


import cn.enjoy.vo.Product;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.List;

@RestController
@RequestMapping(“/consumer”)
public class ConsumerProductController {

public static final String PRODUCT_GET_URL = “http://MICROCLOUD-PROVIDER-PRODUCT/prodcut/get/“;
public static final String PRODUCT_LIST_URL=”http://MICROCLOUD-PROVIDER-PRODUCT/prodcut/list/“;
public static final String PRODUCT_ADD_URL = “http://MICROCLOUD-PROVIDER-PRODUCT/prodcut/add/“;

@Resource
private RestTemplate restTemplate;

@Resource
private HttpHeaders httpHeaders;

@Resource
private LoadBalancerClient loadBalancerClient;

@RequestMapping(“/product/get”)
public Object getProduct(long id) {
Product product = restTemplate.exchange(PRODUCT_GET_URL + id,HttpMethod.GET,new HttpEntity(httpHeaders), Product.class).getBody();
return product;
}

@RequestMapping(“/product/list”)
public Object listProduct() {
ServiceInstance serviceInstance = this.loadBalancerClient.choose(“MICROCLOUD-PROVIDER-PRODUCT”) ;
System.out.println(
“【 ServiceInstance 】host = “ + serviceInstance.getHost()
+ “、port = “ + serviceInstance.getPort()
+ “、serviceId = “ + serviceInstance.getServiceId());
List list = restTemplate.exchange(PRODUCT_LIST_URL,HttpMethod.GET,new HttpEntity(httpHeaders), List.class).getBody();
return list;
}

@RequestMapping(“/product/add”)
public Object addPorduct(Product product) {
Boolean result = restTemplate.exchange(PRODUCT_ADD_URL, HttpMethod.POST,new HttpEntity(product,httpHeaders), Boolean.class).getBody();
return result;
}

}