spring cloud feign组件简单使用
springcloud是使用rest协议(RestTemplate)进行信息传递,同时在netfix的项目中实现了一个feign组件来简化编写代码的麻烦,并且有自动负载均衡
不需要配置类中加上
@LoadBalanced 注解了
不过想修改负载均衡策略,你还是需要在application.yml中配置
调用的原理:
通过动态代理,产生了一个代理类交给了spring容器。然后通过反射获取接口的注解以及里面的配置,获取路径,获取参数名,参数值,获取返回的类型。然后封装到RestTemolate中,然后模拟浏览器请求。
简单使用:
1,加入起步依赖,在调用者模块中加入
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2,启动类添加@EnableFeignClients注解
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker//开启熔断机制
@EnableFeignClients//
public class UserConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(UserConsumerApplication.class,args);
}
/* @Bean
@LoadBalanced //启动负载均衡
public RestTemplate restTemplate(){
return new RestTemplate();
}*/
}
3,创建一个接口,接口里面的方法名,参数名,以及返回值要和controller类一致
package org.example.feign;
import org.example.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
//声明feign组件,name是指定服务名,
//@FeignClient(name = "${feign.name}", url = "${feign.url}")
@FeignClient(name = "user-provider")
public interface UserFeign {
/**
* 这个路径和对应请求微服务的路径一至
*/
@GetMapping("/user/{id}")
public User findById(@PathVariable(name = "id") Integer id);
}
4,controller类,直接注入接口,然后调用接口的方法即可
package org.example.controller;
import org.example.feign.UserFeign;
import org.example.pojo.User;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/feign")
public class TestFeignController {
@Autowired
private UserFeign userFeign;
@GetMapping("/{id}")
public User findByid(@PathVariable(name = "id") Integer id){
//接受浏览器请求
//调用feign
User user = userFeign.findById(id);
return user;
}
}
负载均衡配置
1,通过Ribbon来配置
# 修改服务地址轮询策略,默认是轮询,配置之后变随机
# WeightedResponseTimeRule 根据服务响应时间权重值策略
# RoundRobinRule 轮询策略
# RandomRule 随机策略
# Zone Avoidance Rule 区域避免规则。
# 配置负载均衡
user-provider:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #默认是轮询,配置为随机
ConnectTimeout: 1000 # 连接超时时间
ReadTimeout: 2000 # 数据读取超时时间,连接之后,数据传输过程
MaxAutoRetries: 0 # 最大重试次数(第一个服务)
MaxAutoRetriesNextServer: 0 # 最大重试下一个服务次数(集群的情况才会用到)
OkToRetryOnAllOperations: false # 是否对所有的请求都重试
2,或者通过fegin来配置
feign:
client:
config:
feignName:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: full
errorDecoder: com.example.SimpleErrorDecoder
retryer: com.example.SimpleRetryer
defaultQueryParameters:
query: queryValue
defaultRequestHeaders:
header: headerValue
requestInterceptors:
- com.example.FooRequestInterceptor
- com.example.BarRequestInterceptor
decode404: false
encoder: com.example.SimpleEncoder
decoder: com.example.SimpleDecoder
contract: com.example.SimpleContract
熔断器支持(默认没有开启)
# To disable Hystrix in Feign
feign:
hystrix:
enabled: true
开启后如果你发现下游微服务正常,但是一直进入熔断,可以看看我发的下面的这两个连接来解决
第一个连接配置config类后,注意得把配置文件中的配置注释掉
Feign开启HyStrix后如何配置线程隔离及熔断策略_问题不太大的博客-CSDN博客_feign hystrix自定义隔离 开启hystrix:feign.hystrix.enabled=true时, RequestContextHolder.getRequestAttributes()为空_aresdata的博客-CSDN博客_feign.hystrix.enabled
使用:
创建一个对应的Feign类的实现类
package org.example.feign.impl;
import org.example.feign.UserFeign;
import org.example.pojo.User;
@Component
public class UserFeignImpl implements UserFeign {
//降级方法
@Override
public User findById(Integer id) {
User user = new User();
user.setId(0);
user.setUsername("默认名称");
return user;
}
}
然后在@FeignClient注解加上一个参数fallback
package org.example.feign;
import org.example.feign.impl.UserFeignImpl;
import org.example.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
//声明feign组件,name是指定服务名,
//@FeignClient(name = "${feign.name}", url = "${feign.url}")
@FeignClient(name = "user-provider",fallback = UserFeignImpl.class)
public interface UserFeign {
@GetMapping("/user/{id}")
public User findById(@PathVariable(name = "id") Integer id);
}
注意项:
如果你需要使用Hystrix那么就不要把@RequestMapping注解写到类上,因为实现类实现了接口,而@RequestMapping加在接口上,那么实现类也会生成两个动态代理类和一个同样的路径,导致url路径不唯一,所以会报错
解决方法:
1,直接不在类上加@RequestMapping注解
2,或者在@FeignClient加入一个参数:path即可
package org.example.feign;
import org.example.feign.impl.UserFeignImpl;
import org.example.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
//声明feign组件,name是指定服务名,
//@FeignClient(name = "${feign.name}", url = "${feign.url}")
@FeignClient(name = "user-provider",fallback = UserFeignImpl.class,path="/user")
public interface UserFeign {
@GetMapping("/{id}")
public User findById(@PathVariable(name = "id") Integer id);
}
另外还可以了解一下请求压缩,响应压缩,和日志级别配置
(15条消息) SpringCloud Feign 优化_xjune的专栏-CSDN博客
超时配置
在OpenFeign中设置超时时间是一个重要的配置,因为它决定了Feign客户端在等待服务响应时的等待时长。以下是如何在OpenFeign中设置超时时间的步骤:
1. **全局超时设置**:
你可以在`application.yml`或`application.properties`文件中为所有Feign客户端设置默认的超时时间。例如,以下配置设置了连接超时为2000毫秒(2秒),读取超时为60000毫秒(60秒):
feign:
client:
config:
default:
connectTimeout: 2000
readTimeout: 60000
2. **单个服务超时设置**:
如果需要为特定的Feign客户端设置不同的超时时间,可以在配置前缀中指定客户端的名称。例如,为名为`serviceA`的服务设置超时时间:
feign:
client:
config:
serviceA:
connectTimeout: 2000
readTimeout: 60000
3. **方法级别的超时设置**:
对于单个Feign接口中的方法,你可以使用`@FeignClient`注解的`path`属性来指定特定的路径,并通过`Request.Options`来设置该方法的超时时间。例如:
@FeignClient(name = "serviceA", path = "/api/v1", configuration = FeignConfig.class)
public interface ServiceAClient {
@GetMapping("/resource")
String getResource(@Request.Options(Request.Options options) String resourceId);
}
在`FeignConfig`类中,你可以定义`Request.Options`来设置特定的超时时间:
@Configuration
public class FeignConfig {
@Bean
public Request.Options requestOptions() {
return new Request.Options(2000, 60000);
}
}
多个方法
@Configuration
public class ServiceAClientConfig {
@Bean
public Request.Options serviceAResourceOptions() {
// 为特定请求设置更长的读取超时:连接超时2秒,读取超时10秒
return new Request.Options(2000, 10000);
}
}
在Feign客户端接口上,你可以使用 configuration
属性来指定配置类,该配置类包含了方法级别的 Request.Options
Bean。
@FeignClient(name = "serviceA", configuration = ServiceAClientConfig.class)
public interface ServiceAClient {
@GetMapping("/resource")
String getResource(@Request.Options(ServiceAClientConfig.serviceAResourceOptions()) String resourceId);
}
4. **使用Hystrix进行熔断保护**:
如果你的Feign客户端启用了Hystrix,你还需要配置Hystrix的超时时间,以确保它大于Feign的超时时间。例如:
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 65000
5. **启用Feign日志**:
为了更好地调试和监控Feign客户端的调用,你可以启用Feign的日志记录。例如,设置日志级别为`full`:
feign:
client:
config:
serviceA:
loggerLevel: full
6. **处理超时异常**:
当Feign客户端请求超时时,它会抛出`FeignException`。你可以在你的服务中捕获这个异常并进行相应的处理。
请注意,超时时间的设置应该根据你的业务需求和后端服务的性能来调整。如果你的服务响应时间较长,可能需要增加超时时间。同时,确保你的服务能够快速失败,以避免不必要的等待。