欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringCloud?Nacos?+?Ribbon?調(diào)用服務(wù)的實現(xiàn)方式(兩種)

 更新時間:2022年03月10日 10:05:53   作者:磊哥  
這篇文章主要介紹了SpringCloud?Nacos?+?Ribbon?調(diào)用服務(wù)的兩種方法,分別是通過代碼的方式調(diào)用服務(wù)和通過注解方式調(diào)用服務(wù),每種方式給大家介紹的非常詳細(xì),需要的朋友可以參考下

在 Nacos 中,服務(wù)調(diào)用主要是通過 RestTemplate + Ribbon 實現(xiàn)的,RestTemplate 是 Spring 提供的 Restful 請求實現(xiàn)類,而 Ribbon 是客戶端負(fù)載均衡器,通過 Ribbon 可以獲取服務(wù)實例的具體信息(IP 和端口號),之后再通過 RestTemplate 加服務(wù)實例的具體信息就可以完成一次服務(wù)調(diào)用了。

而 RestTemplate + Ribbon 調(diào)用服務(wù)的實現(xiàn)方式兩種:通過代碼的方式調(diào)用服務(wù)和通過注解方式調(diào)用服務(wù)。但兩種實現(xiàn)方式的原理都是一樣的:都是通過注冊中心,將可用服務(wù)列表拉取到本地(客戶端),再通過客戶端負(fù)載均衡器得到某個服務(wù)器的具體信息,然后請求此服務(wù)器即可,如下圖所示:

1.代碼方式調(diào)用

通過代碼的方式調(diào)用服務(wù)在實際工作中并不常用,主要是寫法太麻煩,但了解它對于后面理解注解調(diào)用方式有很大的幫助,所以我們這里重點來看一下。服務(wù)調(diào)用需要有兩個角色:一個是服務(wù)提供者(Provider),另一個是服務(wù)調(diào)用者(Consumer),接下來我們來創(chuàng)建一下這兩個角色。

1.1 創(chuàng)建服務(wù)提供者:Provider

第一步:先創(chuàng)建一個 Spring Boot 項目(Spring Cloud 項目是基于 Spring Boot 創(chuàng)建的),添加 spring-web 和 nacos-discovery 依賴,具體依賴信息如下:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 添加 Nacos 支持 -->
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

第二步:設(shè)置 Nacos 相關(guān)配置,在 application.yml 中添加以下配置:

spring:
  application:
    name: springcloud-nacos-provider # 項目名稱(nacos 注冊的服務(wù)名)
  cloud:
    nacos:
      discovery:
        username: nacos # nacos 登錄用戶名
        password: nacos666 # nacos 密碼
        server-addr: 127.0.0.1:8848 # nacos 服務(wù)端地址
server:
  port: 8081 # 項目啟動端口號

第三步:添加服務(wù)方法,如下代碼所示:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class HttpProviderApplication {

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

    /**
     * 為客戶端提供可調(diào)用的接口
     */
    @RequestMapping("/call/{name}")
    public String call(@PathVariable String name) {
        return "I'm Provider. Received a message from: " + name;
    }
}

然后使用相同的方法再創(chuàng)建 2 個服務(wù)提供者,最終對應(yīng)的端口號分別為:

127.0.0.1:8081 127.0.0.1:8082 127.0.0.1:8083

這 3 個服務(wù)提供者分別打印的內(nèi)容是“I'm Provider...”、“I'm Provider2...”、“I'm Provider3...”,如下圖所示:

1.2 創(chuàng)建服務(wù)調(diào)用者:Consumer

本文的核心是服務(wù)調(diào)用者的實現(xiàn)代碼,它的創(chuàng)建方式和服務(wù)提供者的創(chuàng)建方式類似。第一步:創(chuàng)建一個 Spring Boot 項目,添加 spring-web 和 nacos-discovery 依賴,具體依賴內(nèi)容如下:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 添加 Nacos 支持 -->
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

可能有人會有疑問,本文標(biāo)題是 Spring Cloud Alibaba Nacos + Ribbon,那為什么不添加 Ribbon 的依賴呢?這是因為 Spring Cloud Alibaba Nacos 中已經(jīng)內(nèi)置了 Ribbon 框架了,打開項目的依賴樹就可以清楚的看到了,如下圖所示:

第二步:設(shè)置 Nacos 相關(guān)配置,在 application.yml 中添加以下配置:

spring:
  application:
    name: springcloud-nacos-consumer # 項目名稱(nacos 注冊的服務(wù)名)
  cloud:
    nacos:
      discovery:
        username: nacos # nacos 登錄用戶名
        password: nacos666 # nacos 密碼
        server-addr: 127.0.0.1:8848 # nacos 服務(wù)端地址
server:
  port: 8091 # 項目啟動端口號

第三步:在項目啟動類中,使用 Spring Java Config 的方式聲明 RestTemplate 對象,如下代碼所示:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class RibbonCodeConsumerApplication {

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

    /**
     * 使用 Spring Java Config 方式聲明 RestTemplate
     */
    @Bean
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

第四步:使用 RestTemplate + Ribbon 的代碼方式調(diào)用服務(wù),首先使用 Ribbon 提供的 LoadBalancerClient 對象的 choose 方法,根據(jù) Nacos 中的服務(wù) id 獲取某個健康的服務(wù)實例,服務(wù)實例中包含服務(wù)的 IP 地址和端口號,然后再使用 RestTemplate 根據(jù)獲取到的 IP 和 端口號訪問服務(wù)即可,具體實現(xiàn)代碼如下:

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;

@RestController
public class ConsumerController {
    // Ribbon 提供的負(fù)載均衡對象
    @Resource
    private LoadBalancerClient loadBalancerClient;

    // Spring 提供進(jìn)行 Restful 請求對象
    @Resource
    private RestTemplate restTemplate;

    @GetMapping("/consumer")
    public String consumer(@RequestParam String name) {
        // 根據(jù) Ribbon 提供的對象 + Nacos 的服務(wù) id 獲取服務(wù)實例
        ServiceInstance serviceInstance = loadBalancerClient.choose("springcloud-nacos-provider");
        // 獲取服務(wù)實例中的 ip
        String ip = serviceInstance.getHost();
        // 獲取服務(wù)實例中的端口號
        int port = serviceInstance.getPort();
        // 使用 restTemplate 請求并獲取結(jié)果
        String result = restTemplate.getForObject("http://" + ip + ":" + port + "/call/" + name,String.class);
        return result;
    }
}

以上程序的執(zhí)行結(jié)果如下圖所示:

2.注解方式調(diào)用

使用注解方式調(diào)用服務(wù)就簡單多了,服務(wù)提供者的創(chuàng)建方法和上面相同,這里就不再贅述了,接下來我們來創(chuàng)建一個注解方式的服務(wù)調(diào)用者 Consumer。第一步:創(chuàng)建一個 Spring Boot 項目,添加 spring-web 和 nacos-discovery 依賴,具體依賴內(nèi)容如下:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 添加 Nacos 支持 -->
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

第二步:設(shè)置 Nacos 相關(guān)配置,在 application.yml 中添加以下配置:

spring:
  application:
    name: springcloud-nacos-consumer # 項目名稱(nacos 注冊的服務(wù)名)
  cloud:
    nacos:
      discovery:
        username: nacos # nacos 登錄用戶名
        password: nacos666 # nacos 密碼
        server-addr: 127.0.0.1:8848 # nacos 服務(wù)端地址
server:
  port: 8092 # 項目啟動端口號

第三步:在項目啟動類中,使用 Spring Java Config 的方式聲明 RestTemplate 對象,此步驟中,需要在 RestTemplate 對象上加上 @LoadBalanced 注解,加上此注解之后就可以讓 RestTemplate 對象自動支持負(fù)載均衡了,如下代碼所示:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class RibbonAnnotationConsumerApplication {

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

    @LoadBalanced // 使 RestTemplate 自動支持 Ribbon 負(fù)載均衡
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

第四步:創(chuàng)建客戶端請求方法,具體實現(xiàn)代碼如下:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
public class ConsumerController {
    @Resource
    private RestTemplate restTemplate;

    @GetMapping("/consumer")
    public String consumer(@RequestParam String name) {
        // 請求并獲取結(jié)果(springcloud-nacos-provider 為 Nacos 服務(wù)id)
        String result = restTemplate.getForObject("http://springcloud-nacos-provider/call/" + name, String.class);
        return result;
    }
}

以上程序的執(zhí)行結(jié)果如下圖所示:

注解實現(xiàn)原理分析

通過上述代碼我們可以看出,Nacos 實現(xiàn)調(diào)用服務(wù)的關(guān)鍵是通過 @LoadBalanced,它為 RestTemplate 賦予了負(fù)載均衡的能力,從而可以正確的調(diào)用到服務(wù),那 @LoadBalanced 是如何實現(xiàn)的呢?要知道這個問題的答案,就得閱讀 LoadBalancerAutoConfiguration 的源碼。LoadBalancerAutoConfiguration 是實現(xiàn)客戶端負(fù)載均衡器的自動裝配類,隨著 Spring 的啟動而啟動,它的源碼內(nèi)容有很多,我們這里截取部分核心的方法來看一下:

@Bean
public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
    return () -> {
        restTemplateCustomizers.ifAvailable((customizers) -> {
            Iterator var2 = this.restTemplates.iterator();

            while(var2.hasNext()) {
                RestTemplate restTemplate = (RestTemplate)var2.next();
                Iterator var4 = customizers.iterator();

                while(var4.hasNext()) {
                    RestTemplateCustomizer customizer = (RestTemplateCustomizer)var4.next();
                    customizer.customize(restTemplate);
                }
            }

        });
    };
}

這里的 this.restTemplates.iterator() 既所有被 @LoadBalanced 注解修飾的 RestTemplate 對象,所有被 @LoadBalanced 修飾的 RestTemplate 對象會被強(qiáng)轉(zhuǎn)為 RestTemplateCustomizer 對象,而這個對象的實現(xiàn)源碼如下:

@Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(final LoadBalancerInterceptor loadBalancerInterceptor) {
    return (restTemplate) -> {
        List<ClientHttpRequestInterceptor> list = new ArrayList(restTemplate.getInterceptors());
        list.add(loadBalancerInterceptor);
        restTemplate.setInterceptors(list);
    };
}

也就是所有被 @LoadBalanced 注解修飾的 RestTemplate 對象,會為其添加一個 loadBalancerInterceptor 的攔截器,攔截器的實現(xiàn)源碼如下:

public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {
    private LoadBalancerClient loadBalancer;
    private LoadBalancerRequestFactory requestFactory;

    public LoadBalancerInterceptor(LoadBalancerClient loadBalancer, LoadBalancerRequestFactory requestFactory) {
        this.loadBalancer = loadBalancer;
        this.requestFactory = requestFactory;
    }

    public LoadBalancerInterceptor(LoadBalancerClient loadBalancer) {
        this(loadBalancer, new LoadBalancerRequestFactory(loadBalancer));
    }

    public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
        URI originalUri = request.getURI();
        String serviceName = originalUri.getHost();
        Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
        return (ClientHttpResponse)this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution));
    }
}

從上述源碼可以看出,@LoadBalanced 的執(zhí)行流程是,被 @LoadBalanced 注解修飾的 RestTemplate 對象,會被 LoadBalancerInterceptor 攔截器所攔截,攔截之后使用 LoadBalancerClient 對象,按照負(fù)載均衡的策略獲取一個健康的服務(wù)實例,然后再通過服務(wù)實例的 IP 和端口,調(diào)用實例方法,從而完成服務(wù)請求。

總結(jié)

Nacos 調(diào)用 Restful 服務(wù)是通過內(nèi)置的 Ribbon 框架實現(xiàn)的,它有兩種調(diào)用方法,通過代碼的方式或通過注解的方式完成調(diào)用。其中注解的方式使用起來比較簡單,只需要在 RestTemplate 對象上添加一個 @LoadBalanced 注解,就可以為請求對象賦予負(fù)載均衡的能力了。

到此這篇關(guān)于SpringCloud Nacos + Ribbon 調(diào)用服務(wù)的兩種方法!的文章就介紹到這了,更多相關(guān)SpringCloud Nacos調(diào)用服務(wù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java經(jīng)典排序算法之歸并排序?qū)崿F(xiàn)代碼

    Java經(jīng)典排序算法之歸并排序?qū)崿F(xiàn)代碼

    這篇文章主要介紹了Java經(jīng)典排序算法之歸并排序?qū)崿F(xiàn)代碼,歸并排序是建立在歸并操作上的一種有效的排序算法,該算法是采用分治法的一個非常典型的應(yīng)用,將已有序的子序列合并,得到完全有序的序列,需要的朋友可以參考下
    2023-10-10
  • mybatis查詢字段為null設(shè)置為0的操作

    mybatis查詢字段為null設(shè)置為0的操作

    這篇文章主要介紹了mybatis查詢字段為null設(shè)置為0的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • java判斷字符串是否為null的四種方式匯總

    java判斷字符串是否為null的四種方式匯總

    這篇文章主要介紹了java判斷字符串是否為null的四種方式匯總,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • spring mvc 使用kaptcha配置生成驗證碼實例

    spring mvc 使用kaptcha配置生成驗證碼實例

    本篇文章主要介紹了spring mvc 使用kaptcha生成驗證碼實例,詳細(xì)的介紹了使用Kaptcha 生成驗證碼的步驟,有興趣的可以了解一下
    2017-04-04
  • Java虛擬機(jī)精選面試題20道

    Java虛擬機(jī)精選面試題20道

    現(xiàn)在面試Java開發(fā)時,基本都會問到Java虛擬機(jī)的知識,根據(jù)職位不同問的內(nèi)容深淺又有所區(qū)別。本文整理了10道面試中常問的Java虛擬機(jī)面試題,希望對正在面試的同學(xué)有所幫助
    2021-06-06
  • 你知道Java中的注解可以繼承嗎?

    你知道Java中的注解可以繼承嗎?

    注解想必大家都用過,也叫元數(shù)據(jù),是一種代碼級別的注釋,可以對類或者方法等元素做標(biāo)記說明。那么今天我想問大家的是類被繼承了,注解能否繼承呢?可能會和大家想的不一樣,感興趣的可以往下看
    2022-12-12
  • Java實現(xiàn)求數(shù)組最長子序列算法示例

    Java實現(xiàn)求數(shù)組最長子序列算法示例

    這篇文章主要介紹了Java實現(xiàn)求數(shù)組最長子序列算法,涉及java針對數(shù)組的遞歸遍歷、判斷相關(guān)操作技巧,需要的朋友可以參考下
    2018-07-07
  • java實現(xiàn)簡單的彈球游戲

    java實現(xiàn)簡單的彈球游戲

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)簡單的彈球游戲,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • java中的instanceof關(guān)鍵字詳細(xì)解讀

    java中的instanceof關(guān)鍵字詳細(xì)解讀

    這篇文章主要介紹了java中的instanceof關(guān)鍵字詳細(xì)解讀,instanceof 是 Java 的保留關(guān)鍵字,它的作用是測試它左邊的對象是否是它右邊的類的實例,返回 boolean 的數(shù)據(jù)類型,需要的朋友可以參考下
    2024-01-01
  • java二叉樹的遍歷方式詳解

    java二叉樹的遍歷方式詳解

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)二叉樹遍歷的四種方式,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能給你帶來幫助
    2021-08-08

最新評論