Ribbon
1 服务调用
Eureka内部集成了Ribbon
- 在创建RestTemplate 的时候,声明@LoadBalanced
- 使用restTemplate远程调用微服务:不需要拼接微服务的URL,用待请求的服务名替换URL地址
2 负载均衡
Ribbon是一个典型的客户端负载均衡器,Ribbon会根据服务的所有地址,根据内部的负载均衡算法,获取本次请求的有效地址。
使用方式:
- 在消费者的restTemplate bean上添加注解@LoadBalanced实现负载均衡.
- 修改调用方法内的url为 http://+服务名+接口地址
负载均衡策略
策略类 | 命名 | 描述 |
---|---|---|
com.netflix.loadbalancer.RandomRule | 随机策略 | 随机选择server |
com.netflix.loadbalancer.RoundRobinRule | 轮询策略 | 按照顺序选择server(ribbon默认策略) |
com.netflix.loadbalancer.RetryRule | 重试策略 | 在一个配置时间段内,当选择server不成功,则一直尝试选择一个可用的server |
com.netflix.loadbalancer.BestAvailableRule | 最低并发策略 | 逐个考察server,如果server断路器打开,则忽略,再选择其中并发链接最低的server |
com.netflix.loadbalancer.AvailabilityFilteringRule | 可用过滤策略 | 过滤掉一直失败并被标记为circuit tripped的server,过滤掉那些高并发链接的server(active connections超过配置的阈值) |
com.netflix.loadbalancer.ResponseTimeWeightedRule | 响应时间加权重策略 | 根据server的响应时间分配权重,响应时间越长,权重越低,被选择到的概率也就越低。响应时间越短,权重越高,被选中的概率越高,这个策略很贴切,综合了各种因素,比如:网络,磁盘,io等,都直接影响响应时间 |
com.netflix.loadbalancer.ZoneAvoidanceRule | 区域权重策略 | 综合判断server所在区域的性能,和server的可用性,轮询选择server并且判断一个AWS Zone的运行性能是否可用,剔除不可用的Zone中的所有server |
修改负载均衡策略
client-name: #自定义的服务名
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #针对client-a服务使用随机策略
3 Ribbon重试机制
ribbon的重试机制,默认是开启的,需要添加超时与重试的策略配置,如下:
<!-- 消费者端引入重试依赖 -->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
消费者端配置重试参数:
client-name: #自定义的服务名
ribbon:
ConnectTimeout: 30000 #Ribbon的连接超时时间
ReadTimeout: 60000 #Ribbon的数据读取超时时间
MaxAutoRetries: 1 #对当前服务的重试次数
MaxAutoRetriesNextServer: 1 #切换服务的重试次数(不包含上一个服务的重试)
OkToRetryOnAllOperations: true #是否对所有操作都进行重试
#说明:这里配置的ConnectTimeout和ReadTimeout是当HTTP客户端使用的是HttpClient才生效,这个时间最终会被设置到HttpClient中。#在设置的时候需要结合hystrix的超时时间来综合考虑,针对使用的场景,设置太小会导致很多请求失败,设置太大会导致熔断控制变差。
7个核心接口:
接口 | 简述 | 默认实现 |
---|---|---|
IClientConfig | 定义ribbon中管理配置的接口 | DefaultClientConfigImpl |
IRule | 定义ribbon中负载均衡策略的接口 | ZoneAvoidanceRule |
IPing | 定义定期ping服务,检查可用性的接口 | DummyPing |
ServerList | 定义获取服务列表方法的接口 | ConfigurationBasedServerList |
ServerListFilter | 定义特定场景下,获取服务列表的方法接口 | ZonePreferenceServerListFilter |
ILoadBalancer | 定义负载均衡选择服务的核心方法接口 | ZoneAwareLoadBalancer |
ServerListUpdater | 为DynamicServerListLoadBalancer定义动态更新服务列表的接口 | PollingServerListUpdater |
4 Ribbon源码
Feign组件
Feign组件入门
-
导入依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>2.0.0.RELEASE</version> </dependency>
-
配置调用接口
/** * 声明需要调用的微服务名称 * name:服务提供者的名称 */ @FeignClient(name = "USER-SERVICE") public interface UserFeignClient { //配置需要调用的微服务接口 @RequestMapping(value = "/user/getUserById/{id}",method = RequestMethod.GET) User getUserById(@PathVariable("id") Long id); }
-
在启动类上激活feign
//激活Feign @EnableFeignClients @SpringBootApplication public class ConsumerApplication { public static void main(String[] args) { SpringApplication.run(ConsumerApplication.class,args); } }
-
通过自定义的接口调用远程为服务
@Autowired UserFeignClient userFeignClient; @RequestMapping(value = "/getUserFeignById/{id}",method = RequestMethod.GET) public User getUserFeignById(@PathVariable Long id) { return userFeignClient.getUserById(id); }
请求压缩
Spring Cloud Feign支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。通过配置以下参数即可开启请求与响应的压缩功能:
feign:
compression:
request:
enabled: true #开启请求压缩
response:
enabled: true #开启响应压缩
同时,也可以对请求的数据类型,以及触发压缩的大小下限进行设置:
feign:
compression:
request:
enabled: true #开启请求压缩
min-request-size: 2048 #设置触发压缩的大小下限
mime-types: text/xml, application/xml,applcation/json #设置压缩的数据类型
配置feign日志
#配置feign日志输出
#日志配置 NONE:不输出日志(性能最好) BASIC:适用于生产环境追踪问题
#HEADERS:在BASIC的基础上,记录请求和响应头信息 FULL:记录所有
feign:
client:
config:
user-service:
loggerLevel: FULL
logging:
level:
com.lee.consumer.feign: debug
Feign和Ribbon的区别
- Ribbon是一个客户端的负载均衡器
- Feign是在Ribbon的基础上进行了封装
Feign源码分析
启动类注解@EnableFeignClients
--> 载入@Import(FeignClientsRegistrar.class)
--> implements ImportBeanDefinitionRegistrar
--> @Override registerBeanDefinitions(...)
--> registerFeignClients 注册方法(1.注册配置;2.创建并注册FeignClientFactoryBean)
FeignClientFactoryBean
-->implements FactoryBean(实现spring中的FactoryBean接口)
-->@Override public Object getObject()(重写getObject方法)
-->InvocationHandlerFactory.create()(return new FeignInvocationHandler(target, dispatch)动态代理对象)
注解的主要作用:
* 扫描所有的@FeignClient注解,找到对应的接口
* 创建标注了@FeignClient接口的动态代理对象
* FeignInvocationHandler