SCA - Feign入门实战

实战

环境

Nacos
Nacos Version:2.0.3

Demo Application:
System: macOS 10.14.6
JDK: 1.8.0_251
Spring Boot:2.2.13.RELEASE
Spring Cloud:Hoxton.SR12
Spring Cloud Alibaba: 2.2.5.RELEASE

添加依赖

<!-- feign -->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

添加注解

启动类添加@EnableFeignClients

关键代码

定义feign client

good-service服务的feign client

@FeignClient(name = "good-service")
public interface GoodServiceClient {
    @GetMapping("/good/{id}")
    Result queryGood(@PathVariable("id") String id);
}

定义接口

接口方法WfbiFeignApplication::getGoodByID

@GetMapping("/{id}")
public Result getGoodByID(@PathVariable("id") String id) {
	return goodServiceClient.queryGood(id);
}

feign脱离ribbon使用

@FeignClient(name = "aservice", url = "${aservice.url}")
public interface AServiceClient {
    ... ...
}

可单独配置服务aservice的api地址url进行远程调用。

feign拦截器

拦截器可以为每个HTTP请求/响应执行从身份验证到日志记录的各种隐式任务。

定义拦截器FeignHeaderInterceptor

@Slf4j
public class FeignHeaderInterceptor implements RequestInterceptor {

    /**
     * 调用链传递token
     *
     * @param requestTemplate
     */
    @Override
    public void apply(RequestTemplate requestTemplate) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String accessToken = request == null ? StringUtils.EMPTY : request.getHeader(HttpHeaders.AUTHORIZATION);
        log.info("=================Feign Interceptor AccessToken: " + accessToken);
        requestTemplate.header(HttpHeaders.AUTHORIZATION, accessToken);
    }
}

注意 不能添加@Component注解,否则会全局生效。

添加配置加入调用链

# feign interceptor
feign.client.config.good-service.request-interceptors[0]=com.wfbi.wfbifeign.FeignHeaderInterceptor

good-service可用deault代替,代表对所有服务适用该拦截器。

feign 整合 sentinel

添加依赖

<!-- sentinel -->
<dependency>
	<groupId>com.alibaba.cloud</groupId>
	<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

添加配置

# feign整合sentinel
feign.sentinel.enabled=true

# sentinel config
spring.cloud.sentinel.transport.dashboard=localhost:10000
spring.cloud.sentinel.transport.port=8719
spring.cloud.sentinel.web-context-unify=false

断路代码

方式一 fallback方式

GoodServiceFallBack实现GoodServiceClient

@Component
public class GoodServiceFallBack implements GoodServiceClient{
    @Override
    public Result queryGood(String id) {
        return new Result().setCode(1).setMessage("断路message:" + id);
    }
}

GoodServiceClient配置fallback

@FeignClient(name = "good-service", fallback = GoodServiceFallBack.class)
public interface GoodServiceClient {
    @GetMapping("/good/{id}")
    Result queryGood(@PathVariable("id") String id);
}
方式二 fallbackFactory方式

GoodServiceFactory实现FallbackFactory

@Slf4j
@Component
public class GoodServiceFactory implements FallbackFactory<GoodServiceClient> {

    @Override
    public GoodServiceClient create(Throwable throwable) {
        return new GoodServiceClient() {
            @Override
            public Result queryGood(String id) {
                log.error("GoodServiceClient::queryGood error:", throwable);
                return new Result().setCode(1).setMessage("fallbackFactory断路message:" + id);
            }
        };
    }
}

GoodServiceClient配置fallbackFactory

@FeignClient(name = "good-service", fallbackFactory = GoodServiceFactory.class)
public interface GoodServiceClient {
    @GetMapping("/good/{id}")
    Result queryGood(@PathVariable("id") String id);
}

配置sentinel熔断规则
在这里插入图片描述
为方便演示,直接将最大RT设置为1ms。请求查看效果如下:
在这里插入图片描述
推荐fallbackFactory方式,可以捕获异常并输出日志

遇到的问题

Requested bean is currently in creation: Is there an unresolvable circular reference

解决方案:spring-cloud 从Hoxton.SR12降级为Hoxton.SR9。
参考

配置项

配置项作用
Logger.Level指定日志级别
Retryer指定重试策略
ErrorDecoder指定错误解码器
Request.Options超时时间
Collection<RequestInterceptor>拦截器
SetterFactory用于设置Hystrix的配置属性,Fgien整合Hystrix才会用

支持配置方式

代码配置和属性配置(优先选择)。

代码配置日志级别

Feign有四种类型:NONE(默认)、BASIC、HEADERS、FULL。

  • NONE: 不记录任何日志信息,这是默认值。
  • BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
  • HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
  • FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据

参数配置类FeignConfiguration

public class FeignConfiguration {
    @Bean
    public Logger.Level level() {
        // 打印所有细节
        return Logger.Level.FULL;
    }
}

在类上面加了@Configuration注解的话,就必须将该类放到@ComponentScan能扫描的包以外,否则这个类的配置将会被所有的FeignClient共享,就无法实现针对服务的细粒度配置了,详见JAVA父子上下文。所以这里建议不加。

FeignClient配置类GoodServiceClient

@FeignClient(name = "good-service", configuration = FeignConfiguration.class)
public interface GoodServiceClient {
    @GetMapping("/good/{id}")
    Result queryGood(@PathVariable("id") String id);
}

属性配置日志级别

# 配置good-service日志输出级别
feign.client.config.good-service.loggerLevel=full

常用配置

源码配置类FeignClientProperties

public static class FeignClientConfiguration {
    private Level loggerLevel;
    private Integer connectTimeout;
    private Integer readTimeout;
    private Class<Retryer> retryer;
    private Class<ErrorDecoder> errorDecoder;
    private List<Class<RequestInterceptor>> requestInterceptors;
    private Map<String, Collection<String>> defaultRequestHeaders;
    private Map<String, Collection<String>> defaultQueryParameters;
    private Boolean decode404;
    private Class<Decoder> decoder;
    private Class<Encoder> encoder;
    private Class<Contract> contract;
    private ExceptionPropagationPolicy exceptionPropagationPolicy;
    private Boolean followRedirects;
    ... ...

启用默认hystrix断路器

openfeign集成了hystrix断路器,但默认关闭的,可通过如下配置开启

feign.hystrix.enabled=true

请求超时配置

# Feign的连接建立超时时间,默认为10秒
feign.client.config.default.connectTimeout=10000
# Feign的请求处理超时时间,默认60s
feign.client.config.default.readTimeout=60000
# Feign使用默认的超时配置,在该类源码中可见,默认单次请求最大时长1秒,重试5次
feign.client.config.default.retryer=feign.Retryer.Default

注意:

  • ribbon&feign同时配置,则feign优先级高生效,推荐ribbon配置(有争议,个人参考的
  • default可以改成服务名,针对具体服务生效

与hystrix结合需配置熔断超时时间

feign.hystrix.enabled=true
# 熔断超时设置,默认为 1 秒
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000
# 强制打开熔断器,如果该属性设置为 true,强制断路器进入打开状态,将会拒绝所有的请求。 默认 false 关闭的
hystrix.command.defautl.circuitBreaker.forceOpen=false
# 触发熔断错误比例阈值,默认值 50%
hystrix.command.defautl.circuitBreaker.errorThresholdPercentage=50
# 熔断后休眠时长,默认值 5 秒
hystrix.command.defautl.circuitBreaker.sleepWindowInMilliseconds=3000
# 熔断触发最小请求次数,默认值是 20
hystrix.command.defautl.circuitBreaker.requestVolumeThreshold=10

注意:
default可以改为服务名,甚至具体方法,

hystrix.command.GoodServiceClient#queryGood(String).execution.isolation.thread.timeoutInMilliseconds=1500
超时重试

因为ribbon的重试机制和Feign的重试机制有冲突,所以源码中默认关闭Feign的重试机制(默认的简单实现Retryer.Default)。推荐ribbon重试。
注意
需配置hystrix的timeoutInMillisecond大于ribbon的 ( ConnectTimeout + ReadTimeout ) × 2。否则还没来得及重试就走断路了。

压缩

支持对请求和响应进行GZIP压缩,以提高通信效率,通过下面的参数即可开启请求与响应的压缩功能:

# 配置请求GZIP压缩
feign.compression.request.enabled=true
# 配置响应GZIP压缩
feign.compression.response.enabled=true
# 配置压缩支持的MIME TYPE
feign.compression.request.mime-types=text/xml,application/xml,application/json
# 配置压缩数据阈值,默认2048B
feign.compression.request.min-request-size=2048
# 对于除OkHttpClient外的http客户端,可以启用默认gzip解码器以UTF-8编码解码gzip响应:
feign.compression.response.useGzipDecoder=true

编码解码

Encoder&Decoder

使用场景

  • 第三方需要特定的参数格式,如xml、json
  • 第三方返回的格式需要做本地化转换,以便进行业务处理
  • 为了追求性能,进行数据编码,如protobuf编码。

具体参考
feign自定义请求拦截器、编码器、解码器

注意 在使用中发现方法签名为method(Object) 这种格式才会进入对应的编解码器。

ErrorDecoder

发生错误、异常情况时使用的解码器,允许你对异常进行特殊处理。

使用场景

  • 需要对固定错误码进行处理,比如返回400错误码时抛出指定异常。

定义返回码为400时返回固定异常

class IllegalArgumentExceptionDecoder implements ErrorDecoder {
	@Override
	public Exception decode(String methodKey, Response response) {
	  if (response.status() == 400)
	     throw new IllegalArgumentException("bad zone name");

	  // 错误码如果不是400,会交给Default进行解码
	  // 改进:这里使用单例即可,Default不用每次都去new
	  return new ErrorDecoder.Default().decode(methodKey, response);
	}
}

注意 若设置decode404=true,那么它交给的是Decoder去解析,而非ErrorDecoder

Feign简介

Feign是Spring Cloud提供的一个声明式的伪Http客户端, 它使得调用远程服务就像调用本地服务一样简单, 只需要创建一个接口并添加一个注解即可。

Nacos很好的兼容了Feign, Feign默认集成了 Ribbon, 所以在Nacos下使用Fegin默认就实现了负载均衡的效果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值