Nacos服務(wù)發(fā)現(xiàn)-二、Nacos服務(wù)發(fā)現(xiàn)快速入門

上一篇 Nacos服務(wù)發(fā)現(xiàn)-一、概覽

本小節(jié),將演示如何使用Spring Cloud Alibaba Nacos Discovery為Spring cloud 應(yīng)用程序與 Nacos 的無縫集成。 通過一些原生的Spring Cloud注解,我們可以快速來實現(xiàn)Spring Cloud微服務(wù)的服務(wù)發(fā)現(xiàn)機(jī)制,并使用Nacos Server作為服務(wù)發(fā)現(xiàn)中心,統(tǒng)一管理所有微服務(wù)。

2.1 Spring Cloud服務(wù)協(xié)作流程

現(xiàn)在,我們對Spring cloud內(nèi)的一些組件還不了解,為了能夠完全理解快速入門程序,我們需要學(xué)習(xí)以下內(nèi)容。

Spring Cloud 常見的集成方式是使用Feign+Ribbon技術(shù)來完成服務(wù)間遠(yuǎn)程調(diào)用及負(fù)載均衡的,如下圖:

image-20210116111826042.png
  1. 在微服務(wù)啟動時,會向服務(wù)發(fā)現(xiàn)中心上報自身實例信息,這里ServiceB 包含多個實例。每個實例包括:IP地址、端口號信息。
  2. 微服務(wù)會定期從Nacos Server(服務(wù)發(fā)現(xiàn)中心)獲取服務(wù)實例列表。
  3. 當(dāng)ServiceA調(diào)用ServiceB時,Ribbon組件從本地服務(wù)實例列表中查找ServiceB的實例,如獲取了多個實例如Instance1、Instance2。這時Ribbon會通過用戶所配置的負(fù)載均衡策略從中選擇一個實例。
  4. 最終,F(xiàn)eign組件會通過Ribbon選取的實例發(fā)送HTTP請求。

采用Feign+Ribbon的整合方式,是由Feign完成遠(yuǎn)程調(diào)用的整個流程。而Feign集成了Ribbon,F(xiàn)eign使用Ribbon完成調(diào)用實例的負(fù)載均衡。

2.1.1 負(fù)載均衡的概念

在SpringCloud服務(wù)協(xié)議流程中,ServiceA通過負(fù)載均衡調(diào)用ServiceB,下邊來了解一下負(fù)載均衡:

負(fù)載均衡就是將用戶請求(流量)通過一定的策略,分?jǐn)傇诙鄠€服務(wù)實例上執(zhí)行,它是系統(tǒng)處理高并發(fā)、緩解網(wǎng)絡(luò)壓力和進(jìn)行服務(wù)端擴(kuò)容的重要手段之一。它分為服務(wù)端負(fù)載均衡客戶端負(fù)載均衡。

服務(wù)器端負(fù)載均衡

image-20210116113909914.png

在負(fù)載均衡器中維護(hù)一個可用的服務(wù)實例清單,當(dāng)客戶端請求來臨時,負(fù)載均衡服務(wù)器按照某種配置好的規(guī)則(負(fù)載均衡算法)從可用服務(wù)實例清單中選取其一,去處理客戶端的請求。這就是服務(wù)端負(fù)載均衡。

例如Nginx,通過Nginx進(jìn)行負(fù)載均衡,客戶端發(fā)送請求至Nginx,Nginx通過負(fù)載均衡算法,在多個服務(wù)器之間選擇一個進(jìn)行訪問。即在服務(wù)器端再進(jìn)行負(fù)載均衡算法分配。

客戶端服務(wù)負(fù)載均衡

image-20210116114005588.png
我們接下來要講的Ribbon,就屬于客戶端負(fù)載均衡。在Ribbon客戶端會有一個服務(wù)實例地址列表,在發(fā)送請求前通過負(fù)載均衡算法選擇一個服務(wù)實例,然后進(jìn)行訪問,這是客戶端負(fù)載均衡。即在客戶端就進(jìn)行負(fù)載均衡算法分配。

Ribbon是一個客戶端負(fù)載均衡器,它的責(zé)任是通過負(fù)載均衡策略從一組實例列表中挑選合適的實例

Ribbon核心組件IRule是負(fù)載均衡策略接口,它有如下實現(xiàn),大家僅做了解:

  • RoundRobinRule(默認(rèn)):輪詢,即按一定的順序輪換獲取實例的地址

  • RandomRule:隨機(jī),即以隨機(jī)的方式獲取實例的地址

  • AvailabilityFilteringRule: 會先過濾掉由于多次訪問故障而處于斷路器跳閘狀態(tài)的服務(wù),以及并發(fā)的連接數(shù)量超過閾值的服務(wù),然后對剩余的服務(wù)列表按照輪詢策略進(jìn)行訪問

  • WeightedResponseTimeRule: 根據(jù)平均響應(yīng)時間計算所有服務(wù)的權(quán)重,響應(yīng)時間越快,服務(wù)權(quán)重越大,被選中的機(jī)率越高

    剛啟動時,如果統(tǒng)計信息不足,則使用RoundRobinRule策略,等統(tǒng)計信息足夠時,會切換到WeightedResponseTimeRule

  • RetryRule:先按照RoundRobinRule的策略獲取服務(wù),如果獲取服務(wù)失敗,則在指定時間內(nèi)會進(jìn)行重試,獲取可用的服務(wù)

  • BestAvailableRule:會先過濾掉由于多次訪問故障而處于斷路器跳閘狀態(tài)的服務(wù),然后選擇一個并發(fā)量最小的服務(wù)

  • ZoneAvoidanceRule:默認(rèn)規(guī)則,復(fù)合判斷Server所在區(qū)域的性能和Server的可用性選擇服務(wù)器

可通過下面方式在Spring Boot 配置文件中修改默認(rèn)的負(fù)載均衡策略:

account‐service.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

注:account-service是調(diào)用的服務(wù)的名稱,后面的組成部分是固定的。

2.1.2 Feign 介紹

Feign是Netflix開發(fā)的聲明式、模板化的HTTP客戶端, Feign可以幫助我們更快捷、優(yōu)雅地調(diào)用HTTP API。Feign的英文表意為"假裝,偽裝,變形",可以理解為將HTTP報文請求方式偽裝為簡單的Java接口調(diào)用方式。

小結(jié)

通過上面的學(xué)習(xí),已經(jīng)了解Spring Cloud的微服務(wù)是如何協(xié)作的,通過哪些組件的配合能夠完成服務(wù)間協(xié)作?我們了解了什么是負(fù)載均衡,F(xiàn)eign用于服務(wù)間Http調(diào)用,Ribbon用于執(zhí)行負(fù)載均衡算法選取訪問實例,而Ribbon的實例列表來源是由Spring Cloud的服務(wù)發(fā)現(xiàn)中心提供(當(dāng)前實現(xiàn)為Nacos)。下一節(jié),我們將通過實作的方式使用Feign調(diào)用服務(wù)提供者

2.2 使用Feign進(jìn)行服務(wù)調(diào)用

2.2.1 Nacos

# 通過單機(jī)模式啟動Nacos
startup -m standalone

2.2.2 生產(chǎn)者

(1) 創(chuàng)建生產(chǎn)者模塊

image-20210116124142462.png

(2) 在pom.xml添加依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>nacosdiscover</artifactId>
        <groupId>net.zhi365</groupId>
        <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>service-feign-provider</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- SpringCloud Ailibaba Nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!-- SpringCloud Ailibaba Nacos Config -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>
    </dependencies>
</project>

(3) 創(chuàng)建啟動類

ServiceFeignProviderApplication.java

package net.zhi365.servicefeignprovider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * @author Xin.li
 * @date 2021-01-16 12:49
 */
@SpringBootApplication
//  開啟服務(wù)發(fā)現(xiàn)與Feign客戶端
@EnableDiscoveryClient
@EnableFeignClients
public class ServiceFeignProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceFeignProviderApplication.class, args);
    }
}

(4) 生產(chǎn)者服務(wù)實現(xiàn)

ProviderController.java

package net.zhi365.servicefeignprovider.web;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Xin.li
 * @date 2021-01-16 12:52
 */
@RestController
public class ProviderController {

    @GetMapping("/service")
    public String service() {
        System.out.println("provider invoke");
        return "provider invoke";
    }
}

(5) 編寫配置文件

application.yml

server:
  port: 56110
spring:
  application:
    name: feign-provider
  cloud:
    nacos:
      server-addr: localhost:8848

2.2.3 消費者

(1) 新建模塊spring-feign-consumer并在pom文件中添加相應(yīng)依賴

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>nacosdiscover</artifactId>
        <groupId>net.zhi365</groupId>
        <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>spring-feign-consumer</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>

        <!-- SpringCloud Ailibaba Nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!-- SpringCloud Ailibaba Nacos Config -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
    </dependencies>
</project>

(2) 模塊啟動類

SpringFeignConsumerApplication.java

package net.zhi365.springfeignconsumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * @author Xin.li
 * @date 2021-01-16 12:10
 */
@SpringBootApplication
//  開啟服務(wù)發(fā)現(xiàn)與Feign客戶端
@EnableDiscoveryClient
@EnableFeignClients
public class SpringFeignConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringFeignConsumerApplication.class, args);
    }
}

(3) 聲明Feign客戶端

ServiceProviderAgent.java

package net.zhi365.springfeignconsumer.remote;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @author Xin.li
 * @date 2021-01-16 11:57
 */
@FeignClient(value = "feign-provider")
public interface ServiceProviderAgent {

    @GetMapping(value = "/service")
    public String serviceProvider();
}

(4) 服務(wù)調(diào)用

package net.zhi365.springfeignconsumer.web;

import net.zhi365.springfeignconsumer.remote.ServiceProviderAgent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @author Xin.li
 * @date 2021-01-16 12:15
 */
@RestController
public class ConsumerController {

    @Autowired
    private ServiceProviderAgent serviceProviderAgent;

    @GetMapping(value = "/service")
    public String service(){
        //  調(diào)用服務(wù)
        String providerResult = serviceProviderAgent.serviceProvider();

        return "consumer invoke | " + providerResult;
    }
}

2.2.4 服務(wù)調(diào)用

(1) 在Nacos中查看服務(wù)

image-20210116143524321.png

(2) 訪問消費者頁面

http://localhost:56120/service/

image-20210116143620585.png

小結(jié):

非常簡單,并且在業(yè)務(wù)調(diào)用時,減少了與業(yè)務(wù)無關(guān)的http請求相關(guān)代碼的編寫,使業(yè)務(wù)邏輯清晰。我們來分析一下Feign幫我們做了哪些事情:

  • 在聲明Feign客戶端之后,F(xiàn)eign會根據(jù)@FeignClient注解使用Java的動態(tài)代理技術(shù)生成代理類,在這里我們指定@FeignClient value為service,則說明這個類的遠(yuǎn)程目標(biāo)為Spring Cloud的服務(wù)名稱為service的微服務(wù)。
  • service的具體訪問地址,F(xiàn)eign會交由Ribbon獲取,若該服務(wù)有多個實例地址,Ribbon會采用指定的負(fù)載均衡策略選取實例。
  • Feign兼容Spring的Web注解(如:@GetMapping),它會分析聲明Feign客戶端方法中的Spring注解,得出Http請求Method、參數(shù)信息以及返回信息結(jié)構(gòu)。
  • 當(dāng)業(yè)務(wù)調(diào)用Feign客戶端方法時,會調(diào)用代理類,根據(jù)以上分析結(jié)果,由代理類完成實際的參數(shù)封裝、遠(yuǎn)程Http請求,返回結(jié)果封裝等操作。

2.3 測試多實例負(fù)載均衡

(1) 配置應(yīng)用1-56100

image-20210116145919458.png

(2) 配置應(yīng)用2-56110

復(fù)制應(yīng)用1為應(yīng)用2,并指定啟動端口為56110

image-20210116150048068.png

(3) 查看Nacos服務(wù)

image-20210116150438439.png

(4) 查看負(fù)載情況

image-20210116150610157.png

經(jīng)過多次調(diào)用,觀看后臺日志,發(fā)現(xiàn)是被輪流調(diào)用,至此負(fù)載均衡實現(xiàn)成功~

注:Rabbin默認(rèn)負(fù)載均衡策略是輪詢

下一篇 Nacos服務(wù)發(fā)現(xiàn)-三、Nacos服務(wù)發(fā)現(xiàn)基礎(chǔ)應(yīng)用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容