最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Spring Cloud OpenFeign調(diào)用流程

2022-11-21 21:27 作者:Erwin_Feng  | 我要投稿

上一節(jié)給大家分享了Spring Cloud OpenFeign的啟動(dòng)流程,接下來(lái)給大家分享一下調(diào)用流程。話不多說(shuō),咱們直接開(kāi)始。

視頻:https://www.bilibili.com/video/BV1A84y1C7XD/

調(diào)用流程

xxxFeignClient

→ feign.ReflectiveFeign.FeignInvocationHandler#invoke

→ feign.InvocationHandlerFactory.MethodHandler#invoke

→ feign.SynchronousMethodHandler#invoke

→ feign.SynchronousMethodHandler#executeAndDecode

→ org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient#execute

→ feign.Client.Default#execute

→ feign.AsyncResponseHandler#handleResponse

動(dòng)態(tài)代理

feign.ReflectiveFeign.FeignInvocationHandler#invoke

public?Object?invoke(Object?proxy,?Method?method,?Object[]?args)?throws?Throwable?{
??return?dispatch.get(method).invoke(args);
}

這里說(shuō)一下 dispatch 屬性,它的類(lèi)型是Map<Method,?MethodHandler>意思是,可以通過(guò)方法找到對(duì)應(yīng)的Handler,這樣就可以進(jìn)入到 SynchronousMethodHandler#invoke。

feign.SynchronousMethodHandler#executeAndDecode

從這個(gè)方法的名稱(chēng)也能看出來(lái),這個(gè)是執(zhí)行請(qǐng)求,并且實(shí)現(xiàn)解碼的功能,這是一個(gè)核心的方法。

負(fù)載均衡

org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient#execute

這個(gè)是實(shí)現(xiàn)均衡,實(shí)現(xiàn)將URL中服務(wù)名轉(zhuǎn)成 真實(shí)的IP。

下面我們看看它是如何被自動(dòng)注入的。

首先在 spring.factories 文件中,做了配置

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.openfeign.loadbalancer.FeignLoadBalancerAutoConfiguration

FeignLoadBalancerAutoConfiguration 中引入 DefaultFeignLoadBalancerConfiguration

@ConditionalOnClass(Feign.class)
@ConditionalOnBean({?LoadBalancerClient.class,?LoadBalancerClientFactory.class?})
@AutoConfigureBefore(FeignAutoConfiguration.class)
@AutoConfigureAfter({?BlockingLoadBalancerClientAutoConfiguration.class,?LoadBalancerAutoConfiguration.class?})
@EnableConfigurationProperties(FeignHttpClientProperties.class)
@Configuration(proxyBeanMethods?=?false)
//?Order?is?important?here,?last?should?be?the?default,?first?should?be?optional
//?see
//?https://github.com/spring-cloud/spring-cloud-netflix/issues/2086#issuecomment-316281653
@Import({?HttpClientFeignLoadBalancerConfiguration.class,?OkHttpFeignLoadBalancerConfiguration.class,
??HttpClient5FeignLoadBalancerConfiguration.class,?DefaultFeignLoadBalancerConfiguration.class?})

public?class?FeignLoadBalancerAutoConfiguration?{

}

new FeignBlockingLoadBalancerClient,并且注入到 Spring Bean 中

@Configuration(proxyBeanMethods?=?false)
@EnableConfigurationProperties(LoadBalancerClientsProperties.class)
class?DefaultFeignLoadBalancerConfiguration?{

?@Bean
?@ConditionalOnMissingBean
?@Conditional(OnRetryNotEnabledCondition.class)
?public?Client?feignClient(LoadBalancerClient?loadBalancerClient,
???LoadBalancerClientFactory?loadBalancerClientFactory)
?{
??return?new?FeignBlockingLoadBalancerClient(new?Client.Default(null,?null),?loadBalancerClient,
????loadBalancerClientFactory);
?}

}

Http請(qǐng)求

下面我們看看 feign 是如何實(shí)現(xiàn) Http 請(qǐng)求的。

feign.Client.Default#execute

@Override
public?Response?execute(Request?request,?Options?options)?throws?IOException?{
??HttpURLConnection?connection?=?convertAndSend(request,?options);
??return?convertResponse(connection,?request);
}

主要就是在這個(gè)方法中,默認(rèn)使用 jdk 實(shí)現(xiàn) http請(qǐng)求。

convertAndSend,這個(gè)方法做了兩件事,一是,打開(kāi) Http 連接,獲取到 HttpURLConnection ,并設(shè)置相關(guān)屬性;二是,如果有參數(shù),就通過(guò)輸出流(OutputStream)寫(xiě)入?yún)?shù)。

convertResponse,這個(gè)方法返回的是 feign.Response ,我們它有哪些屬性:

public?final?class?Response?implements?Closeable?{

??private?final?int?status;
??private?final?String?reason;
??private?final?Map<String,?Collection<String>>?headers;
??private?final?Body?body;
??private?final?Request?request;
??private?final?ProtocolVersion?protocolVersion;

}

首先,這里實(shí)現(xiàn) Closeable 接口,所以必然有 close 方法,我們看一下:

@Override
public?void?close()?{
??Util.ensureClosed(body);
}

好了,明白了,body實(shí)際上是寫(xiě)入流(InputStream)。

總結(jié)一下:這里實(shí)現(xiàn)了Http請(qǐng)求,上傳了參數(shù),或獲得了輸入流。

Http響應(yīng)處理

看完了請(qǐng)求,我們?cè)倩氐?feign.SynchronousMethodHandler#executeAndDecode,看下面的代碼

CompletableFuture<Object>?resultFuture?=?new?CompletableFuture<>();
asyncResponseHandler.handleResponse(resultFuture,?metadata.configKey(),?response,
????metadata.returnType(),
????elapsedTime);

try?{
??if?(!resultFuture.isDone())
????throw?new?IllegalStateException("Response?handling?not?done");

??return?resultFuture.join();
}?catch?(CompletionException?e)?{
??Throwable?cause?=?e.getCause();
??if?(cause?!=?null)
????throw?cause;
??throw?e;
}

這里是通過(guò) CompletableFuture,來(lái)裝配響應(yīng)結(jié)果。

feign.AsyncResponseHandler#handleResponse,這個(gè)方法就也就是處理Http響應(yīng)結(jié)果的入口。

比如要判斷狀態(tài)碼,獲取結(jié)果,關(guān)閉輸入流等。

響應(yīng)結(jié)果解碼

解碼流程如下:

feign.AsyncResponseHandler#decode

→ org.springframework.cloud.openfeign.support.ResponseEntityDecoder#decode

→ org.springframework.cloud.openfeign.support.SpringDecoder#decode

→ org.springframework.cloud.openfeign.support.SpringDecoder.FeignResponseAdapter#FeignResponseAdapter

→ org.springframework.web.client.HttpMessageConverterExtractor#extractData

→ org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter#read

為什么需要解碼呢?

http響應(yīng)的結(jié)果類(lèi)型是String,而我們需要的是一個(gè)對(duì)象,比如:

@FeignClient(
????????value?=?"openfeign-goods-service",
????????path?=?"/goods"
)

public?interface?IGoodsFeignClient?{

????@GetMapping("/list")
????ResultTemplate<ListTemplate<GoodsModel>>?list();

}

我是 Erwin Feng,一個(gè)專(zhuān)注于高質(zhì)量編程的開(kāi)發(fā)者。如果你對(duì)我內(nèi)容感興趣,可以關(guān)注我的微信公眾號(hào)【Erwin Feng】,可以第一時(shí)間收到更新推送!


Spring Cloud OpenFeign調(diào)用流程的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
建阳市| 汕尾市| 灌云县| 娱乐| 伊宁市| 枝江市| 侯马市| 佳木斯市| 临潭县| 安平县| 沂水县| 辽阳市| 新和县| 竹山县| 鄢陵县| 娱乐| 禹州市| 金秀| 衡南县| 九龙城区| 连南| 大埔区| 潮州市| 临安市| 呼伦贝尔市| 青岛市| 叶城县| 克山县| 宁城县| 赣州市| 古蔺县| 饶平县| 江油市| 新源县| 蕲春县| 如东县| 启东市| 磐安县| 东乡县| 双城市| 彭泽县|