主頁 > 後端開發 > 學習一下 SpringCloud (六)-- 注冊中心與配置中心 Nacos、網關 Gateway

學習一下 SpringCloud (六)-- 注冊中心與配置中心 Nacos、網關 Gateway

2021-04-01 17:34:18 後端開發

(1) 相關博文地址:

學習一下 SpringCloud (一)-- 從單體架構到微服務架構、代碼拆分(maven 聚合): https://www.cnblogs.com/l-y-h/p/14105682.html
學習一下 SpringCloud (二)-- 服務注冊中心 Eureka、Zookeeper、Consul、Nacos :https://www.cnblogs.com/l-y-h/p/14193443.html
學習一下 SpringCloud (三)-- 服務呼叫、負載均衡 Ribbon、OpenFeign : https://www.cnblogs.com/l-y-h/p/14238203.html
學習一下 SpringCloud (四)-- 服務降級、熔斷 Hystrix、Sentinel : https://www.cnblogs.com/l-y-h/p/14364167.html    
學習一下 SpringCloud (五)-- 配置中心 Config、訊息總線 Bus、鏈路追蹤 Sleuth、配置中心 Nacos : https://www.cnblogs.com/l-y-h/p/14447473.html

(2)代碼地址:

https://github.com/lyh-man/SpringCloudDemo

 

一、了解一下 SpringCloud Alibaba

1、SpringCloudAlibaba

(1)簡單說明

【說明:】
    通過前面幾篇博客的介紹,已對 SpringCloud 部分框架有了一些認識,比如: Eureka、Ribbon、Hystrix、Config、Bus 等,
    但這些框架都有類似的問題:進入了維護模式 或者 功能不完善(使用場景有限,無法很好地適應新需求)
注:
    模塊置于維護模式意味著 Spring Cloud 團隊不再向模塊添加新功能,僅修復攔截器漏洞和安全問題,
    
    SpringCloud 版本迭代速度挺快的,這就導致了一個問題: 一些舊版本出現的問題還未解決就推出了一個新的版本,
    而某模塊進入了維護模式,即不再開發新功能,其使用價值有限,使用人數也就逐漸減少,相當于 打入冷宮,難有翻身余地,
    
    一個舊技術的沒落,必定有一個新技術取而代之,
    而 SpringCloudAlibaba 就是這個新技術之一,有必要重點學習一下,    

 

 

 

(2)SpringCloudAlibaba

【SpringCloudAlibaba:】
    Spring Cloud Alibaba 致力于提供微服務開發的一站式解決方案,
    此專案包含開發分布式應用微服務的必需組件,方便開發者通過 Spring Cloud 編程模型輕松使用這些組件來開發分布式應用服務,
    依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以將 Spring Cloud 應用接入阿里微服務解決方案,通過阿里中間件來迅速搭建分布式應用系統,

【相關地址:】
    https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md
    https://spring-cloud-alibaba-group.github.io/github-pages/hoxton/en-us/index.html
    https://github.com/alibaba/spring-cloud-alibaba/wiki
    
【版本管理:】
    當前 Spring Cloud Alibaba 最新版本為 2.2.5.RELEASE,
    其推薦對應 Spring Cloud 版本為 Spring Cloud Hoxton.SR8,
    其推薦對應 Spring Boot 版本為 2.3.2.RELEASE,
可參考:
    https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

 

 

 

(3)引入依賴
  使用 SpringCloudAlibaba 與使用 SpringCloud 類似,一般都在父工程的 pom.xml 檔案中通過 <dependencyManagement> 標簽進行版本管理,然后在使用其組件時,直接引入相關組件依賴,無需管理版本,
  當然直接引入相關組件依賴 并 指定版本號的方式亦可,

【在父工程中管理版本:】
<properties>
    <spring.cloud.alibaba.version>2.2.5.RELEASE</spring.cloud.alibaba.version>
</properties>

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

 

2、SpringCloudAlibaba 主要功能 與 實作組件

(1)SpringCloudAlibaba 主要功能 與 實作組件

【功能與實作組件:】
服務限流降級:
    基本說明:
        默認支持 WebServlet、WebFlux, OpenFeign、RestTemplate、Spring Cloud Gateway, Zuul, Dubbo 和 RocketMQ 限流降級功能的接入,
        可以在運行時通過控制臺實時修改限流降級規則,還支持查看限流降級 Metrics 監控,
    實作組件:
        Sentinel: 把流量作為切入點,從流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩定性,
        
服務注冊與發現:
    基本說明:
        適配 Spring Cloud 服務注冊與發現標準,默認集成了 Ribbon 的支持,
    實作組件:
        Nacos: 一個更易于構建云原生應用的動態服務發現和服務管理平臺,
        
分布式配置管理:
    基本說明:
        支持分布式系統中的外部化配置,配置更改時自動重繪,
    實作組件:    
        Nacos: 一個更易于構建云原生應用的配置管理平臺,
        
訊息驅動能力:
    基本說明:
        基于 Spring Cloud Stream 為微服務應用構建訊息驅動能力,
    實作組件:    
        RocketMQ: 一款開源的分布式訊息系統,基于高可用分布式集群技術,提供低延時的、高可靠的訊息發布與訂閱服務,

分布式事務:
    基本說明:
        使用 @GlobalTransactional 注解, 高效并且對業務零侵入地解決分布式事務問題,
    實作組件:
        Seata: 阿里巴巴開源產品,一個易于使用的高性能微服務分布式事務解決方案,
        
阿里云物件存盤:
    基本說明:
        阿里云提供的海量、安全、低成本、高可靠的云存盤服務,支持在任何應用、任何時間、任何地點存盤和訪問任意型別的資料,
    實作組件:
        Alibaba Cloud OSS: 阿里云物件存盤服務(Object Storage Service,簡稱 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存盤服務,您可以在任何應用、任何時間、任何地點存盤和訪問任意型別的資料,
        
分布式任務調度:
    基本說明:
        提供秒級、精準、高可靠、高可用的定時(基于 Cron 運算式)任務調度服務,同時提供分布式的任務執行模型,如網格任務,網格任務支持海量子任務均勻分配到所有 Worker(schedulerx-client)上執行,
    實作組件:    
        Alibaba Cloud SchedulerX: 阿里中間件團隊開發的一款分布式任務調度產品,提供秒級、精準、高可靠、高可用的定時(基于 Cron 運算式)任務調度服務,

阿里云短信服務:
    基本說明:
        覆寫全球的短信服務,友好、高效、智能的互聯化通訊能力,幫助企業迅速搭建客戶觸達通道,
    實作組件:
        Alibaba Cloud SMS: 覆寫全球的短信服務,友好、高效、智能的互聯化通訊能力,幫助企業迅速搭建客戶觸達通道,    

 

(2)開發中常使用的技術搭配

【開發中使用的技術:】
    在平時開發中使用的技術搭配,我一般采用一下方案:
SpringCloud:
    OpenFeign:   宣告式 HTTP 客戶端(即 遠程服務呼叫),
    Ribbon:      負載均衡(OpenFeign 中已集成,無需單獨引入),
    Gateway:     API 網關,
    Sleuth:      分布式鏈路追蹤(即 請求呼叫鏈監控),
    
SpringCloudAlibaba:
    Nacos:      注冊中心 以及 配置中心(即 服務注冊、發現  以及  動態配置管理),
    Sentinel:   服務容錯(即限流、降級、熔斷),
    Seata:      解決分布式事務,
    
注:
    通過前面幾篇博客的學習,知道了 OpenFeign、Ribbon、Sleuth、Sentinel 相關操作,
    OpenFeign、Ribbon 相關操作詳見:https://www.cnblogs.com/l-y-h/p/14238203.html
    Sleuth 相關操作詳見:https://www.cnblogs.com/l-y-h/p/14447473.html#_label4
    Sentinel 相關操作詳見:https://www.cnblogs.com/l-y-h/p/14364167.html#_label2
    
下面將逐個學習 Nacos、Gateway、Seata,

 

二、服務注冊中心、配置中心 -- Nacos

1、什么是 Nacos?

(1)Nacos

【Nacos:】
    Nacos 即 Dynamic Naming and Configuration Service(動態命名與配置服務),由 Naming 前兩個字母,Configuration 前兩個字母,以及 Service 首字母組成,
    Nacos 是一個更易于構建云原生應用的動態服務發現、配置管理 以及 服務管理平臺,
簡單的理解:
    Nacos 就是 注冊中心 + 配置中心, 
    即 Nacos = Eureka + Config + Bus,
    
【相關地址:】
    https://nacos.io/zh-cn/index.html
    https://github.com/alibaba/nacos

 

(2)如何使用 Nacos

【如何使用 Nacos:】
    Nacos 分為 Server、Client,其中 Server 作為注冊中心以及配置中心,可以獨立部署,
    而想要使用 Nacos,僅需在 微服務當中引入 client 相關依賴即可,
其中:
    Server 最新版本為 1.4.1,根據實際情況可以自行選擇版本,
    使用注冊中心功能,需要引入 spring-cloud-starter-alibaba-nacos-discovery 依賴,
    使用配置中心功能,需要引入 spring-cloud-starter-alibaba-nacos-config 依賴,
注:
    下載地址:https://github.com/alibaba/nacos/releases/download/1.4.1/nacos-server-1.4.1.tar.gz

 

2、安裝 Nacos Server 單機版(Linux 直接下載并啟動、持久化資料到 MySQL 8)

(1)說明:
  Nacos 默認使用內嵌資料庫(Derby)實作資料的存盤,一般使用 單機版 Nacos Server 無需額外配置持久化操作,直接啟動即可,
  但大型的專案中,Nacos Server 一般采用集群方式部署,若仍使用默認資料庫進行資料存盤,那么各個 Nacos Server 之間的資料一致性就是一個頭疼的問題, Nacos 支持持久化資料到 MySQL 中,集群中所有節點共享 MySQL 資料源,從而保證資料一致性,

(2)下載、并解壓 nacos-server

【下載:】
wget https://github.com/alibaba/nacos/releases/download/1.4.1/nacos-server-1.4.1.tar.gz

【解壓:】
tar -axvf nacos-server-1.4.1.tar.gz

 

(3)直接啟動
  未進行持久化配置,使用默認的 Derby 進行資料存盤,

【進入解壓后的 bin 目錄:】
    cd ./nacos/bin

【以單機模式啟動:】
    sh startup.sh -m standalone
注:
    通過執行 sh shutdown.sh 可以關閉 Nacos,

【登錄 Nacos:】
    默認通過 8848 埠可以訪問 Nacos,
    賬號、密碼默認均為 nacos
比如:
    http://120.26.184.41:8848/nacos

 

 

 

 

 

 

(4)持久化資料到 MySQL 中
Step1:
  連接資料庫,并構建資料表,

【構建資料表:】
    進入解壓后的 nacos 的 conf 目錄,可以看到有 nacos-mysql.sql 檔案,
    連接上 MySQL,新建一個資料庫(nacos_config),并執行 nacos-mysql.sql 檔案中的 SQL 陳述句,
注:
    可以直接使用官方提供的 nacos-mysql.sql 檔案,
    https://github.com/alibaba/nacos/blob/master/distribution/conf/nacos-mysql.sql

注:
    MySQL 請自行安裝,此處不贅述,
可參考如下博客(僅供參考,長時間未更新,可能會出現一些問題):
    Windows 安裝 MySQL:https://www.cnblogs.com/l-y-h/p/11700113.html
    Linux 安裝 MySQL:https://www.cnblogs.com/l-y-h/p/12576633.html
    Docker 安裝 MySQL:https://www.cnblogs.com/l-y-h/p/12622730.html#_label5
    Docker Compose 安裝 MySQL:https://www.cnblogs.com/l-y-h/p/12622730.html#_label8_2

 

 

 

 

 

 

Step2:
  配置 nacos 與 mysql 連接資訊,

【配置資料源資訊:】
    同樣在 conf 目錄下,有一個 application.properties 檔案,
    編輯該檔案,在檔案末尾添加如下資料源資訊(根據 MySQL 資訊自行修改):

spring.datasource.platform=mysql

db.num=1
db.url.0=jdbc:mysql://120.26.184.41:3306/nacos_config?useUnicode=true&characterEncoding=utf8
db.user=root
db.password=123456

 

 

 

Step3:
  重新啟動 nacos,再次登錄nacos (http://120.26.184.41:8848/nacos) ,并新增一個組態檔,
  此時在 MySQL 中可以看到相關資訊,

 

 

 

3、安裝 Nacos Server 單機版(docker-compose 啟動,持久化資料到 MySQL 8)

(1)說明
  若需持久化到 mysql,同樣也得在 mysql 中生成相應的表,相關 SQL 檔案可以參考上面 持久化操作(此處省略),
  可以直接使用官方提供的 MySQL 鏡像,nacos/nacos-mysql:8.0.16,其有一個資料庫 nacos_devtest 已包含了相關的表結構,

【nacos-docker 相關鏈接:】
    https://nacos.io/zh-cn/docs/quick-start-docker.html
    https://github.com/nacos-group/nacos-docker

【docker-compose 使用參考鏈接:】
    https://www.cnblogs.com/l-y-h/p/12622730.html#_label8_2
    
【nacos-mysql SQL:】
    https://github.com/alibaba/nacos/blob/master/distribution/conf/nacos-mysql.sql

 

 

 

(2)使用已有的 mysql 檔案,
  簡化操作,直接使用上面的 mysql,
  若需啟動新的 mysql,需要手動執行 SQL,用于創建 nacos 所需相關表結構,
注:
  https://github.com/alibaba/nacos/blob/master/distribution/conf/nacos-mysql.sql

【docker-compose.yml】
version: '3.7'
services:
  nacos:
    image: nacos/nacos-server:1.4.1
    container_name: nacos
    restart: always
    environment:
      - MODE=standalone
      - TZ=Asia/Shanghai
      - SPRING_DATASOURCE_PLATFORM=mysql
      - MYSQL_SERVICE_HOST=120.26.184.41
      - MYSQL_SERVICE_PORT=3306
      - MYSQL_SERVICE_DB_NAME=nacos_config
      - MYSQL_SERVICE_USER=root
      - MYSQL_SERVICE_PASSWORD=123456
      - JVM_XMS=50m
      - JVM_MMS=50m
    volumes:
      - ./standalone-logs/:/home/nacos/logs
    ports:
      - 8848:8848

相關引數設定如下(對于高版本 Nacos 引數有些許不同):
  NACOS_SERVER_PORT 需要改為 NACOS_APPLICATION_PORT
  多個帶有 MASTER 的引數需要去掉 MASTER,比如:MYSQL_MASTER_SERVICE_HOST 需要改為 MYSQL_SERVICE_HOST,

 

 

 

通過 docker-compose up -d 啟動后,訪問 http://120.26.184.41:8848/nacos,
成功登錄后,可以看到之前配置的檔案,即啟動 nacos 成功,

 

 

 

(3)使用 nacos 官方提供的 mysql 鏡像進行持久化操作,
注意:
  此處使用的 nacos 鏡像為:nacos/nacos-server:1.4.1,
  使用的 mysql 鏡像為:nacos/nacos-mysql:8.0.16,

坑:
  執行 docker-compose up -d 后,訪問 nacos,若訪問 nacos 失敗時,可以查看日志檔案 start.out,若出現 Caused by: java.lang.IllegalStateException: No DataSource set 的問題,可以重新啟動一下容器(docker-compose restart),若仍然出錯,則將 nacos-mysql:8.0.16 更換為 nacos-mysql:5.7 ,

【docker-compose.yml】
version: '3.7'
services:
  mysql:
    container_name: nacos-mysql
    image: nacos/nacos-mysql:8.0.16
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=nacos_devtest
      - MYSQL_USER=nacos
      - MYSQL_PASSWORD=nacos
    volumes:
      - ./mysql/data:/var/lib/mysql
      - ./mysql/log:/var/log/mysql
    ports:
      - "3307:3306"
  nacos:
    image: nacos/nacos-server:1.4.1
    container_name: nacos
    restart: always
    environment:
      - MODE=standalone
      - TZ=Asia/Shanghai
      - SPRING_DATASOURCE_PLATFORM=mysql
      - MYSQL_SERVICE_HOST=120.26.184.41
      - MYSQL_SERVICE_PORT=3307
      - MYSQL_SERVICE_DB_NAME=nacos_devtest
      - MYSQL_SERVICE_USER=root
      - MYSQL_SERVICE_PASSWORD=root
      - JVM_XMS=50m
      - JVM_MMS=50m
    volumes:
      - ./standalone-logs/:/home/nacos/logs
    depends_on:
      - mysql
    ports:
      - 8848:8848

 

4、Nacos 作為 服務注冊中心(服務注冊與發現)

(1)說明:

【說明:】
    通過前面的操作,已經成功啟動了 Nacos Server,接下來整合 Nacos Client 即可,
    此處的 Nacos Server 為注冊中心,
    新建三個模塊 nacos_client_7100、nacos_client_7101、nacos_client_7102 用于演示服務提供者,
    新建一個模塊 nacos_client_consumer 用于演示服務消費者(使用 OpenFeign 呼叫服務),
    Nacos 已集成 Ribbon 并提供負載均衡,
注:
    此處模塊創建僅 描述 主要流程,不詳細截圖(可參考之前的博客),

【參考鏈接:】
    https://nacos.io/zh-cn/docs/quick-start-spring-cloud.html
    https://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-discovery
    https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme-zh.md

 

(2)新建模塊 nacos_client_7100
Step1:
  修改 pom.xml,引入 nacos-discovery 依賴,

【引入 Nacos 依賴:】
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

 

 

 

Step2:
  修改 application.yml,配置 nacos,

【application.yml】
server:
  port: 7100

spring:
  application:
    name: nacos-client
  cloud:
    nacos:
      discovery:
        # 配置 nacos 地址
        server-addr: 120.26.184.41:8848

 

 

 

Step3:
  撰寫一個測驗 controller,簡單測驗一下是否正常,

【TestController】
package com.lyh.springcloud.nacos_client_7100.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.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RequestMapping("/nacos")
@RestController
public class TestController {
    @Value("${server.port}")
    private String port;

    @Value("${spring.application.name}")
    private String name;

    @Autowired
    private DiscoveryClient discoveryClient;

    @RequestMapping("/info")
    public String getInfo() {
        return name + "-" + port;
    }

    @GetMapping("/discovery")
    public Map<String, List<ServiceInstance>> discovery() {
        // 獲取服務名串列
        List<String> servicesList = discoveryClient.getServices();

        // 根據服務名 獲取 每個服務名下的 各個服務的資訊
        Map<String, List<ServiceInstance>> map = new HashMap<>();
        servicesList.stream().forEach(service -> {
            map.put(service, discoveryClient.getInstances(service));
        });

        return map;
    }
}

 

 

 

Step4:
  啟動當前服務,
  在啟動類上添加 @EnableDiscoveryClient 注解(不添加貌似也沒啥影響),

 

 

 

Step5:
  訪問 http://120.26.184.41:8848/nacos/
  登陸后,選擇 “服務管理” ==》“服務串列”,即可看到當前有哪些服務注冊進來了,

 

 

 訪問 http://localhost:7100/nacos/discovery

 

 

 訪問 http://localhost:7100/nacos/info

 

 

 

(3)新建模塊 nacos_client_7101、nacos_client_7102
  這兩個模塊與 nacos_client_7100 類似,僅埠號不同(創建程序此處省略),
  啟動服務后,再次查看 nacos 控制臺,可以看到出現 3 個實體,

 

 

 

 

 

 

(4)新建模塊 nacos_client_consumer
  nacos-discovery 已集成 Ribbon,默認實作負載均衡方式為 輪詢,

 

 

 

Step1:
  引入 nacos-discovery 、openfeign 依賴,

【依賴:】
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

 

 

 

Step2:
  修改 application.yml 檔案,

【application.yml】
server:
  port: 7200

spring:
  application:
    name: nacos-client-consumer
  cloud:
    nacos:
      discovery:
        # 配置 nacos 地址
        server-addr: 120.26.184.41:8848

 

 

 

Step3:
  撰寫 openfeign 介面,呼叫 nacos_client 服務,

【ConsumerFeign】
package com.lyh.springcloud.nacos_client_consumer.service;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;

@Component
@FeignClient(name = "nacos-client")
public interface ConsumerFeign {

    @RequestMapping("/nacos/info")
    String getInfo();
}

 

 

 

Step4:
  撰寫 controller,用于測驗,

【TestController】
package com.lyh.springcloud.nacos_client_consumer.controller;

import com.lyh.springcloud.nacos_client_consumer.service.ConsumerFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/consumer")
@RestController
public class TestController {

    @Autowired
    private ConsumerFeign consumerFeign;

    @RequestMapping("/info")
    public String getInfo() {
        return consumerFeign.getInfo();
    }
}

 

 

 

Step5:
  簡單測驗一下 負載均衡,

 

 

 

訪問:http://localhost:7200/consumer/info  ,默認輪詢呼叫 nacos-client 服務,

 

 

 

5、Nacos 作為配置中心(自動重繪)

(1)說明

【說明:】
    前面使用 Nacos Server 作為注冊中心,此處作為 配置中心,
    修改 nacos_client_7100 模塊作為演示,
注:
    Nacos 作為配置中心時,用法與 Config 很類似,
    Config 使用可參考:https://www.cnblogs.com/l-y-h/p/14447473.html#_label1

【參考鏈接:】
    https://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-config
    https://github.com/alibaba/spring-cloud-alibaba/tree/master/spring-cloud-alibaba-examples/nacos-example/nacos-config-example

 

(2)修改 nacos_client_7100
Step1:
  添加 nacos-config 依賴,

【依賴:】
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

 

 

 

Step2:
  添加 bootstrap.yml 檔案,并進行配置中心相關設定,
  修改 application.yml 檔案,修改其環境為 dev,
注:
  組態檔默認拼接為:${spring.cloud.nacos.prefix} - ${spring.profiles.active} . ${spring.cloud.nacos.file-extension}
  spring.cloud.nacos.prefix 默認為 spring.application.name,
  spring.profiles.active 為當前環境(比如:dev、test、prod 等),
  spring.cloud.nacos.file-extension 為組態檔后綴名,一般為:yaml、properties,

下面組態檔,將會讀取配置中心中 nacos-client-config-dev.yml 檔案,

【bootstrap.yml】
server:
  port: 7100

spring:
  application:
    name: nacos-client-config
  cloud:
    nacos:
      discovery:
        # 配置 nacos server 地址(作為注冊中心)
        server-addr: 120.26.184.41:8848
      config:
        # 配置 nacos server 地址(作為配置中心)
        server-addr: 120.26.184.41:8848
        # 設定組態檔前綴,默認為 ${spring.application.name}
        prefix: ${spring.application.name}
        # 設定組態檔后綴名
        file-extension: yml
        
【application.yml】
spring:
  profiles:
    active: dev

config:
  info: ${spring.application.name}-${server.port}-${spring.profiles.active}

 

 

 

Step3:
  撰寫測驗 controller,用于測驗,
  需要添加 @RefreshScope 注解,用于自動重繪,

【TestConfigController】
package com.lyh.springcloud.nacos_client_7100.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/config")
@RestController
@RefreshScope
public class TestConfigController {

    @Value("${config.info}")
    private String configInfo;

    @GetMapping("/info")
    public String getInfo() {
        return configInfo;
    }
}

 

 

 

Step4:
  訪問:http://localhost:7100/config/info
  初始時,若 Nacos Server 中不存在組態檔,則會先加載本地 組態檔中的 config.info,

 

 

 在配置中心添加組態檔如下:

 

 

 

再次訪問,則獲取到的是配置中心最新的配置資訊,

 

 

 

6、Namespace、Group、DataID

(1)問題與解決:

【問題:】
    實際開發中,一個服務可能會對應多個配置環境(dev、test、prod 等),
    那么如何保證服務啟動時 能 讀取到 正確的 組態檔?
    
    一個大型的微服務系統中,存在很多服務,每個服務都有不同的配置環境,
    那么能否統一的、有規劃的對配置進行管理呢?
    
【解決:】
    Nacos 中 使用 命名空間(Namespace)、Group(分組)、DataID(組態檔 ID)對組態檔進行管理,

 

(2)Namespace、Group、DataID

【Namespace:】
Namespace 默認為 public,一般用于實作環境隔離,不同的命名空間是相互隔離的,
比如:
    現在有三個環境:開發、測驗、生產,則可以創建三個命名空間,每個命名空間對應一個環境,
    需要切換環境時,只需切換 命名空間 即可,

【Group:】
Group 默認為 DEFAULT_GROUP,通過一個有意義的字串對 配置集 或者 服務 進行分組,

【DataID:】
DataID 就是每個組態檔的唯一標識,

【簡單理解:】
    Namespace、Group、DataID 的關系可以理解成一個 檔案系統,
    Namespace 為最頂層的目錄,其可以包含多個 Group,
    Group 為 二級目錄,其可以包含多個 DataID,
    DataID 為 檔案名,
    Namespace + Group + DataID 組成組態檔的唯一標識,
注:
    Namespace 可以通過 spring.cloud.nacos.config.namespace 指定(在 bootstrap.yml 中指定,且為 命名空間的 id 值),
    Group 可以通過 spring.cloud.nacos.config.group 指定(在 bootstrap.yml 中指定),

 

 

 

(3)演示
Step1:
  修改 nacos_client_7100 組態檔如下,添加一個分組 TEST_GROUP,

 

 

 

Step2:
  訪問配置中心,查看當前組態檔串列,
  如下圖所示,僅有一個分組為 DEFAULT_GROUP 的組態檔,

 

 

 

Step3:
  訪問:http://localhost:7100/config/info
  由于配置中心中不存在 TEST_GROUP 分組的組態檔,所以加載本地組態檔資訊,

 

 

 

Step4:
  在配置中心添加一個 nacos-client-config-dev.yml 且分組為 TEST_GROUP 的檔案,

 

 

 

Step5:
  再次訪問 http://localhost:7100/config/info
  可以讀取到 分組為 TEST_GROUP 的 nacos-client-config-dev.yml 檔案中的資訊,

 

 

 

7、nacos 獲取配置的方式(配置共享)

(1)問題與解決

【問題:】
    通過前面的使用,已經知道最基本的 組態檔獲取方式為 ${spring.cloud.nacos.prefix} - ${spring.profiles.active} . ${spring.cloud.nacos.file-extension},
    若僅僅這么使用,只能獲取到配置中心的一個組態檔,
    當服務部署了集群后,每個服務對應一個組態檔,此時這些組態檔可能會出現很多重復的內容,
    服務出現變動時,可能需要修改每個組態檔,增加了無用的作業量,
    
    那么能否拆分組態檔,使部分組態檔可以共享?
    能否使服務同時獲取多個組態檔?
    
【解決:】
    nacos 提供了三種獲取組態檔的方式,
方式:
    A:通過內部相關規則自動生成相關的 Data Id 配置(${spring.cloud.nacos.prefix} - ${spring.profiles.active} . ${spring.cloud.nacos.file-extension}),
    B:通過 spring.cloud.nacos.config.extension-configs[n].data-id 的方式支持多個擴展 Data Id 的配置,
    C:通過 spring.cloud.nacos.config.shared-configs[n].data-id 支持多個共享 Data Id 的配置,
優先級:
    A > B > C
注:
    extension-configs、shared-configs 支持獲取多個組態檔(n 越大優先級越高),

 

(2)演示 extension-configs 使用
Step1:
  extension-configs 說明:

【extension-configs 說明:】
    extension-configs 型別為 List<NacosConfigProperties.Config>
Config:
    dataId   String 型別,即組態檔名(比如:config-dev.yml)
    group    String 型別,即分組名,默認為 DEFAULT_GROUP
    refresh  boolean 型別,是否具備自動重繪,默認為 false(修改組態檔不自動重繪)

 

Step2:
  修改 bootstrap.yml 、application.yml如下:

【bootstrap.yml】
server:
  port: 7100

spring:
  application:
    name: nacos-client-config
  cloud:
    nacos:
      discovery:
        # 配置 nacos server 地址(作為注冊中心)
        server-addr: 120.26.184.41:8848
      config:
        # 配置 nacos server 地址(作為配置中心)
        server-addr: 120.26.184.41:8848
        # 設定組態檔前綴,默認為 ${spring.application.name}
        prefix: ${spring.application.name}
        # 設定組態檔后綴名
        file-extension: yml
        extension-configs[0]:
          data-id: test-0-dev.yml
        extension-configs[1]:
          data-id: test-1-dev.yml
        extension-configs[2]:
          data-id: test-2-dev.yml
          group: DEFAULT_GROUP
          refresh: true

【application.yml】
spring:
  profiles:
    active: dev

config:
  info: ${spring.application.name}-${server.port}-${spring.profiles.active}
  test-0: test-0
  test-1: test-1
  test-2: test-2

 

 

 

Step3:
  修改 controller,獲取配置資訊,

package com.lyh.springcloud.nacos_client_7100.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/config")
@RestController
@RefreshScope
public class TestConfigController {

    @Value("${config.info}")
    private String configInfo;

    @Value("${config.test-0}")
    private String test0;

    @Value("${config.test-1}")
    private String test1;

    @Value("${config.test-2}")
    private String test2;

    @GetMapping("/test")
    public String test() {
        return test0 + " ---- " + test1 + " ---- " + test2;
    }

    @GetMapping("/info")
    public String getInfo() {
        return configInfo;
    }
}

 

 

 

 

Step4:
  訪問配置中心,查看當前配置串列,

 

 

 

Step5:
  訪問:http://localhost:7100/config/test
  由于配置串列為空,服務僅加載本地組態檔,

 

 

 

Step6:
  添加組態檔,

 

 

 

 

 

 

 

 

Step7:
  再次訪問:http://localhost:7100/config/test
  由于 test-0-dev.yml 以及 test-1-dev.yml 沒有配置自動重繪,所以值沒有正常變化,
  而 test-2-dev.yml 配置了自動重繪,其值正常變化,

 

 

 

(3)演示 shared-configs 使用
  shared-configs 用法 與 extension-configs 相同,區別是 extension-configs 優先級高于 shared-configs,(此處省略驗證步驟,參考上面 extension-configs 的使用)

【bootstrap.yml】
server:
  port: 7100

spring:
  application:
    name: nacos-client-config
  cloud:
    nacos:
      discovery:
        # 配置 nacos server 地址(作為注冊中心)
        server-addr: 120.26.184.41:8848
      config:
        # 配置 nacos server 地址(作為配置中心)
        server-addr: 120.26.184.41:8848
        # 設定組態檔前綴,默認為 ${spring.application.name}
        prefix: ${spring.application.name}
        # 設定組態檔后綴名
        file-extension: yml
        shared-configs[0]:
          data-id: test-0-dev.yml
        shared-configs[1]:
          data-id: test-1-dev.yml
        shared-configs[2]:
          data-id: test-2-dev.yml
          group: DEFAULT_GROUP
          refresh: true

 

8、docker-compose 部署 Nacos Server(偽集群版)

(1)說明:
  集群至少得有 3 個 Nacos Server 節點,節點多的話 可以搞個 Nginx 做個代理,
  有條件的可以搞三臺 云服務器 玩玩,沒條件的可以搞三臺 虛擬機 玩玩,
  想偷懶的可以直接在一臺服務器上啟動 三個 Nacos Server 節點(大坑,不建議做),
注:
  此處為了偷懶,使用 docker-compose 一次性啟動 mysql 以及3 個 Nacos 節點,相關的坑我也做了一些說明,鬼知道我為了解決這些坑經歷了什么 (=_=),

(2)Nacos 常用幾個日志檔案(此處以 偽集群版日志 進行舉例)

【判斷 nacos 是否正常啟,一般看下面幾個日志檔案:】
日志檔案:
    /home/nacos/logs/start.out            nacos 是否正常啟動
    /home/nacos/logs/nacos.log            nacos 執行程序中是否報錯
    /home/nacos/logs/naming-raft.log      nacos 選舉是否例外

【對于 start.out 檔案:】
若 Nacos 一直未啟動完成,一般會輸出:  
    Nacos is starting...
比如:
    2021-03-25 15:11:05,419 INFO Nacos is starting...
    
若 Nacos 啟動完成,一般會輸出:
    Nacos started successfully in cluster mode. use external storage
比如:
    2021-03-25 15:11:06,811 INFO Nacos started successfully in cluster mode. use external storage
    
【對于 naming-raft.log 檔案:】
若 Nacos 一直未選舉成功,其輸出日志如下:
   ERROR NACOS-RAFT vote failed: 500, url: http://120.26.184.41:8850/nacos/v1/ns/raft/vote
   ERROR NACOS-RAFT vote failed: 500, url: http://120.26.184.41:8851/nacos/v1/ns/raft/vote
   WARN [IS LEADER] no leader is available now!

若選舉成功,輸出日志為:
2021-03-26 09:46:49,896 INFO received approve from peer: {"ip":"120.26.184.41:8850","voteFor":"120.26.184.41:8849","term":5,"leaderDueMs":19506,"heartbeatDueMs":3500,"state":"FOLLOWER"}
2021-03-26 09:46:49,897 INFO 120.26.184.41:8849 has become the LEADER
2021-03-26 09:46:49,898 INFO received approve from peer: {"ip":"120.26.184.41:8851","voteFor":"120.26.184.41:8849","term":5,"leaderDueMs":17941,"heartbeatDueMs":3500,"state":"FOLLOWER"}

【對于 nacos.log 檔案:】
當 Nacos 選舉例外時,可能會輸出:
    java.lang.IllegalStateException: can not find peer: 172.22.0.5:8848

若沒有錯誤日志輸出,輸出如下日志,可以認為啟動正常:
2021-03-26 09:34:08,199 INFO Started Nacos in 94.251 seconds (JVM running for 100.9)
2021-03-26 09:34:08,199 INFO Nacos Log files: /home/nacos/logs
2021-03-26 09:34:08,208 INFO Nacos Log files: /home/nacos/conf
2021-03-26 09:34:08,208 INFO Nacos Log files: /home/nacos/data
2021-03-26 09:34:08,209 INFO Nacos started successfully in cluster mode. use external storage
2021-03-26 09:34:08,873 INFO Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-03-26 09:34:08,873 INFO Initializing Servlet 'dispatcherServlet'
2021-03-26 09:34:08,954 INFO Completed initialization in 81 ms

 

(3)偽集群版(大坑)
Step1:撰寫 docker-compose.yml 檔案
  與單機版 docker-compose.yml 類似,
  多了引數 NACOS_SERVERS、NACOS_APPLICATION_PORT,
  修改了 JVM_XMS 、JVM_MMS 等引數,
  修改了 nacos-mysql 版本,
  修改了 nacos-server 版本,
注意:
  添加了 NACOS_APPLICATION_PORT 后,需要修改相應的埠映射 ports,
  添加了 NACOS_SERVERS 后,設定多節點可以使用 逗號 或者 空格 隔開,
  JVM_XMS 等引數設定過小時,Nacos 可能跑不起來(適量調大一點),
  若你嘗試過一切手段,配置均正常時,Nacos 仍然跑不起來 或者 選舉失敗,而在網上找不到任何解決辦法時,這邊建議你 更換 鏡像版本試一下 (=_=),鬼知道我試了多少次才解決的,


這邊使用的都是官方鏡像,可以自己手動生成鏡像,具體有些什么坑,請自行嘗試!!!

【docker-compose.yml】
version: '3.7'
services:
  mysql:
    container_name: nacos-cluster-mysql
    image: nacos/nacos-mysql:5.7
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=nacos_devtest
      - MYSQL_USER=nacos
      - MYSQL_PASSWORD=nacos
    volumes:
      - ./mysql/data:/var/lib/mysql
      - ./mysql/log:/var/log/mysql
    ports:
      - "3308:3306"
  nacos1:
    image: nacos/nacos-server:1.3.0
    container_name: nacos1
    restart: always
    environment:
      - NACOS_SERVERS=120.26.184.41:8849 120.26.184.41:8850 120.26.184.41:8851
      - NACOS_SERVER_IP=120.26.184.41
      - NACOS_APPLICATION_PORT=8849
      - TZ=Asia/Shanghai
      - SPRING_DATASOURCE_PLATFORM=mysql
      - MYSQL_SERVICE_HOST=120.26.184.41
      - MYSQL_SERVICE_PORT=3308
      - MYSQL_SERVICE_DB_NAME=nacos_devtest
      - MYSQL_SERVICE_USER=root
      - MYSQL_SERVICE_PASSWORD=root
      - JVM_XMS=100m
      - JVM_MMS=100m
    volumes:
      - ./cluster-logs/nacos1:/home/nacos/logs
    depends_on:
      - mysql
    ports:
      - 8849:8849
  nacos2:
    image: nacos/nacos-server:1.3.0
    container_name: nacos2
    restart: always
    environment:
      - NACOS_SERVERS=120.26.184.41:8849 120.26.184.41:8850 120.26.184.41:8851
      - NACOS_SERVER_IP=120.26.184.41
      - NACOS_APPLICATION_PORT=8850
      - TZ=Asia/Shanghai
      - SPRING_DATASOURCE_PLATFORM=mysql
      - MYSQL_SERVICE_HOST=120.26.184.41
      - MYSQL_SERVICE_PORT=3308
      - MYSQL_SERVICE_DB_NAME=nacos_devtest
      - MYSQL_SERVICE_USER=root
      - MYSQL_SERVICE_PASSWORD=root
      - JVM_XMS=100m
      - JVM_MMS=100m
    volumes:
      - ./cluster-logs/nacos2:/home/nacos/logs
    depends_on:
      - mysql
    ports:
      - 8850:8850
  nacos3:
    image: nacos/nacos-server:1.3.0
    container_name: nacos3
    restart: always
    environment:
      - NACOS_SERVERS=120.26.184.41:8849 120.26.184.41:8850 120.26.184.41:8851
      - NACOS_SERVER_IP=120.26.184.41
      - NACOS_APPLICATION_PORT=8851
      - TZ=Asia/Shanghai
      - SPRING_DATASOURCE_PLATFORM=mysql
      - MYSQL_SERVICE_HOST=120.26.184.41
      - MYSQL_SERVICE_PORT=3308
      - MYSQL_SERVICE_DB_NAME=nacos_devtest
      - MYSQL_SERVICE_USER=root
      - MYSQL_SERVICE_PASSWORD=root
      - JVM_XMS=100m
      - JVM_MMS=100m
    volumes:
      - ./cluster-logs/nacos3:/home/nacos/logs
    depends_on:
      - mysql
    ports:
      - 8851:8851

      
【巨坑:】
    想偷懶,卻掉進了個大坑(沒解決),特此記錄一下,有時間再仔細研究,
情景再現:
    在阿里云服務器上,想使用 docker-compose 一次性啟動三個 Nacos Server 以及 mysql,結果一直啟動失敗,
坑一:    
    nacos-mysql:8.0.16 無法啟動,更換成 nacos-mysql:5.7 之后正常啟動,
    但若 nacos-mysql:8.0.16 是事先就啟動好的(即不跟隨 Nacos Server 啟動),那么連接是正常的,
    為什么會出現這種情況,沒有仔細研究,此處僅簡單記錄一下可能存在的問題,

坑二:
    訪問 http://120.26.184.41:8850/nacos,可以成功登錄進去,
    但點擊 “集群管理” =》 “節點串列”,依次點擊 “節點元資料”,可以發現其 "state" 均為 "CANDIDATE",
    即 集群中三個節點 并未選舉成功,未成功選舉出 LEADER、FOLLOWER,
    
坑三:
    集群節點 "state" 均為 "FOLLOWER",沒有 "LEADER",選舉仍然失敗,
    出現了 8848 埠,貌似其被選擇為 LEADER,
    
坑四:
    當前覺得你的配置沒有問題了,但是 選舉依然失敗,這邊建議你更換一下鏡像看看,
    此處 nacos/nacos-server:1.4.1 選舉總是失敗,更換 nacos/nacos-server:1.3.0 之后沒問題了,
    具體原因沒有深入研究,此處僅記錄一下可能存在的問題,

 

Step2:填坑記錄一:
  將 nacos-mysql:8.0.16 鏡像替換為 nacos-mysql:5.7 后,重新啟動即可,

 

 

 

 

 

 

Step3:填坑記錄二:
  若在控制臺頁面中,看見節點 “state” 均為 “CANDIDATE”,這是選舉出問題了,可以查看 nacos 日志(naming-raft.log、nacos.log),

【nacos.log 錯誤日志為:(如下兩句陳述句回圈出現)】
    java.lang.IllegalStateException: can not find peer: 172.22.0.3:8848
    java.lang.IllegalStateException: can not find peer: 172.22.0.5:8848
    
【naming-raft.log 錯誤日志為:】
    ERROR NACOS-RAFT vote failed: 500, url: http://120.26.184.41:8850/nacos/v1/ns/raft/vote
    ERROR NACOS-RAFT vote failed: 500, url: http://120.26.184.41:8851/nacos/v1/ns/raft/vote
    WARN [IS LEADER] no leader is available now!
    
【分析:】
    通過 nacos.log 的 ip 地址,可以猜測當前 nacos 讀取到的是內網 IP,
    而集群串列中不存在這個 IP,所以無法連接到其余 節點(無法通信),進而選舉失敗,
    
【解決:】
    既然獲取不到 IP 地址,那就手動輸入 IP 地址,
    在環境變數中,通過 NACOS_SERVER_IP 指定當前主機的 IP 即可,
    比如: - NACOS_SERVER_IP=120.26.184.41

 

 

 

 

 

 

 

 

 

Step4:填坑記錄三
  通過上面截圖,可以看到三個節點狀態均從 "CANDIDATE" 變為了 "FOLLOWER",為什么沒有選舉出 "LEADER"?

【查看 naming-raft.log 日志如下:】
2021-03-25 17:45:09,770 INFO received approve from peer: {"ip":"120.26.184.41:8848","voteFor":"120.26.184.41:8848","term":9,"leaderDueMs":18440,"heartbeatDueMs":2000,"state":"FOLLOWER"}
2021-03-25 17:45:09,772 INFO received approve from peer: {"ip":"120.26.184.41:8848","voteFor":"120.26.184.41:8848","term":9,"leaderDueMs":18531,"heartbeatDueMs":5000,"state":"CANDIDATE"}
2021-03-25 17:45:09,788 INFO received approve from peer: {"ip":"120.26.184.41:8848","voteFor":"120.26.184.41:8848","term":9,"leaderDueMs":18671,"heartbeatDueMs":5000,"state":"FOLLOWER"}
2021-03-25 17:45:15,001 WARN [IS LEADER] no leader is available now!
2021-03-25 17:45:28,123 INFO vote 120.26.184.41:8848 as leader, term: 10

【分析:】
    通過日志可以看到貌似 120.26.184.41:8848 這個東西被選為了 LEADER,
    而實際上 我開放的是 8849、8850、8851 三個埠,但是這三個埠并沒有被訪問,

【解決:】
    默認埠號為 8848,既然獲取不到埠,那就手動設定埠,
    在環境變數中,通過 NACOS_APPLICATION_PORT 指定當前主機需要訪問的埠即可,  
    修改 NACOS_APPLICATION_PORT 后,埠映射 ports 也需要修改,
比如:
    environment:
      - NACOS_APPLICATION_PORT=8851
    ports:
      - 8851:8851

 

 

 

 

 

 

 

 

 

(4)連接 Nacos 集群
  在 Nacos Client 組態檔中,直接通過 server-addr 設定節點地址即可,多個節點之間可使用 逗號 隔開,
  若使用 Nginx 做代理,則 server-addr 設定 Nginx 訪問地址即可,
  Nginx 在 Nacos 真集群版中使用(請繼續往下看),

【比如:】
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 120.26.184.41:8849,120.26.184.41:8850,120.26.184.41:8851
      config:
        server-addr: 120.26.184.41:8849,120.26.184.41:8850,120.26.184.41:8851

【bootstrap.yml】
server:
  port: 7100

spring:
  application:
    name: nacos-client-config
  cloud:
    nacos:
      discovery:
        # 配置 nacos server 地址(作為注冊中心)
        # server-addr: 120.26.184.41:8848
        server-addr: 120.26.184.41:8849,120.26.184.41:8850,120.26.184.41:8851
      config:
        # 配置 nacos server 地址(作為配置中心)
        # server-addr: 120.26.184.41:8848
        server-addr: 120.26.184.41:8849,120.26.184.41:8850,120.26.184.41:8851
        # 設定組態檔前綴,默認為 ${spring.application.name}
        prefix: ${spring.application.name}
        # 設定組態檔后綴名
        file-extension: yml
        shared-configs[0]:
          data-id: test-0-dev.yml
        shared-configs[1]:
          data-id: test-1-dev.yml
        shared-configs[2]:
          data-id: test-2-dev.yml
          group: DEFAULT_GROUP
          refresh: true

 

 

 

9、docker-compose 部署 Nacos Server(真集群版)

(1)說明:
  上面使用 docker-compose 演示了偽集群的操作,許多坑已經踩過了,真集群部署就更加簡單了,將上面偽集群版的 docker-compose.yml 檔案拆分成 幾個小的 docker-compose.yml 檔案,分別在不同的機器上啟動即可(當然 ip 是需要修改的),
此處創建三個 虛擬機,地址分別為:192.168.157.128、192.168.157.129、192.168.157.130,
  在 192.168.157.128 上啟動 mysql、nginx、nacos1,
  在 129、130 上分別啟動 nacos2、nacos3,
其中:
  使用 nginx 反向代理 nacos1、nacos2、nacos3,通過 nginx 訪問 Nacos Server,
  使用 mysql 做配置資訊持久化操作,
注:
  此處可以使用較高版本的 mysql、nacos,比如:nacos-mysql:8.0.16、nacos-server:1.4.1 ,

(2)配置 mysql 以及 nginx,
Step1:
  自定義一個 nginx.conf,進行代理配置,
  如下所示,主要關注 server 以及 upstream nacos_server,

 

【nginx.conf】
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    # 負載均衡
    upstream nacos_server {
    # 默認加權輪詢方式執行負載均衡
    # weight 表示服務器權重,默認為 1,
    # max_fails 表示 nginx 與 服務器通信失敗 的最大次數,默認為 1,
    # fail_timeout 為失敗超時時間,默認 10 秒,在 fail_timeout 時間內,失敗次數達到 max_fails,則 Nginx 認為該服務器不可用,
        server 192.168.157.128:8849 weight=1 max_fails=2 fail_timeout=10s;
        server 192.168.157.129:8850 weight=1 max_fails=2 fail_timeout=10s;
        server 192.168.157.130:8851 weight=1 max_fails=2 fail_timeout=10s;
    }

    server {
        listen  10080;     # 設定監聽埠
        server_name 192.168.157.128;         # 設定 IP 地址
        location / {
            # 設定代理地址(根據 upstream 的值修改)
            # 訪問請求 http://192.168.157.128:10080 時,會替換為 http://192.168.157.128:8849/nacos/ 
            proxy_pass http://nacos_server/nacos/;
            
        # 下面幾個設定默認即可
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header REMOTE-HOST $remote_addr;
            add_header X-Cache $upstream_cache_status;
            add_header Cache-Control no-cache;
        }
    }
    include /etc/nginx/conf.d/*.conf;
}

 

Step2:
  撰寫 docker-compose.yml 檔案,配置 mysql、nginx,
  需要將 上面自定義的 conf 檔案 掛載到 nginx 的 /etc/nginx/nginx.conf 目錄下,

【docker-compose.yml】
version: '3.7'
services:
  nginx:
    container_name: nginx
    image: nginx:latest
    restart: always
    ports:
      - "10080:10080"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./logs:/var/log/nginx/
  mysql:
    container_name: nacos-cluster-mysql
    image: nacos/nacos-mysql:5.7
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=nacos_devtest
      - MYSQL_USER=nacos
      - MYSQL_PASSWORD=nacos
    volumes:
      - ./mysql/data:/var/lib/mysql
      - ./mysql/log:/var/log/mysql
    ports:
      - "3308:3306"

 

(3)配置 nacos1、nacos2、nacos3

【nacos1:】
version: '3.7'
services:
  nacos1:
    image: nacos/nacos-server:1.3.0
    container_name: nacos1
    restart: always
    environment:
      - NACOS_SERVERS=192.168.157.128:8849 192.168.157.129:8850 192.168.157.130:8851
      - NACOS_SERVER_IP=192.168.157.128
      - NACOS_APPLICATION_PORT=8849
      - TZ=Asia/Shanghai
      - SPRING_DATASOURCE_PLATFORM=mysql
      - MYSQL_SERVICE_HOST=192.168.157.128
      - MYSQL_SERVICE_PORT=3308
      - MYSQL_SERVICE_DB_NAME=nacos_devtest
      - MYSQL_SERVICE_USER=root
      - MYSQL_SERVICE_PASSWORD=root
      - JVM_XMS=100m
      - JVM_MMS=100m
    volumes:
      - ./nacos1:/home/nacos/logs
    ports:
      - 8849:8849
      
【nacos2:】
version: '3.7'
services:
  nacos2:
    image: nacos/nacos-server:1.3.0
    container_name: nacos2
    restart: always
    environment:
      - NACOS_SERVERS=192.168.157.128:8849 192.168.157.129:8850 192.168.157.130:8851
      - NACOS_SERVER_IP=192.168.157.129
      - NACOS_APPLICATION_PORT=8850
      - TZ=Asia/Shanghai
      - SPRING_DATASOURCE_PLATFORM=mysql
      - MYSQL_SERVICE_HOST=192.168.157.128
      - MYSQL_SERVICE_PORT=3308
      - MYSQL_SERVICE_DB_NAME=nacos_devtest
      - MYSQL_SERVICE_USER=root
      - MYSQL_SERVICE_PASSWORD=root
      - JVM_XMS=100m
      - JVM_MMS=100m
    volumes:
      - ./nacos2:/home/nacos/logs
    ports:
      - 8850:8850

【nacos3:】
version: '3.7'
services:
  nacos3:
    image: nacos/nacos-server:1.3.0
    container_name: nacos3
    restart: always
    environment:
      - NACOS_SERVERS=192.168.157.128:8849 192.168.157.129:8850 192.168.157.130:8851
      - NACOS_SERVER_IP=192.168.157.130
      - NACOS_APPLICATION_PORT=8851
      - TZ=Asia/Shanghai
      - SPRING_DATASOURCE_PLATFORM=mysql
      - MYSQL_SERVICE_HOST=192.168.157.128
      - MYSQL_SERVICE_PORT=3308
      - MYSQL_SERVICE_DB_NAME=nacos_devtest
      - MYSQL_SERVICE_USER=root
      - MYSQL_SERVICE_PASSWORD=root
      - JVM_XMS=100m
      - JVM_MMS=100m
    volumes:
      - ./nacos3:/home/nacos/logs
    ports:
      - 8851:8851

 

(4)啟動
  分別啟動 nginx、mysql、nacos1、nacos2、nacos3,
  訪問:http://192.168.157.128:10080/ 會自動跳轉到相應的 Nacos 控制臺界面,

 

 

 

手動關閉 8850 埠的 Nacos,剩余節點會重新進行選舉,選舉出 LEADER,

 

 

 

(5)連接 nacos 集群
  若未使用 Nginx 代理時,直接在 Nacos Client 組態檔中,直接通過 server-addr 設定節點地址即可,多個節點之間可使用 逗號 隔開,

spring:
  cloud:
    nacos:
      discovery:
        # 配置 nacos server 地址(作為注冊中心)
        server-addr: 192.168.157.128:8849,192.168.157.129:8850,192.168.157.130:8851
      config:
        # 配置 nacos server 地址(作為配置中心)
        server-addr: 192.168.157.128:8849,192.168.157.129:8850,192.168.157.130:8851

  若使用 Nginx 做代理,則 server-addr 設定 Nginx 訪問地址即可,
注:
  此處關于 proxy_pass 設定的地址 有個小坑記錄一下,

server{
    listen  10080;     # 設定監聽埠
    server_name 192.168.157.128;         # 設定 IP 地址
    location / {
        # 設定代理地址(根據 upstream 的值修改)
        # 訪問請求 http://192.168.157.128:10080 時,會替換為 http://192.168.157.128:8849/nacos/ 
        proxy_pass http://nacos_server/nacos/;
        #proxy_pass http://nacos_server/;
}

若使用 proxy_pass http://nacos_server/,則在 Nacos Client 中直接配置 Nginx 地址即可,
此時,客戶端正常啟動,可以通過 Nginx 訪問到 Nacos Server 集群,獲取組態檔,
但是直接通過 Nginx 地址(http://192.168.157.128:10080 或者 http://192.168.157.128:10080/nacos),無法跳轉到 Nacos 控制臺界面,

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.157.128:10080
      config:
        server-addr: 192.168.157.128:10080

 

若使用 proxy_pass http://nacos_server/nacos/,則通過 Nginx 地址(http://192.168.157.128:10080) 正常跳轉進 Nacos 控制臺界面,但若此時 Nacos Client 直接配置 Nginx 地址時,服務啟動會例外,啟動失敗,
報錯資訊如下:

【錯誤資訊:】
org.springframework.context.ApplicationContextException: Failed to start bean 'webServerStartStop'; nested exception is java.lang.reflect.UndeclaredThrowableException

Caused by: java.lang.reflect.UndeclaredThrowableException: null

Caused by: com.alibaba.nacos.api.exception.NacosException: failed to req API:/nacos/v1/ns/instance after all servers([192.168.157.128:10080]) tried: ErrCode:404, ErrMsg:<html><body><h1>Whitelabel Error Page</h1><p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p><div id='created'>Fri Mar 26 20:22:33 CST 2021</div><div>There was an unexpected error (type=Not Found, status=404).</div><div>No message available</div></body></html>

 

為了使服務正常執行,此處使用 proxy_pass http://nacos_server/ , Nginx 跳轉不了 Nacos Server 控制臺界面問題,有時間再來解決,

 

三、網關 -- Gateway

1、什么是 Gateway?

(1)什么是 Gateway?

【Gateway:】
    Gateway 直譯為 網關,是基于 Spring Boot 2.x、Spring WebFlux、Project Reactor 構建的 API 網關服務,
    Gateway 目的是 提供一個簡單的方式進行 路由轉發,用于保護、控制、增強 對于 API 介面的訪問,
簡單理解:
    Gateway 可以理解為 所有流量(請求)的入口,所有瀏覽器請求 都得通過 Gateway 進行路由,才能訪問到服務提供的 API 介面,可以類比于 Nginx 反向代理進行理解,
    Gateway 底層使用的是 Netty 框架,
注:
    在 Gateway 之前,會使用 Zuul 作為網關,有興趣的請自行了解,
    Zuul 1.x 是基于 Servlet 2.5 的 阻塞 I/O 的 API 網關,不支持長連接,
    Zuul 2.x 是基于 Netty 的 非阻塞 I/O 的 API 網關,支持長連接,
    SpringCloud 并沒有整合 Zuul 2.x,而是自己開發的一個 Gateway,
    Gateway 畢竟是親生的,在微服務中整合起來相對簡單,所以使用較多的還是 Gateway,
     
【官網地址:】
    https://spring.io/projects/spring-cloud-gateway
    https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/

 

 

 

 

(2)網關使用場景?
  如下圖所示,網關作為所有流量的 入口,根據路由規則 將請求路由到各個微服務上,

  若網關部署為 集群時,可以使用 Nginx 對其進行負載均衡,

 

 

 

(3)Gateway 功能
Gateway 基于 Spring Framework 5,Project Reactor、Spring Boot 2.0 構建,其基本功能如下:
  能夠匹配任何請求屬性的路由(支持動態路由,可以根據微服務名進行路由),
  可以針對特殊路由指定 Predicates 和 Filter 規則,且 Filter、Predicates 易撰寫,
  集成 斷路器 功能(Circuit Breaker),
  集成 服務發現 功能(Spring Cloud DiscoveryClient),
  集成 請求限流 功能,
  支持 路徑重寫 功能,


2、Gateway 核心概念(Route、Filter、Predicate)

(1)Route(路由)
  路由是構建網關的基本模塊,基本構成組件: ID、目標 URL、Predicate 集合、Filter 集合 組成,當 Predicate 為 true 時,匹配該路由,

(2)Predicate(斷言)
  可以參考 JDK8 中 java.util.function.Predicate 進行理解,
  可以根據 HTTP 請求中的內容(比如:請求頭、請求引數 等)進行匹配,如果匹配結果為 true,則匹配該路由,

(3)Filter(過濾)
  指的是 Spring 框架中 GatewayFilter 的實體,根據過濾器,可以在 請求被 路由前 或者 路由后 對請求進行更改,

(4)gateway 作業流程
  Gateway 整個作業流程就是 路由轉發 + 過濾器鏈,
  客戶端 向 Gateway 發送請求,在 Gateway Handler Mapping 中找到與 請求匹配的 路由(根據 Predicate 匹配 Route),然后將其轉發到 Gateway Web Handler 進行處理,
  Handler 通過指定的過濾器鏈后,將請求發送到實際的業務邏輯進行處理,處理完成后回傳,同時過濾器也可以對回傳資料進行處理,
  過濾器 可以在路由處理前 進行 引數校驗、權限校驗、流量監控、協議轉換 等操作,
  過濾器 可以在路由處理后 進行 回應內容修改、日志輸出、流量監控等操作,

 

 

 

3、簡單使用一下 Gateway

(1)說明
  新建一個子模塊 gateway_7200,通過組態檔的方式,簡單測驗一下 路由匹配規則,此處簡單的與 前面使用的 Nacos 一起使用,具體使用規則可參考官方檔案:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/

(2)使用 Gateway
Step1:
  引入 Gateway 依賴,Gateway 注冊到 Nacos Server 中,
注:
  添加 Gateway 依賴后,需要排除 spring-boot-starter-web 依賴,若不排除,則啟動網關服務時將會出錯,

【依賴:】
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

【錯誤:】
    若出現如下例外,需要移除 spring-boot-starter-web 依賴,否則會與 webflux 的 jar 包沖突導致啟動失敗,
   Description:
        Parameter 0 of method modifyRequestBodyGatewayFilterFactory in org.springframework.cloud.gateway.config.GatewayAutoConfiguration required a bean of type 'org.springframework.http.codec.ServerCodecConfigurer' that could not be found.
    Action:
        Consider defining a bean of type 'org.springframework.http.codec.ServerCodecConfigurer' in your configuration.

 

 

 

Step2:
  配置 Gateway,
  如下所示,配置 Nacos 注冊中心地址為 120.26.184.41:8848,
  配置路由規則,此處演示 Path 進行匹配,
注:
  若使用 Path 進行路徑匹配時,匹配成功后,真實訪問路徑其實就是 uri + Path,
比如:
  當請求為 http://localhost:7200/nacos/info/ 時,其將跳轉到 http://localhost:7101/nacos/info 進行處理,
  當請求為 http://localhost:7200/ 時,其將跳轉到 https://www.baidu.com/ 進行處理,

【application.yml】
server:
  port: 7200

spring:
  application:
    name: gateway
  cloud:
    nacos:
      discovery:
        # 配置 nacos 地址
        server-addr: 120.26.184.41:8848
    # 網關配置
    gateway:
      # 配置路由規則
      routes:
      # 路由唯一 id 名
      - id: gateway_route
        # 斷言為 true 時,需執行的 路由地址
        uri: http://localhost:7101
        # 定義斷言,即 地址匹配 規則
        predicates:
        # 當訪問 http://localhost:7200/naocs/info 時,此時斷言匹配成功,根據 uri 將跳轉到 http://localhost:7101/nacos/info
        - Path=/nacos/info
      - id: gateway_route2
        uri: https://www.baidu.com/
        predicates:
        - Path=/

 

Step3:
  啟動 nacos_client_7101、gateway_7200,
  訪問 http://localhost:7200/nacos/info 時,將跳轉到 http://localhost:7101/nacos/info 處理,

 

 

 

  訪問 http://localhost:7200/ 時,將跳轉到 https://www.baidu.com/ 處理,

 

 

 

(3)根據微服務名進行 路由(動態路由)
  實際開發中,一個服務通常以集群的方式部署,若 uri 配置固定的地址進行跳轉,肯定是不合適的,而 微服務注冊在 注冊中心中,網關 只需要通過 注冊中心 提供的 微服務名 找到真實的 微服務,進行路由即可,

修改的配置如下:
  在 uri 中使用 lb://微服務名 進行配置即可,lb 表示負載均衡,
  確保能根據 微服務名 進行路由,需配置 spring.cloud.gateway.discovery.locator.enabled=true
注:
  若注冊中心為 nacos,僅需設定 uri 為 lb://微服務名 即可根據 微服務名進行 路由跳轉,且實作負載均衡,其他注冊中心 Eureka、Zookeeper、Consul 等此處并未進行嘗試,若不能路由,則配置一下 discovery.locator.enabled=true 應該就行了,

 

 

【application.yml】
server:
  port: 7200

spring:
  application:
    name: gateway
  cloud:
    nacos:
      discovery:
        # 配置 nacos 地址
        server-addr: 120.26.184.41:8848
    # 網關配置
    gateway:
      routes:
      - id: gateway_route3
        uri: lb://nacos-client
        predicates:
        # 配置多個地址時,可以使用 逗號 隔開
        - Path=/nacos/info,/nacos/discovery

 

啟動 nacos_client_7101、nacos_client_7102,微服務名為 nacos-client,
當訪問 http://localhost:7200/nacos/info 時,會路由到 http://localhost:7101/nacos/info 與 http://localhost:7102/nacos/info ,并實作負載均衡(此處默認為 輪詢),

 

 

 

 

 

 

4、predicates 規則

  Gateway 內部有許多 Route Predicate factories,可以與 HTTP 請求的不同屬性進行匹配,多個 Predicate 規則可以組合使用,請求匹配成功后,則根據 uri 進行路由跳轉,

常見的 Predicate 規則如下,
(1)時間相關(Before、After、Between)
  Before 表示在 指定時間(datetime) 前的請求 才能匹配路由,
  After 表示在 指定時間(datetime) 后的請求 才能匹配路由,
  Between 表示在 指定時間段(datetime1,datetime2) 內的請求 才能匹配路由,
注:
  時間引數 datetime 為 ZonedDateTime 的資料,
  可以使用 System.out.println(ZonedDateTime.now()); 輸出當前地區、時間,
  比如:2021-03-31T10:35:43.706+08:00[Asia/Shanghai]

【格式:】
predicates:
- After=datetime
- Before=datetime
- Between=datetime1,datetime2

【舉例:】
predicates:
- After=2021-03-31T10:35:43.706+08:00[Asia/Shanghai]
- Before=2021-03-31T10:35:43.706+08:00[Asia/Shanghai]
- Between=2021-03-31T10:35:43.706+08:00[Asia/Shanghai],2021-03-31T10:40:43.706+08:00[Asia/Shanghai]


【舉例:(如下,在指定時間之后的請求才能 路由,指定時間之前,路由將失敗,)】
server:
  port: 7200

spring:
  application:
    name: gateway
  cloud:
    nacos:
      discovery:
        # 配置 nacos 地址
        server-addr: 120.26.184.41:8848
    # 網關配置
    gateway:
      routes:
      - id: gateway_route3
        uri: lb://nacos-client
        predicates:
        # 配置多個地址時,可以使用 逗號 隔開
        - Path=/nacos/info,/nacos/discovery
        - After=2021-03-31T10:40:00.706+08:00[Asia/Shanghai]

 

 

 

(2)Cookie 相關
  Cookie 規則具備兩個引數,一個是 Cookie 屬性名(name),一個是正則運算式(regexp),
  根據 name 以及 regexp 去匹配路由,帶有指定 cookie 資訊的請求才能匹配路由,
有兩種寫法格式,

【格式一:】
predicates:
- Cookie=mycookiename,mycookievalue

【格式二:】
predicates:
- name: Cookie
  args:
    name: mycookiename
    regexp: mycookievalue
    
【舉例:當請求 cookie 中攜帶 username 為 jarry 時,才能匹配路由】
server:
  port: 7200

spring:
  application:
    name: gateway
  cloud:
    nacos:
      discovery:
        # 配置 nacos 地址
        server-addr: 120.26.184.41:8848
    # 網關配置
    gateway:
      routes:
      - id: gateway_route3
        uri: lb://nacos-client
        predicates:
        # 配置多個地址時,可以使用 逗號 隔開
        - Path=/nacos/info,/nacos/discovery
        - After=2021-03-31T10:40:00.706+08:00[Asia/Shanghai]
        - Cookie=username,jarry
#        - name: Cookie
#          args:
#            name: username
#            regexp: tom

【通過 curl 模擬請求:】
curl http://localhost:7200/nacos/info --cookie "username=jarry"    路由匹配成功
curl http://localhost:7200/nacos/info --cookie "username=jarry1"   路由匹配失敗

 

 

(3)Header、Host、Method、Path、Query、Weight 等
  可以自行嘗試,此處不一一舉例,

【Header:】
引數:
    name、regexp, 與 Cookie 規則類似,
    帶有指定請求頭的請求才能匹配路由,

格式:
predicates:
- Header=X-Request-Id, \d+

【Host:】
引數:
    patterns
    帶有指定 host 的請求才能匹配路由,
    
格式:
predicates:
- Host=**.lyh.com

【Method:】
引數:
    methods
    帶有指定方法的請求才能匹配路由,
    
格式:
predicates:
- Method=GET,POST

【Path:】
引數:
    PathMatcher
    帶有指定路徑的請求才能匹配路由,多路徑使用逗號隔開,
    
格式:
predicates:
- Path=/red/{segment},/blue/{segment}

【Query:】
引數:
    param、regexp, 與 Cookie 規則類似,
    帶有指定引數的請求才能匹配路由,
    
格式:
predicates:
- Query=green

【Weight:】
引數:
    group、weight,
    根據權重進行請求分流,80% 請求匹配到 weight_high,20% 請求匹配到 weight_low,
    
格式:
routes:
  - id: weight_high
    uri: https://weighthigh.org
    predicates:
    - Weight=group1, 8
  - id: weight_low
    uri: https://weightlow.org
    predicates:
    - Weight=group1, 2

【舉例:】
server:
  port: 7200

spring:
  application:
    name: gateway
  cloud:
    nacos:
      discovery:
        # 配置 nacos 地址
        server-addr: 120.26.184.41:8848
    # 網關配置
    gateway:
      routes:
      - id: gateway_route3
        uri: lb://nacos-client
        predicates:
        # 配置多個地址時,可以使用 逗號 隔開
        - Path=/nacos/info,/nacos/discovery
        - After=2021-03-31T10:40:00.706+08:00[Asia/Shanghai]
        - Query=green,test.
        - Method=GET,POST
        - Host=**.lyh.com
        - Header=X-Request-Id, \d+
        - Cookie=username,jarry
        
【通過 curl 測驗:(發送 GET、POST 請求)】
curl -X POST "http://localhost:7200/nacos/info?green=test1" --cookie "username=jarry" --header "X-Request-Id:123" --header "Host:www.lyh.com
curl "http://localhost:7200/nacos/info?green=test1" --cookie "username=jarry" --header "X-Request-Id:123" --header "Host:www.lyh.com

 

 

5、Filter 規則

  Gateway 內部有許多 GatewayFilter Factories,可以修改 HTTP 請求 以及 HTTP 回應,
  僅簡單介紹幾個 Filter,其余請自行參閱官方檔案進行使用,
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories

(1)添加引數(比如:AddRequestParameter)
  引數為 name、value,用于在請求末尾追加引數(比如: ?name1=value1&name2=value2)
  可以在 predicates 指定變數 segment,并處理,

【格式:】
spring:
  cloud:
    gateway:
      routes:
      - id: add_request_parameter_route1
        uri: https://example.org
        predicates:
        - Path=/test/{segment}
        filters:
        - AddRequestParameter=foo, bar-{segment}
      - id: add_request_parameter_route2
        uri: https://example.org
        filters:
        - AddRequestParameter=red, blue
        
【舉例:(修改 gateway 組態檔如下)】
server:
  port: 7200

spring:
  application:
    name: gateway
  cloud:
    nacos:
      discovery:
        # 配置 nacos 地址
        server-addr: 120.26.184.41:8848
    # 網關配置
    gateway:
      routes:
      - id: gateway_route4
        uri: http://localhost:7101
        predicates:
        - Path=/nacos/test/{username}
        filters:
        - AddRequestParameter=password,{username}
        - AddRequestParameter=email,jarry@163.com
        
【在 nacos_client_7101 中添加如下代碼:】
@GetMapping("/test/{username}")
public String test(@PathVariable String username,
                   @RequestParam(required = false) String password,
                   @RequestParam(required = false) String email,
                   @RequestParam(required = false) Integer age) {
    username = (username != null ? username : "hello");
    password = (password != null ? password : "helloworld");
    email = (email != null ? email : "[email protected]");
    age = (age != null ? age : 24);
    return username + " " + password + " " + email + " " + age;
}

當訪問 http://localhost:7200/nacos/test/hello 時,predicates 匹配成功,filters 發揮最用,等同于發送請求 http://localhost:7101/nacos/test/hello?password=hello&[email protected]

 

 (2)修改路徑(比如:PrefixPath、StripPrefix)

【PrefixPath:】
    PrefixPath 用于指定 路徑前綴,
比如:
gateway:
  routes:
  - id: gateway_route5
    uri: http://localhost:7101
    predicates:
    - Path=/info
    filters:
    - PrefixPath=/nacos
    
當訪問 http://localhost:7200/info 時,將跳轉到 http://localhost:7101/nacos/info

【StripPrefix:】
    StripPrefix 用于跳過 路徑前綴(數值型),
比如:
gateway:
  routes:
  - id: gateway_route5
    uri: http://localhost:7101
    predicates:
    - Path=/info/**
    filters:
    - StripPrefix=1

當訪問 http://localhost:7200/info/nacos/info 時,將跳轉到 http://localhost:7101/nacos/info

其余 Filter 可自行參考檔案,也可以自定義 Filter,后續有時間再來補充,,,

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/270645.html

標籤:其他

上一篇:SpringBoot內嵌Tomcat啟動原理

下一篇:Hashtable 漸漸被人們遺忘了,只有面試官還記得,感動

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more