OpenFeign进阶

一、什么是Feign

Feign是声明式Web服务客户端,它使编写Web服务客户端更加容易。Feign不做任何请求处理,通过处理注解相关信息生成Request,并对调用返回的数据进行解码,从而实现简化HTTP API的开发。

二、Feign和Openfeign的区别

Feign最早是由Netflix公司进行维护的,后来Netflix不再对其进行维护,最终Feign由社区进行维护,更名为Openfeign并将原项目迁移至新的仓库。

Feign集成了Ribbon、RestTemplate实现了负载均衡的执行Http调用,只不过对原有的方式(Ribbon+RestTemplate)进行了封装,开发者不必手动使用RestTemplate调服务,而是定义一个接口,在这个接口中标注一个注解即可完成服务调用,这样更加符合面向接口编程的宗旨,简化了开发。

三、常用负载均衡策略

  • 随机(Random)算法:在实例列表中随机选择某个实例。

  • 轮询(RoundRobin)算法:按顺序选择实例。

  • 最少连接数(Least Connections)算法:每次取连接数最少的实例。

  • 一致性哈希(Consistent Hashing)算法:基于一致性哈希算法总是将相同参数的请求落在同一个实例上。

  • 权重随机(Weigthd Random):随机取一个数,根据这个数属于哪个范围选择对应的实例。

四、Openfeign如何负载均衡

一般而言,我们生产者注册多个服务,消费者调用时需要使用负载均衡从中选取一个健康并且可用的生产者服务。因为Openfeign内部集成Ribbon,所以也支持此特性。Openfeign默认的负载均衡策略是轮询调用。

五、Ribbon负载均衡原理

我们以前接触的nginx的负载均衡是服务端的负载均衡,而Ribbon为客户端提供负载均衡,其内部提供了一个负载均衡器ILoadBalance。

LoadBalancerClient在初始化的时候,会通过ILoadBalance向Eureka注册中心获取服务注册列表,并且每10s一次向EurekaClient发送“ping”,来判断服务的可用性,如果服务的可用性发生了改变或者服务数量和之前的不一致,则从注册中心更新或者重新拉取。LoadBalancerClient有了这些服务注册列表,就可以根据具体的IRule来进行负载均衡,来获取调用的服务。

六、Ribbon负载均衡方式

6.1 随机策略RandomRule
随机策略RandomRule

核心代码:

int index = rand.nextInt(serverCount); // 使用jdk内部的Random类随机获取索引值index
server = upList.get(index); // 得到服务器实例
6.2 RoundRobinRule轮询策略

表示每次都取下一个服务器,如果失败会继续向下尝试获取10次

RoundRobinRule轮询策略
RoundRobinRule轮询策略
6.3 WeightedResponseTimeRule加权策略
WeightedResponseTimeRule加权策略

开始的时候还没有权重列表,采用父类的轮询方式,有一个默认每30秒更新一次权重列表的定时任务,该定时任务会根据实例的响应时间来更新权重列表,choose方法做的事情就是,用一个(0,1)的随机double数乘以最大的权重得到randomWeight,然后遍历权重列表,找出第一个比randomWeight大的实例下标,然后返回该实例。

6.4 BestAvailableRule策略用来选取最少并发量请求的服务器
BestAvailableRule

七、Openfeign更改负载均衡策略(默认轮询)

7.1 方式一:使用已经提供的
@Bean
public IRule ribbonRule() {
return new BestAvailableRule();//最小请求数
}
7.2 方式二:使用自定义的

通过底层源码我们发现,这些策略都继承了AbstractLoadBalancerRule抽象类,所以我们写自定义负载均衡策略,只需要2步

第一步:编写类继承AbstractLoadBanlancerRule抽象类,实现choose方法。

第二步:注入类实例

@Bean
public IRule ribbonRule() {
return new 自定义的类();//自定义负载策略类
}

八、Openfeign网络通信方式

如果不做特殊配置,OpenFeign默认使用jdk自带的HttpURLConnection,我们知道HttpURLConnection没有连接池、性能和效率比较低,如果采用默认,很可能会遇到性能问题导致系统故障。因此我们可以将其改为okhttp或者httpclient。

8.1 Feign中http client
8.1.1 Apache HttpClient

可以采用Apache HttpClient,properties文件中增加下面配置

feign.httpclient.enabled=true

pom文件中增加依赖

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
    <version>9.3.1</version>
</dependency>
8.1.2 OkHttpClient

也可以采用OkHttpClient,properties文件中增加下面配置

feign.okhttp.enabled=true

pom文件中增加依赖

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-okhttp</artifactId>
    <version>10.2.0</version>
</dependency>
8.2 Ribbon中的Http Client

通过OpenFeign作为注册中心的客户端时,默认使用Ribbon做负载均衡,Ribbon默认也是用jdk自带的HttpURLConnection,需要给Ribbon也设置一个Http client,比如使用okhttp,在properties文件中增加下面配置。

ribbon.okhttp.enabled=true

九、Openfeign日志级别

OpenFeign的日志级别有

  • NONE: 默认的,不显示任何日志。

  • BASIC: 仅记录请求方法、URL、响应状态码以及执行时间。

  • HEADERS:除了BASIC 中自定义的信息外,还有请求和响应的信息头。

  • FULL: 除了HEADERS中定义的信息外, 还有请求和响应的正文以及元数据。

自己写一个配置类

@Configuration
public class OpenFeignLogConfig {
  @Bean
  Logger.Level feignLoggerLeave(){
    return Logger.Level.FULL;
  }
}

配置文件

logging:
  level:
  *[feign日志以什么级别监控哪个接口]:
  com.king.springcloud.service.OrderFeignService: debug

十、OpenFeign超时时间

10.1 全局超时时间

OpenFeign可以设置超时时间,简单粗暴,设置一个全局的超时时间,如下

feign.client.config.default.connectTimeout=2000
feign.client.config.default.readTimeout=60000

如果不配置超时时间,默认是连接超时10s,读超时60s,在源码feign.Request的内部类Options中定义。

10.2 单服务设置超时时间

需要对serviceC单独设置一个超时时间,代码如下

feign.client.config.serviceC.connectTimeout=2000
feign.client.config.serviceC.readTimeout=60000

这个时间会覆盖全局默认的超时时间。

十一、Ribbon超时时间

作为负载均衡,Ribbon超时时间也是可以配置的,可以在properties增加下面配置

ribbon.ConnectTimeout=2000
ribbon.ReadTimeout=11000

有文章讲ribbon配置的超时时间必须要满足接口响应时间,其实不然,配置feign的超时时间就足够了,因为它可以覆盖掉ribbon的超时时间。

十二、开启熔断

可以在properties增加下面配置

feign.hystrix.enabled=true

十三、开启重试

13.1 OpenFeign开启重试

OpenFeign默认是不支持重试的,可以在源代码FeignClientsConfiguration中feignRetryer中看出

@Bean
@ConditionalOnMissingBeanpublic
Retryer feignRetryer { return Retryer.NEVER_RETRY;}

要开启重试,我们可以自定义Retryer,比如下面这行代码

Retryer retryer = new Retryer.Default(100, 1000, 2);

表示每间隔100ms,最大间隔1000ms重试一次,最大重试次数是1,因为第三个参数包含了第一次请求。

13.2 Ribbon重试
13.2.1 拉取服务列表

Ribbon默认从服务端拉取列表的时间间隔是30s,这个对优雅发布很不友好,一般我们会把这个时间改短,如下改成3s

myService.ribbon.ServerListRefreshInterval=3

其中myService是你的目的地微服务的名称

13.2.2 重试

Ribbon重试有不少需要注意的地方,这里分享4个。

1、同一实例最大重试次数,不包括首次调用,配置如下

serviceC.ribbon.MaxAutoRetries=1

这个次数不包括首次调用,配置了1,重试策略会先尝试在失败的实例上重试一次,如果失败,请求下一个实例。

2、同一个服务其他实例的最大重试次数,这里不包括第一次调用的实例。默认值为1

serviceC.ribbon.MaxAutoRetriesNextServer=1

3、是否对所有操作都重试,如果改为true,则对所有操作请求都进行重试,包括post,建议采用默认配置false

serviceC.ribbon.OkToRetryOnAllOperations=false

4、对指定的http状态码进行重试

serviceC.retryableStatusCodes=404,408,502,500

十四、使用OpenFeign做http客户端

即使不用注册中心,使用OpenFeign做普通http客户端也是很方便的,但是有三点需要注意:

  • 不用配置ribbon相关参数。
  • 使用RestTemplate调用时,不考虑负载均衡。
  • 使用过程中OpenFeign要组装出自己的一套请求,跟直接使用http客户端比,会有一定开销。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容