溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

SpringCloud?OpenFeign怎么遠(yuǎn)程調(diào)用

發(fā)布時(shí)間:2022-08-24 10:56:01 來(lái)源:億速云 閱讀:149 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“SpringCloud OpenFeign怎么遠(yuǎn)程調(diào)用”的相關(guān)知識(shí),小編通過(guò)實(shí)際案例向大家展示操作過(guò)程,操作方法簡(jiǎn)單快捷,實(shí)用性強(qiáng),希望這篇“SpringCloud OpenFeign怎么遠(yuǎn)程調(diào)用”文章能幫助大家解決問(wèn)題。

一、什么是Feign

Feign makes writing java http clients easier,這是官方給出的一個(gè)說(shuō)明,本意翻譯是:Feign使編寫Java http客戶端更容易,Feign是一個(gè)http請(qǐng)求調(diào)用的輕量級(jí)框架,可以以Java接口注解的方式調(diào)用Http請(qǐng)求,F(xiàn)eign可以通過(guò)處理注解,將請(qǐng)求模板化,當(dāng)實(shí)際調(diào)用的時(shí)候,傳入?yún)?shù),根據(jù)參數(shù)再應(yīng)用到請(qǐng)求上,進(jìn)而轉(zhuǎn)化成真正的請(qǐng)求。

Feign封裝了Http調(diào)用流程,更適合面向接口化的編程習(xí)慣。

在服務(wù)調(diào)用的場(chǎng)景中,我們經(jīng)常調(diào)用基于Http協(xié)議的服務(wù),而我們經(jīng)常使用到的遠(yuǎn)程調(diào)用框架可能有HttpURLConnection、Apache HttpComponnets、OkHttp3 、Forest、Netty等等,這些框架在基于自身的專注點(diǎn)提供了自身特性。而從角色劃分上來(lái)看,他們的職能是一致的提供Http調(diào)用服務(wù)。

二、理解遠(yuǎn)程調(diào)用

  • 本地調(diào)用(Local Procedure Call,簡(jiǎn)稱LPC

  • 遠(yuǎn)程調(diào)用(Remote Procedure Call,簡(jiǎn)稱RPC

feign主要是為我們提供了遠(yuǎn)程調(diào)用的服務(wù),那么什么是遠(yuǎn)程調(diào)用呢? 遠(yuǎn)程調(diào)用說(shuō)白了可以理解為不同服務(wù)之間方法的調(diào)用,實(shí)質(zhì)上是兩臺(tái)主機(jī)間的網(wǎng)絡(luò)通信 ,涉及到網(wǎng)絡(luò)通信又必然會(huì)有序列化、反序列化,編解碼等一些必須要考慮的問(wèn)題,現(xiàn)在業(yè)界內(nèi)比較流行的一些 RPC 框架,例如:Dubbo提供的是基于接口的遠(yuǎn)程方法調(diào)用,通過(guò)rpc遠(yuǎn)程調(diào)用框架,客戶端只需要知道接口的定義即可調(diào)用遠(yuǎn)程服務(wù)。

SpringCloud?OpenFeign怎么遠(yuǎn)程調(diào)用

而 feign主要就是用來(lái)簡(jiǎn)化我們發(fā)起遠(yuǎn)程調(diào)用的代碼,以一個(gè)遠(yuǎn)程調(diào)用Github開放的API為

/**
 * GitHub客戶端GitHubFeign,訪問(wèn)GitHub開發(fā)平臺(tái)API,開放平臺(tái)API地址:https://www.apifox.cn/apihub/
 *
 * @author: jacklin
 * @date: 2022/6/30 21:20
 */
@FeignClient(name = "github-client", url = "https://api.github.com")
public interface GitHubFeign {


    /**
     * 查找github標(biāo)準(zhǔn)庫(kù)信息
     * <p>
     * https://api.github.com/search/repositories   v
     *
     * @author: jacklin
     * @since 2022/6/30 21:27
     **/
    @GetMapping(value = "/search/repositories", produces = MediaType.APPLICATION_JSON_VALUE)
    String searchRepositories(@RequestParam("q") String q);
}

第一步: Maven pom文件中引入 OpenFeign 組件。

SpringCloud?OpenFeign怎么遠(yuǎn)程調(diào)用

第二步:客戶端需要定義一個(gè)GitHubFeign接口,里面定義一個(gè)searchRepositories()方法,可以看到這個(gè)接口上添加了@FeignClient注解,而括號(hào)里面指定了服務(wù)名:github-client,顯示聲明這個(gè)接口是用來(lái)遠(yuǎn)程調(diào)用GitHub API服務(wù)的,url用來(lái)指定調(diào)用服務(wù)的全路徑,其他方法路徑前綴必須與url地址一致,完整的請(qǐng)求路徑URL地址:https://api.github.com/search/repositories

第三步:需要在服務(wù)啟動(dòng)類添加@EnableFeignClients注解,在服務(wù)啟動(dòng)時(shí),Spring掃描被@FeignClints修飾的接口,基于動(dòng)態(tài)代理生成本地JDK Proxy代理對(duì)象實(shí)例,然后將這些代理實(shí)例注冊(cè)到Spring IOC容器中,當(dāng)遠(yuǎn)程接口被調(diào)用時(shí),由Proxy代理實(shí)例去完成真正的遠(yuǎn)程訪問(wèn),并返回結(jié)果。

第四步:在Controller引入GitHubFeign服務(wù),完成遠(yuǎn)程服務(wù)調(diào)用:

@RestController
@RequestMapping(value = "/github", produces = MediaType.APPLICATION_JSON_VALUE)
public class GithubController {

    @Resource
    private GitHubFeign gitHubFeign;

    /**
     * 查找github標(biāo)準(zhǔn)庫(kù)信息
     *
     * @author: jacklin
     * @since 2022/6/30 21:36
     **/
    @GetMapping(value = "/searchRepositories")
    String searchRepositories(@RequestParam(value = "q") String q) {
        return gitHubFeign.searchRepositories(q);
    }
}

返回結(jié)果數(shù)據(jù)如下:

SpringCloud?OpenFeign怎么遠(yuǎn)程調(diào)用

可以看出,feign使得遠(yuǎn)程調(diào)用跟本地方法是一樣,極大的簡(jiǎn)化了rpc遠(yuǎn)程調(diào)用的方式。

三、OpenFeign和Feign的區(qū)別

可以認(rèn)為OpenFeign是Feign的增強(qiáng)版,不同的是OpenFeign支持Spring MVC注解

FeignOpenFeign
Feign是Netflix公司寫的,是SpringCloud組件中的一個(gè)輕量級(jí)RESTful的HTTP服務(wù)客戶端,是SpringCloud中的第一代負(fù)載均衡客戶端。OpenFeign的前身是Neflix Feign,Spring Cloud在Feign的基礎(chǔ)上擴(kuò)展支持了SpringMVC的注解,如@RequestMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通過(guò)動(dòng)態(tài)代理的方式產(chǎn)生實(shí)現(xiàn)類,實(shí)現(xiàn)類中做負(fù)載均衡并調(diào)用其他服務(wù)。

OpenFeignFeign底層都內(nèi)置了Ribbon負(fù)載均衡組件,在導(dǎo)入OpenFeign依賴后無(wú)需專門導(dǎo)入Ribbon依賴,用做客戶端負(fù)載均衡,去調(diào)用注冊(cè)中心服務(wù)。

四、OpenFeign核心工作原理

  • 通過(guò) @EnableFeignCleints觸發(fā)Spring應(yīng)用程序?qū)lasspath中@FeignClient修飾類的掃描。

  •  解析到 @FeignClient 修飾類后,Feign框架通過(guò)擴(kuò)展Spring Bean Deifinition的注冊(cè)邏輯,最終注冊(cè)一個(gè)FeignClientFacotoryBean進(jìn)入Spring容器

  •  Spring容器在初始化其他用到 @FeignClient 接口的類時(shí), 獲得的是FeignClientFacotryBean產(chǎn)生的一個(gè)代理對(duì)象Proxy。

  •  基于Java原生的動(dòng)態(tài)代理機(jī)制,針對(duì)Proxy的調(diào)用,都會(huì)被統(tǒng)一轉(zhuǎn)發(fā)給Feign框架所定義的一個(gè) InvocationHandler,由該Handler完成后續(xù)的HTTP轉(zhuǎn)換,發(fā)送、接收以及HTTP響應(yīng)的工作。

五、OpenFeign包掃描原理

要想通過(guò)OpenFeign實(shí)現(xiàn)遠(yuǎn)程調(diào)用,就涉及到一個(gè)OpenFeign的核心注解:@EnableFeignClient,根據(jù)字面意思可以知道,該注解是開啟OpenFeign的功能,一般都會(huì)被添加到我們的啟動(dòng)類上。

Spring包掃描的大體流程:

  • 開啟OpenFeign功能@EnableFeignClients,接著通過(guò)@Import(FeignClientsRegistrar.class) 這個(gè)import的方式導(dǎo)入FeignClientsRegistrar類,開啟OpenFeign組件的加載。

@SpringBootApplication
@EnableFeignClients
public class MambaBlockDemoApplication {

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

FeignClientsRegistrar負(fù)責(zé)Feign接口的加載,源碼如下:

@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
   //注冊(cè)配置
   registerDefaultConfiguration(metadata, registry);
   //注冊(cè)FeignClient
   registerFeignClients(metadata, registry);
}
  • registerFeignClients()方法會(huì)調(diào)用findCandidateComponents()方法來(lái)查找指定路徑的basePackages下所有被@FeignClients注解修飾的類、接口。

LinkedHashSet<BeanDefinition> candidateComponents = Set<BeanDefinition> findCandidateComponents(String basePackage)
  • 只保留被@FeignClient的修飾的接口。

for (BeanDefinition candidateComponent : candidateComponents) {
   if (candidateComponent instanceof AnnotatedBeanDefinition) {
      // verify annotated class is an interface
      AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;
      AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
      Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface");

      Map<String, Object> attributes = annotationMetadata
            .getAnnotationAttributes(FeignClient.class.getCanonicalName());

      String name = getClientName(attributes);
      registerClientConfiguration(registry, name, attributes.get("configuration"));
      //注入到Spring容器中
      registerFeignClient(registry, annotationMetadata, attributes);
   }
}

關(guān)于“SpringCloud OpenFeign怎么遠(yuǎn)程調(diào)用”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí),可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會(huì)為大家更新不同的知識(shí)點(diǎn)。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI