SpringCloud----基礎

概述

  目前市場上主流的 第一套微服務架構解決方案:Spring Boot + Spring Cloud Netflixcss

  Spring Cloud 爲開發人員提供了快速構建分佈式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智能路由,微代理,控制總線)。分佈式系統的協調致使了樣板模式, 使用 Spring Cloud 開發人員能夠快速地支持實現這些模式的服務和應用程序。他們將在任何分佈式環境中運行良好,包括開發人員本身的筆記本電腦,裸機數據中心,以及 Cloud Foundry 等託管平臺。java

  Spring Cloud 項目部是基於Spring Boot進行開發,而且都是使用Maven作項目管理工具。在實際開發中,咱們通常都會建立一依賴管理項目做爲Maven的Parent項目使用,這樣作能夠極大的方便咱們對Jar 包版本的統一管理。git

  注意:sprint Cloud Netfix 在2018年12月進入維護期github

  市場上主流的 第一套微服務架構解決方案:Apache Dubbo ZooKeeper(不完善)web

  目前市場上主流的 第三套微服務架構解決方案:Spring Boot + Spring Cloud Alibabaspring

 

咱們採用Spring Boot + Spring Cloud Alibaba來學習數據庫

Spring Boot是框架,Spring Cloud Alibaba是技術手段,解決微服務中的注意問題apache

Spring Cloud Alibaba 解決 微服務須要主要問題瀏覽器

  Api網關:服務路由安全

  服務之間通信:http,RPC,異步調用

  服務註冊與發現-->高可用

  熔斷,限流,服務降級

分佈式開發中根本問題就是網絡不可靠

 

主要功能

  • 服務限流降級:默認支持 Servlet、Feign、RestTemplate、Dubbo 和 RocketMQ 限流降級功能的接入,能夠在運行時經過控制檯實時修改限流降級規則,還支持查看限流降級 Metrics 監控。
  • 服務註冊與發現:適配 Spring Cloud 服務註冊與發現標準,默認集成了 Ribbon 的支持。
  • 分佈式配置管理:支持分佈式系統中的外部化配置,配置更改時自動刷新。
  • 消息驅動能力:基於 Spring Cloud Stream 爲微服務應用構建消息驅動能力。
  • 阿里雲對象存儲:阿里雲提供的海量、安全、低成本、高可靠的雲存儲服務。支持在任何應用、任什麼時候間、任何地點存儲和訪問任意類型的數據。
  • 分佈式任務調度:提供秒級、精準、高可靠、高可用的定時(基於 Cron 表達式)任務調度服務。同時提供分佈式的任務執行模型,如網格任務。網格任務支持海量子任務均勻分配到全部 Worker(schedulerx-client)上執行。

組件

  • Sentinel:把流量做爲切入點,從流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩定性。
  • Nacos:一個更易於構建雲原生應用的動態服務發現、配置管理和服務管理平臺。
  • RocketMQ:一款開源的分佈式消息系統,基於高可用分佈式集羣技術,提供低延時的、高可靠的消息發佈與訂閱服務。
  • Alibaba Cloud ACM:一款在分佈式架構環境中對應用配置進行集中管理和推送的應用配置中心產品。
  • Alibaba Cloud OSS: 阿里雲對象存儲服務(Object Storage Service,簡稱 OSS),是阿里雲提供的海量、安全、低成本、高可靠的雲存儲服務。您能夠在任何應用、任什麼時候間、任何地點存儲和訪問任意類型的數據。
  • Alibaba Cloud SchedulerX: 阿里中間件團隊開發的一款分佈式任務調度產品,提供秒級、精準、高可靠、高可用的定時(基於 Cron 表達式)任務調度服務。

 

使用

一、建立統一的依賴管理

  舒適提示

  當前 Spring Cloud Alibaba 的 0.2.1.RELEASE 版本基於 Spring Cloud Finchley(F)開發,故在選擇 Spring Boot 版本時不要使用 2.1.0 及以上版本(由於 2.1.x 版本必須使用 Spring Cloud Greenwich,俗稱 G 版),請使用官方 Demo 中使用的 2.0.6.RELEASE,以避免發生意想不到的問題(好比服務沒法註冊到服務器)

  Spring Cloud Alibaba 項目都是基於 Spring Cloud,而 Spring Cloud 項目又是基於 Spring Boot 進行開發,而且都是使用 Maven 作項目管理工具。在實際開發中,咱們通常都會建立一個依賴管理項目做爲 Maven 的 Parent 項目使用,這樣作能夠極大的方便咱們對 Jar 包版本的統一管理。

建立依賴管理項目

建立一個工程名爲 hello-spring-cloud-alibaba-dependencies 的項目,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">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.6.RELEASE</version>
    </parent>

    <groupId>com.funtl</groupId>
    <artifactId>hello-spring-cloud-alibaba-dependencies</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <name>hello-spring-cloud-alibaba-dependencies</name>
    <url>http://www.funtl.com</url>
    <inceptionYear>2018-Now</inceptionYear>

    <properties>
        <!-- Environment Settings -->
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

        <!-- Spring Settings -->
        <spring-cloud.version>Finchley.SR2</spring-cloud.version>
        <spring-cloud-alibaba.version>0.2.1.RELEASE</spring-cloud-alibaba.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <!-- Compiler 插件, 設定 JDK 版本 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <showWarnings>true</showWarnings>
                </configuration>
            </plugin>

            <!-- 打包 jar 文件時,配置 manifest 文件,加入 lib 包的 jar 依賴 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <addMavenDescriptor>false</addMavenDescriptor>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <configuration>
                            <archive>
                                <manifest>
                                    <!-- Add directory entries -->
                                    <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                                    <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
                                    <addClasspath>true</addClasspath>
                                </manifest>
                            </archive>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <!-- resource -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
            </plugin>

            <!-- install -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-install-plugin</artifactId>
            </plugin>

            <!-- clean -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-clean-plugin</artifactId>
            </plugin>

            <!-- ant -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
            </plugin>

            <!-- dependency -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
            </plugin>
        </plugins>

        <pluginManagement>
            <plugins>
                <!-- Java Document Generate -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-javadoc-plugin</artifactId>
                    <executions>
                        <execution>
                            <phase>prepare-package</phase>
                            <goals>
                                <goal>jar</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

                <!-- YUI Compressor (CSS/JS壓縮) -->
                <plugin>
                    <groupId>net.alchim31.maven</groupId>
                    <artifactId>yuicompressor-maven-plugin</artifactId>
                    <version>1.5.1</version>
                    <executions>
                        <execution>
                            <phase>prepare-package</phase>
                            <goals>
                                <goal>compress</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <encoding>UTF-8</encoding>
                        <jswarn>false</jswarn>
                        <nosuffix>true</nosuffix>
                        <linebreakpos>30000</linebreakpos>
                        <force>true</force>
                        <includes>
                            <include>**/*.js</include>
                            <include>**/*.css</include>
                        </includes>
                        <excludes>
                            <exclude>**/*.min.js</exclude>
                            <exclude>**/*.min.css</exclude>
                        </excludes>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>

        <!-- 資源文件配置 -->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <excludes>
                    <exclude>**/*.java</exclude>
                </excludes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
    </build>

    <repositories>
        <repository>
            <id>aliyun-repos</id>
            <name>Aliyun Repository</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>

        <repository>
            <id>sonatype-repos</id>
            <name>Sonatype Repository</name>
            <url>https://oss.sonatype.org/content/groups/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>sonatype-repos-s</id>
            <name>Sonatype Repository</name>
            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>

        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>aliyun-repos</id>
            <name>Aliyun Repository</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
</project>
  • parent:繼承了 Spring Boot 的 Parent,表示咱們是一個 Spring Boot 工程
  • package:pom,表示該項目僅當作依賴項目,沒有具體的實現代碼
  • spring-cloud-alibaba-dependencies:在 properties 配置中預約義了版本號爲 0.2.1.RELEASE ,表示咱們的 Spring Cloud Alibaba 對應的是 Spring Cloud Finchley 版本
  • build:配置了項目所需的各類插件
  • repositories:配置項目下載依賴時的第三方庫

依賴版本說明

  在2019 年 01 月 05 日以前,項目的最新版本是 0.2.1.RELEASE 和 0.1.1.RELEASE,版本 0.2.1.RELEASE 對應的是 Spring Cloud Finchley 版本,版本 0.1.1.RELEASE 對應的是 Spring Cloud Edgware 版本。項目還處在孵化階段,故全部版本號都以 0 開頭;後續確定會有不少強大的功能幫助咱們更好的實現分佈式應用的開發;

經過https://maven.aliyun.com/mvn/search 能夠瀏覽項目版本

與 Spring Cloud Netflix 的區別

主要增長了 org.springframework.cloud:spring-cloud-alibaba-dependencies

 

二、服務註冊與發現

   Spring Cloud Netflix 採用 Eureka 作做爲咱們的服務註冊與發現服務器,現利用 Spring Cloud Alibaba 提供的 Nacos 組件替代該方案。

什麼是 Nacos

  Nacos 致力於幫助您發現、配置和管理微服務。Nacos 提供了一組簡單易用的特性集,幫助您快速實現動態服務發現、服務配置、服務元數據及流量管理。

  Nacos 幫助您更敏捷和容易地構建、交付和管理微服務平臺。 Nacos 是構建以「服務」爲中心的現代應用架構 (例如微服務範式、雲原生範式) 的服務基礎設施。

基本架構及概念

 

服務 (Service)

  服務是指一個或一組軟件功能(例如特定信息的檢索或一組操做的執行),其目的是不一樣的客戶端能夠爲不一樣的目的重用(例如經過跨進程的網絡調用)。Nacos 支持主流的服務生態,如 Kubernetes Service、gRPC|Dubbo RPC Service 或者 Spring Cloud RESTful Service.

服務註冊中心 (Service Registry)

  服務註冊中心,它是服務,其實例及元數據的數據庫。服務實例在啓動時註冊到服務註冊表,並在關閉時註銷。服務和路由器的客戶端查詢服務註冊表以查找服務的可用實例。服務註冊中心可能會調用服務實例的健康檢查 API 來驗證它是否可以處理請求。

服務元數據 (Service Metadata)

  服務元數據是指包括服務端點(endpoints)、服務標籤、服務版本號、服務實例權重、路由規則、安全策略等描述服務的數據

服務提供方 (Service Provider)

  是指提供可複用和可調用服務的應用方

服務消費方 (Service Consumer)

  是指會發起對某個服務調用的應用方

配置 (Configuration)

  在系統開發過程當中一般會將一些須要變動的參數、變量等從代碼中分離出來獨立管理,以獨立的配置文件的形式存在。目的是讓靜態的系統工件或者交付物(如 WAR,JAR 包等)更好地和實際的物理運行環境進行適配。配置管理通常包含在系統部署的過程當中,由系統管理員或者運維人員完成這個步驟。配置變動是調整系統運行時的行爲的有效手段之一。   

配置管理 (Configuration Management)

  在數據中心中,系統中全部配置的編輯、存儲、分發、變動管理、歷史版本管理、變動審計等全部與配置相關的活動統稱爲配置管理。

名字服務 (Naming Service)

  提供分佈式系統中全部對象(Object)、實體(Entity)的「名字」到關聯的元數據之間的映射管理服務,例如 ServiceName -> Endpoints Info, Distributed Lock Name -> Lock Owner/Status Info, DNS Domain Name -> IP List, 服務發現和 DNS 就是名字服務的2大場景。

配置服務 (Configuration Service)

  在服務或者應用運行過程當中,提供動態配置或者元數據以及配置管理的服務提供者。

下載安裝

準備環境

Nacos 依賴 Java 環境來運行。若是您是從代碼開始構建並運行 Nacos,還須要爲此配置 Maven 環境,請確保是在如下版本環境中安裝使用:

  • 64 bit OS,支持 Linux/Unix/Mac/Windows,推薦選用 Linux/Unix/Mac。
  • 64 bit JDK 1.8+
  • Maven 3.2.x+

下載並安裝

# 下載源碼
git clone https://github.com/alibaba/nacos.git

# 安裝到本地倉庫
cd nacos/
mvn -Prelease-nacos clean install -U

注:下載依賴時間較長,請耐心等待...

啓動服務

cd distribution/target/nacos-server-0.7.0/nacos/bin

# Linux
./startup.sh -m standalone

# Windows
startup.cmd

訪問服務

打開瀏覽器訪問:http://localhost:8848/nacos

注:從 0.8.0 版本開始,須要登陸纔可訪問,默認帳號密碼爲 nacos/nacos

 

三、建立服務提供者

概述

經過一個簡單的示例來感覺一下如何將服務註冊到 Nacos,其實和 Eureka 沒有太大差異。

建立一個工程名爲 hello-spring-cloud-alibaba-nacos-provider 的服務提供者項目,pom.xml 配置以下:

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">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>com.funtl</groupId>
        <artifactId>hello-spring-cloud-alibaba-dependencies</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <relativePath>../hello-spring-cloud-alibaba-dependencies/pom.xml</relativePath>
    </parent>

    <artifactId>hello-spring-cloud-alibaba-nacos-provider</artifactId>
    <packaging>jar</packaging>

    <name>hello-spring-cloud-alibaba-nacos-provider</name>
    <url>http://www.funtl.com</url>
    <inceptionYear>2018-Now</inceptionYear>

    <dependencies>
        <!-- Spring Boot Begin -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Spring Boot End -->

        <!-- Spring Cloud Begin -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- Spring Cloud End -->
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.funtl.hello.spring.cloud.alibaba.nacos.provider.NacosProviderApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Application

 

package com.funtl.hello.spring.cloud.alibaba.nacos.provider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@EnableDiscoveryClient
public class NacosProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(NacosProviderApplication.class, args);
    }

    @RestController
    public class EchoController {
        @GetMapping(value = "/echo/{message}")
        public String echo(@PathVariable String message) {
            return "Hello Nacos Discovery " + message;
        }
    }
}

application.yml

spring:
  application:
    name: nacos-provider
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

server:
  port: 8081

management:
  endpoints:
    web:
      exposure:
        include: "*"

啓動工程

  打開nacos,你會發現一個服務已經註冊在服務中了,服務名爲 nacos-provider

 

 這時打開 http://localhost:8081/echo/hi ,你會在瀏覽器上看到:

Hello Nacos Discovery hi

服務的端點檢查

spring-cloud-starter-alibaba-nacos-discovery 在實現的時候提供了一個 EndPoint, EndPoint 的訪問地址爲 http://ip:port/actuator/nacos-discovery

目的:每個往nacos服務器註冊的服務器都會有這一個服務。nacos定時向每個服務器發送http://ip:port/actuator/nacos-discovery請求,來判斷該服務器是否還處於健康狀態;

經過瀏覽器訪問 http://localhost:8081/actuator/nacos-discovery 你會在瀏覽器上看到

  

 

 

附:Nacos Starter 更多配置項信息

配置項 Key 默認值 說明
服務端地址 spring.cloud.nacos.discovery.server-addr Nacos Server 啓動監聽的ip地址和端口
服務名 spring.cloud.nacos.discovery.service ${spring.application.name} 給當前的服務命名
權重 spring.cloud.nacos.discovery.weight 1 取值範圍 1 到 100,數值越大,權重越大
網卡名 spring.cloud.nacos.discovery.network-interface 當IP未配置時,註冊的IP爲此網卡所對應的IP地址,若是此項也未配置,則默認取第一塊網卡的地址
註冊的IP地址 spring.cloud.nacos.discovery.ip 優先級最高
註冊的端口 spring.cloud.nacos.discovery.port -1 默認狀況下不用配置,會自動探測
命名空間 spring.cloud.nacos.discovery.namespace 經常使用場景之一是不一樣環境的註冊的區分隔離,例如開發測試環境和生產環境的資源(如配置、服務)隔離等。
AccessKey spring.cloud.nacos.discovery.access-key 當要上阿里雲時,阿里雲上面的一個雲帳號名
SecretKey spring.cloud.nacos.discovery.secret-key 當要上阿里雲時,阿里雲上面的一個雲帳號密碼
Metadata spring.cloud.nacos.discovery.metadata 使用 Map 格式配置,用戶能夠根據本身的須要自定義一些和服務相關的元數據信息
日誌文件名 spring.cloud.nacos.discovery.log-name  
接入點 spring.cloud.nacos.discovery.enpoint UTF-8 地域的某個服務的入口域名,經過此域名能夠動態地拿到服務端地址
是否集成 Ribbon ribbon.nacos.enabled true 通常都設置成 true 便可

 

四、建立服務消費者

概述

  服務消費者的建立與服務提供者大同小異,這裏採用最原始的一種方式,即顯示的使用 LoadBalanceClient 和 RestTemplate 結合的方式來訪問。

POM

  建立一個工程名爲 hello-spring-cloud-alibaba-nacos-consumer 的服務消費者項目,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">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>com.funtl</groupId>
        <artifactId>hello-spring-cloud-alibaba-dependencies</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <relativePath>../hello-spring-cloud-alibaba-dependencies/pom.xml</relativePath>
    </parent>

    <artifactId>hello-spring-cloud-alibaba-nacos-consumer</artifactId>
    <packaging>jar</packaging>

    <name>hello-spring-cloud-alibaba-nacos-consumer</name>
    <url>http://www.funtl.com</url>
    <inceptionYear>2018-Now</inceptionYear>

    <dependencies>
        <!-- Spring Boot Begin -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Spring Boot End -->

        <!-- Spring Cloud Begin -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- Spring Cloud End -->
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.funtl.hello.spring.cloud.alibaba.nacos.consumer.NacosConsumerApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Application

package com.funtl.hello.spring.cloud.alibaba.nacos.consumer;

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

@SpringBootApplication
@EnableDiscoveryClient
public class NacosConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(NacosConsumerApplication.class, args);
    }
}

Configuration

  建立一個名爲 NacosConsumerConfiguration 的 Java 配置類,主要做用是爲了注入 RestTemplate

package com.funtl.hello.spring.cloud.alibaba.nacos.consumer.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration                                //該註解至關於spring-context.mxl
public class NacosConsumerConfiguration {

    @Bean                                     //至關於在xml中寫入<bean id="RestTemplate" class="org.springframework.web.client"></beam>
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

Controller

建立一個名爲 NacosConsumerController 測試用的 Controller

package com.funtl.hello.spring.cloud.alibaba.nacos.consumer.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class NacosConsumerController {

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @Autowired
    private RestTemplate restTemplate;

    @Value("${spring.application.name}")     //能夠直接讀取到配置文件中的屬性
    private String appName;

    @GetMapping(value = "/echo/app/name")
    public String echo() {
        //使用 LoadBalanceClient 和 RestTemplate 結合的方式來訪問
        ServiceInstance serviceInstance = loadBalancerClient.choose("nacos-provider");   //nacos服務器中註冊的服務器名字
        String url = String.format("http://%s:%s/echo/%s", serviceInstance.getHost(), serviceInstance.getPort(), appName); //nacos-provider服務器的ip:端口
        return restTemplate.getForObject(url, String.class);
    }
}

application.yml

spring:
  application:
    name: nacos-consumer
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

server:
  port: 9091

management:
  endpoints:
    web:
      exposure:
        include: "*"

啓動工程

經過瀏覽器訪問 http://localhost:8848/nacos,即 Nacos Server 網址

你會發現多了一個名爲 nacos-consumer 的服務

這時打開 http://localhost:9091/echo/app/name ,你會在瀏覽器上看到:

Hello Nacos Discovery nacos-consumer

服務的端點檢查測試

經過瀏覽器訪問 http://localhost:9091/actuator/nacos-discovery 你會在瀏覽器上看到:

 

 

五、建立服務消費者(Feign)

POM

建立一個工程名爲 hello-spring-cloud-alibaba-nacos-consumer-feign 的服務消費者項目,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">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>com.funtl</groupId>
        <artifactId>hello-spring-cloud-alibaba-dependencies</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <relativePath>../hello-spring-cloud-alibaba-dependencies/pom.xml</relativePath>
    </parent>

    <artifactId>hello-spring-cloud-alibaba-nacos-consumer-feign</artifactId>
    <packaging>jar</packaging>

    <name>hello-spring-cloud-alibaba-nacos-consumer-feign</name>
    <url>http://www.funtl.com</url>
    <inceptionYear>2018-Now</inceptionYear>

    <dependencies>
        <!-- Spring Boot Begin -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Spring Boot End -->

        <!-- Spring Cloud Begin -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- Spring Cloud End -->
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.funtl.hello.spring.cloud.alibaba.nacos.consumer.feign.NacosConsumerFeignApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

主要增長了 org.springframework.cloud:spring-cloud-starter-openfeign 依賴

Application

經過 @EnableFeignClients 註解開啓 Feign 功能

package com.funtl.hello.spring.cloud.alibaba.nacos.consumer.feign;

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

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class NacosConsumerFeignApplication {
    public static void main(String[] args) {
        SpringApplication.run(NacosConsumerFeignApplication.class, args);
    }
}

建立 Feign 接口

經過 @FeignClient("服務名") 註解來指定調用哪一個服務。代碼以下:

package com.funtl.hello.spring.cloud.alibaba.nacos.consumer.feign.service;

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

@FeignClient(value = "nacos-provider")
public interface EchoService {

    @GetMapping(value = "/echo/{message}")       //調用provide提供的接口
    String echo(@PathVariable("message") String message);
}

Controller

package com.funtl.hello.spring.cloud.alibaba.nacos.consumer.feign.controller;

import com.funtl.hello.spring.cloud.alibaba.nacos.consumer.feign.service.EchoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class NacosConsumerFeignController {

    @Autowired
    private EchoService echoService;

    @GetMapping(value = "/echo/hi")
    public String echo() {
        return echoService.echo("Hi Feign");
    }
}

application.yml

spring:
  application:
    name: nacos-consumer-feign
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

server:
  port: 9092

management:
  endpoints:
    web:
      exposure:
        include: "*"

啓動工程

經過瀏覽器訪問 http://localhost:8848/nacos,即 Nacos Server 網址

你會發現多了一個名爲 nacos-consumer-feign 的服務

這時打開 http://localhost:9092/echo/hi ,你會在瀏覽器上看到:

Hello Nacos Discovery Hi Feign

測試負載均衡

  • 啓動多個 consumer-provider 實例,效果圖以下:

  • 修改 consumer-provider 項目中的 Controller 代碼,用於肯定負載均衡生效
package com.funtl.hello.spring.cloud.alibaba.nacos.provider;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@EnableDiscoveryClient
public class NacosProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(NacosProviderApplication.class, args);
    }

    @Value("${server.port}")
    private String port;

    @RestController
    public class EchoController {
        @GetMapping(value = "/echo/{message}")
        public String echo(@PathVariable String message) {
            return "Hello Nacos Discovery " + message + " i am from port " + port;
        }
    }
}
  • 在瀏覽器上屢次訪問 http://localhost:9092/echo/hi ,瀏覽器交替顯示:
Hello Nacos Discovery Hi Feign i am from port 8081
Hello Nacos Discovery Hi Feign i am from port 8082
相關文章
相關標籤/搜索