• Feign导航


    简介

    最近都在弄微服务的东西,现在来记录下收获。我从一知半解到现在能从0搭建使用最大的感触有两点

    1.微服务各大组件的版本很多,网上很多博客内容不一定适合你的版本,很多时候苦苦琢磨都是无用功

    2.网上博客参差不齐,有些甚至错误的。更离谱的是,好的文章阅读量除非高出天际,不然就都很低,比那些复制粘贴,随便应付的都低(这个搜索推荐算法不知道基于什么的)

    通过这段时间学习,我觉得最重要是从好的博客入手,先不要着急怎么组件怎么使用,而是先了解组件的作用,大概的原理,然后才是使用,这样搭建和尝试的过程中才能更好的定位问题,最后再次回到原理和一些实际问题的处理(不知道实际问题怎样的,直接搜那个组件的面试题往往效果最好)

    接下来的内容,都以导航的形式展现给大家(毕竟优秀的轮子很多,直接看大佬写的不香嘛),再顺带提些自己的理解

    传送门

    更多微服务的介绍可点击下方链接

    微服务介绍Nginx导航Nacos导航Gateway导航Ribbon导航Feign导航Sentinel导航

    博主微服务git练手项目:https://github.com/NiceJason/SpringCloudDemo

    Feign导航

    Feign详细讲解:https://blog.csdn.net/luanlouis/article/details/82821294

    文中有几个地方的点提一下

    1.将调用抽象为starter

    文中提到,作者团队将远程调用抽象成接口,定义了服务端starter,服务消费者在使用的时候,只需要引入Starter,就可以调用服务。这个比较适合平台无关性,接口抽象出来的好处就是可以根据服务调用实现方式自有切换。这种思路跟Spring里面的log框架类似,我们调用log都是调用接口,Spring内部默认有一套日志类实现了此接口,我们经常自己指定log4j2去代替它,只要引用配置和相关starter就行,代码上丝毫不用动。

    2.高版本Feign

    @GetMapping,@PutMapping在高版本的Feign中也是可用的了(目前直接把Controller的方法直接复制到@FeignClient接口中调用是没问题)

    3.让Feign支持文件传输

    我们可以看到好的框架扩展性真的强,如Encode和Decode都是接口暴露出来,我们经常用JacksonEncoder,JacksonDecoder去替代它又或者SpringCloud这种框架有自己的替代方案。我们虽然写业务较多,没什么机会写这种牛逼的组件,但这设计思想还是可以用的。顺便提一下由于Feign默认的读取的配置FeignClientsConfiguration,里面的Encoder默认是springEncoder,该类型不支持文件格式,所以要换成以下

     1 import feign.form.spring.SpringFormEncoder;
     2 import org.springframework.beans.factory.ObjectFactory;
     3 import org.springframework.beans.factory.annotation.Autowired;
     4 import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
     5 import org.springframework.cloud.openfeign.support.SpringEncoder;
     6 import org.springframework.context.annotation.Bean;
     7 import org.springframework.context.annotation.Configuration;
     8 
     9 /**
    10  * @Author DiaoJianBin
    11  * @Description Feign的通用配置
    12  * @Date 2021/3/11 9:56
    13  */
    14 @Configuration(proxyBeanMethods = false)
    15 public class FeignConfig {
    16 
    17     @Autowired
    18     private ObjectFactory<HttpMessageConverters> messageConverters;
    19 
    20     @Bean
    21     public SpringFormEncoder feignFormEncoder(){
    22         return new SpringFormEncoder(new SpringEncoder(messageConverters));
    23     }
    24 }

    其中SpringFormEncoder的部分代码如下,可以看到开头判断了是否是MultipartFile类或者数组

     1 @Override
     2   public void encode (Object object, Type bodyType, RequestTemplate template) throws EncodeException {
     3     if (bodyType.equals(MultipartFile[].class)) {
     4       val files = (MultipartFile[]) object;
     5       val data = new HashMap<String, Object>(files.length, 1.F);
     6       for (val file : files) {
     7         data.put(file.getName(), file);
     8       }
     9       super.encode(data, MAP_STRING_WILDCARD, template);
    10     } else if (bodyType.equals(MultipartFile.class)) {
    11       val file = (MultipartFile) object;
    12       val data = singletonMap(file.getName(), object);
    13       super.encode(data, MAP_STRING_WILDCARD, template);
    14     } else if (isMultipartFileCollection(object)) {
    15       val iterable = (Iterable<?>) object;
    16       val data = new HashMap<String, Object>();
    17       for (val item : iterable) {
    18         val file = (MultipartFile) item;
    19         data.put(file.getName(), file);
    20       }
    21       super.encode(data, MAP_STRING_WILDCARD, template);
    22     } else {
    23       super.encode(object, bodyType, template);
    24     }
    25   }

    4.Feign的重试注意点

    文中讲了Feign的重试,一般微服务都会整合Ribbon,发送的负载均衡,重试等都是由Ribbon负责的,可以看Feign里的源码

    我们想要启用Feign会在SpringbootApplication类上加注解@EnableFeignClients

     这个注解里有如下说明,告诉我们默认配置看FeignClientsConfiguration

     然后看FeignClientsConfiguration类可以看到,可以在这里打个断点,然后启动项目就能了解清楚啦

     

    从这可以看到,Feign默认是关闭重试的

    具体想开启重试,即要开启Ribbon的重试,具体内容可以在传送门点击Ribbon导航,里面有介绍

    5.Feign开启OkHttpClient

    目前效率最高的当属okHttpClient,以下是怎么在Feign中开启和配置相关内容

    #使用okHttp作为客户端
    feign.httpclient.enabled=false
    feign.okhttp.enabled=true
    
    #配置其中的属性,开启okhttp后下面几个无效
    #默认最大连接数
    #feign.httpclient.max-connections=1000
    #单个调用最大连接数
    #feign.httpclient.max-connections-per-route=100
    #当http返回码为3xxx时,默认会重定向操作
    #feign.httpclient.follow-redirect=false
    
    #配置Sentinel
    feign.hystrix.enabled=true
    feign.sentinel.enabled=true

    6.Feign的回退注意点

    从上面的配置中,有人可能会问,为啥开启了hystrix又开启sentinel,两者不都是熔断限流的组件嘛,在我项目里用的是sentinel,所以sentinel需要开启

    而hystrix开启是因为Feign的回退(fallbackFactory或者fallback)需要开启这个才能正常执行,像我们经常这样写

     1 /**
     2  * @Author DiaoJianBin
     3  * @Description 访问BusinessService服务的接口
     4  *              有2种回退策略
     5  *              1.fallback = BusinessServiceTestClientFallback.class
     6  *              2.fallbackFactory = BusinessServiceTestFallballFactory.class
     7  *              当两者存在时,只能有一种生效,fallback优先级高于fallbackFactory
     8  *              但是fallback无法处理异常,就是你不知道啥原因进入了降级
     9  *              推荐用fallback优先级高于fallbackFactory
    10  * @Date 2021/3/11 11:23
    11  */
    12 @Primary
    13 @FeignClient(value = "business-service",path = "/test",decode404 = true,fallbackFactory = BusinessServiceTestFallballFactory.class)
    14 public interface BusinessServiceTestClient {
    15 
    16     /**
    17      * 即使目标实际Controller的方法有HttpServletRequst
    18      * 但是不需要传此参数,就不用写
    19      * @param message
    20      * @return
    21      */
    22     @PostMapping(value = "/getSlowMessage")
    23     String getSlowMessage(@RequestBody String message);
    24 }

    如果用了fallbackFactory或者fallback,这里需要注意@Primary注解要加上,不然@Autowired注入不了,因为FeignClient会根据接口生成一个代理类,而fallbackFactory或者fallback指定的类又得@Component才行,这样注入Spring会混乱,但你没法指定代理类生成的名字

    7.@FeignClient中的name和url参数

    关于调用目前有两种:
    从源码可以得知,name是value的别名,value也是name的别名。两者的作用是一致的,name指定FeignClient的名称,如果项目使用了Ribbon,name属性会作为微服务的名称,用于服务发现。
    1、接口提供方在注册中心。
    如果服务提供方已经注册到注册中心了,那么name或者value的值为:服务提供方的服务名称。必须为所有客户端指定一个name或者value
    @FeignClient(value="run-product",fallback = ProductClientServiceFallBack.class)
     
    2、单独的一个http接口,接口提供方没有注册到注册中心。
    @FeignClient(name="runClient11111",url="localhost:8001")
    此处name的值为:调用客户端的名称。
     
    以上两种方式都能正常调用。name可以为注册中心的实例名称,加上url属性时,name的值就与注册中心实例名称无关(URL一般用于本地调试)。

    8.Feign自定义拦截器

     1 /**
     2  * @Author DiaoJianBin
     3  * @Description  openFeign的拦截器,可以在请求发送前做些处理
     4  * @Date 2021/3/14 16:10
     5  */
     6 public class UserFeignInterceptor implements RequestInterceptor {
     7     @Override
     8     public void apply(RequestTemplate template) {
     9         System.out.println("例如在这里添加token");
    10         template.header("token","123");
    11     }
    12 }

    小结

            本篇博客主要讲了Feign一些注意点,正常的Feign的使用大家可以自行搜索,很简单。目前个人使用Feign主要还是系统服务的内部调用,访问第三方服务(如微信支付)往往要SSL验证等,这个时候用RestTemplate比较方便。希望能帮到大家~

    学习和点赞一样,可不能下次一定啊! 感谢你的三连~
  • 相关阅读:
    ArrayList实现原理及源码分析之JDK8
    红黑树原理和算法介绍
    TreeMap实现原理及源码分析之JDK8
    HashMap实现原理及源码分析之JDK8
    mysql索引的使用
    HashMap实现原理及源码分析之JDK7
    arthas Can not find tools.jar 使用报错
    idea maven 更新不到本地 手动添加的 jar
    Nodejs安装及环境配置
    安装独立版本的MAT
  • 原文地址:https://www.cnblogs.com/top-housekeeper/p/14789296.html
Copyright © 2020-2023  润新知