一、概述
Ribbon是為了實作服務與服務之間調用的負載均衡,是用戶端負載均衡,并且預設采用輪詢的政策。(類似于Nginx,但是Ribbon是用于服務端的,Nginx是用戶端的)
找官方文檔
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICMyYTMvw1dvwlMvwlM3VWaWV2Zh1Wa-cmbw5yNv9mN4xWMvNDOvwlN3UTO1gzNtUGall3LcVmdhNXLwRHdo9CXt92YucWbpRWdvx2Yx5yazF2Lc9CX6MHc0RHaiojIsJye.png)
根據文檔配置pom依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
複制
啟動類上加LoadBalance注解
package com.qf.springcloud.consumer;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
@EnableHystrixDashboard
@ServletComponentScan(basePackages = "com.qf.springcloud.consumer")
public class ConsumerStarterApp {
public static void main(String[] args) {
SpringApplication.run(ConsumerStarterApp.class,args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
// @Bean
// public IRule randomRule(){
// return new RandomRule();
// }
}
複制
修改controller,改成直接通路就可以
package com.qf.springcloud.consumer.controller;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.qf.springcloud.consumer.client.ProviderClient;
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.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
@RestController
public class ConsumerController {
/*@Autowired
private EurekaClient eurekaClient;*/
@Autowired
private RestTemplate restTemplate;
@Autowired
private ProviderClient providerClient;
@GetMapping("/consumer/test")
public String test() throws InterruptedException {
/*//1. 通過Eureka擷取PROVIDER服務的ip和port
InstanceInfo provider = eurekaClient.getNextServerFromEureka("PROVIDER", false);
String ip = provider.getIPAddr();
int port = provider.getPort();
//2. 通過RestTemplate調用provider的/provider/test
String result = restTemplate.getForObject("http://" + ip + ":" + port + "/provider/test", String.class);*/
/*
//1. 通路目标服務
String result = restTemplate.getForObject("http://PROVIDER/provider/test", String.class);
*/
Thread.sleep(2000);
System.out.println("test:" + Thread.currentThread().getName());
String result = providerClient.test();
//3. 傳回結果
return result;
}
@GetMapping("/param/test/{type}")
/*
@HystrixCommand(fallbackMethod = "paramTestFallback",commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled",value = "true"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "20"),
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "30000"),
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "10")
})
*/
public Map paramTest(@PathVariable Integer type) throws InterruptedException {
System.out.println("paramTest:" + Thread.currentThread().getName());
if (type == 1){
// path
return providerClient.path(123);
}else if (type == 2){
int i = 1 / 0;
// param
return providerClient.param("張老三",233);
}else{
// body
Map map = new HashMap();
map.put("abcdefg","hijklmn");
return providerClient.body(map);
}
}
public Map paramTestFallback(Integer type){
System.out.println("paramTestFallback:" + Thread.currentThread().getName());
Map map = new HashMap();
map.put("msg","我的Consumer自己出現了問題");
return map;
}
}
複制
為了掩飾負載均衡,是以我們建立多個provider,複制原來的provider,在application.yml中修改它的端口号
spring:
application:
# 指定服務名稱
name: provider
eureka:
client:
service-url:
# 指定注冊到的eureka的位址資訊
defaultZone: http://admin:admin@localhost:8761/eureka/,http://admin:admin@localhost:8762/eureka/
server:
port: 8081
複制
在controller也修改一下它的内容讓它們有所區分
package com.qf.springcloud.provider.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProviderController {
@Value("${server.port}")
private String port;
@GetMapping("/provider/test")
public String test(){
return "Hello Eureka!!!" + port;
}
}
複制
重新開機consumer,實作負載均衡(預設輪詢)
使用注解或者yml來修改複雜均衡政策
修改consumer中的啟動類,注解中的(随機效果)
package com.qf.springcloud.consumer;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
@EnableHystrixDashboard
@ServletComponentScan(basePackages = "com.qf.springcloud.consumer")
public class ConsumerStarterApp {
public static void main(String[] args) {
SpringApplication.run(ConsumerStarterApp.class,args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
// @Bean
// public IRule randomRule(){
// return new RandomRule();
// }
}
複制
使用yml配置響應時間權重的負載均衡
PROVIDER:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightResponseTimeRule
複制
重新開機,先以輪訓開始,然後根據響應時間配置設定權重