OpenFeign和Ribbon
1.概述
1.1 OpendFeign简介
1.1.1 综合说明
OpenFeign 可以使消费者将提供者提供的服务名伪装为接口进行消费,消费者只需使用“Service 接口+ 注解”的方式。
即可直接调用 Service 接口方法,而无需再使用 RestTemplate 了。其实原理还是使用RestTemplate,而通过Feign(伪装)成我们熟悉的习惯.
1.1.2 Feign和OpendFeign
Spring Boot 1.x 环境下使用的是 Feign,而该项目现已更新为了 OpenFeign。所以后续使用的依赖也发生了变化。
1.1.3 Ribbon 与 OpenFeign
Ribbon 是 Netflix 公司的一个开源的负载均衡项目,是一个客户端负载均衡器,运行在消费者端。
面试问到 dubbo和spring cloud的区别时,在dubbo的话,消费方和提供方都可以实现负载均衡,而且spring cloud 是在消费方。
OpenFeign 中使用 Ribbon 进行负载均衡,所以 OpenFeign 直接内置了 Ribbon。即在导入OpenFeign 依赖后,无需再专门导入 Ribbon 依赖了。
2. OpenFeign客户端
2.1 创建消费者工程
(1)添加依赖
<!--feign依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
(2)定义要调Controlle和Service的接口
@RestController
@RequestMapping("/consumer")
public class DepartController {
@Autowired
private DepartService service;
@GetMapping("/get/{id}")
public Depart getHandle(@PathVariable("id") int id) {
return service.getDepartById(id);
}
@Service
@FeignClient("provider-depart") // 指定当前Service所绑定的微服务名称在
@RequestMapping("/provider")
public interface DepartService {
@GetMapping("/get/{id}")
Depart getDepartById(@PathVariable("id") int id);
(3)yml配置文件
spring:
application: # 指定微服务对外暴露的名称
name: consumer-depart
eureka:
client:
service-url: # 指定Eureka集群服务注册中心
defaultZone: http://localhost:8100/eureka,http://localhost:8200/eureka,http://localhost:8300/eureka
feign:
client:
config:
default:
connectTimeout: 5000 # 指定Feign连接提供者的超时时限
readTimeout: 5000 # 指定Feign从请求到获取提供者响应的超时时限
compression:
request:
enabled: true # 开启对请求的压缩
# 指定对哪些MIME类型的文件进行压缩
mime-types: ["text/xml", "application/xml", "application/json"]
min-request-size: 2048 # 指定启用压缩的最小文件大小,单位字节
response:
enabled: true # 开启对客户端响应的压缩
(4)在启动类添加注解EnableFeignClients
// 指定Feign接口所在的包
@EnableFeignClients(basePackages = "com.service")
@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
2.2 创建提供者工程
(1)写Controller和Service
@RequestMapping("/provider")
@RestController
public class DepartController {
@Autowired
private DepartService service;
@GetMapping("/get/{id}")
public Depart getHandle(@PathVariable("id") int id) {
return service.getDepartById(id);
}
}
(2)yml配置
server:
port: 8081
application:
name: provider-depart # 暴露微服务名称
# 指定Eureka服务中心
eureka:
client:
service-url: # 指定Eureka服务注册中心
defaultZone: http://localhost/eureka,http://localhost:8200/eureka,http://localhost:8300/eureka
详细的service层的实体类就不贴出来,和数据库的配置。案例主要目的是为了理解OpenFeign.
3.Ribbon
3.1 创建 Ribbon工程
复制2.2的工程再改一下工程名字和端口8082和8083
server:
port: 8082
通过返回值的端口来区分负载均衡是否生效
@RequestMapping("/provider/depart")
@RestController
public class DepartController {
@Autowired
private DepartService service;
// 读取配置文件中的属性值
@Value("${server.port}")
private int port;
// 注入服务发现客户端
@Autowired
private DiscoveryClient client;
@GetMapping("/get/{id}")
public Depart getHandle(@PathVariable("id") int id) {
Depart depart = service.getDepartById(id);
// 部门名称后加上端口号
depart.setName(depart.getName() + port);
return depart;
}
}
3.2Ribbon的负载均衡策略
类 | 命名 | 说明 |
---|---|---|
RoundRobinRule | 轮询策略 | Ribbon的默认负载均衡策略 |
RandomRule | 随机策略 | 从所有可用的提供者中随机选择一个 |
RetryRule | 重试策略 | 从所有可用的提供者中随机选择一个,若获取失败的话,则可以在指定的时间内重试,默认为500毫秒 |
BestAvailableRule | 最低并发策略 | 选择并发量最小的 提供者 |
AvailabilityFilteringRule | 可用过滤策略 | 过滤掉处于被标记伟circuit tripped状态的 提供者,或已经超过连接极限的 提供者,对剩余 provider 采用轮询策略 |
ZoneAvoidanceRule | 复合判断策略 | 判断 提供所在区域的性能及 provider 的可用性选择服务器。 |
WeightedResponseTimeRule | 权重响应时间策略 | 根据每个 提供的平均响应时间计算其权重,响应时间越快权重越大,被选中的机率就越高。在刚启动时采用轮询策略。后面就会根据权重进行选择了。 |
3.3 自己实现负载均衡策略
Ribbon 默认采用的轮休策略,即RoundRobinRule。
(1) 创建 Configuration类
@Configuration
public class CodeConfig {
// 开启消息者端的负载均衡功能,默认是轮询策略
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
// 指定Ribbon使用随机算法策略
@Bean
public IRule loadBalanceRule() {
return new TestRule();
}
}
(2) 创建负载均衡类
/**
* 自定义负载均衡算法:
*/
public class CustomRule implements IRule {
private ILoadBalancer iLoadBalancer ;
public CustomRule() {
}
@Override
public Server choose(Object key) {
// 获取所有可用的提供者
List<Server> servers = iLoadBalancer.getReachableServers();
// 从提供者中随机获取可用的提供者
return this.getRandomServers(servers);
}
//
private Server getRandomServers(List<Server> servers ) {
// 获取一个[0,servers .size())的随机整数
int index = new Random().nextInt(servers .size());
return servers.get(index);
}
@Override
public void setLoadBalancer(ILoadBalancer iLoadBalancer ) {
this.iLoadBalancer = iLoadBalancer;
}
@Override
public ILoadBalancer getLoadBalancer() {
return iLoadBalancer ;
}
}
(3).更改yml文件
# 修改负载均衡策略
provider-depart: # 要负载均衡的提供者微服务名称
ribbon: # 指定要使用的负载均衡策略
NFLoadBalancerRuleClassName: com.abc.rule.testRule