服务调用
文章目录
1. Ribbon
1.1. Ribbon概述
Ribbon是一个负载均衡器,有助于控制HTTP和TCP客户端行为。Eureka一般配置Ribbon一起使用,Ribbon提供客户端负载均衡的功能,Ribbon利用从Eureka中读取到的服务信息,在调用服务节点提供的服务时,会合理的进行负载。
Eureka内部集成了Ribbon。
1.2. 主要作用
-
服务调用
基于Ribbon实现服务调用,通过拉取到的所有服务列表组成(服务名-请求路径)映射关系,借助RestTemplate调用。
-
在创建RestTemplate的时候,声明
@LoadBalanced
注解(Ribbon提供的负载均衡注解)@LoadBalanced @Bean public RestTemplate restTemplate() { return new RestTemplate(); }
-
使用RestTemplate调用远程微服务时,不需要拼接远程IP:port,只需要使用服务名代替ip:port即可
-
-
负载均衡
当有多个服务提供者时,Ribbon可以根据负载均衡的算法自动的选择需要调用的服务地址。
Ribbon是一个典型的客户端负载均衡器,Ribbon会获取所有的服务地址,根据内部的负载均衡算法,获取本次请求的有效地址。
-
负载均衡策略
- com.netflix.loadbalancer.RoundRobinRule:以轮询的方式进行负载均衡 (默认策略)
- com.netflix.loadbalancer.RandomRule:随机策略
- com.netflix.loadbalancer.RetryRule:重试策略
- com.netflix.loadbalancer.WeightedResponseTimeRule:权重策略,会计算每个服务的权重,越高的被调用的可能性越大。
- com.netflix.loadbalancer.BestAvailableRule:最佳策略,遍历所有的服务实例,过滤掉故障实例,并返回请求数最小的服务实例。
- com.netflix.loadbalancer.AvailabilityFilteringRule:可用过滤策略,过滤掉故障和请求数超过阀值的服务实例,再从剩下的服务实例中轮询调用。
-
策略选择
- 如果每个机器配置差不多,则建议不修改策略(默认轮询策略)
- 如果部分机器配置强,则可以改为WeightedResponseTimeRule(权重策略)
-
在服务消费者方配置文件中修改负载均衡策略
#服务提供者方的服务名称 serviceName: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
-
1.3. 请求重试机制
服务消费者根据Ribbon负载均衡请求了一个服务,若超出了设定的请求超时时间,则会将服务请求转发到另一个服务进行请求。
-
在服务消费者方引入spring重试组件
<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency>
-
在Ribbon中配置重试机制
#服务提供者方的服务名称 serviceName: ribbon: ConnectTimeout: 250 #Ribbon的创建连接超时时间,单位毫秒 ReadTimeout: 1000 #Ribbon的数据读取超时时间,单位毫秒 OkToRetryOnAllOperations: true #是否对所有操作都进行重试 MaxAutoRetriesNextServer: 1 #切换实例的重试次数 MaxAutoReteies: 1 #对当前实例的重试次数
1.4. Ribbon源码解析
-
启动过程
使用
@LoanBalanced
注解对Spring容器中的RestTemplate对象打一个标记通过RibbonAutoConfiguration配置类进行自动装配,在这个类装配之前会自动装配LoanBalancerAutoConfiguration配置类,在此类中会向RestTemplate中添加请求拦截器。
@Bean @ConditionalOnMissingBean public RestTemplateCustomizer restTemplateCustomizer(RetryLoadBalancerInterceptor loadBalancerInterceptor) { return (restTemplate) -> { List<ClientHttpRequestInterceptor> list = new ArrayList(restTemplate.getInterceptors()); list.add(loadBalancerInterceptor); restTemplate.setInterceptors(list); }; } // 使用流式表达式的方式创建RestTemplateCustomizer接口的实现类 // restTemplate.getInterceptors()获取restTemplate的所有请求拦截器
-
发起请求
使用restTemlpate.getForObject(url,Class)发送请求时,会执行LoadBalancerInterceptor拦截器中的intercept()方法,根据ILoadBalancer(负载均衡器)和负载均衡策略获取到待执行的server地址,最后发送请求。
2. Feign
2.1. Feign概述
Feign是Netflix公司开发的声明式、模版化的HTTP客户端。
- Feign可以帮助我们更加快捷、优雅地调用HTTP API
- 在Spring Cloud中使用Ferign非常简单,创建一个接口,并在接口上添加一些注解就可以了
- Feign支持多种注解,如Feign自带的注解或者JAX-RS注解等
- Spring Cloud对Feign进行了增强,使Feign支持了SpringMVC注解,并整合了Ribbon和Eureka,从而让Feign的使用更加方便。
2.2. 基于Feign的服务调用
-
导入依赖
<!--导入SpringCloud整合的openFeign--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
-
配置调用接口
/** * @FeignClient(name = "微服务名称") : 声明需要调用的服务提供者的服务名称 */ @FeignClient(name = "service-product") public interface ProductFeignClient { /** * 配置需要调用的服务提供者的接口,支持SpringMVC的方式 * @RequestMapping(value = "接口请求路径") */ @RequestMapping(value = "/product/{id}", method = RequestMethod.GET) public Product findById(@PathVariable("id") Long id); }
-
在启动类激活Feign
@EnableFeignClients
-
通过自动的接口调用远程微服务
// 获取配置好的接口对象 @Autowired private ProductFeignClient productFeignClient; // 使用时直接调用这个接口中的方法即可 Product product = productFeignClient.findById(id);
2.3. 负载均衡
Feign本身已经集成了Ribbon依赖和自动配置,因此我们不需要再额外引入依赖,也不需要再注册RestTemplate对象,我们也可以用Ribbon的方式来进行配置,可以通过ribbon.xx来进行全局配置,也可以通过服务名.ribbon.xx来对指定的服务进行配置。
2.4. Feign的配置
从Spring Cloud Edgware版本开始,Feign支持使用属性自定义Feign的配置:
- Feign的配置
feign:
client:
config:
feignClientName: #FeignClient的名称,即微服务的名称 @FeignClient(name="service-product")
connectTimeout: 5000 #建立连接的超时时间
readTimeout: 5000 #读取超时时间
loggerLevel: FULL #Feign的日志级别
errorDecoder: com.example.SimpleErrorDecoder #Feign的错误解码器
retryer: com.example.SimpleRetryer #配置重试
requestInterceptors: #配置拦截器
- com.example.FooRequestInterceptor
- com.example.BarRequestInterceptor
decode404: false
-
请求压缩
支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗,配置方式如下:
feign: compression: request: enable: true #开启请求数据压缩 response: enable: true #开启响应数据压缩
同时,也可以对请求的数据类型,以及触发压缩的大小下限进行设置:
feign: compression: request: enable: true #开启请求数据压缩 mime-types: text/html,application/xml,application/json #设置压缩的数据类型(默认值) min-request-size: 2048 #设置触发压缩的大小下限(默认值,单位KB)
-
日志级别
feign: client: config: feignClientName: #FeignClient的名称 loggerLevel: FULL #Feign的日志级别 logging: level: com.exaple.feign.ProductFeignClient: debug
feign.client.config.feignName.loggerLevel:日志级别配置:
- NONE : 不打印日志,默认配置,执行效率高(生产环境建议此配置)
- BASIC : 适用于生产环境追踪问题
- HEADERS : 在BASIC的基础上,记录请求和响应头信息
- FULL : 输出所有 (开发阶段查找问题)