0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Spring Cloud Feign总结问题,注意点,性能调优,切换okhttp3

电子设计 来源:电子设计 作者:电子设计 2020-12-10 22:43 次阅读

Feign常见问题总结

FeignClient接口如使用@PathVariable ,必须指定value属性

//在一些早期版本中, @PathVariable("id") 中的 "id" ,也就是value属性,必须指定,不能省略。
@FeignClient("microservice-provider-user")
public interface UserFeignClient {
  @RequestMapping(value = "/simple/{id}", method = RequestMethod.GET)
  public User findById(@PathVariable("id") Long id);
  ...
}

Java代码自定义Feign Client的注意点与坑

@FeignClient(name = "microservice-provider-user", configuration = UserFeignConfig.class)
public interface UserFeignClient {
  @GetMapping("/users/{id}")
  User findById(@PathVariable("id") Long id);
}

/**
 * 该Feign Client的配置类,注意:
 * 1. 该类可以独立出去;
 * 2. 该类上也可添加@Configuration声明是一个配置类;
 * 配置类上也可添加@Configuration注解,声明这是一个配置类;
 * 但此时千万别将该放置在主应用程序上下文@ComponentScan所扫描的包中,
 * 否则,该配置将会被所有Feign Client共享,无法实现细粒度配置!
 * 个人建议:像我一样,不加@Configuration注解
 *
 * @author zhouli
 */
class UserFeignConfig {
  @Bean
  public Logger.Level logger() {
    return Logger.Level.FULL;
  }
}
  • 配置类上也可添加@Configuraiton 注解,声明这是一个配置类;但此时千万别将该放置在主应用程序上下文@ComponentScan 所扫描的包中,否则,该配置将会被所有Feign Client共享(相当于变成了通用配置,其实本质还是Spring父子上下文扫描包重叠导致的问题),无法实现细粒度配置!
  • 个人建议:像我一样,不加@Configuration注解,省得进坑。
  • 最佳实践:尽量用配置属性自定义Feign的配置!!!

@FeignClient 注解属性

//@FeignClient(name = "microservice-provider-user")
//在早期的Spring Cloud版本中,无需提供name属性,从Brixton版开始,@FeignClient必须提供name属性,否则应用将无法正常启动!
//另外,name、url等属性支持占位符。例如:
@FeignClient(name = "${feign.name}", url = "${feign.url}")

类级别的@RequestMapping会被Spring MVC加载

@RequestMapping("/users")
@FeignClient(name = "microservice-user")
public class TestFeignClient {
    // ...
}

类上的@RequestMapping 注解也会被Spring MVC加载。该问题现已经被解决,早期的版本有两种解决方案:
方案1:不在类上加@RequestMapping 注解;
方案2:添加如下代码:

@Configuration
@ConditionalOnClass({ Feign.class })
public class FeignMappingDefaultConfiguration {
    @Bean
    public WebMvcRegistrations feignWebRegistrations() {
        return new WebMvcRegistrationsAdapter() {
            @Override
            public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
                return new FeignFilterRequestMappingHandlerMapping();
            }
        };
    }

    private static class FeignFilterRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
        @Override
        protected boolean isHandler(Class beanType) {
            return super.isHandler(beanType) && !beanType.isInterface();
        }
    }
}

首次请求失败
Ribbon的饥饿加载(eager-load)模式

如需产生Hystrix Stream监控信息,需要做一些额外操作
Feign本身已经整合了Hystrix,可直接使用@FeignClient(value = "microservice-provider-user", fallback = XXX.class) 来指定fallback类,fallback类继承@FeignClient所标注的接口即可。

但是假设如需使用Hystrix Stream进行监控,默认情况下,访问http://IP:PORT/actuator/hystrix.stream 是会返回404,这是因为Feign虽然整合了Hystrix,但并没有整合Hystrix的监控。如何添加监控支持呢?需要以下几步:

第一步:添加依赖,示例:


org.springframework.cloudspring-cloud-starter-hystrix

第二步:在启动类上添加@EnableCircuitBreaker 注解,示例:

@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
@EnableCircuitBreaker
public class MovieFeignHystrixApplication {
  public static void main(String[] args) {
    SpringApplication.run(MovieFeignHystrixApplication.class, args);
  }
}

第三步:在application.yml中添加如下内容,暴露hystrix.stream端点:

management:
  endpoints:
    web:
      exposure:
        include: 'hystrix.stream'

这样,访问任意Feign Client接口的API后,再访问http://IP:PORT/actuator/hystrix.stream ,就会展示一大堆Hystrix监控数据了。

原文链接:http://www.itmuch.com/spring-...

Feign 上传文件

加依赖

io.github.openfeign.formfeign-form3.0.3io.github.openfeign.formfeign-form-spring3.0.3

编写Feign Client

@FeignClient(name = "ms-content-sample", configuration = UploadFeignClient.MultipartSupportConfig.class)
public interface UploadFeignClient {
    @RequestMapping(value = "/upload", method = RequestMethod.POST,
            produces = {MediaType.APPLICATION_JSON_UTF8_VALUE},
            consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ResponseBody
    String handleFileUpload(@RequestPart(value = "file") MultipartFile file);

    class MultipartSupportConfig {
        @Bean
        public Encoder feignFormEncoder() {
            return new SpringFormEncoder();
        }
    }
}

如代码所示,在这个Feign Client中,我们引用了配置类MultipartSupportConfig ,在MultipartSupportConfig 中,我们实例化了SpringFormEncoder 。这样这个Feign Client就能够上传啦。
注意点

//RequestMapping注解中的produeces 、consumes 不能少;
@RequestMapping(value = "/upload", method = RequestMethod.POST,
            produces = {MediaType.APPLICATION_JSON_UTF8_VALUE},
            consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
  • 接口定义中的注解@RequestPart(value = "file") 不能写成@RequestParam(value = "file")
  • 最好将Hystrix的超时时间设长一点,例如5秒,否则可能文件还没上传完,Hystrix就超时了,从而导致客户端侧的报错。

原文链接:http://www.itmuch.com/spring-...

Feign实现Form表单提交

添加依赖:

io.github.openfeign.formfeign-form3.2.2io.github.openfeign.formfeign-form-spring3.2.2

Feign Client示例:

@FeignClient(name = "xxx", url = "http://www.itmuch.com/", configuration = TestFeignClient.FormSupportConfig.class)
public interface TestFeignClient {
    @PostMapping(value = "/test",
            consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE},
            produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}
            )
    void post(Map queryParam);

    class FormSupportConfig {
        @Autowired
        private ObjectFactory messageConverters;
        // new一个form编码器,实现支持form表单提交
        @Bean
        public Encoder feignFormEncoder() {
            return new SpringFormEncoder(new SpringEncoder(messageConverters));
        }
        // 开启Feign的日志
        @Bean
        public Logger.Level logger() {
            return Logger.Level.FULL;
        }
    }
},>

调用示例:

@GetMapping("/user/{id}")
public User findById(@PathVariable Long id) {
  HashMap param = Maps.newHashMap();
  param.put("username","zhangsan");
  param.put("password","pwd");
  this.testFeignClient.post(param);
  return new User();
},>

日志:

...[TestFeignClient#post] ---> POST http://www.baidu.com/test HTTP/1.1
...[TestFeignClient#post] Accept: application/json;charset=UTF-8
...[TestFeignClient#post] Content-Type: application/x-www-form-urlencoded; charset=UTF-8
...[TestFeignClient#post] Content-Length: 30
...[TestFeignClient#post] 
...[TestFeignClient#post] password=pwd&username=zhangsan
...[TestFeignClient#post] ---> END HTTP (30-byte body)

由日志可知,此时Feign已能使用Form表单方式提交数据。

原文链接:http://www.itmuch.com/spring-...

Feign GET请求如何构造多参数

假设需请求的URL包含多个参数,例如http://microservice-provider-... ,该如何使用Feign构造呢?
我们知道,Spring Cloud为Feign添加了Spring MVC的注解支持,那么我们不妨按照Spring MVC的写法尝试一下:

@FeignClient("microservice-provider-user")
public interface UserFeignClient {
  @RequestMapping(value = "/get", method = RequestMethod.GET)
  public User get0(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方法发送请求。于是导致了异常。正确写法如下

方法一[推荐]
注意:使用该方法无法使用Fegin的继承模式

@FeignClient("microservice-provider-user")
public interface UserFeignClient {
  @GetMapping("/get")
  public User get0(@SpringQueryMap User user);
}

方法二[推荐]

@FeignClient(name = "microservice-provider-user")
public interface UserFeignClient {
  @RequestMapping(value = "/get", method = RequestMethod.GET)
  public User get1(@RequestParam("id") Long id, @RequestParam("username") String username);
}

这是最为直观的方式,URL有几个参数,Feign接口中的方法就有几个参数。使用@RequestParam注解指定请求的参数是什么。

方法三[不推荐]
多参数的URL也可使用Map来构建。当目标URL参数非常多的时候,可使用这种方式简化Feign接口的编写。

@FeignClient(name = "microservice-provider-user")
public interface UserFeignClient {
  @RequestMapping(value = "/get", method = RequestMethod.GET)
  public User get2(@RequestParam Map map);
},>

在调用时,可使用类似以下的代码。

public User get(String username, String password) {
  HashMap map = Maps.newHashMap();
  map.put("id", "1");
  map.put("username", "张三");
  return this.userFeignClient.get2(map);
},>

注意:这种方式不建议使用。主要是因为可读性不好,而且如果参数为空的时候会有一些问题,例如map.put("username", null); 会导致服务调用方(消费者服务)接收到的username是"" ,而不是null。

原文链接:http://www.itmuch.com/spring-...

切换为 Okhttp3 提升 QPS 性能优化

加依赖引入okhttp3

io.github.openfeignfeign-okhttp${version}

写配置

feign:
  # feign启用hystrix,才能熔断、降级
  # hystrix:
  # enabled: true
  # 启用 okhttp 关闭默认 httpclient
  httpclient:
    enabled: false #关闭httpclient
    # 配置连接池
    max-connections: 200 #feign的最大连接数
    max-connections-per-route: 50 #fegin单个路径的最大连接数
  okhttp:
    enabled: true
  # 请求与响应的压缩以提高通信效率
  compression:
    request:
      enabled: true
      min-request-size: 2048
      mime-types: text/xml,application/xml,application/json
    response:
      enabled: true

参数配置

/**
 * 配置 okhttp 与连接池
 * ConnectionPool 默认创建5个线程,保持5分钟长连接
 */
@Configuration
@ConditionalOnClass(Feign.class)
@AutoConfigureBefore(FeignAutoConfiguration.class) //SpringBoot自动配置
public class OkHttpConfig {

    // 默认老外留给你彩蛋中文乱码,加上它就 OK
    @Bean
    public Encoder encoder() {
        return new FormEncoder();
    }

    @Bean
    public okhttp3.OkHttpClient okHttpClient() {
        return new okhttp3.OkHttpClient.Builder()
                //设置连接超时
                .connectTimeout(10, TimeUnit.SECONDS)
                //设置读超时
                .readTimeout(10, TimeUnit.SECONDS)
                //设置写超时
                .writeTimeout(10, TimeUnit.SECONDS)
                //是否自动重连
                .retryOnConnectionFailure(true)
                .connectionPool(new ConnectionPool(10, 5L, TimeUnit.MINUTES))
                .build();
    }
}

来源:赵小胖个人博客

审核编辑 黄昊宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    11232

    浏览量

    208966
  • JAVA
    +关注

    关注

    19

    文章

    2960

    浏览量

    104566
  • 数据库
    +关注

    关注

    7

    文章

    3768

    浏览量

    64286
  • python
    +关注

    关注

    56

    文章

    4783

    浏览量

    84475
收藏 人收藏

    评论

    相关推荐

    史上最全性能总结

    在说什么是性能之前,我们先来说一下,计算机的体系结构。
    的头像 发表于 05-13 08:57 6283次阅读
    史上最全<b class='flag-5'>性能</b><b class='flag-5'>调</b><b class='flag-5'>优</b><b class='flag-5'>总结</b>

    EDAS再升级!全面支持Spring Cloud应用

    摘要: 近日,阿里中间件(Aliware)的企业级分布式应用服务EDAS宣布再次升级,全面支持Spring Cloud应用。此查看原文:[url=]http://click.aliyun.com
    发表于 02-02 15:20

    HBase性能概述

    HBase性能
    发表于 07-03 11:35

    Spring Cloud Config公共配置解决方案

    Spring Cloud Config 多服务公共配置
    发表于 08-30 09:05

    基于全HDD aarch64服务器的Ceph性能实践总结

    和成本之间实现了最佳平衡,可以作为基于arm服务器来部署存储的参考设计。2 Ceph架构3 测试集群硬件配置:3台arm服务器每台arm服务器:软件配置性能测试工具4
    发表于 07-05 14:26

    infosphere CDC性能的文档

    infosphere CDC性能的文档
    发表于 09-07 09:30 7次下载
    infosphere CDC<b class='flag-5'>性能</b><b class='flag-5'>调</b><b class='flag-5'>优</b>的文档

    架构分析高效HTTP客户端OkHttp有什么优势

    OkHttp3中,其灵活性很大程度上体现在,可以拦截其任意一个环节,而这个优势便是okhttp3整个请求响应架构体系的精髓所在:
    的头像 发表于 05-05 23:13 3839次阅读
    架构分析高效HTTP客户端<b class='flag-5'>OkHttp</b>有什么优势

    Spring Cloud Feign性能优化

    首先,把 tomcat 换成 undertow,这个性能在 Jmeter 的压测下,undertow 比 tomcat 高一倍第一步,pom 修改去除tomcat
    的头像 发表于 12-10 22:43 493次阅读

    基于SharedPreferences的OkHttp3的持久CookieJar实现

    介绍 基于 SharedPreferences 的 OkHttp3 的持久 CookieJar 实现。该库通常用于存储从 http url 获取的 cookie。如果我们再次点击 url 并获取
    发表于 04-12 10:37 3次下载

    Spring Cloud Tencent发布最新匹配版本!

    Cloud 2022。此篇文章详细讲述了 Spring Cloud Tencent 从 2021 版本升级到 2022 版本的改动
    的头像 发表于 12-09 15:34 1076次阅读

    Spring Cloud 2022.0.0正式发布

    由于 Spring 现在提供了他们自己实现的接口 HTTP 客户端解决方案,因此从 2022.0.0 开始,Spring Cloud OpenFeign 已到达特性完成状态。这意味着 Spri
    的头像 发表于 12-22 10:39 702次阅读

    dubbo和spring cloud区别

    Dubbo和Spring Cloud是两个非常流行的微服务框架,各有自己的特点和优势。在本文中,我们将详细介绍Dubbo和Spring Cloud的区别。 1.架构设计: Dubbo是
    的头像 发表于 12-04 14:47 1626次阅读

    鸿蒙开发实战:【性能组件】

    性能组件包含系统和应用框架,旨在为开发者提供一套性能
    的头像 发表于 03-13 15:12 405次阅读
    鸿蒙开发实战:【<b class='flag-5'>性能</b><b class='flag-5'>调</b><b class='flag-5'>优</b>组件】

    鸿蒙OS封装【axios 网络请求】(类似Android的Okhttp3

    HarmonyOS 封装 axios 网络请求 包含 token 类似Android Okhttp3
    的头像 发表于 03-26 21:14 2639次阅读

    Spring Cloud Gateway网关框架

    SpringCloud Gateway功能特征如下: (1) 基于Spring Framework 5, Project Reactor 和 Spring Boot 2.0 进行构建; (2) 动态路由:能够匹配任何请求属性; (3
    的头像 发表于 08-22 09:58 439次阅读
    <b class='flag-5'>Spring</b> <b class='flag-5'>Cloud</b> Gateway网关框架