Feign学习笔记(一)

8 篇文章 0 订阅
5 篇文章 0 订阅

Feign 声明式远程调用

1.简介

Feign 是一个声明式的HTTP 客户端,它的目的就是让远程调用更加简单。Feign 提供了 HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好 HTTP 请求的参数、格式、地址等信息。
Feign 整合了 Ribbon(负载均衡)和 Hystrix(服务熔断),可以让我们不再需要显式地使用这两个组件。
SpringCloudFeign 在 NetflixFeign 的基础上扩展了对 SpringMVC 注解的支持,在其实现下,我们只需创建一个接口并用注解的方式来配置它,即可完成对服务提供方的接口绑定。简化了SpringCloudRibbon 自行封装服务调用客户端的开发量

2.如何使用呢?

步骤:

  • 导包
<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  • 创建接口并在接口上加@FeignClient(name=“要调用的服务名”) 可以使用占位符

  • 启动类上加上EnableClients(basePackages = “feign接口所在包名”) 可以使用占位符

    小结:
    建议使用模块化方式,在编写一个服务时将该服务拆分为三个模块:

    • clien模块用来专门放feign接口的,以便其它服务直接依赖使用
    • common模块用来存放各个微服务公用的一些实体类或工具等
    • server模块服务核心模块
      例如:在这里插入图片描述

3.组成

在这里插入图片描述
以上所列出的属性均可参考Feign官网配置进行配置
原理
在这里插入图片描述

4.Feign日志

Feign默认是不输出日志的,那么如何为feign配置日志输出呢?


参考官网:官网配置feign日志

Feign的日志级别:

级别打印内容
NONE(默认值)不记录任何日志
BASIC仅记录请求方法,URL,响应状态代码以及执行时间(最常用)
HEADERS记录BASIC级别的基础上,记录请求和响应的header
FULL记录请求和响应的header,body和元数据

问题1: 细粒度配置

用Java代码实现让特定的Feign接口为Full日志级别
解决1:

// 自定义一个接口:
@FeignClient(name = "user-center",configuration = UserCenterFeignConfiguration.class)
public interface UserCenterFeignClient {

    /**
     * http://user-center/users/{id}
     * @param id
     * @return
     */
    @GetMapping("/users/{id}")
    UserDTO findById(@PathVariable Integer id);
}

/**
再写一个配置类:
该配置类并没加@Configuration注解,否则就必须挪到@Component扫描的包以外,如果加了并且没将其挪到上述扫描的包以外的话,那么我们所定义的所有Feign的日志级别都将为FULL 。这个问题是典型的父子上下文问题
*/
public class UserCenterFeignConfiguration {
    @Bean
    public Logger.Level level() {
        return Logger.Level.FULL;
    }
}

// 最后我们还要在配置文件中加入配置才可以实现:(吐槽太麻烦了)
logging:
  level:
/**这里加feign接口的全路径的目的在于,想要打印feign日志必须建立在feign接口的日志级别为debug之上*/
    com:
      ray:
        content_center:
          feignclient:
            UserCenterFeignClient: debug

解决2: 属性配置方式

@FeignClient(name = "user-center")
public interface UserCenterFeignClient {

    /**
     * http://user-center/users/{id}
     * @param id
     * @return
     */
    @GetMapping("/users/{id}")
    UserDTO findById(@PathVariable Integer id);
}

feign:
  client:
    config: 
      #想要调用的微服务的名称
     user-center:
       loggerLevel: full

问题2:全局配置

Java代码方式实现所有Feign接口都为指定日志级别

  • 方式一:出现我们在上面的细粒度配置的父子上下文问题(不推荐)
  • 方式二:在@EnableFeignClients(defaultConfiguration=xxx.class)
    public class xxx {
          @Bean
          public Logger.Level level() {
              return Logger.Level.FULL;
          }
      }
    
    配置属性方式
    	feign:
      	  client:
      	    config:
      	      #全局配置
      	     default:
      	       loggerLevel: full
    

5.配置最佳实践总结

在这里插入图片描述
在这里插入图片描述

6.多参数请求构造

Tips: 版本:Spring Cloud Greenwich SR1,理论上支持更高版本

GET请求多参数的URL

假设需请求的URL包含多个参数,例如http://localhost:8080/get?id=1&userName=“ray”,该如何使用Feign构造呢?

通过官网我们知道:Feign添加了Spring MVC的注解支持:那就尝试一波

public class User{
	String userName;
	Long id;
}

@FeignClient("user-service")
public interface UserFeignClient {
  @RequestMapping(value = "/get", method = RequestMethod.GET)
  public User get(User user);
}

然而,这种写法并不正确,控制台输出如下异常:

feign.FeignException: status 405 reading UserFeignClient#get0(User); content:
{"timestamp":1482676142940,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method 'POST' not supported","path":"/get"}

由异常可知,尽管我们指定了GET方法,Feign依然会使用POST方法发送请求

正确写法如下:

  • 方式一:官网推荐食用
    @FeignClient("user-service")
    	public interface UserFeignClient {
    	  @GetMapping("/get")
    	  public User get(@SpringQueryMap User user);
    }
    
  • 方式二:
    @FeignClient(name = "user-service")
    public interface UserFeignClient {
      @RequestMapping(value = "/get", method = RequestMethod.GET)
      public User get(@RequestParam("id") Long id, @RequestParam("username") String userName);
    }
    

POST请求包含多个参数

假设服务提供者的Controller是这样的:

@RestController
public class UserController {
	  @PostMapping("/post")
	  public User post(@RequestBody User user) {}
}

咱们如何使用Feign去请求呢?如下:

@FeignClient(name = "user-service")
public interface UserFeignClient {
  @PostMapping("/post")
  public User post(@RequestBody User user);
}

7.Feign脱离Ribbon使用

Feign如何调用没有注册到注册中心的服务,如何做呢?
比如我想调用baidu:www.baidu.com

//这里的name一定要写,不然就会报错
@FeignClient(name = "baidu", url = "http://www.baidu.com")
public interface TestBaiduFeignClient {

    @GetMapping("")
    String index();
}

其它场景:
比如你想调用一个外部系统的HTTP接口,就可以这么玩啦。
举2个例子:

  • 你想调用支付宝的HTTP API;
  • 你的Spring Cloud微服务,想要调用遗留项目的接口(遗留项目还没有来得及重构成Spring Cloud)

总而言之, Feign本身就是一个Http客户端,你可以用Feign发送你想要发送的http请求。想请求哪儿调哪儿哈

8.RestTemplate VS Feign

角度RestTemplateFeign
可读性,可维护性一般极佳
开发体验欠佳极佳
性能很好中等(RestTemplate的50%左右)
灵活性极佳中等(内置功能可满足绝大多数需求)

如何选择呢?

原则: 尽量用Feign,杜绝使用RestTemplate,合理选择

9. Feign的性能优化

  • 连接池(提升15%左右)
    1.使用apache httpclient优化的
    先引入依赖:
    <dependency>
                <groupId>io.github.openfeign</groupId>
                <artifactId>feign-httpclient</artifactId>
    </dependency>
    feign:
       httpclient:
    #     让feign使用apache httpclient做请求;而不是默认的urlconnection
         enabled: true
    #     feign的最大连接数
         max-connections: 200
    #     feign单个路径的最大连接数
         max-connections-per-route: 50
         
    2.使用okhttpclient优化
    同样引入包,写配置
    
  • 日志级别(设置为BASIC)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值