中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringCloud?Gateway動態轉發后端服務如何實現

發布時間:2023-03-28 11:52:30 來源:億速云 閱讀:165 作者:iii 欄目:開發技術

今天小編給大家分享一下SpringCloud Gateway動態轉發后端服務如何實現的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

一、概述

通過把SpringCloudGateway的相關路由配置規則保存到數據庫中,可以動態的靈活調整路由。在本文的實現中,我們通過請求header中的特定值,動態選擇對應的后端服務地址。

二、項目中加入依賴

在項目的gradle中增加依賴關系。

build.gradle:

plugins {
    id 'org.springframework.boot' version '3.0.2'
    id 'io.spring.dependency-management' version '1.1.0'
    id 'java'
}

group = 'cn.springcamp'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
    testCompileOnly {
        extendsFrom testAnnotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation "org.springframework.boot:spring-boot-starter-json"
    implementation 'org.springframework.boot:spring-boot-starter-validation'
    implementation 'org.springframework.boot:spring-boot-starter-data-r2dbc'
    implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
    runtimeOnly 'com.h3database:h3'
    runtimeOnly 'io.r2dbc:r2dbc-h3'
    annotationProcessor 'org.projectlombok:lombok'
    testAnnotationProcessor 'org.projectlombok:lombok'
    testImplementation "org.springframework.boot:spring-boot-starter-test"
    testImplementation 'org.junit.vintage:junit-vintage-engine'
    testImplementation 'io.projectreactor:reactor-test'
    testImplementation 'com.h3database:h3'
    testImplementation 'io.r2dbc:r2dbc-h3'
    testImplementation 'org.junit.vintage:junit-vintage-engine'
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:2022.0.1"
    }
}

test {
    useJUnitPlatform()
}

由于SpringCloudGateway基于SpringWebFlux技術構建,所以依賴中的數據庫配置需要使用r2dbc 。

三、配置文件

示例程序首選通過配置文件對路由進行基本配置,配置文件代碼:

spring:
  r2dbc:
    url: r2dbc:h3:mem:///testdb?options=DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
    username: sa
    password:
  cloud:
    gateway:
      routes:
        - id: routeOne
          predicates:
            - Path=/route1/**
          uri: no://op
          filters:
            - UriHostPlaceholderFilter=10001
        - id: routeTwo
          predicates:
            - Path=/route2/**
          uri: no://op
          filters:
            - UriHostPlaceholderFilter=10001

配置文件中配置了2個路由,對應的接口地址路徑分別是 /route1/**Path=/route2/**,路徑中的 ***表示模糊匹配,只要是以 /route1/為前綴的路徑都可以被訪問到。

后端服務地址配置了一個無意的地址: uri: no://op,因為我們的處理邏輯會通過從數據庫中讀取配置來動態替換后端服務地址。

四、動態路由數據存儲格式

我們通過 ROUTE_FILTER_ENTITY這個數據庫表來存儲接口后端服務配置數據。表結構為:

CREATE TABLE "ROUTE_FILTER_ENTITY"
(
   id VARCHAR(255) PRIMARY KEY,
   route_id VARCHAR(255),  -- 路由ID,對應配置文件中的 ```id```配置項
   code VARCHAR(255), -- 接口請求header中的code參數的值
   url VARCHAR(255) -- 后端服務地址
);

當客戶端訪問 /route1/test接口時,根據配置文件的路由配置,SpringCloudGateway 會命中 id: routeOne這個路由規則,這個規則對應的后端服務地址是 uri: no://op,并不是我們期望的真實后端服務地址。

因此,我們需要讀取到真實的后端服務地址,并將請求轉發到這個地址。跟據 routeId 和 接口請求header中的code參數的值,就可以從 ROUTE_FILTER_ENTITY 表中查到對應的后端服務地址 url這個字段的值。

我們已經讀取到了后端服務地址,還需要將請求轉發到這個地址,下面介紹轉發的方法。

五、后端服務動態轉發

動態轉發通過自定義 filter 的方式實現,自定義 filter 代碼如下:

@Component
public class UriHostPlaceholderFilter extends AbstractGatewayFilterFactory<UriHostPlaceholderFilter.Config> {
    @Autowired
    private RouteFilterRepository routeFilterRepository;
    public UriHostPlaceholderFilter() {
        super(Config.class);
    }
    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList("order");
    }
    @Override
    public GatewayFilter apply(Config config) {
        return new OrderedGatewayFilter((exchange, chain) -> {
            String code = exchange.getRequest().getHeaders().getOrDefault("code", new ArrayList<>()).stream().findFirst().orElse("");
            String routeId = exchange.getAttribute(GATEWAY_PREDICATE_MATCHED_PATH_ROUTE_ID_ATTR);
            if (StringUtils.hasText(code)) {
                String newurl;
                try {
                    newurl = routeFilterRepository.findByRouteIdAndCode(routeId, code).toFuture().get().getUrl();
                } catch (InterruptedException | ExecutionException e) {
                    throw new RuntimeException(e);
                }
                if (StringUtils.hasText(exchange.getRequest().getURI().getQuery())) {
                    newurl = newurl + "?" + exchange.getRequest().getURI().getQuery();
                }
                URI newUri = null;
                try {
                    newUri = new URI(newurl);
                } catch (URISyntaxException e) {
                    log.error("uri error", e);
                }
                exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, newUri);
            }
            return chain.filter(exchange);
        }, config.getOrder());
    }
    @Data
    @NoArgsConstructor
    public static class Config {
        private int order;
        public Config(int order) {
            this.order = order;
        }
    }
}

通過擴展 AbstractGatewayFilterFactory 類,我們自定義了 UriHostPlaceholderFilter 這個 filter 。

代碼的核心邏輯在 apply 方法中。

首先通過 String code = exchange.getRequest().getHeaders().getOrDefault("code", new ArrayList<>()).stream().findFirst().orElse("")可以獲取到接口請求 header 中 code 這個參數的值。

再通過 String routeId = exchange.getAttribute(GATEWAY_PREDICATE_MATCHED_PATH_ROUTE_ID_ATTR)可以獲取到 routeId 。

最后通過 newurl = routeFilterRepository.findByRouteIdAndCode(routeId, code).toFuture().get().getUrl()就可以從數據庫中讀取到配置好的后端服務地址。

拿到后端服務地址后, 通過調用 exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, newUri);將請求轉發到對應的地址。

六、單元測試

在單元測試代碼中,我們預置了一條后端服務動態配置數據:

insert into ROUTE_FILTER_ENTITY values('1','routeOne','alpha','http://httpbin.org/anything')

然后模擬請求 /route1/test?a=test這個接口,根據我們的配置,請求會被轉發到 http://httpbin.org/anything

執行單元測試后,可以從日志中發現,接口返回的數據是 http://httpbin.org/anything 這個后端服務返回的數據。

當我們希望調整后端服務地址時,只需要把 ROUTE_FILTER_ENTITY 表中的這條配置數據中的 url 字段改成其它的任何服務地址即可,大大增加了程序的靈活度。

以上就是“SpringCloud Gateway動態轉發后端服務如何實現”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

洞口县| 海兴县| 广丰县| 鹤壁市| 武鸣县| 茌平县| 大洼县| 南和县| 贞丰县| 许昌县| 定边县| 梅河口市| 鹤庆县| 长海县| 会泽县| 汉沽区| 禹州市| 江津市| 鹤山市| 广汉市| 广宁县| 淄博市| 广丰县| 交城县| 武乡县| 汾阳市| 彩票| 五家渠市| 福海县| 韶山市| 黎川县| 教育| 舟曲县| 河南省| 涿州市| 双桥区| 抚远县| 临沧市| 阿荣旗| 登封市| 丰都县|