在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何利用Gateway搭建網關服務?

jf_78858299 ? 來源:csdn ? 作者:?!な堑惯^來的天 ? 2023-01-21 16:06 ? 次閱讀

網關作為微服務中非常重要的一部分,是必須要掌握的;本文記錄一下我是如何使用Gateway搭建網關服務及實現動態路由的,幫助大家學習如何快速搭建一個網關服務,了解路由相關配置,鑒權的流程及業務處理,有興趣的一定看到最后,非常適合沒接觸過網關服務的同學當作入門教程。

搭建服務

框架

SpringBoot 2.1

<parent>
   <groupId>org.springframework.bootgroupId>
   <artifactId>spring-boot-starter-parentartifactId>
   <version>2.1.0.RELEASEversion>
parent>

Spring-cloud-gateway-core

<dependency>
   <groupId>org.springframework.cloudgroupId>
   <artifactId>spring-cloud-gateway-coreartifactId>
dependency>

common-lang3

<dependency>
   <groupId>org.apache.commonsgroupId>
   <artifactId>commons-lang3artifactId>
dependency>

路由配置

網關作為請求統一入口,路由就相當于是每個業務系統的入口,通過路由規則則可以匹配到對應微服務的入口,將請求命中到對應的業務系統中

server:
  port: 8080
 
spring:
  cloud:
    gateway:
      enabled: true
      routes:
      - id: demo-server
        uri: http://localhost:8081
        predicates:
        - Path=/demo-server/**
        filters:
          - StripPrefix= 1

routes

圖片

解讀配置

現在有一個服務demo-server部署在本機,地址和端口127.0.0.1:8081,所以路由配置uri為http://localhost:8081

使用網關服務路由到此服務,predicates -Path=/demo-server/**,網關服務的端口為8080,啟動網關服務,訪問localhost:8080/demo-server,路由斷言就會將請求路由到demo-server

直接訪問demo-server的接口localhost:8081/api/test,通過網關的訪問地址則為localhost:8080/demo-server/api/test,predicates配置將請求斷言到此路由,filters-StripPrefix=1代表將地址中/后的第一個截取,所以demo-server就截取掉了

使用gateway通過配置文件即可完成路由的配置,非常方便,我們只要充分的了解配置項的含義及規則就可以了;但是這些配置如果要修改則需要重啟服務,重啟網關服務會導致整個系統不可用,這一點是無法接受的,下面介紹如何通過Nacos實現動態路由

動態路由

使用nacos結合gateway-server實現動態路由,我們需要先部署一個nacos服務,可以使用docker部署或下載源碼在本地啟動,具體操作可以參考官方文檔即可

Nacos配置
  • groupId: 使用網關服務名稱即可
  • dataId: routes
  • 配置格式:json
[{
      "id": "xxx-server",
      "order": 1, #優先級
      "predicates": [{ #路由斷言
          "args": {
              "pattern": "/xxx-server/**"
          },
          "name": "Path"
      }],
      "filters":[{ #過濾規則
          "args": {
              "parts": 0 #k8s服務內部訪問容器為http://xxx-server/xxx-server的話,配置0即可
          },
          "name": "StripPrefix" #截取的開始索引
      }],
      "uri": "http://localhost:8080/xxx-server" #目標地址
  }]

json格式配置項與yaml中對應,需要了解配置在json中的寫法

比對一下json配置與yaml配置
{
    "id":"demo-server",
    "predicates":[
        {
            "args":{
                "pattern":"/demo-server/**"
            },
            "name":"Path"
        }
    ],
    "filters":[
        {
            "args":{
                "parts":1
            },
            "name":"StripPrefix"
        }
    ],
    "uri":"http://localhost:8081"
}
spring:
  cloud:
    gateway:
      enabled: true
      routes:
      - id: demo-server
        uri: http://localhost:8081
        predicates:
        - Path=/demo-server/**
        filters:
          - StripPrefix= 1
代碼實現

Nacos實現動態路由的方式核心就是通過Nacos配置監聽,配置發生改變后執行網關相關api創建路由

圖片

@Component
public class NacosDynamicRouteService implements ApplicationEventPublisherAware {
 
    private static final Logger LOGGER = LoggerFactory.getLogger(NacosDynamicRouteService.class);
 
    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;
 
    private ApplicationEventPublisher applicationEventPublisher;
 
    /** 路由id */
    private static List<String> routeIds = Lists.newArrayList();
 
    /**
     * 監聽nacos路由配置,動態改變路由
     * @param configInfo
     */
    @NacosConfigListener(dataId = "routes", groupId = "gateway-server")
    public void routeConfigListener(String configInfo) {
        clearRoute();
        try {
            List gatewayRouteDefinitions = JSON.parseArray(configInfo, RouteDefinition.class);
            for (RouteDefinition routeDefinition : gatewayRouteDefinitions) {
                addRoute(routeDefinition);
            }
            publish();
            LOGGER.info("Dynamic Routing Publish Success");
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        } 
    }
    /**
     * 清空路由
     */
    private void clearRoute() {
        for (String id : routeIds) {
            routeDefinitionWriter.delete(Mono.just(id)).subscribe();
        }
        routeIds.clear();
    }
 
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }
    /**
     * 添加路由
     * 
     * @param definition
     */
    private void addRoute(RouteDefinition definition) {
        try {
            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
            routeIds.add(definition.getId());
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
    }
    /**
     * 發布路由、使路由生效
     */
    private void publish() {
        this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this.routeDefinitionWriter));
    }
}

過濾器

gateway提供GlobalFilter及Ordered兩個接口用來定義過濾器,我們自定義過濾器只需要實現這個兩個接口即可

  • GlobalFilter filter() 實現過濾器業務
  • Ordered getOrder() 定義過濾器執行順序

通常一個網關服務的過濾主要包含 鑒權(是否登錄、是否黑名單、是否免登錄接口...) 限流(ip限流等等)功能,我們今天簡單介紹鑒權過濾器的流程實現

鑒權過濾器

需要實現鑒權過濾器,我們先得了解登錄及鑒權流程,如下圖所示

由圖可知,我們鑒權過濾核心就是驗證token是否有效,所以我們網關服務需要與業務系統在同一個redis庫,先給網關添加redis依賴及配置

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-data-redis-reactiveartifactId>
dependency>
spring:
  redis:
    host: redis-server
    port: 6379
    password:
    database: 0

代碼實現

  1. 定義過濾器AuthFilter
  2. 獲取請求對象 從請求頭或參數或cookie中獲取token(支持多種方式傳token對于客戶端更加友好,比如部分web下載請求會新建一個頁面,在請求頭中傳token處理起來比較麻煩)
  3. 沒有token,返回401
  4. 有token,查詢redis是否有效
  5. 無效則返回401,有效則完成驗證放行
  6. 重置token過期時間、添加內部請求頭信息方便業務系統權限處理
@Component
public class AuthFilter implements GlobalFilter, Ordered {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    private static final String TOKEN_HEADER_KEY = "auth_token";
    @Override
    public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1.獲取請求對象
        ServerHttpRequest request = exchange.getRequest();
        // 2.獲取token
        String token = getToken(request);
        ServerHttpResponse response = exchange.getResponse();
        if (StringUtils.isBlank(token)) {
            // 3.token為空 返回401
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        // 4.驗證token是否有效
        String userId = getUserIdByToken(token);
        if (StringUtils.isBlank(userId)) {
            // 5.token無效 返回401
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        // token有效,后續業務處理
        // 從寫請求頭,方便業務系統從請求頭獲取用戶id進行權限相關處理
        ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
        request = builder.header("user_id", userId).build();
        // 延長緩存過期時間-token緩存用戶如果一直在操作就會一直重置過期
        // 這樣避免用戶操作過程中突然過期影響業務操作及體驗,只有用戶操作間隔時間大于緩存過期時間才會過期
        resetTokenExpirationTime(token, userId);
        // 完成驗證
        return chain.filter(exchange);
    }
 
    @Override
    public int getOrder() {
        // 優先級 越小越優先
        return 0;
    }
 
    /**
     * 從redis中獲取用戶id
     * 在登錄操作時候 登陸成功會生成一個token, redis得key為auth_token:token 值為用戶id
     *
     * @param token
     * @return
     */
    private String getUserIdByToken(String token) {
        String redisKey = String.join(":", "auth_token", token);
        return redisTemplate.opsForValue().get(redisKey);
    }
 
    /**
     * 重置token過期時間
     *
     * @param token
     * @param userId
     */
    private void resetTokenExpirationTime(String token, String userId) {
        String redisKey = String.join(":", "auth_token", token);
        redisTemplate.opsForValue().set(redisKey, userId, 2, TimeUnit.HOURS);
    }
 
    /**
     * 獲取token
     *
     * @param request
     * @return
     */
    private static String getToken(ServerHttpRequest request) {
        HttpHeaders headers = request.getHeaders();
        // 從請求頭獲取token
        String token = headers.getFirst(TOKEN_HEADER_KEY);
        if (StringUtils.isBlank(token)) {
            // 請求頭無token則從url獲取token
            token = request.getQueryParams().getFirst(TOKEN_HEADER_KEY);
        }
        if (StringUtils.isBlank(token)) {
            // 請求頭和url都沒有token則從cookies獲取
            HttpCookie cookie = request.getCookies().getFirst(TOKEN_HEADER_KEY);
            if (cookie != null) {
                token = cookie.getValue();
            }
        }
        return token;
    }
}

總結

Gateway通過配置項可以實現路由功能,整合Nacos及配置監聽可以實現動態路由,實現GlobalFilter,Ordered兩個接口可以快速實現一個過濾器,文中也詳細的介紹了登錄后的請求鑒權流程。

來源:https://blog.csdn.net/qq_31587111/article/details/122731977

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 網關
    +關注

    關注

    9

    文章

    4561

    瀏覽量

    51310
  • 路由
    +關注

    關注

    0

    文章

    278

    瀏覽量

    41883
  • Gateway
    +關注

    關注

    1

    文章

    16

    瀏覽量

    7898
收藏 人收藏

    評論

    相關推薦

    如何使用Gateway搭建網關服務及實現動態路由

    本文記錄一下我是如何使用Gateway搭建網關服務及實現動態路由的,幫助大家學習如何快速搭建一個網關服務
    的頭像 發表于 09-23 15:15 ?1842次閱讀

    #硬聲創作季 14-JAVAEE實戰項目課程—CAT安裝使用-GateWay網關服務搭建

    網關JAVA編程語言Gate網關設備
    Mr_haohao
    發布于 :2022年09月05日 07:17:38

    cc2530和linux gateway之間的通信網關端的服務都沒有正常啟動是什么原因?

    點。我希望通過中心節點去控制端節點。另外在網關端我安裝了Z-Stack_Linux_Gateway-1.0.1,即TI的gateway上的SDK,現在我遇到了些問題: 網關上運行zig
    發表于 08-14 07:43

    Thing***oard之Gateway使用示例有哪些

    Thing***oard之Gateway使用示例國慶期間西安陰雨綿綿,閑來無事,把thing***orad運行搭建起來,體驗了一把??傮w來講CE版本還是很棒的,提供了物聯網平臺該有的基礎能力
    發表于 07-12 07:51

    服務網關gateway的相關資料推薦

    目錄微服務網關 gateway 概述[路由器網關 Zuul 概述]嵌入式 Zuul 反向代理微服務網關 gateway 概述1、想象一下一個
    發表于 12-23 08:19

    [魯班貓創意氛圍賽]項目提交:本地LoRaWAN網關

    chirpstack-gateway-bridge 橋接器,橋接集中器與服務器之間的通訊 chirpstack 服務器,用來管理集中器,設備等角色,并管理數據,設備描述等,相關數據保存在數據庫里 當前
    發表于 05-13 16:11

    利用Gateway實現上位機監控

    前言此技術文件用于介紹觸控大師的Gateway Server(網關服務)的設定與使用方式。用戶可以通過這個功能來實現上位機局域網遠程監控的功能。特點􀁺提供 1 個以太
    發表于 11-29 16:00 ?0次下載
    <b class='flag-5'>利用</b><b class='flag-5'>Gateway</b>實現上位機監控

    六、利用ESP32搭建網絡服務器(一)

    六、利用ESP32搭建網絡服務器(一)歡迎使用Markdown編輯器新的改變功能快捷鍵合理的創建標題,有助于目錄的生成如何改變文本的樣式插入鏈接與圖片如何插入一段漂亮的代碼片生成一個適合你的列表創建
    發表于 12-29 19:00 ?3次下載
    六、<b class='flag-5'>利用</b>ESP32<b class='flag-5'>搭建網絡服務</b>器(一)

    網站搭建時該如何選擇租用服務

    搭建網站的時候是必須要用到服務器。服務器分很多種,有用來開發游戲叫游戲服務器,用來存放數據叫數據庫服務器,有應用
    發表于 03-14 09:44 ?908次閱讀

    Dubbo Gateway基于Java的Dubbo網關實現

    ./oschina_soft/dubbo-gateway.zip
    發表于 06-14 10:28 ?3次下載
    Dubbo <b class='flag-5'>Gateway</b>基于Java的Dubbo<b class='flag-5'>網關</b>實現

    Spring Cloud Gateway服務網關的部署與使用詳細教程

    Gateway 網關搭建: 3、Spring Cloud Gateway 配置項的說明: 4、Gateway 集成 nacos 注冊中心
    的頭像 發表于 10-11 17:46 ?1796次閱讀

    如何使用Gateway搭建網關服務及實現動態路由?

    網關作為請求統一入口,路由就相當于是每個業務系統的入口,通過路由規則則可以匹配到對應微服務的入口,將請求命中到對應的業務系統中
    的頭像 發表于 11-15 10:12 ?1510次閱讀

    新品速遞 | 虹科CAN FD轉LAN網關:PCAN-Ethernet Gateway FD DR

    PCAN-Ethernet Gateway FD DR網關可以通過IP網絡訪問傳統CAN總線或CAN FD總線。
    的頭像 發表于 11-03 17:43 ?1433次閱讀
    新品速遞 | 虹科CAN FD轉LAN<b class='flag-5'>網關</b>:PCAN-Ethernet <b class='flag-5'>Gateway</b> FD DR

    網關GateWay的基本概念和使用詳解

    SpringCloudGateway網關是所有微服務的統一入口。
    的頭像 發表于 08-08 09:39 ?2303次閱讀
    <b class='flag-5'>網關</b><b class='flag-5'>GateWay</b>的基本概念和使用詳解

    Spring Cloud Gateway網關框架

    Spring Cloud Gateway網關框架 本軟件微服務架構中采用Spring Cloud Gateway網關控制框架,Spring
    的頭像 發表于 08-22 09:58 ?520次閱讀
    Spring Cloud <b class='flag-5'>Gateway</b><b class='flag-5'>網關</b>框架
    主站蜘蛛池模板: 亚洲国产视频网| 男女交性永久免费视频播放| 天天干天天色综合| 色惰网站| 国产亚洲精品aaa大片| 操综合| 欧美一区二区精品| 美女视频黄a视频美女大全| 美女隐私黄www视频| 在线观看免费视频国产| 亚洲三级免费| 三级理论在线| 玖玖精品国产| 日本高清www| 伦理一区二区三区| 国产三级影院| 亚洲黄色一区| 国产免费一级在线观看| 欧美性性性性性ⅹxxbbbb| 国产chinesetube| 成人免费国产gav视频在线| 男生脱美女内裤内衣动态图| 亚洲国产综合人成综合网站00| 色综久久| 色网站欧美| 六月色播| 97色在线视频观看香蕉| 91桃色国产线观看免费| 天天操天天舔天天射| 国产男人午夜视频在线观看| 亚洲一卡2卡3卡4卡5卡乱码 | 黄色一级片毛片| 欧美久操| 7777sq国产精品| 午夜视频网站在线观看| 九九热精品在线| 天天躁夜夜躁狠狠躁2021西西| 亚洲免费国产| 五月网址| 国产资源在线观看| www.jizz中国|