Ribbon负载均衡和Feign负载均衡
- 篇幅较长,请配合目录观看
- 项目准备
- 1. Ribbon
- 1.1 LB(负载均衡)
- 1.2 相关链接
- 1.3 Ribbon核心组件IRule(面试题)
- 2. 新建springcloud-producer-8383项目(Module-Maven)
- 2.1 复制pom依赖
- 2.2 复制java代码
- 2.3 复制application.properties并修改
- 2.4 启动7001和8181,8282,8383
- 2.5 springcloud-consumer开启负载均衡
- 2.6 springcloud-consumer修改controller
- 2.7 重启程序入口并访问http://127.0.0.1:8282/list
- 2.7.1 通过下面的工具类测试
- 3. 修改负载均衡算法
- 3.1 springcloud-consumer配置application.properties
- 3.2 编写Test
- 3.3 启动程序类并运行test测试
- 4. 修改负载均衡算法第二种方式
- 4.1 注释掉第一种方式的配置
- 4.2 修改程序入口
- 4.3 运行test测试
- 5. Ribbon重置机制
- 5.1 springcloud-consumer导入依赖
- 5.2 application.properties配置
- 6. Feign负载均衡
- 6.1 相关链接
- 6.2 springcloud-consumer导包
- 6.3 编写UserClient
- 6.4 修改Controller
- 6.5 程序入口添加注解
- 6.6 访问接口
- 7 Feign集成带参方法
篇幅较长,请配合目录观看
项目准备
- 7001,8181,8282,8383改配置
eureka.client.service-url.defaultZone=http://eureka.7001.com:7001/eureka - 本章重点不在eureka
- 主Ribbon 次Feign
1. Ribbon
SpringCloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。
简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出LoadBalanCer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。
1.1 LB(负载均衡)
LB,即负载均衡( LoadBalanced ),在微服务或分布式集群中经常用的一种应用。
负载均衡简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA。
常见的负载均衡有软件nginx , LVS,硬件F5等。
相应的在中间件,例如:dubbo和 SpringCloud中均给我们提供了负载均衡,SpringCloud的负载均衡算法可以自定义。
1.2 相关链接
1.3 Ribbon核心组件IRule(面试题)
策略名称 | 策略对应的类名 | 实现原理 |
轮询策略(默认) | RoundRobinRule | 轮询策略表示每次都顺序取下一个 provider,比如一共有 5 个provider,第 1 次取第 1 个,第 2次取第 2 个,第 3 次取第 3 个,以此类推 |
权重轮询策略 | WeightedResponseTimeRule | 1.根据每个 provider 的响应时间分配一个权重,响应时间越长,权重越小,被选中的可能性越低。2.原理:一开始为轮询策略,并开启一个计时器,每 30 秒收集一次每个 provider 的平均响应时间,当信息足够时,每个 provider附上一个权重,并按权重随机选择provider,高权越重的 provider会被高概率选中。 |
随机策略 | RandomRule | 从 provider 列表中随机选择一个provider |
最少并发数策略 | BestAvailableRule | 选择正在请求中的并发数最小的 provider,除非这个provider 在熔断中。 |
在“选定的负载均衡策略”基础上进行重试机制 | RetryRule | 1.“选定的负载均衡策略”这个策略是轮询策略RoundRobinRule 2.该重试策略先设定一个阈值时间段,如果在这个阈值时间段内当选择 provider 不成功,则一直尝试采用“选定的负载均衡策略:轮询策略”最后选择一个可用的provider |
可用性敏感策略 | AvailabilityFilteringRule | 过滤性能差的 provider,有 2种:第一种:过滤掉在 eureka 中处于一直连接失败 provider 第二种:过滤掉高并发的 provider |
区域敏感性策略 | ZoneAvoidanceRule | 1.以一个区域为单位考察可用性,对于不可用的区域整个丢弃,从剩下区域中选可用的provider2.如果这个 ip 区域内有一个或多个实例不可达或响应变慢,都会降低该 ip 区域内其他 ip 被选中的权重。 |
2. 新建springcloud-producer-8383项目(Module-Maven)
2.1 复制pom依赖
2.2 复制java代码
2.3 复制application.properties并修改
server.port=8383
eureka.client.service-url.defaultZone=http://eureka.7001.com:7001/eureka
eureka.instance.instance-id=springcloud-producer-8383
eureka.instance.lease-expiration-duration-in-seconds=90
eureka.instance.lease-renewal-interval-in-seconds=30
2.4 启动7001和8181,8282,8383
2.5 springcloud-consumer开启负载均衡
package com.wpj.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
/**
* 远程调用的工具类 OkHttp客户端
*/
@Configuration
public class RestTemplateConfig {
// 这次我们使用了OkHttp客户端,只需要注入工厂即可
@Bean
@LoadBalanced // 开启负载均衡
public RestTemplate restTemplate(){
return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
}
}
2.6 springcloud-consumer修改controller
package com.wpj.controller;
import com.wpj.bean.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.context.annotation.Scope;
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
@Scope("prototype")
public class UserController {
@Resource
private RestTemplate restTemplate;
private static final String url="http://springcloud-producer";
@RequestMapping("/list")
public List<User> list(){
return this.restTemplate.getForObject(url+"/list",List.class);
}
}
2.7 重启程序入口并访问http://127.0.0.1:8282/list
在springcloud-producer和springcloud-producer-8383的Controller输出一段话
2.7.1 通过下面的工具类测试
3. 修改负载均衡算法
3.1 springcloud-consumer配置application.properties
# {服务名称}.ribbon.NFLoadBalancerRuleClassName
# 配置Ribbon的负载均衡的算法,默认轮询,修改为随机
SPRINGCLOUD-PRODUCER.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
3.2 编写Test
package com.wpj.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestRibbon {
@Resource
RibbonLoadBalancerClient client;
@Test
public void test1(){
for (int i = 1; i <=10 ; i++) {
ServiceInstance instance = client.choose("SPRINGCLOUD-PRODUCER");
String ip = instance.getHost();
int port = instance.getPort();
System.out.println(ip+":"+port);
}
}
}
3.3 启动程序类并运行test测试
4. 修改负载均衡算法第二种方式
4.1 注释掉第一种方式的配置
4.2 修改程序入口
package com.wpj;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableEurekaClient
public class ConsumerApplication {
/**
* 显示实例化 负载均衡的策略对象,那么默认的轮询策略就会失效
* @return
*/
@Bean
public RandomRule createRule(){
return new RandomRule();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
4.3 运行test测试
5. Ribbon重置机制
5.1 springcloud-consumer导入依赖
<!-- Ribbon重试机制-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
5.2 application.properties配置
# 配置重试机制
# 开启Spring Cloud的重试功能
spring.cloud.loadbalancer.retry.enabled=true
# Ribbon的连接超时时间
SPRINGCLOUD-PRODUCER.ribbon.ConnectTimeout=250
# Ribbon的数据读取超时时间
SPRINGCLOUD-PRODUCER.ribbon.ReadTimeout=1000
# 是否对所有操作都进行重试
SPRINGCLOUD-PRODUCER.ribbon.OkToRetryOnAllOperations=true
# 切换实例的重试次数
SPRINGCLOUD-PRODUCER.ribbon.MaxAutoRetriesNextServer=1
# 对当前实例的重试次数
SPRINGCLOUD-PRODUCER.ribbon.MaxAutoRetries=1
6. Feign负载均衡
Feign是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单, 它的使用方法是定义一个接口,然后在上面添加注解,同时也支持JAX-RS标准的注解。Feign也支持可拔插式的编码器和解码器。Spring Cloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡。
封装了一个注解,简化Ribbon的调用代码,让代码更加清晰,方便开发~~
6.1 相关链接
6.2 springcloud-consumer导包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
6.3 编写UserClient
package com.wpj.api;
import com.wpj.bean.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@FeignClient("springcloud-producer")
public interface UserClient {
@RequestMapping("/list")
public List<User> list();
}
6.4 修改Controller
package com.wpj.controller;
import com.wpj.api.UserClient;
import com.wpj.bean.User;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@RestController
@Scope("prototype")
public class UserController {
@Resource
private UserClient userClient;
@RequestMapping("/list")
public List<User> list(){
return userClient.list();
}
}
6.5 程序入口添加注解
package com.wpj;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class ConsumerApplication {
/**
* 显示实例化 负载均衡的策略对象,那么默认的轮询策略就会失效
* @return
*/
@Bean
public RandomRule createRule(){
return new RandomRule();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
6.6 访问接口
7 Feign集成带参方法
/**
* 根据ID查询
* @param id
* @return
*/
@RequestMapping("/getById")
public User getById(@RequestParam Integer id);
/**
* 模拟传递对象参数
* @param user
* @return
*/
@RequestMapping("/updateUser")
public int updateUser(@RequestBody User user);