1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        SpringCloud Gateway網(wǎng)關(guān)組件,你真的懂了嗎?

        共 8793字,需瀏覽 18分鐘

         ·

        2021-09-13 03:26

        點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)

        Java術(shù) | 

        對(duì)于傳統(tǒng)的單體應(yīng)用,我們似乎沒有遇到過某種問題,它在如今盛行的微服務(wù)架構(gòu)中非常常見,它就是接口訪問。在單體應(yīng)用中,我們?cè)L問的都僅僅是這一個(gè)應(yīng)用的內(nèi)容,而微服務(wù)則不同,在微服務(wù)架構(gòu)中,一個(gè)應(yīng)用被拆分成了很多的微服務(wù):這給前端訪問產(chǎn)生了一些麻煩,一般來說,前端都會(huì)抽取出一個(gè)公共的訪問地址,但這些微服務(wù)都分布在不同的機(jī)器上,導(dǎo)致訪問地址都是不一樣的,基于此,網(wǎng)關(guān)的出現(xiàn)能夠輕松解決這一問題。所有想要訪問接口的客戶端、用戶等都先將請(qǐng)求發(fā)至網(wǎng)關(guān),再由網(wǎng)關(guān)來解決將該請(qǐng)求交給哪個(gè)服務(wù)進(jìn)行處理。

        SpringCloud為我們提供了網(wǎng)關(guān)的實(shí)現(xiàn)——Gateway,通過Gateway,我們能夠?qū)崿F(xiàn)身份認(rèn)證和權(quán)限校驗(yàn);服務(wù)路由和負(fù)載均衡;請(qǐng)求限流等功能。

        網(wǎng)關(guān)初體驗(yàn)

        SpringCloud Gateway是作為一個(gè)獨(dú)立的微服務(wù)工作的,所以我們需要?jiǎng)?chuàng)建一個(gè)SpringBoot應(yīng)用,并引入Nacos和Gateway的依賴:

        <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>

        Gateway也是需要注冊(cè)到Nacos中的,因?yàn)橹挥凶?cè)到Nacos中網(wǎng)關(guān)才能夠發(fā)現(xiàn)有哪些服務(wù)是健康的,有哪些服務(wù)可以正常使用。在網(wǎng)關(guān)服務(wù)中,我們無需編寫任何代碼,只需要在application.yml中填寫相關(guān)配置即可:

        server:
        port: 10000
        spring:
        application:
        name: service-gateway
        cloud:
        nacos:
        discovery:
        server-addr: localhost:8848
        gateway:
        routes: # 網(wǎng)關(guān)的路由配置
        - id: service-user-route
        uri: lb://service-user
        predicates:
        - Path:=/user/**

        網(wǎng)關(guān)的路由配置總共需要配置三項(xiàng),其中id是該路由的唯一標(biāo)識(shí),uri指定的是需要路由到的服務(wù)地址,而predicates表示斷言,如果滿足斷言的要求,則網(wǎng)關(guān)便會(huì)將請(qǐng)求交給uri指定的服務(wù), lb:// 表示將請(qǐng)求負(fù)載均衡到 service-user 服務(wù)。斷言的形式有很多,比如這里使用的Path,它是用來判斷請(qǐng)求路徑的,當(dāng)請(qǐng)求路徑以u(píng)ser開頭,該請(qǐng)求就會(huì)被這一網(wǎng)關(guān)配置處理。

        接下來在service-user服務(wù)中編寫一個(gè)方法:

        @RestController
        @RequestMapping("/user")
        public class UserController {

        @Autowired
        private UserService userService;

        @GetMapping("/find/{userId}")
        public User find(@PathVariable("userId") Long userId){
        User user = userService.findById(userId);
        return user;
        }
        }

        將這兩個(gè)應(yīng)用分別啟動(dòng),然后訪問 http://localhost:10000/user/find/1,注意一定是訪問網(wǎng)關(guān)服務(wù),所以端口是10000,然后訪問路徑為 /user/find/1 ,由于路徑以u(píng)ser開頭,所以該請(qǐng)求就會(huì)被網(wǎng)關(guān)交給service-user服務(wù)進(jìn)行處理。

        路由配置

        在剛剛的例子中,我們使用到了一個(gè)路徑的路由斷言,只需要在-Path中配置/user/**,那么以u(píng)ser開頭的請(qǐng)求就會(huì)被網(wǎng)關(guān)處理,這是如何實(shí)現(xiàn)的呢?事實(shí)上,Gateway中有很多的路由斷言工廠,當(dāng)我們?cè)谂渲梦募袑?duì)斷言進(jìn)行配置后,這些配置就會(huì)被路由斷言工廠進(jìn)行解析并處理,而-Path配置就是由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory來處理的。SpringCloud Gateway中一共提供了11種基本的路由斷言工廠,分別如下:

        1.BeforeRoutePredicateFactory:判斷是否為某個(gè)時(shí)間點(diǎn)之前的請(qǐng)求2.AfterRoutePredicateFactory:判斷是否為某個(gè)時(shí)間點(diǎn)之后的請(qǐng)求3.BetweenRoutePredicateFactory:判斷是否為某兩個(gè)時(shí)間點(diǎn)之間的請(qǐng)求4.CookieRoutePredicateFactory:判斷是否包含某些cookie5.HeaderRoutePredicateFactory:判斷是否包含某些header6.HostRoutePredicateFactory:判斷請(qǐng)求是否是訪問某個(gè)host7.MethodRoutePredicateFactory:判斷請(qǐng)求方式是否是指定的方式8.PathRoutePredicateFactory:判斷請(qǐng)求路徑是否滿足規(guī)則9.QueryRoutePredicateFactory:判斷請(qǐng)求參數(shù)是否包含指定的參數(shù)10.RemoteAddrRoutePredicateFactory:判斷請(qǐng)求ip是否在指定的范圍內(nèi)11.WeightRoutePredicateFactory:權(quán)重處理

        其中BeforeRoutePredicateFactory,配置如下:

        spring:
        cloud:
        gateway:
        routes:
        - id: before_route
        uri: lb://service-user
        predicates:
        - Before=2017-01-20T17:42:47.789-07:00[America/Denver]

        它表示請(qǐng)求的時(shí)間在2017年1月20日17點(diǎn)42分之前的請(qǐng)求就滿足該路由配置,網(wǎng)關(guān)就會(huì)將請(qǐng)求交給service-user。

        AfterRoutePredicateFactory配置如下:

        spring:
        cloud:
        gateway:
        routes:
        - id: after_route
        uri: lb://service-user
        predicates:
        - After=2017-01-20T17:42:47.789-07:00[America/Denver]

        它表示請(qǐng)求的時(shí)間在2017年1月20日17點(diǎn)42分之后的請(qǐng)求就滿足該路由配置。

        BetweenRoutePredicateFactory配置如下:

        spring:
        cloud:
        gateway:
        routes:
        - id: between_route
        uri: lb://service-user
        predicates:
        - Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]

        它表示請(qǐng)求的時(shí)間在2017年1月20日17點(diǎn)42分與2017年1月21日17點(diǎn)42分之間的請(qǐng)求就滿足該路由配置。

        CookieRoutePredicateFactory配置如下:

        spring:
        cloud:
        gateway:
        routes:
        - id: cookie_route
        uri: lb://service-user
        predicates:
        - Cookie=chocolate, ch.p

        它表示請(qǐng)求中必須含有一個(gè)名字為chocolate的cookie,其值為滿足ch.p正則表達(dá)式的內(nèi)容,當(dāng)然也可以直接配置一個(gè)cookie的鍵值,鍵與值之間用逗號(hào)分隔: - Cookie=name,zhangsan 。

        HeaderRoutePredicateFactory配置如下:

        spring:
        cloud:
        gateway:
        routes:
        - id: header_route
        uri: lb://service-user
        predicates:
        - Header=X-Request-Id, \d+

        它表示請(qǐng)求中必須含有一個(gè)名為 X-Request-Id 的請(qǐng)求頭,其值為滿足\d+正則表達(dá)式的內(nèi)容,也可以直接配置一個(gè)鍵值: - Header=Accept-Language,zh-CN 。

        HostRoutePredicateFactory配置如下:

        spring:
        cloud:
        gateway:
        routes:
        - id: host_route
        uri: lb://service-user
        predicates:
        - Host=**.somehost.org,**.anotherhost.org

        它表示請(qǐng)求的Host必須具有**.somehost.org,**.anotherhost.org內(nèi)容。

        MethodRoutePredicateFactory配置如下:

        spring:
        cloud:
        gateway:
        routes:
        - id: method_route
        uri: lb://service-user
        predicates:
        - Method=GET,POST

        它表示請(qǐng)求的方式必須為GET或Post。

        PathRoutePredicateFactory配置如下:

        spring:
        cloud:
        gateway:
        routes:
        - id: path_route
        uri: lb://service-user
        predicates:
        - Path=/red/{segment},/blue/{segment}

        這個(gè)相信大家很熟悉了,就是用來匹配請(qǐng)求路徑的,其中segment是一個(gè)占位符,表示單層路徑匹配,比如: /red/1 、 /red/blue 、 /blue/1 、 /blue/red 都是滿足要求的。

        QueryRoutePredicateFactory配置如下:

        spring:
        cloud:
        gateway:
        routes:
        - id: query_route
        uri: lb://service-user
        predicates:
        - Query=name

        它表示請(qǐng)求中必須攜帶名為name的參數(shù),比如: http://localhost:10000/find?name=zhangsan 。

        RemoteAddrRoutePredicateFactory配置如下:

        spring:
        cloud:
        gateway:
        routes:
        - id: remoteaddr_route
        uri: lb://service-user
        predicates:
        - RemoteAddr=192.168.1.1/24

        它表示請(qǐng)求IP必須在192.168.1.1/24網(wǎng)段內(nèi),如果你學(xué)過計(jì)算機(jī)網(wǎng)絡(luò),應(yīng)該能夠明白,不了解的也不要緊,我就簡單介紹一下。 192.168.1.1/24 采用的是斜線記法,斜杠后面的數(shù)字表示的是網(wǎng)絡(luò)前綴,即:該IP地址的前24位為網(wǎng)絡(luò)號(hào),后8位為主機(jī)號(hào),將IP轉(zhuǎn)換為二進(jìn)制,如下:

        1100 0000 1010 1000 0000 0001 0000 0001

        也就是說,當(dāng)主機(jī)號(hào)全為1時(shí),該IP為最大地址,即:192.168.1.255,所以192.168.1.1/24代表的IP段是192.168.1.1~192.168.1.255。由此可知,只要請(qǐng)求IP在該IP段范圍內(nèi)則是符合要求的。

        WeightRoutePredicateFactory配置如下:

        spring:
        cloud:
        gateway:
        routes:
        - id: weight_high
        uri: lb://service-user
        predicates:
        - Path=/user/**
        - Weight=group1, 8
        - id: weight_low
        uri: lb://service-user2
        predicates:
        - Path=/user/**
        - Weight=group1, 2

        這里配置了兩個(gè)路由規(guī)則,當(dāng)請(qǐng)求路徑以/user開頭時(shí)這兩個(gè)規(guī)則都符合條件,但因?yàn)榕渲昧藱?quán)重分組,這兩個(gè)規(guī)則的分組均為group1,所以Gateway會(huì)按照權(quán)重比進(jìn)行權(quán)衡,將80%的該請(qǐng)求交給service-user處理,將20%的該請(qǐng)求交給service-user2處理。

        過濾器配置

        在路由的配置中,我們還可以配置一項(xiàng)filter,它是Gateway提供的過濾器,可以對(duì)進(jìn)入網(wǎng)關(guān)的請(qǐng)求和返回的響應(yīng)進(jìn)行相應(yīng)的處理。與路由斷言類似,Gateway同樣提供了過濾器工廠,而且有31種之多:這里僅僅是截取了官網(wǎng)上列舉的部分過濾器工廠,比如第一個(gè)AddRequestHeader GatewayFilterFactory,從名字就能夠看出來,這是用來添加請(qǐng)求頭信息的,具體配置方式如下:

        spring:
        cloud:
        gateway:
        routes:
        - id: add_request_header_route
        uri: lb://service-user
        predicates:
        - Path=/user/**
        filters:
        - AddRequestHeader=X-Request-red, blue

        此時(shí)若是請(qǐng)求路徑滿足以/user開頭,那么該請(qǐng)求就會(huì)被過濾器添加上一個(gè)請(qǐng)求頭信息,內(nèi)容為 X-Request-red:blue ;通過配置默認(rèn)過濾器,可以使過濾器對(duì)所有的路由配置生效:

        spring:
        cloud:
        gateway:
        routes:
        - id: add_request_header_route
        uri: lb://service-user
        predicates:
        - Path=/user/**
        default-filters:
        - AddRequestHeader=X-Request-red, blue

        為了更加靈活地適應(yīng)各種場(chǎng)景,Gateway還提供了一種特殊的過濾器——GlobalFiler(全局過濾器),它的作用與default-filter類似,區(qū)別在于GlobalFilter需要我們自己去實(shí)現(xiàn),要做的就是實(shí)現(xiàn)GlobalFilter接口:

        @Order(0)
        @Component
        public class MyGlobalFilter implements GlobalFilter {

        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 獲取請(qǐng)求參數(shù)
        ServerHttpRequest request = exchange.getRequest();
        MultiValueMap<String, String> params = request.getQueryParams();
        String tag = params.getFirst("tag");
        if ("admin".equals(tag)) {
        // 放行
        chain.filter(exchange);
        }
        ServerHttpResponse response = exchange.getResponse();
        // 設(shè)置狀態(tài)碼
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        // 攔截
        return response.setComplete();
        }
        }

        該過濾器可以實(shí)現(xiàn)對(duì)身份的校驗(yàn),只有管理員身份的請(qǐng)求才被放行,其它請(qǐng)求就會(huì)被攔截。

        處理跨域

        跨域是每一個(gè)前后端分離項(xiàng)目都需要面臨的問題,但有了網(wǎng)關(guān),我們就可以將處理跨域的流程寫在網(wǎng)關(guān)里,無需在每一個(gè)微服務(wù)中都進(jìn)行配置了。

        需要注意跨域問題是指瀏覽器禁止請(qǐng)求的發(fā)起者與服務(wù)端發(fā)生跨域的ajax請(qǐng)求。

        配置方式如下:

        spring:
        cloud:
        gateway:
        globalcors: # 全局跨域處理
        add-to-simple-url-handler-mapping: true # 解決options詢問請(qǐng)求被攔截的問題
        cors-configurations:
        '[/**]':
        allowedOrigins: # 配置允許哪些網(wǎng)站跨域
        - "http://localhost:8000"
        - "http://localhost:9000"
        allowedMethods: # 配置允許哪些請(qǐng)求方式跨域
        - "GET"
        - "POST"
        - "DELETE"
        - "PUT"
        - "OPTIONS"
        allowedHeaders: "*" # 允許在請(qǐng)求中攜帶的頭信息
        allowCredentials: true # 允許請(qǐng)求攜帶Cookie
        maxAge: 360000 # 跨域檢測(cè)的有效時(shí)間

        瀏覽器在向服務(wù)器發(fā)起請(qǐng)求之前,會(huì)先發(fā)送一個(gè)option請(qǐng)求進(jìn)行詢問,查看是否滿足要求,為了防止這個(gè)詢問請(qǐng)求被攔截,所以需要配置 add-to-simple-url-handler-mapping: true ; [/**] 表示對(duì)所有的請(qǐng)求進(jìn)行處理; maxAge: 360000 用于配置跨域檢測(cè)的有效時(shí)間,當(dāng)瀏覽器發(fā)送了一次option請(qǐng)求進(jìn)行詢問并且成功后,在這段有效時(shí)間內(nèi),服務(wù)器將不再要求對(duì)瀏覽器發(fā)送過來的請(qǐng)求進(jìn)行檢測(cè),由此提高了性能。

        本文作者:汪偉俊 為Java技術(shù)迷專欄作者 投稿,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載。

        1、靈魂一問:你的登錄接口真的安全嗎?
        2、HashMap 中這些設(shè)計(jì),絕了~
        3、在 IntelliJ IDEA 中這樣使用 Git,賊方便了!
        4、計(jì)算機(jī)時(shí)間到底是怎么來的?程序員必看的時(shí)間知識(shí)!
        5、這些IDEA的優(yōu)化設(shè)置趕緊安排起來,效率提升杠杠的!
        6、21 款 yyds 的 IDEA插件
        7、真香!用 IDEA 神器看源碼,效率真高!

        點(diǎn)分享

        點(diǎn)收藏

        點(diǎn)點(diǎn)贊

        點(diǎn)在看 

        瀏覽 92
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            依依成人在线 | 国产999精品久久久久久绿帽 | 约操美女 | 四虎永久免费 | 啊灬啊灬啊灬高潮来了 | 娘子你的乳儿又香又软 | 亚洲AV成人无码电影在线观看 | 日本老妇乱伦 | 九七成人网 | 最近日韩中文字幕中文翻译歌词 |