0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

簡化本地Feign調(diào)用的方法

jf_ro2CN3Fa ? 來源:碼農(nóng)參上 ? 2023-06-20 10:01 ? 次閱讀

在平常的工作中,OpenFeign作為微服務(wù)間的調(diào)用組件使用的非常普遍,接口配合注解的調(diào)用方式突出一個簡便,讓我們能無需關(guān)注內(nèi)部細節(jié)就能實現(xiàn)服務(wù)間的接口調(diào)用。

但是工作中用久了,發(fā)現(xiàn)Feign也有些使用起來麻煩的地方,下面先來看一個問題,再看看我們在工作中是如何解決,以達到簡化Feign使用的目的。

先看問題

在一個項目開發(fā)的過程中,我們通常會區(qū)分開發(fā)環(huán)境、測試環(huán)境和生產(chǎn)環(huán)境,如果有的項目要求更高的話,可能還會有個預(yù)生產(chǎn)環(huán)境。

開發(fā)環(huán)境作為和前端開發(fā)聯(lián)調(diào)的環(huán)境,一般使用起來都比較隨意,而我們在進行本地開發(fā)的時候,有時候也會將本地啟動的微服務(wù)注冊到注冊中心nacos上,方便進行調(diào)試。

這樣,注冊中心的一個微服務(wù)可能就會擁有多個服務(wù)實例,就像下面這樣:

7f82bc4c-0f0a-11ee-962d-dac502259ad0.png

眼尖的小伙伴肯定發(fā)現(xiàn)了,這兩個實例的ip地址有一點不同。

線上環(huán)境現(xiàn)在一般使用容器化部署,通常都是由流水線工具打成鏡像然后扔到docker中運行,因此我們?nèi)タ匆幌路?wù)在docker容器內(nèi)的ip:

7f990bbe-0f0a-11ee-962d-dac502259ad0.png

可以看到,這就是注冊到nacos上的服務(wù)地址之一,而列表中192開頭的另一個ip,則是我們本地啟動的服務(wù)的局域網(wǎng)地址??匆幌孪旅孢@張圖,就能對整個流程一目了然了。

7fb393c6-0f0a-11ee-962d-dac502259ad0.jpg

總結(jié)一下:

兩個service都是通過宿主機的ip和port,把自己的信息注冊到nacos上

線上環(huán)境的service注冊時使用docker內(nèi)部ip地址

本地的service注冊時使用本地局域網(wǎng)地址

那么這時候問題就來了,當我本地再啟動一個serviceB,通過FeignClient來調(diào)用serviceA中的接口時,因為Feign本身的負載均衡,就可能把請求負載均衡到兩個不同的serviceA實例。

如果這個調(diào)用請求被負載均衡到本地serviceA的話,那么沒什么問題,兩個服務(wù)都在同一個192.168網(wǎng)段內(nèi),可以正常訪問。但是如果負載均衡請求到運行在docker內(nèi)的serviceA的話,那么問題來了,因為網(wǎng)絡(luò)不通,所以會請求失?。?/p>

7fd42a50-0f0a-11ee-962d-dac502259ad0.png

說白了,就是本地的192.168和docker內(nèi)的虛擬網(wǎng)段172.17屬于純二層的兩個不同網(wǎng)段,不能互訪,所以無法直接調(diào)用。

那么,如果想在調(diào)試時把請求穩(wěn)定打到本地服務(wù)的話,有一個辦法,就是指定在FeignClient中添加url參數(shù),指定調(diào)用的地址:

@FeignClient(value="serviceA",url="http://127.0.0.1:8088/")
publicinterfaceClientA{
@GetMapping("/test/get")
Stringget();
}

但是這么一來也會帶來點問題:

代碼上線時需要再把注解中的url刪掉,還要再次修改代碼,如果忘了的話會引起線上問題

如果測試的FeignClient很多的話,每個都需要配置url,修改起來很麻煩

那么,有什么辦法進行改進呢?為了解決這個問題,我們還是得從Feign的原理說起。

Feign原理

簡單來說,就是項目中加的@EnableFeignClients這個注解,實現(xiàn)時有一行很重要的代碼:

@Import(FeignClientsRegistrar.class)

這個類實現(xiàn)了ImportBeanDefinitionRegistrar接口,在這個接口的registerBeanDefinitions方法中,可以手動創(chuàng)建BeanDefinition并注冊,之后spring會根據(jù)BeanDefinition實例化生成bean,并放入容器中。

Feign就是通過這種方式,掃描添加了@FeignClient注解的接口,然后一步步生成代理對象,具體流程可以看一下下面這張圖:

7ff8fc4a-0f0a-11ee-962d-dac502259ad0.jpg

后續(xù)在請求時,通過代理對象的FeignInvocationHandler進行攔截,并根據(jù)對應(yīng)方法進行處理器的分發(fā),完成后續(xù)的http請求操作。

ImportBeanDefinitionRegistrar

上面提到的ImportBeanDefinitionRegistrar,在整個創(chuàng)建FeignClient的代理過程中非常重要, 所以我們先寫一個簡單的例子看一下它的用法。先定義一個實體類:

@Data
@AllArgsConstructor
publicclassUser{
Longid;
Stringname;
}

通過BeanDefinitionBuilder,向這個實體類的構(gòu)造方法中傳入具體值,最后生成一個BeanDefinition:

publicclassMyBeanDefinitionRegistrar
implementsImportBeanDefinitionRegistrar{
@Override
publicvoidregisterBeanDefinitions(AnnotationMetadataimportingClassMetadata,
BeanDefinitionRegistryregistry){
BeanDefinitionBuilderbuilder
=BeanDefinitionBuilder.genericBeanDefinition(User.class);
builder.addConstructorArgValue(1L);
builder.addConstructorArgValue("Hydra");

AbstractBeanDefinitionbeanDefinition=builder.getBeanDefinition();
registry.registerBeanDefinition(User.class.getSimpleName(),beanDefinition);
}
}

registerBeanDefinitions方法的具體調(diào)用時間是在之后的ConfigurationClassPostProcessor執(zhí)行postProcessBeanDefinitionRegistry方法時,而registerBeanDefinition方法則會將BeanDefinition放進一個map中,后續(xù)根據(jù)它實例化bean。

在配置類上通過@Import將其引入:

@Configuration
@Import(MyBeanDefinitionRegistrar.class)
publicclassMyConfiguration{
}

注入這個User測試:

@Service
@RequiredArgsConstructor
publicclassUserService{
privatefinalUseruser;

publicvoidgetUser(){
System.out.println(user.toString());
}
}

結(jié)果打印,說明我們通過自定義BeanDefinition的方式成功手動創(chuàng)建了一個bean并放入了spring容器中:

User(id=1,name=Hydra)

好了,準備工作鋪墊到這結(jié)束,下面開始正式的改造工作。

改造

到這里先總結(jié)一下,我們糾結(jié)的點就是本地環(huán)境需要FeignClient中配置url,但線上環(huán)境不需要,并且我們又不想來回修改代碼。

除了像源碼中那樣生成動態(tài)代理以及攔截方法,官方文檔中還給我們提供了一個手動創(chuàng)建FeignClient的方法。

簡單來說,就是我們可以像下面這樣,通過Feign的Builder API來手動創(chuàng)建一個Feign客戶端。

80198afa-0f0a-11ee-962d-dac502259ad0.png

簡單看一下,這個過程中還需要配置Client、Encoder、Decoder、Contract、RequestInterceptor等內(nèi)容。

Client:實際http請求的發(fā)起者,如果不涉及負載均衡可以使用簡單的Client.Default,用到負載均衡則可以使用LoadBalancerFeignClient,前面也說了,LoadBalancerFeignClient中的delegate其實使用的也是Client.Default

Encoder和Decoder:Feign的編解碼器,在spring項目中使用對應(yīng)的SpringEncoder和ResponseEntityDecoder,這個過程中我們借用GsonHttpMessageConverter作為消息轉(zhuǎn)換器來解析json

RequestInterceptor:Feign的攔截器,一般業(yè)務(wù)用途比較多,比如添加修改header信息等,這里用不到可以不配

Contract:字面意思是合約,它的作用是將我們傳入的接口進行解析驗證,看注解的使用是否符合規(guī)范,然后將關(guān)于http的元數(shù)據(jù)抽取成結(jié)果并返回。如果我們使用RequestMapping、PostMapping、GetMapping之類注解的話,那么對應(yīng)使用的是SpringMvcContract

其實這里剛需的就只有Contract這一個,其他都是可選的配置項。我們寫一個配置類,把這些需要的東西都注入進去:

@Slf4j
@Configuration(proxyBeanMethods=false)
@EnableConfigurationProperties({LocalFeignProperties.class})
@Import({LocalFeignClientRegistrar.class})
@ConditionalOnProperty(value="feign.local.enable",havingValue="true")
publicclassFeignAutoConfiguration{
static{
log.info("feignlocalroutestarted");
}

@Bean
@Primary
publicContractcontract(){
returnnewSpringMvcContract();
}

@Bean(name="defaultClient")
publicClientdefaultClient(){
returnnewClient.Default(null,null);
}

@Bean(name="ribbonClient")
publicClientribbonClient(CachingSpringLoadBalancerFactorycachingFactory,
SpringClientFactoryclientFactory){
returnnewLoadBalancerFeignClient(defaultClient(),cachingFactory,
clientFactory);
}

@Bean
publicDecoderdecoder(){
HttpMessageConverterhttpMessageConverter=newGsonHttpMessageConverter();
ObjectFactorymessageConverters=()->newHttpMessageConverters(httpMessageConverter);
SpringDecoderspringDecoder=newSpringDecoder(messageConverters);
returnnewResponseEntityDecoder(springDecoder);
}

@Bean
publicEncoderencoder(){
HttpMessageConverterhttpMessageConverter=newGsonHttpMessageConverter();
ObjectFactorymessageConverters=()->newHttpMessageConverters(httpMessageConverter);
returnnewSpringEncoder(messageConverters);
}
}

在這個配置類上,還有三行注解,我們一點點解釋。

首先是引入的配置類LocalFeignProperties,里面有三個屬性,分別是是否開啟本地路由的開關(guān)、掃描FeignClient接口的包名,以及我們要做的本地路由映射關(guān)系,addressMapping中存的是服務(wù)名和對應(yīng)的url地址:

@Data
@Component
@ConfigurationProperties(prefix="feign.local")
publicclassLocalFeignProperties{
//是否開啟本地路由
privateStringenable;

//掃描FeignClient的包名
privateStringbasePackage;

//路由地址映射
privateMapaddressMapping;
}

下面這行注解則表示只有當配置文件中feign.local.enable這個屬性為true時,才使當前配置文件生效:

@ConditionalOnProperty(value="feign.local.enable",havingValue="true")

最后,就是我們重中之重的LocalFeignClientRegistrar了,我們還是按照官方通過ImportBeanDefinitionRegistrar接口構(gòu)建BeanDefinition然后注冊的思路來實現(xiàn)。

并且,F(xiàn)eignClientsRegistrar的源碼中已經(jīng)實現(xiàn)好了很多基礎(chǔ)的功能,比如掃掃描包、獲取FeignClient的name、contextId、url等等,所以需要改動的地方非常少,可以放心的大抄特超它的代碼。

先創(chuàng)建LocalFeignClientRegistrar,并注入需要用到的ResourceLoader、BeanFactory、Environment。

@Slf4j
publicclassLocalFeignClientRegistrarimplements
ImportBeanDefinitionRegistrar,ResourceLoaderAware,
EnvironmentAware,BeanFactoryAware{

privateResourceLoaderresourceLoader;
privateBeanFactorybeanFactory;
privateEnvironmentenvironment;

@Override
publicvoidsetResourceLoader(ResourceLoaderresourceLoader){
this.resourceLoader=resourceLoader;
}

@Override
publicvoidsetBeanFactory(BeanFactorybeanFactory)throwsBeansException{
this.beanFactory=beanFactory;
}

@Override
publicvoidsetEnvironment(Environmentenvironment){
this.environment=environment;
}

//先省略具體功能代碼...
}

然后看一下創(chuàng)建BeanDefinition前的工作,這一部分主要完成了包的掃描和檢測@FeignClient注解是否被添加在接口上的測試。下面這段代碼基本上是照搬源碼,除了改動一下掃描包的路徑,使用我們自己在配置文件中配置的包名。

@Override
publicvoidregisterBeanDefinitions(AnnotationMetadataimportingClassMetadata,BeanDefinitionRegistryregistry){
ClassPathScanningCandidateComponentProviderscanner=ComponentScanner.getScanner(environment);
scanner.setResourceLoader(resourceLoader);
AnnotationTypeFilterannotationTypeFilter=newAnnotationTypeFilter(FeignClient.class);
scanner.addIncludeFilter(annotationTypeFilter);

StringbasePackage=environment.getProperty("feign.local.basePackage");
log.info("begintoscan{}",basePackage);

SetcandidateComponents=scanner.findCandidateComponents(basePackage);

for(BeanDefinitioncandidateComponent:candidateComponents){
if(candidateComponentinstanceofAnnotatedBeanDefinition){
log.info(candidateComponent.getBeanClassName());

//verifyannotatedclassisaninterface
AnnotatedBeanDefinitionbeanDefinition=(AnnotatedBeanDefinition)candidateComponent;
AnnotationMetadataannotationMetadata=beanDefinition.getMetadata();
Assert.isTrue(annotationMetadata.isInterface(),
"@FeignClientcanonlybespecifiedonaninterface");

Mapattributes=annotationMetadata
.getAnnotationAttributes(FeignClient.class.getCanonicalName());

Stringname=FeignCommonUtil.getClientName(attributes);
registerFeignClient(registry,annotationMetadata,attributes);
}
}
}

接下來創(chuàng)建BeanDefinition并注冊,F(xiàn)eign的源碼中是使用的FeignClientFactoryBean創(chuàng)建代理對象,這里我們就不需要了,直接替換成使用Feign.builder創(chuàng)建。

privatevoidregisterFeignClient(BeanDefinitionRegistryregistry,
AnnotationMetadataannotationMetadata,Mapattributes){
StringclassName=annotationMetadata.getClassName();
Classclazz=ClassUtils.resolveClassName(className,null);
ConfigurableBeanFactorybeanFactory=registryinstanceofConfigurableBeanFactory
?(ConfigurableBeanFactory)registry:null;
StringcontextId=FeignCommonUtil.getContextId(beanFactory,attributes,environment);
Stringname=FeignCommonUtil.getName(attributes,environment);

BeanDefinitionBuilderdefinition=BeanDefinitionBuilder
.genericBeanDefinition(clazz,()->{
Contractcontract=beanFactory.getBean(Contract.class);
ClientdefaultClient=(Client)beanFactory.getBean("defaultClient");
ClientribbonClient=(Client)beanFactory.getBean("ribbonClient");
Encoderencoder=beanFactory.getBean(Encoder.class);
Decoderdecoder=beanFactory.getBean(Decoder.class);

LocalFeignPropertiesproperties=beanFactory.getBean(LocalFeignProperties.class);
MapaddressMapping=properties.getAddressMapping();

Feign.Builderbuilder=Feign.builder()
.encoder(encoder)
.decoder(decoder)
.contract(contract);

StringserviceUrl=addressMapping.get(name);
StringoriginUrl=FeignCommonUtil.getUrl(beanFactory,attributes,environment);

Objecttarget;
if(StringUtils.hasText(serviceUrl)){
target=builder.client(defaultClient)
.target(clazz,serviceUrl);
}elseif(StringUtils.hasText(originUrl)){
target=builder.client(defaultClient)
.target(clazz,originUrl);
}else{
target=builder.client(ribbonClient)
.target(clazz,"http://"+name);
}

returntarget;
});

definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
definition.setLazyInit(true);
FeignCommonUtil.validate(attributes);

AbstractBeanDefinitionbeanDefinition=definition.getBeanDefinition();
beanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE,className);

//hasadefault,won'tbenull
booleanprimary=(Boolean)attributes.get("primary");
beanDefinition.setPrimary(primary);

String[]qualifiers=FeignCommonUtil.getQualifiers(attributes);
if(ObjectUtils.isEmpty(qualifiers)){
qualifiers=newString[]{contextId+"FeignClient"};
}

BeanDefinitionHolderholder=newBeanDefinitionHolder(beanDefinition,className,
qualifiers);
BeanDefinitionReaderUtils.registerBeanDefinition(holder,registry);
}

在這個過程中主要做了這么幾件事:

通過beanFactory拿到了我們在前面創(chuàng)建的Client、Encoder、Decoder、Contract,用來構(gòu)建Feign.Builder

通過注入配置類,通過addressMapping拿到配置文件中服務(wù)對應(yīng)的調(diào)用url

通過target方法替換要請求的url,如果配置文件中存在則優(yōu)先使用配置文件中url,否則使用@FeignClient注解中配置的url,如果都沒有則使用服務(wù)名通過LoadBalancerFeignClient訪問

在resources/META-INF目錄下創(chuàng)建spring.factories文件,通過spi注冊我們的自動配置類:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=
com.feign.local.config.FeignAutoConfiguration

最后,本地打包即可:

mvncleaninstall

測試

引入我們在上面打好的包,由于包中已經(jīng)包含了spring-cloud-starter-openfeign,所以就不需要再額外引feign的包了:


com.cn.hydra
feign-local-enhancer
1.0-SNAPSHOT

在配置文件中添加配置信息,啟用組件:

feign:
local:
enable:true
basePackage:com.service
addressMapping:
hydra-service:http://127.0.0.1:8088
trunks-service:http://127.0.0.1:8099

創(chuàng)建一個FeignClient接口,注解的url中我們可以隨便寫一個地址,可以用來測試之后是否會被配置文件中的服務(wù)地址覆蓋:

@FeignClient(value="hydra-service",
contextId="hydra-serviceA",
url="http://127.0.0.1:8099/")
publicinterfaceClientA{
@GetMapping("/test/get")
Stringget();

@GetMapping("/test/user")
UsergetUser();
}

啟動服務(wù),過程中可以看見了執(zhí)行掃描包的操作:

803fe876-0f0a-11ee-962d-dac502259ad0.png

在替換url過程中添加一個斷點,可以看到即使在注解中配置了url,也會優(yōu)先被配置文件中的服務(wù)url覆蓋:

806f7668-0f0a-11ee-962d-dac502259ad0.png

使用接口進行測試,可以看到使用上面的代理對象進行了訪問并成功返回了結(jié)果:

809b35be-0f0a-11ee-962d-dac502259ad0.png

如果項目需要發(fā)布正式環(huán)境,只需要將配置feign.local.enable改為false或刪掉,并在項目中添加Feign原始的@EnableFeignClients即可。

總結(jié)

本文提供了一個在本地開發(fā)過程中簡化Feign調(diào)用的思路,相比之前需要麻煩的修改FeignClient中的url而言,能夠節(jié)省不少的無效勞動,并且通過這個過程,也可以幫助大家了解我們平常使用的這些組件是怎么與spring結(jié)合在一起的,熟悉spring的擴展點。





審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 編解碼器
    +關(guān)注

    關(guān)注

    0

    文章

    250

    瀏覽量

    24185
  • URL
    URL
    +關(guān)注

    關(guān)注

    0

    文章

    138

    瀏覽量

    15275
  • 虛擬機
    +關(guān)注

    關(guān)注

    1

    文章

    899

    瀏覽量

    27978
  • HTTP接口
    +關(guān)注

    關(guān)注

    0

    文章

    21

    瀏覽量

    1756

原文標題:簡化本地Feign調(diào)用,老手教你這么玩

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    labview屬性節(jié)點、本地變量和直接數(shù)據(jù)流不同調(diào)用方法速度

    1、直接數(shù)據(jù)流,速度最快2、本地變量,速度稍慢3、采用屬性節(jié)點Description,速度慢了一個數(shù)量級4、直接數(shù)據(jù)流+屬性節(jié)點只增加為兩者單獨調(diào)用時間的累加。5、屬性節(jié)點Value為什么比屬性節(jié)點
    發(fā)表于 11-14 17:13

    如何簡化程序框圖(方法)

    1.如何顯示子VI的部分控件于被調(diào)用該子VI的程序前面板上?2.程序框圖比較亂有哪些方法簡化?比如如何簡化程序框圖比較獨立的程序(自定義函數(shù)嗎?)
    發(fā)表于 04-05 14:17

    屬性節(jié)點、本地變量和直接數(shù)據(jù)流調(diào)用方法對速度的影響

    1、直接數(shù)據(jù)流,速度最快2、本地變量,速度稍慢3、采用屬性Description,速度慢了一個數(shù)量級4、直接數(shù)據(jù)流+屬性節(jié)點只增加為兩者單獨調(diào)用時間的累加。5、屬性節(jié)點Value為什么比屬性節(jié)點
    發(fā)表于 11-13 11:16

    matlab自定義函數(shù)調(diào)用方法

    matlab自定義函數(shù)調(diào)用方法 命令文件/函數(shù)文件+ 函數(shù)文件 - 多
    發(fā)表于 11-29 13:14 ?88次下載

    單片機系統(tǒng)中Web Service的調(diào)用方法研究

    本文介紹了一種在單片機系統(tǒng)中利用嵌入式網(wǎng)絡(luò)模塊實現(xiàn)Web Service調(diào)用方法,利用嵌入式網(wǎng)絡(luò)模塊實現(xiàn)串口到以太網(wǎng)數(shù)據(jù)的轉(zhuǎn)換,將串行數(shù)據(jù)封裝成Web Service請求包.它簡化了下位機和
    發(fā)表于 09-10 15:55 ?18次下載

    vb調(diào)用excel方法大全

    電子發(fā)燒友網(wǎng)站提供《vb調(diào)用excel方法大全.docx》資料免費下載
    發(fā)表于 04-14 10:27 ?6次下載

    Linux常見調(diào)用shell腳本的三種方法

    編寫Linux下的應(yīng)用程序時有時需要調(diào)用Linux的相關(guān)shell腳本,在這些腳本中通過調(diào)用Linux的相關(guān)函數(shù)實現(xiàn)對應(yīng)的功能。比如使用ifconfig配置本地的IP地址,采用這種方式省去了自己編寫應(yīng)用程序去實現(xiàn)的麻煩。
    的頭像 發(fā)表于 06-28 14:28 ?8379次閱讀

    Oracle調(diào)用外部動態(tài)庫的設(shè)置方法

    Oracle調(diào)用外部動態(tài)庫的設(shè)置方法(電源技術(shù)及應(yīng)用總結(jié))-該文檔為Oracle調(diào)用外部動態(tài)庫的設(shè)置講解文檔,是一份不錯的參考資料,感興趣的可以先下載看看,,,,,,,,,,,,,
    發(fā)表于 09-28 13:57 ?12次下載
    Oracle<b class='flag-5'>調(diào)用</b>外部動態(tài)庫的設(shè)置<b class='flag-5'>方法</b>

    C調(diào)用matlab方法

    C調(diào)用matlab方法介紹
    發(fā)表于 07-31 10:55 ?0次下載

    feign調(diào)用常見問題避坑指南!

    摘要:主要是總結(jié)了一下這段時間在使用 feign 的過程中的遇到的一些坑點。
    的頭像 發(fā)表于 12-23 15:13 ?1881次閱讀

    動態(tài)Feign的“萬能”接口調(diào)用

    對于fegin調(diào)用,我們一般的用法都是為每個微服務(wù)都創(chuàng)建對應(yīng)的feignclient接口,然后為每個微服務(wù)的controller接口,一一編寫對應(yīng)的方法,去調(diào)用對應(yīng)微服務(wù)的接口。
    發(fā)表于 12-26 11:42 ?3651次閱讀

    Feign第一次調(diào)用為什么會很慢?

    首先要了解Feign是如何進行遠程調(diào)用的,這里面包括,注冊中心、負載均衡、FeignClient之間的關(guān)系,微服務(wù)通過不論是eureka、nacos也好注冊到服務(wù)端,Feign是靠Ribbon做負載
    的頭像 發(fā)表于 08-17 15:00 ?1493次閱讀
    <b class='flag-5'>Feign</b>第一次<b class='flag-5'>調(diào)用</b>為什么會很慢?

    super調(diào)用父類的構(gòu)造方法

    我們分析這句話“父類對象的引用”,那說明我們使用的時候只能在子類中使用,既然是對象的引用,那么我們也可以用來調(diào)用成員屬性以及成員方法,當然了,這里的 super 關(guān)鍵字還能夠調(diào)用父類的構(gòu)造方法
    的頭像 發(fā)表于 10-10 16:42 ?831次閱讀
    super<b class='flag-5'>調(diào)用</b>父類的構(gòu)造<b class='flag-5'>方法</b>

    什么是遠程過程調(diào)用

    )。 什么是遠程過程調(diào)用呢? 那么對于一個聊天系統(tǒng)有int send_information(int friend_id,string msg)這個方法,我們的一個處理邏輯是不是這樣: 調(diào)用bool
    的頭像 發(fā)表于 11-10 10:10 ?920次閱讀
    什么是遠程過程<b class='flag-5'>調(diào)用</b>

    Feign的超時時間如何設(shè)置呢?

    今天來聊一聊前段時間看到的一個面試題,也是在實際項目中需要考慮的一個問題,Feign 的超時時間如何設(shè)置?
    的頭像 發(fā)表于 11-15 10:22 ?1122次閱讀
    <b class='flag-5'>Feign</b>的超時時間如何設(shè)置呢?