一、概述
Ribbon是为了实现服务与服务之间调用的负载均衡,是客户端负载均衡,并且默认采用轮询的策略。(类似于Nginx,但是Ribbon是用于服务端的,Nginx是客户端的)
找官方文档
根据文档配置pom依赖
代码语言:javascript复制<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
启动类上加LoadBalance注解
代码语言:javascript复制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,改成直接访问就可以
代码语言:javascript复制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中修改它的端口号
代码语言:javascript复制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也修改一下它的内容让它们有所区分
代码语言:javascript复制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中的启动类,注解中的(随机效果)
代码语言:javascript复制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配置响应时间权重的负载均衡
代码语言:javascript复制PROVIDER:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightResponseTimeRule
重启,先以轮训开始,然后根据响应时间分配权重