<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ù)網(wǎng)關(guān)實(shí)踐

          共 6254字,需瀏覽 13分鐘

           ·

          2021-11-09 06:47

          Spring Cloud GateWay 作為分布式架構(gòu)下常見(jiàn)的服務(wù)網(wǎng)關(guān),為內(nèi)部各服務(wù)對(duì)外提供統(tǒng)一的API入口。同時(shí)還為對(duì)外提供服務(wù)的API提供統(tǒng)一的安全、鑒權(quán)、監(jiān)控等功能

          abstract.png

          基本實(shí)踐

          目標(biāo)服務(wù)

          為了便于演示網(wǎng)關(guān)服務(wù)的作用,這里我們先提供一個(gè)目標(biāo)服務(wù)——payment。其服務(wù)接口的Controller實(shí)現(xiàn)如下所示

          @RestController
          @RequestMapping("pay3")
          public?class?PaymentController3?{

          ????@Value("${server.port}")
          ????private?String?serverPort;

          ????@GetMapping("/test1")
          ????public?String?test1()?{
          ????????String?uuid?=?UUID.randomUUID().toString();
          ????????String?msg?=?"[Payment?Service?-?test1],?port:"?+?serverPort
          ????????????+?",?uuid:?"?+?uuid;
          ????????return?msg;
          ????}

          ????@GetMapping("/test2")
          ????public?String?test2(@RequestParam?String?name)?{
          ????????String?msg?=?"[Payment?Service?-?test2],?port:"?+?serverPort
          ????????????+?",?name:?"?+?name;
          ????????return?msg;
          ????}

          ????@GetMapping("/hello1")
          ????public?String?hello1()?{
          ????????String?msg?=?"[Payment?Service?-?hello1],?port:"?+?serverPort;
          ????????return?msg;
          ????}

          ????@GetMapping("/hello2")
          ????public?String?hello2(@RequestParam?Integer?num)?{
          ????????String?msg?=?"[Payment?Service?-?hello2],?port:"?+?serverPort
          ????????????+?",?num:?"?+?num;
          ????????return?msg;
          ????}

          }

          啟動(dòng)payment服務(wù)的兩個(gè)實(shí)例,分別允許在8004、8005端口。這里我們使用Consul作為注冊(cè)中心。如下所示

          figure 1.jpeg

          網(wǎng)關(guān)服務(wù)

          現(xiàn)在我們建立一個(gè)ApiGateWay服務(wù),用于實(shí)踐我們的服務(wù)網(wǎng)關(guān)。首先在POM中引入 spring-cloud-starter-gateway 依賴

          <dependencyManagement>
          ??<dependencies>

          ????
          ????<dependency>
          ??????<groupId>org.springframework.bootgroupId>
          ??????<artifactId>spring-boot-dependenciesartifactId>
          ??????<version>2.2.2.RELEASEversion>
          ??????<type>pomtype>
          ??????<scope>importscope>
          ????dependency>

          ????
          ????<dependency>
          ??????<groupId>org.springframework.cloudgroupId>
          ??????<artifactId>spring-cloud-dependenciesartifactId>
          ??????<version>Hoxton.SR1version>
          ??????<type>pomtype>
          ??????<scope>importscope>
          ????dependency>

          ??dependencies>
          dependencyManagement>

          <dependencies>

          ??
          ??<dependency>
          ????<groupId>org.springframework.cloudgroupId>
          ????<artifactId>spring-cloud-starter-gatewayartifactId>
          ??dependency>

          dependencies>

          其配置文件如下所示。可以看到該服務(wù)網(wǎng)關(guān)也會(huì)被注冊(cè)到Consul中。當(dāng)然在ApiGateWay的POM中也需要引入Consul依賴。具體地,網(wǎng)關(guān)相關(guān)的配置即是通過(guò)spring.cloud.gateway配置項(xiàng)進(jìn)行配置

          server:
          ??port:?9527

          spring:
          ??application:
          ????name:?ApiGateWay
          ??cloud:
          ????#?注冊(cè)中心Consul配置
          ????consul:
          ??????#?Consul?地址信息
          ??????host:?127.0.0.1
          ??????port:?8500
          ??????discovery:
          ????????#?服務(wù)名
          ????????service-name:?${spring.application.name}
          ????#?網(wǎng)關(guān)GateWay配置
          ????gateway:
          ??????discovery:
          ????????locator:
          ??????????#?實(shí)現(xiàn)通過(guò)注冊(cè)中心動(dòng)態(tài)創(chuàng)建基于服務(wù)名的路由
          ??????????enabled:?true
          ??????routes:
          ??????????#?路由的唯一標(biāo)識(shí)
          ????????-?id:?payment_test1_route
          ??????????#?目標(biāo)地址
          ??????????uri:?http://localhost:8004
          ??????????#?路由匹配的謂詞條件
          ??????????predicates:
          ????????????#?Path謂詞,?根據(jù)請(qǐng)求路徑進(jìn)行匹配
          ????????????-?Path=/pay3/test1
          ????????-?id:?payment_test2_route
          ??????????#?基于注冊(cè)中心的動(dòng)態(tài)路由,?格式:?lb協(xié)議(lb://)+服務(wù)名
          ??????????uri:?lb://payment
          ??????????predicates:
          ????????????-?Path=/pay3/test2

          其中:

          • spring.cloud.gateway.routes.id 配置項(xiàng)用于配置路由的唯一標(biāo)識(shí)
          • spring.cloud.gateway.routes.uri 配置項(xiàng)用于路由匹配后進(jìn)行轉(zhuǎn)發(fā)的目標(biāo)地址
          • spring.cloud.gateway.routes.predicates 配置項(xiàng)用于設(shè)置路由匹配所需的謂詞條件。具體地,Path謂詞用于根據(jù)路徑進(jìn)行路由匹配

          具體對(duì)于payment_test1_route而言,其目標(biāo)uri是具體地允許在某端口的服務(wù)。此舉顯然無(wú)法充分體現(xiàn)payment集群服務(wù)的作用。故可通過(guò) spring.cloud.gateway.discovery.locator.enabled 配置項(xiàng)實(shí)現(xiàn)通過(guò)注冊(cè)中心動(dòng)態(tài)創(chuàng)建基于服務(wù)名的路由。這也是為什么需要在ApiGateWay服務(wù)添加Consul依賴。事實(shí)上,GateWay還支持通過(guò)Java配置類的方式進(jìn)行路由配置,如下所示

          @Configuration
          public?class?GateWayConfig?{

          ????@Bean
          ????public?RouteLocator?routeLocator1(RouteLocatorBuilder?routeLocatorBuilder)?{
          ????????return?routeLocatorBuilder.routes()
          ????????????.route("payment_hello1_route",?r?->?r.path("/pay3/hello1")
          ????????????????.uri("http://localhost:8004")?)
          ????????????.route("payment_hello2_route",?r?->?r.path("/pay3/hello2")
          ????????????????.uri("lb://payment")?)
          ????????????.build();
          ????}

          }

          至此ApiGateWay服務(wù)就已經(jīng)基本完成了,其啟動(dòng)類如下所示

          @SpringBootApplication
          @EnableDiscoveryClient?//?使用Consul作為注冊(cè)中心時(shí)使用
          public?class?ApiGateWayApplication?{
          ????public?static?void?main(String[]?args)?{
          ????????SpringApplication.run(ApiGateWayApplication.class,?args);
          ????}
          }

          啟動(dòng)ApiGateWay服務(wù),測(cè)試結(jié)果如下,符合預(yù)期

          figure 2.jpeg

          Predicate謂詞

          根據(jù)前文可知,Predicate謂詞即是GateWay進(jìn)行路由轉(zhuǎn)發(fā)時(shí)所需滿足的匹配條件。這里對(duì)GateWay中常見(jiàn)的謂詞進(jìn)行介紹

          After、Before、Between

          After、Before、Between謂詞要求請(qǐng)求時(shí)的時(shí)間分別位于所配置時(shí)間之后、之前、之間才滿足匹配要求。配置示例如下所示

          #?Case?1
          predicates:
          ??#?請(qǐng)求時(shí)間在指定時(shí)間之后才滿足條件
          ??-?After=2021-09-06T21:51:37.485+08:00[Asia/Shanghai]

          #?Case?2
          predicates:
          ??#?請(qǐng)求時(shí)間在指定時(shí)間之前才滿足條件
          ??-?Before=2021-09-06T21:51:37.485+08:00[Asia/Shanghai]

          #?Case?3
          predicates:
          ??#?請(qǐng)求時(shí)間在指定時(shí)間之間才滿足條件
          ??-?Between=2021-09-06T21:51:37.485+08:00[Asia/Shanghai],?2021-09-06T22:30:37.485+08:00[Asia/Shanghai]

          其中該配置值需要帶時(shí)區(qū)信息,可通過(guò)下述代碼獲取

          public?class?Test1?{

          ????@Test
          ????public?static?void?main(String[]?args)?{
          ????????ZonedDateTime?zonedDateTime?=?ZonedDateTime.now();
          ????????System.out.println(zonedDateTime);
          ????}
          }

          測(cè)試結(jié)果如下所示

          figure 3.jpeg

          Cookie

          Cookie謂詞要求請(qǐng)求攜帶相應(yīng)的cookie信息,其還支持正則表達(dá)式。配置示例如下所示

          #?Case?1
          predicates:
          ??#?請(qǐng)求需攜帶cookie信息,key為id,value為2345
          ??-?Cookie=id,?2345

          #?Case?2
          predicates:
          ??#?請(qǐng)求需攜帶cookie信息,key為id,value為一個(gè)或多個(gè)數(shù)字
          ??-?Cookie=id,?\d+

          這里使用Case 2的謂詞進(jìn)行驗(yàn)證,效果如下,符合預(yù)期

          figure 4.jpeg

          Header

          Header謂詞要求請(qǐng)求攜帶相應(yīng)的請(qǐng)求頭,其還支持正則表達(dá)式。配置示例如下所示

          #?Case?1
          predicates:
          ??#?請(qǐng)求需攜帶請(qǐng)求頭屬性,屬性名為X-Request-Id,value為9978
          ??-?Header=X-Request-Id,?9978

          #?Case?2
          predicates:
          ??#?請(qǐng)求需攜帶請(qǐng)求頭屬性,屬性名為X-Request-Id,value為一個(gè)或多個(gè)數(shù)字
          ??-?Header=X-Request-Id,?\d+

          這里使用Case 2的謂詞進(jìn)行驗(yàn)證,效果如下,符合預(yù)期

          figure 5.jpeg

          Method

          Method謂詞要求請(qǐng)求的方法類型滿足指定類型,其支持多個(gè)值。配置示例如下所示

          #?Case?1
          predicates:
          ??#?請(qǐng)求方法類型需要為?POST?或?GET
          ??-?Method=POST,?GET

          Filter過(guò)濾器

          Filter過(guò)濾器可以實(shí)現(xiàn)對(duì)于HTTP請(qǐng)求、響應(yīng)的修改。根據(jù)過(guò)濾器的執(zhí)行時(shí)機(jī)可分為兩類:pre、post,其分別會(huì)在請(qǐng)求被執(zhí)行前和被執(zhí)行后進(jìn)行調(diào)用。而根據(jù)類型可分為兩類:GateWayFilter、GlobalFilter。前者作用于某個(gè)具體的路由下;后者則會(huì)有條件地作用于全部路由

          GateWayFilter

          對(duì)于GateWayFilter而言,其使用方式與Predicate謂詞類似,直接在配置文件通過(guò)filters進(jìn)行配置即可。這里以GateWayFilter中的AddRequestParameter過(guò)濾器為例進(jìn)行說(shuō)明,其會(huì)添加參數(shù)到請(qǐng)求上。我們對(duì)payment_test2_route路由添加該過(guò)濾器,配置如下所示

          spring:
          ??cloud:
          ????gateway:
          ??????routes:
          ????????-?id:?payment_test2_route
          ??????????uri:?lb://payment
          ??????????predicates:
          ????????????-?Path=/pay3/test2
          ??????????filters:
          ????????????#?添加name參數(shù)的值為T(mén)ony
          ????????????-?AddRequestParameter=name,?Tony

          測(cè)試結(jié)果如下所示,符合預(yù)期

          figure 6.jpeg

          GlobalFilter

          而對(duì)于GlobalFilter而言,日常更多的是自定義全局過(guò)濾器,以滿足一些個(gè)性化的需求。這里以鑒權(quán)為例通過(guò)實(shí)現(xiàn)GlobalFilter、Ordered接口來(lái)自定義一個(gè)全局過(guò)濾器,實(shí)現(xiàn)如下所示

          public?class?CustomGlobalFilter?implements?GlobalFilter,?Ordered?{

          ????@Override
          ????public?Mono?filter(ServerWebExchange?exchange,?GatewayFilterChain?chain)?{
          ????????//?獲取請(qǐng)求頭Token
          ????????String?token?=?exchange.getRequest().getHeaders().getFirst("token");

          ????????//?Token為空,?鑒權(quán)失敗
          ????????if(?StringUtils.isBlank(token)?)?{
          ????????????exchange.getResponse().setStatusCode(?HttpStatus.FORBIDDEN?);
          ????????????return?exchange.getResponse().setComplete();
          ????????}

          ????????//?Token校驗(yàn)通過(guò),?繼續(xù)傳遞請(qǐng)求
          ????????return?chain.filter(exchange);
          ????}

          ????/**
          ?????*?值越小,?優(yōu)先級(jí)越高
          ?????*?@return
          ?????*/

          ????@Override
          ????public?int?getOrder()?{
          ????????return?0;
          ????}
          }

          測(cè)試結(jié)果如下所示,符合預(yù)期

          figure 7.jpeg
          瀏覽 58
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  国产免费小视频 | 依人在线大香蕉 | 豆花综合在线无码 | 亚洲超碰成人在线 | 影音先锋成人 |