一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Feign 集成 Hystrix實現不同的調用接口不同的設置方式

Feign 集成 Hystrix實現不同的調用接口不同的設置方式

2021-09-13 15:53帆影匆匆 Java教程

這篇文章主要介紹了Feign 集成 Hystrix實現不同的調用接口不同的設置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

問題描述

小編在寫項目時遇到一個需求:

假設現在有三個項目A、B、C,其中A、B作為服務提供方,C作為調用方,需要實現C在調用A、B時實現不同的超時時間,比如C調用A時超時是2s,調用B時超時是3s。。。。

本來以為是很簡單的事,但是面向百度編程時發現沒有搜索到,官網也沒有,這就難受了,小編屬于那種不會主動研究源碼的,都是項目有需要或者說看到別人改造了啥玩意特別有意思,否則都不去喵一眼,現在沒辦法只能研究一波源碼,手動改造。

正文

正文分為三個部分描述

  • 源碼研究
  • 提出方案
  • 方案實現

源碼研究

先說說如果找到關鍵的源代碼,如果對hystrix feign 集成比較熟悉的朋友,可以略過,直接看方案,如果希望知道源碼怎么走的朋友建議看下,這個花了我挺長時間的,網上的源碼解析都是只有關鍵代碼展示,但是具體細節怎么走,沒有描述,要不然我也不會花很長時間進行研究閱讀。

Hystrix、feign 簡單介紹

首先我們知道 feign 是spring cloud 中用來進行服務之間的調用,openFeign 當中集成了 ribbon實現了負載均衡的實際的請求

Hystrix是個熔斷器,就是在某些任務執行時及時的失敗返回而不是掛著線程,造成服務器的級聯癱瘓,feign在進行微服務之間調用時如果出現了服務超時,Hystrix進行熔斷,立馬返回結果。

關鍵代碼

如果大家上網去搜 Hystrix 超時配置,應該都是這樣

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=3000

那么 Hystrix 組件工作時肯定需要解析這個配置,調用它

spring boot 配置有個特點,命名方式都是 {組件名}Properties 這種形式,那么搜索下就找到了關鍵的配置類

com.netflix.hystrix.HystrixCommandProperties

Feign 集成 Hystrix實現不同的調用接口不同的設置方式

可以看到這里屬性都是final,就是說不能set,那么只有構造函數或者靜態代碼塊可以改,后者明顯不合適,找找構造方法就能看到

Feign 集成 Hystrix實現不同的調用接口不同的設置方式

這就很像了嘛!隨便點一個進去看

private static HystrixProperty<Boolean> getProperty(String propertyPrefix, HystrixCommandKey key, String instanceProperty, Boolean builderOverrideValue, Boolean defaultValue) {
        return forBoolean()
                .add(propertyPrefix + ".command." + key.name() + "." + instanceProperty, builderOverrideValue)
                .add(propertyPrefix + ".command.default." + instanceProperty, defaultValue)
                .build();
    }

像不像拼接上面配置,那么關鍵是這個 HystrixCommandKey 怎么傳進來的問題,這時候打個斷點就行,啟動項目,進行調用

Feign 集成 Hystrix實現不同的調用接口不同的設置方式

這時候就有調用方法棧了,可以直接看 invoke:104, HystrixInvocationHandler (feign.hystrix)

@Override
  public Object invoke(final Object proxy, final Method method, final Object[] args)
      throws Throwable {
    .............
	 // setterMethodMap 封裝 hystrixCommand 配置信息(超時時間、是否重試.....)
    HystrixCommand<Object> hystrixCommand = new HystrixCommand<Object>(setterMethodMap.get(method)) {
      @Override
      protected Object run() throws Exception {
        ....
        HystrixInvocationHandler.this.dispatch.get(method).invoke(args);
      	....
      }
      @Override
      protected Object getFallback() {
        .........
      }
    };
   ......
    return hystrixCommand.execute();
  }

大致就這樣,其實就是用hystrixCommand調用feign,最主要的是 setterMethodMap 從哪里設置的,

final class HystrixInvocationHandler implements InvocationHandler {
  
  private final Target<?> target;
  private final Map<Method, MethodHandler> dispatch;
  private final FallbackFactory<?> fallbackFactory; // Nullable
  private final Map<Method, Method> fallbackMethodMap;
  private final Map<Method, Setter> setterMethodMap;
	HystrixInvocationHandler(Target<?> target, Map<Method, MethodHandler> dispatch,
                           SetterFactory setterFactory, FallbackFactory<?> fallbackFactory) {
    this.target = checkNotNull(target, "target");
    this.dispatch = checkNotNull(dispatch, "dispatch");
    this.fallbackFactory = fallbackFactory;
    this.fallbackMethodMap = toFallbackMethod(dispatch);
    this.setterMethodMap = toSetters(setterFactory, target, dispatch.keySet());
  }  
}

一樣也是final屬性,那么也是構造函數賦值的,一樣的打個斷點,重新啟動下項目

Feign 集成 Hystrix實現不同的調用接口不同的設置方式

target:56, HystrixTargeter (org.springframework.cloud.openfeign)

看到這里代碼 核心部分

// HystrixTargeter 這個類看代碼就知道,對應這 @FeignClient 注解的接口
@SuppressWarnings("unchecked")
class HystrixTargeter implements Targeter {
	@Override
	public <T> T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context,
						Target.HardCodedTarget<T> target) {
		.....   
   
		feign.hystrix.HystrixFeign.Builder builder = (feign.hystrix.HystrixFeign.Builder) feign;
    // 這里其實是容器中拿到 SetterFactory 配置類
		SetterFactory setterFactory = getOptional(factory.getName(), context,
			SetterFactory.class);
		if (setterFactory != null) {
			builder.setterFactory(setterFactory);
		}
   
    // 從 @FeignClient 注解中讀取或者默認
    
		Class<?> fallback = factory.getFallback();
		if (fallback != void.class) {
			return targetWithFallback(factory.getName(), context, target, builder, fallback);
		}
		Class<?> fallbackFactory = factory.getFallbackFactory();
		if (fallbackFactory != void.class) {
			return targetWithFallbackFactory(factory.getName(), context, target, builder, fallbackFactory);
		}
		return feign.target(target);
	}
	.....
	private <T> T getOptional(String feignClientName, FeignContext context,
		Class<T> beanType) {
		return context.getInstance(feignClientName, beanType);
	}
}

看下 feign.hystrix.SetterFactory

public interface SetterFactory {
  HystrixCommand.Setter create(Target<?> target, Method method);
	// 默認實現
  final class Default implements SetterFactory {
    @Override
    public HystrixCommand.Setter create(Target<?> target, Method method) {
      String groupKey = target.name();
      String commandKey = Feign.configKey(target.type(), method);
      // HystrixCommandKey、group 賦值
      return HystrixCommand.Setter
          .withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
          .andCommandKey(HystrixCommandKey.Factory.asKey(commandKey));
    }
  }
}

看到這里結合上面 HystrixCommandProperties 代碼 是不是有點感覺了,就是說關鍵配置信息的 HystrixCommandKey 是這里指定的

是不是真的,可以驗證下,打個斷點,然后手動把 commandKey 修改了,然后上面 HystrixCommandProperties 斷點處驗證就行,我這里不貼代碼了

提出方案

那結合代碼發現 SetterFactory 這接口是關鍵,而這又是注入的那么簡單了只要我們手動實現這接口并且注入到 spring 容器中就行

在 feign.hystrix.SetterFactory.Default#create 方法中手動實現不同的feign 接口不同的配置,甚至不同的feign

我這里目前是用注解實現的,大家也可以用方法名等規則實現

最終目的就是讓指定的feign 方法獲取指定的配置

@FeignClient(value = "itemRobot", path = "cloud/device")
public interface DeviceApi {
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    ServerResponse<String> login(@RequestParam String appId);
  
   @RequestMapping(value = "/logout", method = RequestMethod.GET)
    ServerResponse<String> logout(@RequestParam String appId);
}
# login() 方法映射
hystrix.command.login.execution.isolation.thread.timeoutInMilliseconds=10000
# logout() 方法映射
hystrix.command.logout.execution.isolation.thread.timeoutInMilliseconds=10000

如果是基于方法級別的不同配置,hystrix 官方有給這樣的注解

com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand
	@HystrixCommand(groupKey="accountPayGroup",commandKey="accountPay",threadPoolKey="account",threadPoolProperties= {
			@HystrixProperty(name="coreSize",value="20"),
			@HystrixProperty(name="maxQueueSize",value="50")
	},commandProperties={
			@HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value="3000"),
			@HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value="40")
	})

ps:我用了發現不生效,目前還在調試,有了進展,再寫一篇

但是不能基于feign 調用不同接口實現,所以如果想基于方法實現不同配置用官方這個就行,如果想一個接口下所有方法一樣配置,不同接口實現不同,那么用我下面這方式也行。

具體實現

指定注解

@Target({TYPE, METHOD})
@Retention(RUNTIME)
public @interface CusHystrixCommandKey {
   // 對應 commandKey
    String name();
}

實現 SetterFactory

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import feign.Feign;
import feign.Target;
import feign.hystrix.SetterFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Component
public class MyHystrixFactory implements SetterFactory {
    @Override
    public HystrixCommand.Setter create(Target<?> target, Method method) {
        String groupKey = target.name();
        String commandKey = Feign.configKey(target.type(), method);
        CusHystrixCommandKey annotation = method.getAnnotation(CusHystrixCommandKey.class);
        if (annotation == null) {
						// 如果指定方法沒有 CusHystrixCommandKey 注解,用 FeignClient.value() 作為key
            FeignClient feignClient = method.getDeclaringClass().getAnnotation(FeignClient.class);
            commandKey = feignClient.value();
        } else {
          // 否則獲取指定的name() 作為key
            commandKey = annotation.name();
        }
        return HystrixCommand.Setter
                .withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
                .andCommandKey(HystrixCommandKey.Factory.asKey(commandKey));
    }
}

測試頁面就不貼了,老方法,萬能的斷點

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/weixin_39660224/article/details/109477040

延伸 · 閱讀

精彩推薦
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7472021-02-04
主站蜘蛛池模板: 成人网18免费网站 | 水野朝阳厨房系列在线观看 | 色婷婷在线视频 | 欧美日韩高清观看一区二区 | 青青青手机视频 | 粗了大了 整进去好爽视频 刺激一区仑乱 | 国产日韩欧美在线观看不卡 | 美女做又爽又黄又猛 | 关晓彤被调教出奶水 | 亚洲国产货青视觉盛宴 | 91四虎国自产在线播放线 | 免费视频片在线观看大片 | 久久久久免费视频 | 国产免费一区二区三区免费视频 | 国产精品理论片在线观看 | 大肥女zzz00o| 娇喘嗯嗯 轻点啊视频福利 九九九九在线精品免费视频 | 日产乱码卡一卡2卡三卡四福利 | 国产主播精品在线 | 成人私人影院在线版 | 成年女人免费 | 无码区国产区在线播放 | 午夜一个人在线观看完整版 | 国产精品1 | 国产经典一区二区三区蜜芽 | 手机看片国产免费现在观看 | 无人视频在线观看完整版高清 | 成人毛片1024你懂的 | 视频一区国产精戏刘婷30 | 亚洲高清无在码在线电影 | 亚洲成人精品久久 | 人人看人人射 | 91大神第九部红酒气质女 | 3d动漫美女被吸乳羞羞视频 | 色偷偷亚洲男人 | 亚洲第一综合网 | 99久久精品6在线播放 | 亚洲天堂免费观看 | 亚洲欧美乱 | 99久久国产综合精品女小说 | caoporen在线视频入口 |