spring cloud feign學(xué)習(xí)三:Feign的更多使用

Ribbon配置

全局配置

由于Spring cloud Feign的客戶端負(fù)載均衡是通過spring cloud Ribbon實(shí)現(xiàn)的术瓮,所以我們可以直接通過配置Ribbon客戶端的方式來自定義各個(gè)服務(wù)客戶端調(diào)用的參數(shù)滤淳。

ribbon.ConnectTimeout=500
ribbon.ReadTimeOut=5000

指定服務(wù)配置

大多數(shù)情況下援制,我們對于服務(wù)調(diào)用的超時(shí)時(shí)間可能會根據(jù)實(shí)際服務(wù)的特性做一些調(diào)整妨退,所以僅僅依靠默認(rèn)的全局配置是不行的。在使用spring cloud feign的時(shí)候鸿摇,針對各個(gè)服務(wù)客戶端進(jìn)行個(gè)性化配置的方式與使用Spring Cloud Ribbon時(shí)的配置方式時(shí)一樣的萨惑,都采用了<client>.ribbon.key=value的格式進(jìn)行設(shè)置。我們使用@Feign(value="user-service")來創(chuàng)建一個(gè)Feign客戶端的時(shí)候贞滨,同時(shí)也創(chuàng)建了一個(gè)名為user-serviceRibbon客戶端入热。所以我們也可以使用@Feign中的name或者value屬性只來設(shè)置對應(yīng)的ribbon參數(shù),比如:

user-service.ribbon.ConnectTimeout=500
user-service.ribbon.ReadTimeout=2000
user-service.ribbon.OkToRetryOnAllOperations=true
user-service.ribbon.MaxAutoRetriesNextServer=2
user-service.ribbon.MaxAutoRetries=1

重試機(jī)制

spring cloud Feign中默認(rèn)實(shí)現(xiàn)了請求的重試機(jī)制晓铆,而上面對user-service客戶端的配置內(nèi)容就是對于請求超時(shí)以及重試配置的詳情勺良,

@GetMapping
public String userHello() throws Exception{
   ServiceInstance serviceInstance = client.getLocalServiceInstance();
   //線程阻塞,測試超時(shí)
   int sleeptime = new Random().nextInt(3000);
   logger.info("sleeptime:"+sleeptime);
   Thread.sleep(sleeptime);
   logger.info("/user,host:"+serviceInstance.getHost()+",service id:"+serviceInstance.getServiceId()+",port:"+serviceInstance.getPort());
   return "hello world";
}
user-service.ribbon.ConnectTimeout=500
user-service.ribbon.ReadTimeout=2000
user-service.ribbon.OkToRetryOnAllOperations=true
user-service.ribbon.MaxAutoRetriesNextServer=2
user-service.ribbon.MaxAutoRetries=1

pay-service應(yīng)用中增加了重試配置參數(shù)骄噪,其中尚困,由于user-service.ribbon.MaxAutoRetries設(shè)置為1,所以重試策略先嘗試訪問首選案例一次链蕊,失敗后才更換實(shí)例訪問事甜,而更換實(shí)例訪問的次數(shù)通過user-service.ribbon.MaxAutoRetriesNextServer參數(shù)設(shè)置為2谬泌,所以會嘗試更換兩次實(shí)例進(jìn)行重試。

Ribbon的超時(shí)與Hystrix的超時(shí)是兩個(gè)概念逻谦。一般需要讓hystrix的超時(shí)時(shí)間大于Ribbon的超時(shí)時(shí)間掌实,否則Hystrix命令超時(shí)后,改命令直接熔斷邦马,重試機(jī)制就沒有任何意義了贱鼻。

Hystrix配置

spring cloud Feign中,除了引入了用于客戶端負(fù)載均衡的spring cloud Ribbon之外滋将,還引入了服務(wù)保護(hù)了容錯(cuò)的工具Hystrix邻悬,spring cloud feign客戶端的方法都封裝到Hystrix命令中進(jìn)行服務(wù)保護(hù)。

全局配置

對于Hystrix的全局配置同spring cloud Ribbon的全局配置一樣随闽,直接使用它的默認(rèn)配置前綴hystrix.command.default就可以進(jìn)行設(shè)置父丰,比如設(shè)置全局的超時(shí)時(shí)間:
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000
在對hystrix進(jìn)行設(shè)置之前,需要確認(rèn)feign.hystrix.enabled參數(shù)沒有被設(shè)置為false橱脸,否則該參數(shù)設(shè)置會關(guān)閉Feign客戶端的Hystrix支持础米。而對于我們之前測試重試機(jī)制時(shí),對于Hystrix的超時(shí)時(shí)間控制除了可以使用上面的配置來增加熔斷超時(shí)時(shí)間添诉,也可以通過feign.hystrix.enabled=false來關(guān)閉Hystrix功能屁桑,或者使用hystrix.command.default.execution.timeout.enabled=false來關(guān)閉熔斷功能。

禁用Hystrix

spring cloud feign中栏赴,可以通過feign.hystrix.enabled=false來關(guān)閉Hystrix功能蘑斧。另外,如果不想全局地關(guān)閉Hystrix支持须眷,而只想針對某個(gè)服務(wù)客戶端關(guān)閉Hystrix支持時(shí)竖瘾,需要通過使用@Scope("protototype")注解為指定的客戶端配置Feign.Builder實(shí)例,

@Configuration
public class DisableHystrixConfigutation {
    
    @Bean
    @Scope("prototype")
    public Feign.Builder feignBuilder(){
        return Feign.builder();
    }
}

pay-service服務(wù)的user-service接口中引入該配置花颗。

@FeignClient(value = "user-service",configuration = DisableHystrixConfigutation.class)
...

參考資料
Feign Hystrix Support

指定命令配置

對于Hystrix命令的配置捕传,在實(shí)際應(yīng)用時(shí)往往也會根據(jù)實(shí)際業(yè)務(wù)情況制定出不同的配置方案。配置方法也跟傳統(tǒng)的Hystrix命令的參數(shù)配置相似扩劝,采用hystrix.command.<commandKey>作為前綴庸论。而<commandKey>默認(rèn)情況下會采用feign客戶端中的方法名作為標(biāo)識,所以棒呛,針對上面的hello方法聂示,可以如下配置:

hystrix.command.hello.isolation.thread.timeoutInmilliseconds=5000

需要注意的是,由于方法名有可能會重復(fù)簇秒,這個(gè)時(shí)候相同的方法名的hystrix配置會共用鱼喉,所以在進(jìn)行方法與配置的時(shí)候需要做好一定的規(guī)劃,當(dāng)然也可以重寫Feign.Builder的實(shí)現(xiàn),并在應(yīng)用主類中創(chuàng)建它的實(shí)例來覆蓋自動化配置的HystrixFegin.Builder實(shí)現(xiàn)扛禽。

服務(wù)降級配置

Hystrix提供的服務(wù)降級是服務(wù)容錯(cuò)的重要功能锋边,由于Spring cloud feign在定義服務(wù)客戶端的時(shí)候與Spring cloud Ribbon有很大的差別,HystrixCommand定義被封裝起來编曼,我們無法像之前介紹spring cloud hystrix時(shí)宠默,通過@HystrixCommand注解的fallback參數(shù)那樣來指定具體的服務(wù)降級處理方法。但是灵巧,spring cloud feign提供了另外一種簡單的定義方式,

定義一個(gè)Feign客戶端的服務(wù)降級類UserServiceFallback抹沪,實(shí)現(xiàn)UserService接口刻肄,其中每個(gè)重寫方法的實(shí)現(xiàn)邏輯都可以用來定義相應(yīng)的服務(wù)降級邏輯,具體如下:

@Component
public class UserServiceFallback implements UserService{

    @Override
    public String index() {
        return "error";
    }

    @Override
    public String hello() {
        return "hello error";
    }

    @Override
    public String hello1(String username) {
        return "hello username is null";
    }

    @Override
    public User hello2(String username, Integer age) {
        return new User("未知",0);
    }

    @Override
    public String hello3(User user) {
        return "user error";
    }
}
  • 在服務(wù)綁定接口user-service中融欧,通過@FeignClient注解的fallback屬性來指定對應(yīng)的服務(wù)降級實(shí)現(xiàn)類:
@FeignClient(value = "user-service",fallback = UserServiceFallback.class)
public interface UserService {

    @RequestMapping("/user/index")
    String index();

    @RequestMapping("/user/hello")
    String hello();

    @RequestMapping(value = "/user/hello1",method = RequestMethod.GET)
    String hello1(@RequestParam("username") String username);

    @RequestMapping(value = "/user/hello2",method = RequestMethod.GET)
    User hello2(@RequestHeader("username") String username, @RequestHeader("age") Integer age);

    @RequestMapping(value = "/user/hello3",method = RequestMethod.POST)
    String hello3(@RequestBody User user);
}

測試敏弃,停止用戶的服務(wù):

localhost:7070/pay/hello1?username=zhihao.miao
localhost:7070/pay/hello2
localhost:7070/pay/hello3

返回了我們在UserServiceFallback中定義的每個(gè)方法的降級的重寫函數(shù)的實(shí)現(xiàn)。

fallbackFactory參數(shù)的使用

If one needs access to the cause that made the fallback trigger, one can use the fallbackFactory attribute inside @FeignClient.
如果需要訪問到造成回退的具體原因噪馏,可以使用@FeignClient.注解的fallbackFactory屬性麦到。

@Component
public class HystrixClientFallbackFactory implements FallbackFactory<UserService> {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public UserService create(Throwable throwable) {
        logger.info("user service exception:" + throwable.getMessage());
        return new HystrixClientWithFallBackFactory(){
            @Override
            public User hello2(String username, Integer age) {
                return super.hello2(username, age);
            }
        };
    }
}

定義HystrixClientWithFallBackFactory實(shí)現(xiàn)由@Feign注解標(biāo)記的接口,我這邊就實(shí)現(xiàn)了hello2方法欠肾,只測試這個(gè)方法瓶颠。

public class HystrixClientWithFallBackFactory implements UserService{

    @Override
    public String index() {
        return null;
    }

    @Override
    public String hello() {
        return null;
    }

    @Override
    public String hello1(String username) {
        return null;
    }

    @Override
    public User hello2(String username, Integer age) {
        User user = new User();
        user.setAge(0);
        user.setUsername("zhihao.miao");
        user.setId(-1);
        return user;
    }

    @Override
    public String hello3(User user) {
        return null;
    }
}

測試,斷開User服務(wù)之后刺桃,進(jìn)入保護(hù)模式粹淋,執(zhí)行HystrixClientWithFallBackFactory中的回退操作,


控制臺上輸出錯(cuò)誤日志:

參考資料
Feign Hystrix Fallbacks

其他配置

請求壓縮

spring cloud feign支持對請求與相應(yīng)進(jìn)行GZIP壓縮瑟慈,以減少通信過程中的性能損耗桃移,我們只需要通過下面的兩個(gè)參數(shù)設(shè)置,就能開啟請求與相應(yīng)的壓縮功能葛碧。

feign:
  compression:
    request:
      enabled: true
    response:
      enabled: true

同時(shí)借杰,我們還可以對請求壓縮做一些更細(xì)致的設(shè)置,比如下面的配置內(nèi)容指定壓縮的請求數(shù)據(jù)類型进泼,并設(shè)置了請求壓縮的大小下限蔗衡,只有超過了這個(gè)大小的請求才會對其進(jìn)行壓縮。

feign:
  compression:
    request:
      enabled: true
      mime-types: text/xml,application/xml,application/json
      min-request-size: 2048

mime-types屬性和min-request-size都是默認(rèn)值

參考資料
Feign request/response compression

日志配置

spring cloud Feign在構(gòu)建被@FeignClient注解修飾的服務(wù)客戶端時(shí)缘琅,會為每一個(gè)客戶端都創(chuàng)建一個(gè)feign.Logger實(shí)例粘都,我們可以利用改日志對象的DEBUG模式來幫助分析Feign的請求細(xì)節(jié)∷⑴郏可以在application.yml配置logging.level.<feignClient>的參數(shù)配置格式來開啟指定feign客戶端的debug日志翩隧,其中<feignClient>為feign客戶端定義接口的完整路徑

logging:
  level: 
    com.zhihao.miao.pay.service.UserService: debug

但是,只添加了該配置還無法實(shí)現(xiàn)對debug日志的輸出。這是因?yàn)閒eign客戶端默認(rèn)的Logger.Level對象定義為NONE級別堆生,該級別不會記錄任何Feign調(diào)用過程中的信息专缠,所以我們需要調(diào)整它的級別,針對全局的日志級別淑仆,可以在應(yīng)用主類中加入Logger.Level的Bean創(chuàng)建涝婉,

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class PayApplication {

    public static void main(String[] args) {
        SpringApplication.run(PayApplication.class,args);
    }

    @Bean
    Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }
}

也可以實(shí)現(xiàn)配置類,然后在Feign客戶端來指定配置類以實(shí)現(xiàn)是否需要調(diào)整不同的日志級別蔗怠,比如說下面的實(shí)現(xiàn):

@Configuration
public class FullLogConfiguration {

    @Bean
    Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }
}
@FeignClient(value = "user-service",configuration = FullLogConfiguration.class)
public interface UserService {

    @RequestMapping("/user/index")
    String index();

    @RequestMapping("/user/hello")
    String hello();

    @RequestMapping(value = "/user/hello1",method = RequestMethod.GET)
    String hello1(@RequestParam("username") String username);

    @RequestMapping(value = "/user/hello2",method = RequestMethod.GET)
    User hello2(@RequestHeader("username") String username, @RequestHeader("age") Integer age);

    @RequestMapping(value = "/user/hello3",method = RequestMethod.POST)
    String hello3(@RequestBody User user);
}

訪問localhost:7070/pay/hello1?username=zhihao.miao接口墩弯,控制臺上打印如下信息:

對于Feign的Logger級別主要有下面4類,可根據(jù)實(shí)際需要進(jìn)行調(diào)整使用:

  • none:不記錄任何信息
  • basic:僅記錄請求方法寞射,url以及響應(yīng)狀態(tài)碼和執(zhí)行時(shí)間
  • headers:除了記錄basic級別的信息之外渔工,還會記錄請求和響應(yīng)的頭信息。
  • FULL:記錄所有請求與響應(yīng)的明細(xì)桥温,包括頭信息引矩,請求體,元數(shù)據(jù)等侵浸。

參考資料
Feign logging

代碼地址
代碼地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末旺韭,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子掏觉,更是在濱河造成了極大的恐慌区端,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件澳腹,死亡現(xiàn)場離奇詭異珊燎,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)遵湖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門悔政,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人延旧,你說我怎么就攤上這事谋国。” “怎么了迁沫?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵芦瘾,是天一觀的道長。 經(jīng)常有香客問我集畅,道長近弟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任挺智,我火速辦了婚禮祷愉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己二鳄,他們只是感情好赴涵,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著订讼,像睡著了一般髓窜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上欺殿,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天寄纵,我揣著相機(jī)與錄音,去河邊找鬼脖苏。 笑死擂啥,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的帆阳。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼屋吨,長吁一口氣:“原來是場噩夢啊……” “哼蜒谤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起至扰,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鳍徽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后敢课,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體阶祭,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年直秆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了濒募。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,127評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡圾结,死狀恐怖瑰剃,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情筝野,我是刑警寧澤晌姚,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站歇竟,受9級特大地震影響挥唠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜焕议,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一宝磨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦懊烤、人聲如沸梯醒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽茸习。三九已至,卻和暖如春壁肋,著一層夾襖步出監(jiān)牢的瞬間号胚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工浸遗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留猫胁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓跛锌,卻偏偏與公主長得像弃秆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子髓帽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內(nèi)容