Feign声明式调用

一、Feign简介

Feign是Netflix开发的声明式、模板化的HTTP客户端,可以更加快捷、优雅地调用HTTP API。SpringCloud对Feign进行了增强,使Feign支持了SpringMVC的注解,并整合了Ribbon和Eureka,在使用Feign时提供了HTTP客户端负载平衡,从而让Feign的使用更加便捷。

GitHub地址:https://github.com/OpenFeign/feign

二、Feign使用

1、pom.xml引入maven依赖

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

2、客户端启动类添加注解@EnableFeignClients

@SpringCloudApplication
@EnableFeignClients(basePackages = {"com.ultrapower.uws"})
public class UwsDataApplication {
    public static void main(String[] args) {
        SpringApplication.run(UwsDataApplication.class);
    }
}

 3、Feign客户端

import com.ultrapower.uws.data.api.feign.hystrix.CollectDeviceFeignClientHystrix;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.List;
import java.util.Map;

@FeignClient(name ="uws-data-service",fallback=CollectDeviceHystrixClient.class)
public interface CollectDeviceFeignClient {
	
	@PostMapping(value="/getDeviceLastestPhone")
        String getDeviceLasestPhone(@RequestBody Map<String, Object> map);

}

@FeignClient中的"uws-data-service"是客户端名称,即提供方的服务名,用于创建Ribbon负载均衡器。在上边的例子中,由于使用了Eureka,所以Ribbon负载时候会把uws-data-service解析成Eureka Server服务注册表中的服务。可以用url属性指定请求的URL(可以是完整的URL或主机名),如http://localhost:8788。同时,SpringCloud中Feign整合了Hystrix,@FeignClient中的fallback属性指定的类,用于服务降级,当请求失败时候交由CollectDeviceHystrixClient处理。

三、自定义Feign配置

在SpringCloud中,Feign默认配置类是FeignClientsConfiguration,该类定义了Feign默认使用的编码器、解码器、契约等。SpringCloud允许通过注解@FeignClient的configuration属性自定义Feign的配置,自定义的配置优先级比FeignClientsConfiguration更高,就是会覆盖默认的配置。

@FeignClient(name = "uws-data-service", configuration = CollectDeviceHystrixClient.class)
public interface CollectDeviceFeignClient {
    //..
}

@FeignClient的name和url属性中支持从配置中引用

@FeignClient(name = "${feign.name}", url = "${feign.url}")
public interface CollectDeviceFeignClient {
    //..
}

 Spring Cloud Netflix 为Feign提供了以下默认的beans (BeanType beanName: ClassName):

  • Decoder feignDecoder: ResponseEntityDecoder (which wraps a SpringDecoder)
  • Encoder feignEncoder: SpringEncoder
  • Logger feignLogger: Slf4jLogger
  • Contract feignContract: SpringMvcContract
  • Feign.Builder feignBuilder: HystrixFeign.Builder
  • Client feignClient: 若启用了Ribbon客户端,就是LoadBalancerFeignClient, 否则默认使用 feign客户端

SpringCloud中,使用OkHttpClient和ApacheHttpClient Feign客户端,在类路径上设置feign.okhttp.enabled或feign.httpclient.enabled为true。你也可以提供一个Apache的ClosableHttpClient或者HTTP的OkHttpClient来定制自己的HTTP客户端。默认情况下,SpringCloudNetflix不为feign提供以下bean,但仍然从应用程序上下文中查找这些类型的bean以创建feign客户端:

  • Logger.Level
  • Retryer
  • ErrorDecoder
  • Request.Options
  • Collection<RequestInterceptor>
  • SetterFactory

创建一个此类bean并将其放置在@FeignClient配置中(如上面的CollectDeviceFeignClient ),可以覆盖所描述的每个bean。配置类不应该被放在主应用上下文的@ComponentScan中,即不能被注解扫描到。

@Configuration
public class CollectDeviceFeignClient {
    @Bean
    public Contract feignContract() {
        return new feign.Contract.Default();
    }

    @Bean
    public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
        return new BasicAuthRequestInterceptor("user", "password");
    }
}

SpringCloud中,Feign默认使用的是SpringMvcContract ,因此它可以使用SpringMVC的注解。但这里使用了feign.Contract.Default代替SpringMvcContract ,并向RequestInterceptor 集合中添加RequestInterceptor 。


 还可以通过配置文件中属性配置 @FeignClient,如下application.yml

feign:
  client:
    config:
      feignName:
        connectTimeout: 5000
        readTimeout: 5000
        loggerLevel: full
        errorDecoder: com.example.SimpleErrorDecoder
        retryer: com.example.SimpleRetryer
        requestInterceptors:
          - com.example.FooRequestInterceptor
          - com.example.BarRequestInterceptor
        decode404: false
        encoder: com.example.SimpleEncoder
        decoder: com.example.SimpleDecoder
        contract: com.example.SimpleContract

默认配置可以在注解@enablefeignclients中设置属性defaultconfiguration完成类似于上述的方式指定。区别在于,此配置文件中将应用于所有feign客户端。

如果你想用配置文件的设置作用于所有的@FeignClient,可以使用默认的Feign名称创建配置属性。如下application.yml

feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
        loggerLevel: basic

 如果我们同时使用@Configuration配置和在配置文件中,那么配置文件中的属性优先级更高。但是若你想使的优先级更高,你可设置feign.client.default-to-properties=false,关闭默认优先级。

如果您需要在RequestInterceptor中使用ThreadLocal 绑定变量,您需要将Hystrix的线程隔离策略设置为“SEMAPHORE ”,或者在Feign中禁用Hystrix。

# To disable Hystrix in Feign
feign:
  hystrix:
    enabled: false
#or
# To set thread isolation to SEMAPHORE
hystrix:
  command:
    default:
      execution:
        isolation:
          strategy: SEMAPHORE

四、Feign and @Primary

当Feign使用Hystrix进行服务降级的时候,同一类型的bean上下文中会有多个,这将导致添加@Autowired注解的类无法注入,因为没有一个bean是最原始的,多个bean Spring不在知道找哪一个。为了解决此问题,Spring Cloud Netflix将所有Feign实例标记为@Primary,从而Spring Framework知道将要注入那个bean。但是在某些情况下这是不可取的,若要关闭这种行为,可将@feignclient的primary属性设置为false。如下

@FeignClient(name = "hello", primary = false)
public interface HelloClient {
	// methods here
}

五、Feign对继承的支持

Feign支持继承,使用继承可以将一些操作公共部分接口分组到一些父接口中,简化开发。

公共部分接口UserService.java

public interface UserService {

    @RequestMapping(method = RequestMethod.GET, value ="/users/{id}")
    User getUser(@PathVariable("id") long id);
}

 提供者UserResource.java

@RestController
public class UserResource implements UserService {

}

 消费者UserClient.java

@FeignClient("users")
public interface UserClient extends UserService {

}

 不过这种方式在SpringCloud官方文档中比不太十分推荐,因为此种方式是服务端与客户端共享接口,造成了服务端与客户端代码的紧耦合。并且Feign目前并没有使用SpringMVC的工作机制(方法参数映射不被继承) 

六、Feign对Hystrix支持

Feign提供了对Hystrix的支持,用于断路或者出错时候服务降级处理。下边是摘自官方文档中的示例,HystrixClientFallback就是降级处理的类,实现了HystrixClient,重写其原方法即可。

@FeignClient(name = "hello", fallback = HystrixClientFallback.class)
protected interface HystrixClient {
    @RequestMapping(method = RequestMethod.GET, value = "/hello")
    Hello iFailSometimes();
}

static class HystrixClientFallback implements HystrixClient {
    @Override
    public Hello iFailSometimes() {
        return new Hello("fallback");
    }
}

 如果要知道触发服务降级的原因,可以使用注解@FeignClient的属性fallbackFactory定义降级处理的类,并继成FallbackFactory<T>,重写create(Throwable cause)方法,返回失败信息

@FeignClient(name = "hello", fallbackFactory = HystrixClientFallbackFactory.class)
protected interface HystrixClient {
	@RequestMapping(method = RequestMethod.GET, value = "/hello")
	Hello iFailSometimes();
}

@Component
static class HystrixClientFallbackFactory implements FallbackFactory<HystrixClient> {
	@Override
	public HystrixClient create(Throwable cause) {
		return new HystrixClient() {
			@Override
			public Hello iFailSometimes() {
				return new Hello("fallback; reason was: " + cause.getMessage());
			}
		};
	}
}

 

七、Feign对压缩的支持

Feign支持请求和响应的gzip压缩,可以通过以下属性来启用请求或者响应

feign.compression.request.enabled=true
feign.compression.response.enabled=true

 Feign还提供了 更为详细的的设置,与web服务器设置 类似。

feign.compression.request.enabled=true
feign.compression.request.mime-types=text/xml,application/xml,application/json
feign.compression.request.min-request-size=2048

可以通过feign.compression.request.mime-types设置压缩类型,默认类型为text/xml,application/xml,application/json。feign.compression.request.min-request-size设置请求最小阀值长度,默认长度2048。

八、Feign对日志的处理

很多场景下,需要知道Feign处理请求的具体细节。Feign也提供了灵活的日志处理,可以为每个Feign客户端指定日志记录策略,每个Feign客户端都会创建一个logger。默认情况下,logger的名称Feign接口的完整类名,Feign的日志只会对DEBUG级别的日志做出响应。

Logger.Level可以为每个Feign客户端配置各自的日志的策略,告诉Feign记录哪些日志。Logger.Level有以下可选值:

  • NONE, 不记录任何值 (默认值).
  • BASIC, 仅记录请求方法,URL、响应状态代码及执行时间
  • HEADERS, 记录Basic级别的基础上,记录请求和响应头
  • FULL, 记录请求和响应头,body和元数据

 如下,设置Logger.Level的策略为FULL

@Configuration
public class FooConfiguration {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}

 在Feign的接口上指定配置配置类

@FeignClient(name = "hello", @Configuration=FooConfiguration.class)
protected interface HystrixClient {
	@RequestMapping(method = RequestMethod.GET, value = "/hello")
	Hello iFailSometimes();
}

在application.yml中指定Feign接口的日志级别为DEBUG

logging:
  level:
    com.ultrapower.uws.base.utils.SnowFlakeUtil: DEBUG

参考:《Spring Cloud与Docker微服务架构实战》周立

参考:https://cloud.spring.io/spring-cloud-static/Finchley.SR2/single/spring-cloud.html#_spring_cloud_openfeign

参考:https://github.com/OpenFeign/feign

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值