SpringCloud Alibaba 微服务实战二十三

Easter79
• 阅读 634

概述

在正常情况下Feign有三种客户端实现:

  1. Client.Default类:默认的 feign.Client 客户端实现类,内部使用 HttpURLConnnection 完成HTTP URL请求处理;

  2. ApacheHttpClient 类:内部使用 Apache httpclient开源组件完成HTTP URL请求处理的feign.Client 客户端实现类;

  3. OkHttpClient类:内部使用 OkHttp3 开源组件完成HTTP URL请求处理的feign.Client 客户端实现类。

    @ConditionalOnClass({ ILoadBalancer.class, Feign.class }) @ConditionalOnProperty(value = "spring.cloud.loadbalancer.ribbon.enabled",   matchIfMissing = true) @Configuration(proxyBeanMethods = false) @AutoConfigureBefore(FeignAutoConfiguration.class) @EnableConfigurationProperties({ FeignHttpClientProperties.class }) @Import({ HttpClientFeignLoadBalancedConfiguration.class,   OkHttpFeignLoadBalancedConfiguration.class,   DefaultFeignLoadBalancedConfiguration.class }) public class FeignRibbonClientAutoConfiguration {  ... }

在前面一节内容中我们看到Feign默认客户端实现 HttpURLConnnection性能不是很好,与Dubbo RPC的性能相差很大。基于 HttpURLConnnection的测试结果如下:

SpringCloud Alibaba 微服务实战二十三

聚合报告

平均响应时间

吞吐量

最小响应时间

最大响应时间

6866ms

59.5/sec

3056ms

12232ms

本章内容我们需要对Feign的所有客户端进行性能测试,以此来确定选择一个最优的客户端调用工具。

测试工具

测试服务器:Intel Core i5-7200U CPU @ 2.50GHz 2.70GHz  6核 16G内存

测试工具:JMeter5.1

线程数:1000

Ramp-Up : 10

SpringCloud Alibaba 微服务实战二十三

JMeter测试工具

「ps : 本文中出现的所有性能测试结果我都至少测试过10遍以上,最后选取的是一个相对平均的结果,测试结果相对还是比较准确的。」

HttpClient

首先我们先将客户端工具切换到HttpClient,查看HttpClientFeignLoadBalancedConfiguration配置类,源码如下

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(ApacheHttpClient.class)
@ConditionalOnProperty(value = "feign.httpclient.enabled", matchIfMissing = true)
@Import(HttpClientFeignConfiguration.class)
class HttpClientFeignLoadBalancedConfiguration {

 @Bean
 @ConditionalOnMissingBean(Client.class)
 public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
   SpringClientFactory clientFactory, HttpClient httpClient) {
  ApacheHttpClient delegate = new ApacheHttpClient(httpClient);
  return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
 }

}

从代码 @ConditionalOnClass({ApacheHttpClient.class})注解可知,只需要在pom文件上加上 HttpClient依赖即可。另外需要在配置文件中配置 feign.httpclient.enabledtrue从@ConditionalOnProperty注解可知,这个配置可以不写,因为在默认情况下就为true。

所以要使用HttpClient我们只需要在消费者模块 order-service引入httpclient依赖即可:

<dependency>
 <groupId>io.github.openfeign</groupId>
 <artifactId>feign-httpclient</artifactId>
</dependency>

测试结果

SpringCloud Alibaba 微服务实战二十三

聚合报告

平均响应时间

吞吐量

最小响应时间

最大响应时间

8390ms

48.5/sec

2691ms

20371ms

在高并发下性能测试居然比不过原生的 HttpURLConnnection ,有点点失望!

OkHttp

同样先查看okhttp的配置类 OkHttpFeignLoadBalancedConfiguration

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(OkHttpClient.class)
@ConditionalOnProperty("feign.okhttp.enabled")
@Import(OkHttpFeignConfiguration.class)
class OkHttpFeignLoadBalancedConfiguration {

 @Bean
 @ConditionalOnMissingBean(Client.class)
 public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
   SpringClientFactory clientFactory, okhttp3.OkHttpClient okHttpClient) {
  OkHttpClient delegate = new OkHttpClient(okHttpClient);
  return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
 }

}

查看注解我们知道要使用OkHttp必须满足两个条件:

  1. 必须满足 OkHttpClient.class 在当前类路径中存在,即引入相应依赖

  2. 必须要配置 feign.okhttp.enabled配置项的值为true

所以这里我先引入OkHttp的依赖:

<dependency>
 <groupId>io.github.openfeign</groupId>
 <artifactId>feign-okhttp</artifactId>
</dependency>

然后修改配置文件,开启OkHttp:

feign:
...
  okhttp:
    enabled: true

测试结果

SpringCloud Alibaba 微服务实战二十三

聚合报告

平均响应时间

吞吐量

最小响应时间

最大响应时间

5335ms

66.3/sec

1874ms

9011ms

三个客户端中性能最好的!

测试结果分析

通过上面测试结果(默认配置)我们很明显可以得出以下两个结论:

  1. OKHttp性能优于其他两种,推荐使用!

  2. 在高并发情况下 Apache httpclient效率甚至还没有默认的 HttpURLConnection效率高。且在压测过程中,发现使用连接池请求卡顿现象很容易出现, apache httpclient 甚至还出现请求卡死情况。httpclient最不推荐使用。

容器优化

Undertow是一个用java编写的灵活的高性能Web服务器,提供基于NIO的阻塞和非阻塞API。相比于 tomcatUndertow的性能更高,更轻量。借此机会我们刚好看看 UndertowOkHttp的测试效果。

首先我们需要引入undertow的依赖并排除tomcat的依赖:

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 <exclusions>
  <exclusion>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-tomcat</artifactId>
  </exclusion>
 </exclusions>
</dependency>

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

测试效果

SpringCloud Alibaba 微服务实战二十三

聚合报告

平均响应时间

吞吐量

最小响应时间

最大响应时间

3817ms

71.7/sec

1830ms

6174ms

通过测试效果可以看出,使用了undertow容器后,性能又有了小小的提升。

总结

本文中的所有测试结论都是基于组件的默认配置,对于那些追求性能而又不想对参数进行调优的可以考虑 OkHttp + Undertow的组合,虽然没办法与dubbo等rpc协议性能相比,但是在springcloud架构中的http调用,这两者之间的组合性能最高。

最后为了方便大家直观比较,将Feign原生 HttpURLConnnection的测试结果和基于 OkHttp + Undertow的测试结果放一起供大家参考:

  • HttpURLConnnection

平均响应时间

吞吐量

最小响应时间

最大响应时间

6866ms

59.5/sec

3056ms

12232ms

  • OkHttp + Undertow

平均响应时间

吞吐量

最小响应时间

最大响应时间

3817ms

71.7/sec

1830ms

6174ms

如果本文对你有帮助,别忘记来个三连:点赞,转发,评论。咱们下期见!

SpringCloud Alibaba 微服务实战二十三

本文分享自微信公众号 - JAVA日知录(javadaily)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k