<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 8793字,需瀏覽 18分鐘

           ·

          2021-09-13 03:26

          點擊關(guān)注公眾號,Java干貨及時送達

          Java術(shù) | 

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

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

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

          SpringCloud Gateway是作為一個獨立的微服務(wù)工作的,所以我們需要創(chuàng)建一個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也是需要注冊到Nacos中的,因為只有注冊到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)的路由配置總共需要配置三項,其中id是該路由的唯一標(biāo)識,uri指定的是需要路由到的服務(wù)地址,而predicates表示斷言,如果滿足斷言的要求,則網(wǎng)關(guān)便會將請求交給uri指定的服務(wù), lb:// 表示將請求負載均衡到 service-user 服務(wù)。斷言的形式有很多,比如這里使用的Path,它是用來判斷請求路徑的,當(dāng)請求路徑以user開頭,該請求就會被這一網(wǎng)關(guān)配置處理。

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

          @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;
          }
          }

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

          路由配置

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

          1.BeforeRoutePredicateFactory:判斷是否為某個時間點之前的請求2.AfterRoutePredicateFactory:判斷是否為某個時間點之后的請求3.BetweenRoutePredicateFactory:判斷是否為某兩個時間點之間的請求4.CookieRoutePredicateFactory:判斷是否包含某些cookie5.HeaderRoutePredicateFactory:判斷是否包含某些header6.HostRoutePredicateFactory:判斷請求是否是訪問某個host7.MethodRoutePredicateFactory:判斷請求方式是否是指定的方式8.PathRoutePredicateFactory:判斷請求路徑是否滿足規(guī)則9.QueryRoutePredicateFactory:判斷請求參數(shù)是否包含指定的參數(shù)10.RemoteAddrRoutePredicateFactory:判斷請求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]

          它表示請求的時間在2017年1月20日17點42分之前的請求就滿足該路由配置,網(wǎng)關(guān)就會將請求交給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]

          它表示請求的時間在2017年1月20日17點42分之后的請求就滿足該路由配置。

          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]

          它表示請求的時間在2017年1月20日17點42分與2017年1月21日17點42分之間的請求就滿足該路由配置。

          CookieRoutePredicateFactory配置如下:

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

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

          HeaderRoutePredicateFactory配置如下:

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

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

          HostRoutePredicateFactory配置如下:

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

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

          MethodRoutePredicateFactory配置如下:

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

          它表示請求的方式必須為GET或Post。

          PathRoutePredicateFactory配置如下:

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

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

          QueryRoutePredicateFactory配置如下:

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

          它表示請求中必須攜帶名為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

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

          1100 0000 1010 1000 0000 0001 0000 0001

          也就是說,當(dāng)主機號全為1時,該IP為最大地址,即:192.168.1.255,所以192.168.1.1/24代表的IP段是192.168.1.1~192.168.1.255。由此可知,只要請求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

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

          過濾器配置

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

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

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

          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)各種場景,Gateway還提供了一種特殊的過濾器——GlobalFiler(全局過濾器),它的作用與default-filter類似,區(qū)別在于GlobalFilter需要我們自己去實現(xiàn),要做的就是實現(xiàn)GlobalFilter接口:

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

          @Override
          public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
          // 獲取請求參數(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();
          }
          }

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

          處理跨域

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

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

          配置方式如下:

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

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

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

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

          點分享

          點收藏

          點點贊

          點在看 

          瀏覽 92
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲在线观看视频 | 大逼色网站 | 天天日天天操天天干 | 韩日毛片 | 色免男免费香蕉视频 |