国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Spring Cloud Alibaba Sentinel 整合 Feign 的設(shè)計(jì)實(shí)現(xiàn)

OldPanda / 1700人閱讀

摘要:作用跟一致跟屬性作用一致給設(shè)置注解絕對(duì)路徑,用于替換服務(wù)名。在服務(wù)名或與之間默認(rèn)是,表示當(dāng)前這個(gè)生成的是否是。內(nèi)部的能獲取服務(wù)名信息,的實(shí)現(xiàn)類能拿到對(duì)應(yīng)的請(qǐng)求路徑信息。很不幸,這個(gè)類也是包級(jí)別的類。整合的代碼目前已經(jīng)在倉(cāng)庫(kù)上,但是沒未發(fā)版。

作者 | Spring Cloud Alibaba 高級(jí)開發(fā)工程師洛夜
來(lái)自公眾號(hào)阿里巴巴中間件投稿

前段時(shí)間 Hystrix 宣布不再維護(hù)之后(Hystrix 停止開發(fā)。。。Spring Cloud 何去何從?),F(xiàn)eign 作為一個(gè)跟 Hystrix 強(qiáng)依賴的組件,必然會(huì)有所擔(dān)心后續(xù)的使用。

作為 Spring Cloud Alibaba 體系中的熔斷器 Sentinel,Sentinel 目前整合了 Feign,本文對(duì)整合過程做一次總結(jié),歡迎大家討論和使用。

Feign 是什么?

Feign 是一個(gè) Java 實(shí)現(xiàn)的 Http 客戶端,用于簡(jiǎn)化 Restful 調(diào)用。

Feign 跟 OkHttp、HttpClient 這種客戶端實(shí)現(xiàn)理念不一樣。Feign 強(qiáng)調(diào)接口的定義,接口中的一個(gè)方法對(duì)應(yīng)一個(gè) Http 請(qǐng)求,調(diào)用方法即發(fā)送一個(gè) Http 請(qǐng)求;OkHttp 或 HttpClient 以過程式的方式發(fā)送 Http 請(qǐng)求。Feign 底層發(fā)送請(qǐng)求的實(shí)現(xiàn)可以跟 OkHttp 或 HttpClient 整合。

要想整合 Feign,首先要了解 Feign 的使用以及執(zhí)行過程,然后看 Sentinel 如何整合進(jìn)去。

Feign 的使用

需要兩個(gè)步驟:

1、使用 @EnableFeignClients 注解開啟 Feign 功能
@SpringBootApplication
@EnableFeignClients // 開啟 Feign 功能
public class MyApplication {
  ...
}

@EnableFeignClients 屬性介紹:

value:String[] 包路徑。比如 org.my.pkg,會(huì)掃描這個(gè)包路徑下帶有 @FeignClient 注解的類并處理;

basePackages:String[] 跟 value 屬性作用一致;

basePackageClasses:Class[] 跟 basePackages 作用一致,basePackages 是個(gè) String 數(shù)組,而 basePackageClasses 是個(gè) Class 數(shù)組,用于掃描這些類對(duì)應(yīng)的 package;

defaultConfiguration:Class[] 默認(rèn)的配置類,對(duì)于所有的 Feign Client,這些配置類里的配置都會(huì)對(duì)它們生效,可以在配置類里構(gòu)造 feign.codec.Decoder, feign.codec.Encoderfeign.Contract 等bean;

clients:Class[] 表示 @FeignClient; 注解修飾的類集合,如果指定了該屬性,那么掃描功能相關(guān)的屬性就是失效。比如 value、basePackages 和 basePackageClasses;

2、使用 @FeignClient 注解修飾接口,這樣會(huì)基于跟接口生成代理類
@FeignClient(name = "service-provider")
public interface EchoService {
  @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
  String echo(@PathVariable("str") String str);
}

只要確保這個(gè)被 @FeignClient 注解修飾到的接口能被 @EnableFeignClients 注解掃描到,就會(huì)基于 java.lang.reflect.Proxy 根據(jù)這個(gè)接口生成一個(gè)代理類。

生成代理類之后,會(huì)被注入到 ApplicationContext 中,直接 AutoWired 就能使用,使用的時(shí)候調(diào)用 echo 方法就相當(dāng)于是發(fā)起一個(gè) Restful 請(qǐng)求。

@FeignClient 屬性介紹:

value:String 服務(wù)名。比如 service-provider, http://service-provider。比如 EchoService 中如果配置了 value=service-provider,那么調(diào)用 echo 方法的 url 為 http://service-provider/echo;如果配置了 value=https://service-provider,那么調(diào)用 echo 方法的 url 為 https://service-provider/divide

serviceId:String 該屬性已過期,但還能用。作用跟 value 一致
name:String 跟 value 屬性作用一致

qualifier:String 給 FeignClient 設(shè)置 @Qualifier 注解

url:String 絕對(duì)路徑,用于替換服務(wù)名。優(yōu)先級(jí)比服務(wù)名高。比如 EchoService 中如果配置了 url=aaa,那么調(diào)用 echo 方法的 url 為 http://aaa/echo;如果配置了 url=https://aaa,那么調(diào)用 echo 方法的 url 為 https://aaa/divide

decode404:boolean 默認(rèn)是 false,表示對(duì)于一個(gè) http status code 為 404 的請(qǐng)求是否需要進(jìn)行 decode,默認(rèn)不進(jìn)行 decode,當(dāng)成一個(gè)異常處理。設(shè)置為true之后,遇到 404 的 response 還是會(huì)解析 body

configuration:Class[] 跟 @EnableFeignClients 注解的 defaultConfiguration 屬性作用一致,但是這個(gè)對(duì)于單個(gè) FeignClient 的配置,而 @EnableFeignClients 里的 defaultConfiguration 屬性是作用域全局的,針對(duì)所有的 FeignClient

fallback:Class 默認(rèn)值是 void.class,表示 fallback 類,需要實(shí)現(xiàn) FeignClient 對(duì)應(yīng)的接口,當(dāng)調(diào)用方法發(fā)生異常的時(shí)候會(huì)調(diào)用這個(gè) Fallback 類對(duì)應(yīng)的 FeignClient 接口方法。

如果配置了 fallback 屬性,那么會(huì)把這個(gè) Fallback 類包裝在一個(gè)默認(rèn)的 FallbackFactory 實(shí)現(xiàn)類 FallbackFactory.Default 上,而不使用 fallbackFactory 屬性對(duì)應(yīng)的 FallbackFactory 實(shí)現(xiàn)類

fallbackFactory:Class 默認(rèn)值是 void.class,表示生產(chǎn) fallback 類的 Factory,可以實(shí)現(xiàn) feign.hystrix.FallbackFactory 接口,FallbackFactory 內(nèi)部會(huì)針對(duì)一個(gè) Throwable 異常返回一個(gè) Fallback 類進(jìn)行 fallback 操作

path:String 請(qǐng)求路徑。 在服務(wù)名或 url 與 requestPath 之間

primary:boolean 默認(rèn)是 true,表示當(dāng)前這個(gè) FeignClient 生成的 bean 是否是 primary。

所以如果在 ApplicationContext中存在一個(gè)實(shí)現(xiàn) EchoService 接口的 Bean,但是注入的時(shí)候并不會(huì)使用該Bean,因?yàn)?FeignClient 生成的 Bean 是 primary

Feign 的執(zhí)行過程

了解了 Feign 的使用之后,接下來(lái)我們來(lái)看 Feign 構(gòu)造一個(gè) Client 的過程。

@EnableFeignClients 注解可以看到,入口在該注解上的 FeignClientsRegistrar 類上,整個(gè)鏈路是這樣的:

從這個(gè)鏈路上我們可以得到幾個(gè)信息:

1.@FeignClient 注解修飾的接口最終會(huì)被轉(zhuǎn)換成 FeignClientFactoryBean 這個(gè) FactoryBeanFactoryBean 內(nèi)部的 getObject 方法最終會(huì)返回一個(gè) Proxy

2.在構(gòu)造 Proxy 的過程中會(huì)根據(jù) org.springframework.cloud.openfeign.Targeter 接口的 target 方法去構(gòu)造。如果啟動(dòng)了hystrix開關(guān)(feign.hystrix.enabled=true),會(huì)使用 HystrixTargeter,否則使用默認(rèn)的 DefaultTargeter

3.Targeter 內(nèi)部構(gòu)造 Proxy 的過程中會(huì)使用 feign.Feign.Builder 去調(diào)用它的 build 方法構(gòu)造 feign.Feign 實(shí)例(默認(rèn)只有一個(gè)子類 ReflectiveFeign)。

如果啟動(dòng)了 hystrix 開關(guān)(feign.hystrix.enabled=true),會(huì)使用 feign.hystrix.HystrixFeign.Builder,否則使用默認(rèn)的feign.Feign.Builder

4.構(gòu)造出 feign.Feign 實(shí)例之后,調(diào)用 newInstance 方法返回一個(gè) Proxy

簡(jiǎn)單看下這個(gè) newInstance 方法內(nèi)部的邏輯:

public  T newInstance(Target target) {
    Map nameToHandler = targetToHandlersByName.apply(target);
    Map methodToHandler = new LinkedHashMap();
    List defaultMethodHandlers = new LinkedList();

    for (Method method : target.type().getMethods()) {
      if (method.getDeclaringClass() == Object.class) {
        continue;
      } else if(Util.isDefault(method)) {
        DefaultMethodHandler handler = new DefaultMethodHandler(method);
        defaultMethodHandlers.add(handler);
        methodToHandler.put(method, handler);
      } else {
        methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
      }
    }
    // 使用 InvocationHandlerFactory 根據(jù)接口的方法信息和 target 對(duì)象構(gòu)造 InvocationHandler
    InvocationHandler handler = factory.create(target, methodToHandler);
    // 構(gòu)造代理
    T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(), new Class[]{target.type()}, handler);

    for(DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {
      defaultMethodHandler.bindTo(proxy);
    }
    return proxy;
  }

這里的 InvocationHandlerFactory 是通過構(gòu)造 Feign 的時(shí)候傳入的:

使用原生的 DefaultTargeter: 那么會(huì)使用 feign.InvocationHandlerFactory.Default 這個(gè) factory,并且構(gòu)造出來(lái)的 InvocationHandlerfeign.ReflectiveFeign.FeignInvocationHandler

使用 hystrix 的 HystrixTargeter: 那么會(huì)在feign.hystrix.HystrixFeign.Builder#build(feign.hystrix.FallbackFactory) 方法中調(diào)用父類的 invocationHandlerFactory 方法傳入一個(gè)匿名的 InvocationHandlerFactory 實(shí)現(xiàn)類,該類內(nèi)部構(gòu)造出的 InvocationHandlerHystrixInvocationHandler

Sentinel 整合 Feign

理解了 Feign 的執(zhí)行過程之后,Sentinel 想要整合 Feign,可以參考 Hystrix 的實(shí)現(xiàn):

1.? 實(shí)現(xiàn) Targeter 接口 SentinelTargeter很不幸,Targeter 這個(gè)接口屬于包級(jí)別的接口,在外部包中無(wú)法使用,這個(gè) Targeter 無(wú)法使用。沒關(guān)系,我們可以沿用默認(rèn)的 HystrixTargeter(實(shí)際上會(huì)用 DefaultTargeter,下文 Note 有解釋)

2.? FeignClientFactoryBean 內(nèi)部構(gòu)造 Targeterfeign.Feign.Builder 的時(shí)候,都會(huì)從 FeignContext 中獲取。所以我們沿用默認(rèn)的 DefaultTargeter 的時(shí)候,內(nèi)部使用的 feign.Feign.Builder 可控,而且這個(gè) Builder 不是包級(jí)別的類,可在外部使用

創(chuàng)建 SentinelFeign.Builder 繼承 feign.Feign.Builder ,用來(lái)構(gòu)造 Feign

SentinelFeign.Builder 內(nèi)部需要獲取 FeignClientFactoryBean 中的屬性進(jìn)行處理,比如獲取 fallback, name, fallbackFactory

很不幸,FeignClientFactoryBean 這個(gè)類也是包級(jí)別的類。沒關(guān)系,我們知道它存在在 ApplicationContext 中的 beanName, 拿到 bean 之后根據(jù)反射獲取屬性就行(該過程在初始化的時(shí)候進(jìn)行,不會(huì)在調(diào)用的時(shí)候進(jìn)行,所以不會(huì)影響性能)

SentinelFeign.Builder 調(diào)用 build 方法構(gòu)造 Feign 的過程中,我們不需要實(shí)現(xiàn)一個(gè)新的 Feign,跟 hystrix 一樣沿用 ReflectiveFeign 即可,在沿用的過程中調(diào)用父類 feign.Feign.Builder 的一些方法進(jìn)行改造即可,比如 invocationHandlerFactory 方法設(shè)置 InvocationHandlerFactorycontract 的調(diào)用

3.? 跟 hystrix 一樣實(shí)現(xiàn)自定義的 InvocationHandler 接口 SentinelInvocationHandler 用來(lái)處理方法的調(diào)用

4.? SentinelInvocationHandler 內(nèi)部使用 Sentinel 進(jìn)行保護(hù),這個(gè)時(shí)候涉及到資源名的獲取。SentinelInvocationHandler 內(nèi)部的 feign.Target 能獲取服務(wù)名信息,feign.InvocationHandlerFactory.MethodHandler 的實(shí)現(xiàn)類 feign.SynchronousMethodHandler 能拿到對(duì)應(yīng)的請(qǐng)求路徑信息。

很不幸,feign.SynchronousMethodHandler 這個(gè)類也是包級(jí)別的類。沒關(guān)系,我們可以自定義一個(gè) feign.Contract 的實(shí)現(xiàn)類 SentinelContractHolder 在處理 MethodMetadata 的過程把這些 metadata 保存下來(lái)(feign.Contract 這個(gè)接口在 Builder 構(gòu)造 Feign 的過程中會(huì)對(duì)方法進(jìn)行解析并驗(yàn)證)。

SentinelFeign.Builder 中調(diào)用 contract 進(jìn)行設(shè)置,SentinelContractHolder 內(nèi)部保存一個(gè) Contract 使用委托方式不影響原先的 Contract 過程

Note: spring-cloud-starter-openfeign 依賴內(nèi)部包含了 feign-hystrix。所以是說(shuō)默認(rèn)使用 HystrixTargeter 這個(gè) Targeter ,進(jìn)入 HystrixTargetertarget 方法內(nèi)部一看,發(fā)現(xiàn)有段邏輯這么寫的:

@Override
public  T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context,
                    Target.HardCodedTarget target) {
  if (!(feign instanceof feign.hystrix.HystrixFeign.Builder)) {
    // 如果 Builder 不是 feign.hystrix.HystrixFeign.Builder,使用這個(gè) Builder 進(jìn)行處理
    // 我們默認(rèn)構(gòu)造了 SentinelFeign.Builder 這個(gè) Builder,默認(rèn)使用 feign-hystrix 依賴也沒有什么問題
    return feign.target(target);
  }
  feign.hystrix.HystrixFeign.Builder builder = (feign.hystrix.HystrixFeign.Builder) feign;
  ...
}

SentinelInvocationHandler 內(nèi)部我們對(duì)資源名的處理策略是: http方法:protocol://服務(wù)名/請(qǐng)求路徑跟參數(shù)

比如這個(gè) TestService:

@FeignClient(name = "test-service")
public interface TestService {
  @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
  String echo(@PathVariable("str") String str);

  @RequestMapping(value = "/divide", method = RequestMethod.GET)
  String divide(@RequestParam("a") Integer a, @RequestParam("b") Integer b);
}

echo 方法對(duì)應(yīng)的資源名:GET:http://test-service/echo/{str}

divide 方法對(duì)應(yīng)的資源名:GET:http://test-service/divide

總結(jié)

1.Feign 的內(nèi)部很多類都是 package 級(jí)別的,外部 package 無(wú)法引用某些類,這個(gè)時(shí)候只能想辦法繞過去,比如使用反射

2.目前這種實(shí)現(xiàn)有風(fēng)險(xiǎn),萬(wàn)一哪天 starter 內(nèi)部使用的 Feign 相關(guān)類變成了 package 級(jí)別,那么會(huì)改造代碼。所以把 Sentinel 的實(shí)現(xiàn)放到 Feign 里并給 Feign 官方提 pr 可能更加合適

3.Feign的處理流程還是比較清晰的,只要能夠理解其設(shè)計(jì)原理,我們就能容易地整合進(jìn)去

歡迎大家對(duì)整合方案進(jìn)行討論,并能給出不合理的地方,當(dāng)然能提pr解決不合理的地方就更好了。

Sentinel Starter 整合 Feign 的代碼目前已經(jīng)在 github 倉(cāng)庫(kù)上,但是沒未發(fā)版。預(yù)計(jì)月底發(fā)版,如果現(xiàn)在就想使用,可以在 pom 中引入 Spring SNAPSHOT 的 repository 或自行下載源碼進(jìn)行編譯。

最后再附上一個(gè)使用 Nacos 做服務(wù)發(fā)現(xiàn)和 Sentinel 做限流的 Feign 例子。

https://github.com/spring-clo...

最后,在Java技術(shù)棧微信公眾號(hào)后臺(tái)回復(fù):cloud,可獲取棧長(zhǎng)整理的一系列 Spring Cloud 教程,目前大量教程還在撰寫中……

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/72710.html

相關(guān)文章

  • Spring Cloud Alibaba Sentinel對(duì)Feign支持

    摘要:得到得到類得到類得到調(diào)用的服務(wù)名稱檢查和屬性省略部分代碼中的方法里面進(jìn)行熔斷限流的處理。在的方法中進(jìn)行的包裝。 Spring Cloud Alibaba Sentinel 除了對(duì) RestTemplate 做了支持,同樣對(duì)于 Feign 也做了支持,如果我們要從 Hystrix 切換到 Sentinel 是非常方便的,下面來(lái)介紹下如何對(duì) Feign 的支持以及實(shí)現(xiàn)原理。 集成 Feig...

    wthee 評(píng)論0 收藏0
  • Spring Cloud Alibaba 新版本發(fā)布:眾多期待內(nèi)容整合打包加入!

    摘要:在之后,也終于發(fā)布了最新的版本。該版本距離上一次發(fā)布,過去了整整個(gè)月下面就隨我一起看看,這個(gè)大家期待已久的版本都有哪些內(nèi)容值得我們關(guān)注。如果是用戶,同時(shí)也是阿里云這些產(chǎn)品的用戶,那么直接使用還是非常方便的。 在Nacos 1.0.0 Release之后,Spring Cloud Alibaba也終于發(fā)布了最新的版本。該版本距離上一次發(fā)布,過去了整整4個(gè)月!下面就隨我一起看看,這個(gè)大家期...

    不知名網(wǎng)友 評(píng)論0 收藏0
  • [Spring-Cloud-Alibaba] Sentinel 整合RestTemplate &am

    摘要:開發(fā)階段很有意義。源碼整合配置文件中添加來(lái)開啟編寫類,實(shí)現(xiàn)默認(rèn)用戶遠(yuǎn)程調(diào)用被限流降級(jí),默認(rèn)用戶應(yīng)用定義可以拿到異常信息無(wú)法拿到異常信息若初啟動(dòng)應(yīng)用,設(shè)置流控規(guī)則,結(jié)果展示如下默認(rèn)用戶源碼 Sentinel API Github : WIKI Sphu (指明要保護(hù)的資源名稱) Tracer (指明調(diào)用來(lái)源,異常統(tǒng)計(jì)接口) ContextUtil(標(biāo)示進(jìn)入調(diào)用鏈入口) 流控規(guī)則(針...

    libin19890520 評(píng)論0 收藏0
  • Spring Cloud Alibaba到底坑不坑?

    摘要:我沒有能力去控制那些自媒體發(fā)布這些不實(shí)的內(nèi)容,但是在我了解的范圍內(nèi),還是盡力輸出一些我的理解。 之前我發(fā)過一篇《說(shuō)說(shuō)我為什么看好Spring Cloud Alibaba》,然后這兩天有網(wǎng)友給我轉(zhuǎn)了這篇文章《坑爹項(xiàng)目spring-cloud-alibaba,我們也來(lái)一個(gè)》,問我的看法是怎么樣的,聊天時(shí)候簡(jiǎn)單說(shuō)了一下。今天在家休息,抽空整理一下內(nèi)容,逐點(diǎn)說(shuō)一下我的看法,主要還是覺得這篇文章...

    娣辯孩 評(píng)論0 收藏0
  • Dubbo Spring Cloud 重塑微服務(wù)治理

    摘要:在服務(wù)治理方面,相較于而言,并不成熟。遺憾的是,往往被部分開發(fā)者片面地視作服務(wù)治理的框架,而非微服務(wù)基礎(chǔ)設(shè)施。因此,建議開發(fā)人員將或者遷移為服務(wù)。因此,下一步需要將其配置服務(wù)遠(yuǎn)程。當(dāng)服務(wù)提供方啟動(dòng)后,下一步實(shí)現(xiàn)一個(gè)服務(wù)消費(fèi)方。 原文鏈接:Dubbo Spring Cloud 重塑微服務(wù)治理,來(lái)自于微信公眾號(hào):次靈均閣 摘要 在 Java 微服務(wù)生態(tài)中,Spring Cloud1 成為...

    wh469012917 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<