微服務(wù)網(wǎng)關(guān)實(shí)戰(zhàn)——SpringCloudGateway-創(chuàng)新互聯(lián)

導(dǎo)讀

作為Netflix Zuul的替代者,Spring Cloud Gateway是一款非常實(shí)用的微服務(wù)網(wǎng)關(guān),在Spring Cloud微服務(wù)架構(gòu)體系中發(fā)揮非常大的作用。本文對(duì)Spring Cloud Gateway常見(jiàn)使用場(chǎng)景進(jìn)行了梳理,希望對(duì)微服務(wù)開(kāi)發(fā)人員提供一些幫助。

成都創(chuàng)新互聯(lián)服務(wù)項(xiàng)目包括鹿城網(wǎng)站建設(shè)、鹿城網(wǎng)站制作、鹿城網(wǎng)頁(yè)制作以及鹿城網(wǎng)絡(luò)營(yíng)銷(xiāo)策劃等。多年來(lái),我們專(zhuān)注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,鹿城網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到鹿城省份的部分城市,未來(lái)相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

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

1.概述

Spring cloud gateway是spring官方基于Spring 5.0、Spring Boot2.0和Project Reactor等技術(shù)開(kāi)發(fā)的網(wǎng)關(guān),Spring Cloud Gateway旨在為微服務(wù)架構(gòu)提供簡(jiǎn)單、有效和統(tǒng)一的API路由管理方式,Spring Cloud Gateway作為Spring Cloud生態(tài)系統(tǒng)中的網(wǎng)關(guān),目標(biāo)是替代Netflix Zuul,其不僅提供統(tǒng)一的路由方式,并且還基于Filer鏈的方式提供了網(wǎng)關(guān)基本的功能,例如:安全、監(jiān)控/埋點(diǎn)、限流等。

2.核心概念

網(wǎng)關(guān)提供API全托管服務(wù),豐富的API管理功能,輔助企業(yè)管理大規(guī)模的API,以降低管理成本和安全風(fēng)險(xiǎn),包括協(xié)議適配、協(xié)議轉(zhuǎn)發(fā)、安全策略、防刷、流量、監(jiān)控日志等貢呢。一般來(lái)說(shuō)網(wǎng)關(guān)對(duì)外暴露的URL或者接口信息,我們統(tǒng)稱(chēng)為路由信息。如果研發(fā)過(guò)網(wǎng)關(guān)中間件或者使用過(guò)Zuul的人,會(huì)知道網(wǎng)關(guān)的核心是Filter以及Filter Chain(Filter責(zé)任鏈)。Sprig Cloud Gateway也具有路由和Filter的概念。下面介紹一下Spring Cloud Gateway中幾個(gè)重要的概念。

  • 路由。路由是網(wǎng)關(guān)最基礎(chǔ)的部分,路由信息有一個(gè)ID、一個(gè)目的URL、一組斷言和一組Filter組成。如果斷言路由為真,則說(shuō)明請(qǐng)求的URL和配置匹配

  • 斷言。Java8中的斷言函數(shù)。Spring Cloud Gateway中的斷言函數(shù)輸入類(lèi)型是Spring5.0框架中的ServerWebExchange。Spring Cloud Gateway中的斷言函數(shù)允許開(kāi)發(fā)者去定義匹配來(lái)自于http request中的任何信息,比如請(qǐng)求頭和參數(shù)等。

  • 過(guò)濾器。一個(gè)標(biāo)準(zhǔn)的Spring webFilter。Spring cloud gateway中的filter分為兩種類(lèi)型的Filter,分別是Gateway Filter和Global Filter。過(guò)濾器Filter將會(huì)對(duì)請(qǐng)求和響應(yīng)進(jìn)行修改處理

微服務(wù)網(wǎng)關(guān)實(shí)戰(zhàn)——Spring Cloud Gateway

如上圖所示,Spring cloudGateway發(fā)出請(qǐng)求。然后再由Gateway Handler Mapping中找到與請(qǐng)求相匹配的路由,將其發(fā)送到Gateway web handler。Handler再通過(guò)指定的過(guò)濾器鏈將請(qǐng)求發(fā)送到我們實(shí)際的服務(wù)執(zhí)行業(yè)務(wù)邏輯,然后返回。

快速入門(mén)

以Spring Boot框架開(kāi)發(fā)為例,啟動(dòng)一個(gè)Gateway服務(wù)模塊(以Consul作為注冊(cè)中心),一個(gè)后端服務(wù)模塊。client端請(qǐng)求經(jīng)gateway服務(wù)把請(qǐng)求路由到后端服務(wù)。

前提條件:

  • Consul:版本1.5.0。

  • Spring bot:版本2.1.5。

  • Spring cloud:版本Greenwich.SR1。

  • Redis:版本5.0.5。

1.微服務(wù)開(kāi)發(fā)

這里以使用Spring Boot框架開(kāi)發(fā)微服務(wù)為例,啟動(dòng)一個(gè)服務(wù)并注冊(cè)到Consul。

引入依賴(lài):


<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>

注冊(cè)服務(wù)到Consul,配置文件配置如下:

spring:
  application:
    name: service-consumer
  cloud:
    consul:
      host: 127.0.0.1
      port: 8500
      discovery:
        service-name: service-consumer

如下定義RestController,發(fā)布HTTP接口。


@RestController
@RequestMapping("/user")
public class UserController {
    @Resource
    private UserService userService;
    @GetMapping(value = "/info")
    public User info() {
        return userService.info();
    }
}

注:此為服務(wù)端配置,經(jīng)Gateway把請(qǐng)求路由轉(zhuǎn)發(fā)到該服務(wù)上。

2.網(wǎng)關(guān)配置

創(chuàng)建一個(gè)Gateway服務(wù),引入以下依賴(lài):


<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>

啟動(dòng)類(lèi)配置如下:

@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

Spring Cloud Gateway對(duì)client端請(qǐng)求起到路由功能,主要配置如下:

server:
  port: 8098
spring:
  application:
    name: service-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true   
          lower-case-service-id: true  
    consul:
      host: 127.0.0.1 #注冊(cè)gateway網(wǎng)關(guān)到consul
      port: 8500
      discovery:
        service-name: service-gateway

此時(shí)使用http://localhost:8089/service-consumer/user/info訪問(wèn)服務(wù),網(wǎng)關(guān)即可對(duì)服務(wù)進(jìn)行路由轉(zhuǎn)發(fā),把請(qǐng)求轉(zhuǎn)發(fā)到具體后端服務(wù)上。此時(shí),url中使用的url前綴service-consumer,是后端服務(wù)在Consul注冊(cè)的服務(wù)名稱(chēng)轉(zhuǎn)為小寫(xiě)字母以后的字符串。

最佳實(shí)踐

01 Gateway網(wǎng)關(guān)配置

本文第二部分開(kāi)發(fā)規(guī)范中定義了網(wǎng)關(guān)進(jìn)行路由轉(zhuǎn)發(fā)的配置,除了上述配置方式還可以使用下面的方式進(jìn)行配置:

gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true
      routes:
      - id: service_consumer
        uri: lb://service-consumer
        predicates:
        - Path= /consumer/**
        filters:
        - StripPrefix=1

在上面的配置中,配置了一個(gè)Path的predicat,將以/consumer/**開(kāi)頭的請(qǐng)求都會(huì)轉(zhuǎn)發(fā)到uri為lb://service-consumer的地址上,lb://service-consumer(注冊(cè)中心中服務(wù)的名稱(chēng))即service-consumer服務(wù)的負(fù)載均衡地址,并用StripPrefix的filter 在轉(zhuǎn)發(fā)之前將/consumer去掉。同時(shí)將spring.cloud.gateway.discovery.locator.enabled改為false,如果不改的話,之前的http://localhost:8081/service-consumer/user/info這樣的請(qǐng)求地址也能正常訪問(wèn),因?yàn)檫@時(shí)為每個(gè)服務(wù)創(chuàng)建了2個(gè)router。

本文第二部分和本節(jié)一共講述了兩種配置方式,兩種配置都可以實(shí)現(xiàn)請(qǐng)求路由轉(zhuǎn)發(fā)的功能。參數(shù)spring.cloud.gateway.discovery.locator.enabled為true,表明Gateway開(kāi)啟服務(wù)注冊(cè)和發(fā)現(xiàn)的功能,并且Spring Cloud Gateway自動(dòng)根據(jù)服務(wù)發(fā)現(xiàn)為每一個(gè)服務(wù)創(chuàng)建了一個(gè)router,這個(gè)router將以服務(wù)名開(kāi)頭的請(qǐng)求路徑轉(zhuǎn)發(fā)到對(duì)應(yīng)的服務(wù)。spring.cloud.gateway.discovery.locator.lowerCaseServiceId是將請(qǐng)求路徑上的服務(wù)名配置為小寫(xiě)(因?yàn)榉?wù)注冊(cè)的時(shí)候,向注冊(cè)中心注冊(cè)時(shí)將服務(wù)名轉(zhuǎn)成大寫(xiě)的了)。

gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true

02 Gateway跨域訪問(wèn)

Spring Cloud Gateway還針對(duì)跨域訪問(wèn)做了設(shè)計(jì),可以使用以下配置解決跨域訪問(wèn)問(wèn)題:


spring:
  cloud:
    gateway:
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedOrigins: "https://docs.spring.io"
            allowedMethods:
            - GET
            allowHeaders:
            - Content-Type

在上面的示例中,允許來(lái)自https://docs.spring.io的get請(qǐng)求進(jìn)行訪問(wèn),并且表明服務(wù)器允許請(qǐng)求頭中攜帶字段Content-Type。

03 Gateway 過(guò)濾器

Spring Cloud Gateway的filter生命周期不像Zuul那么豐富,它只有兩個(gè):“pre”和“post”:

  • pre:這種過(guò)濾器在請(qǐng)求被路由之前調(diào)用??梢岳眠@個(gè)過(guò)濾器實(shí)現(xiàn)身份驗(yàn)證、在集群中選擇請(qǐng)求的微服務(wù)、記錄調(diào)試的信息。

  • post:這種過(guò)濾器在路由到服務(wù)器之后執(zhí)行。這種過(guò)濾器可用來(lái)為響應(yīng)添加HTTP Header、統(tǒng)計(jì)信息和指標(biāo)、響應(yīng)從微服務(wù)發(fā)送給客戶端等。

Spring Cloud gateway的filter分為兩種:GatewayFilter和Globalfilter。GlobalFilter會(huì)應(yīng)用到所有的路由上,而Gatewayfilter將應(yīng)用到單個(gè)路由或者一個(gè)分組的路由上。

利用Gatewayfilter可以修改請(qǐng)求的http的請(qǐng)求或者是響應(yīng),或者根據(jù)請(qǐng)求或者響應(yīng)做一些特殊的限制。更多時(shí)候可以利用Gatewayfilter做一些具體的路由配置。

下面的配置是AddRequestParameter Gatewayfilter的相關(guān)配置。

spring:
  application:
    name: service-gateway
  cloud:
    gateway:
     discovery:
        locator:
         enabled: true
     routes:
     - id: parameter_route
      uri: http://localhost:8504/user/info
      filters:
      - AddRequestParameter=foo, bar
      predicates:
      - Method=GET

上述配置中指定了轉(zhuǎn)發(fā)的地址,設(shè)置所有的GET方法都會(huì)自動(dòng)添加foo=bar,當(dāng)請(qǐng)求符合上述路由條件時(shí),即可在后端服務(wù)上接收到Gateway網(wǎng)關(guān)添加的參數(shù)。

另外再介紹一種比較常用的filter,即StripPrefix gateway filter。

配置如下:

spring:
  cloud:
    gateway:
      routes:
      - id: stripprefixfilter
        uri: lb://service-consumer
        predicates:
        - Path=/consumer/**
        filters:
        - StripPrefix=1

當(dāng)client端使用http://localhost:8098/consumer/user/info路徑進(jìn)行請(qǐng)求時(shí),如果根據(jù)上述進(jìn)行配置Gateway會(huì)將請(qǐng)求轉(zhuǎn)換為http://localhost:8098/service-consumer/user/info。以此作為前端請(qǐng)求的最終目的地。

04 Gateway請(qǐng)求匹配

Gateway網(wǎng)關(guān)可以根據(jù)不同的方式進(jìn)行匹配進(jìn)而把請(qǐng)求分發(fā)到不同的后端服務(wù)上。

通過(guò)header進(jìn)行匹配,把請(qǐng)求分發(fā)到不同的服務(wù)上,配置如下:

spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: http://baidu.com
        predicates:
        - Header=X-Request-Id, \d+

通過(guò)curl測(cè)試:curl http://localhost:8080 -H "X-Request-Id:666666",返回頁(yè)面代碼證明匹配成功。

如果是以Host進(jìn)行匹配,配置如下:

spring:
  cloud:
    gateway:
      routes:
      - id: host_route
        uri: http://baidu.com
        predicates:
        - Host=**.baidu.com

通過(guò)curl http://localhost:8098 -H "Host: www.baidu.com"進(jìn)行測(cè)試,返回頁(yè)面代碼即轉(zhuǎn)發(fā)成功。

可以通過(guò)POST、GET、PUT、DELTE等不同的方式進(jìn)行路由:


spring:
  cloud:
    gateway:
      routes:
      - id: method_route
        uri: http://baidu.com
        predicates:
        - Method=GET

通過(guò) curl http://localhost:8098 進(jìn)行測(cè)試,返回頁(yè)面代碼即表示成功。

上述是單個(gè)匹配進(jìn)行路由,如果把多個(gè)匹配合在一起進(jìn)行路由,必須滿足所有的路有條件才會(huì)進(jìn)行路由轉(zhuǎn)發(fā)。

05 Gateway熔斷

Spring Cloud Gateway也可以利用Hystrix的熔斷特性,在流量過(guò)大時(shí)進(jìn)行服務(wù)降級(jí),同時(shí)項(xiàng)目中必須加上Hystrix的依賴(lài)。


<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

配置后,Gateway將使用fallbackcmd作為名稱(chēng)生成HystrixCommand對(duì)象進(jìn)行熔斷處理。如果想添加熔斷后的回調(diào)內(nèi)容,需要添加以下配置:

spring:
  cloud:
    gateway:
      routes:
      - id: hystrix_route
        uri: lb://consumer-service
        predicates:
        - Path=/consumer/**
        filters:
        - name: Hystrix
          args:
            name: fallbackcmd
            fallbackUri: forward:/fallback
        - StripPrefix=1
hystrix:  
  command:
    fallbackcmd:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 5000 #超時(shí)時(shí)間,若不設(shè)置超時(shí)時(shí)間則有可能無(wú)法觸發(fā)熔斷

上述配置中給出了熔斷之后返回路徑,因此,在Gateway服務(wù)模塊添加/fallback路徑,以作為服務(wù)熔斷時(shí)的返回路徑。


@RestController
public class GatewayController {
    @RequestMapping(value = "/fallback")
    public String fallback(){
        return "fallback nothing";
    }
}

fallbackUri: forward:/fallback配置了 fallback 時(shí)要會(huì)調(diào)的路徑,當(dāng)調(diào)用 Hystrix 的 fallback 被調(diào)用時(shí),請(qǐng)求將轉(zhuǎn)發(fā)到/fallback這個(gè) URI,并以此路徑的返回值作為返回結(jié)果。

06 Gateway重試路由器

通過(guò)簡(jiǎn)單的配置,Spring Cloud Gateway就可以支持請(qǐng)求重試功能。

spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: http://localhost:8504/user/info
        predicates:
        - Path=/user/**
        filters:
        - name: Retry
          args:
            retries: 3
            status: 503
        - StripPrefix=1

Retry GatewayFilter通過(guò)四個(gè)參數(shù)來(lái)控制重試機(jī)制,參數(shù)說(shuō)明如下:

  • retries:重試次數(shù),默認(rèn)值是 3 次。

  • statuses:HTTP 的狀態(tài)返回碼,取值請(qǐng)參考:org.springframework.http.HttpStatus。

  • methods:指定哪些方法的請(qǐng)求需要進(jìn)行重試邏輯,默認(rèn)值是 GET 方法,取值參考:org.springframework.http.HttpMethod。

  • series:一些列的狀態(tài)碼配置,取值參考:org.springframework.http.HttpStatus.Series。符合的某段狀態(tài)碼才會(huì)進(jìn)行重試邏輯,默認(rèn)值是 SERVER_ERROR,值是 5,也就是 5XX(5 開(kāi)頭的狀態(tài)碼),共有5個(gè)值。

使用上述配置進(jìn)行測(cè)試,當(dāng)后臺(tái)服務(wù)不可用時(shí),會(huì)在控制臺(tái)看到請(qǐng)求三次的日志,證明此配置有效。

07 Gateway 限流操作

Spring Cloud Gateway本身集成了限流操作,Gateway限流需要使用Redis,pom文件中添加Redis依賴(lài):


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>

配置文件中配置如下:


spring:
  cloud:
    gateway:
      routes:
      - id: rate_limit_route
        uri: lb://service-consumer
        predicates:
        - Path=/user/**
        filters:
        - name: RequestRateLimiter
          args:
            key-resolver: "#{@hostAddrKeyResolver}"
            redis-rate-limiter.replenishRate: 1
            redis-rate-limiter.burstCapacity: 3
        - StripPrefix=1
    consul:
      host: 127.0.0.1
      port: 8500
      discovery:
        service-name: service-gateway
        instance-id: service-gateway-233

  redis:
    host: localhost
    port: 6379

在上面的配置問(wèn)價(jià)中,配置了Redis的信息,并配置了RequestRateLimiter的限流過(guò)濾器,該過(guò)濾器需要配置三個(gè)參數(shù):

  • BurstCapacity:令牌桶的總?cè)萘俊?/p>

  • replenishRate:令牌通每秒填充平均速率。

  • Key-resolver:用于限流的解析器的Bean對(duì)象的名字。它使用SpEL表達(dá)式#{@beanName}從Spring容器中獲取bean對(duì)象。

注意:filter下的name必須是RequestRateLimiter。

Key-resolver參數(shù)后面的bean需要自己實(shí)現(xiàn),然后注入到Spring容器中。KeyResolver需要實(shí)現(xiàn)resolve方法,比如根據(jù)ip進(jìn)行限流,則需要用hostAddress去判斷。實(shí)現(xiàn)完KeyResolver之后,需要將這個(gè)類(lèi)的Bean注冊(cè)到Ioc容器中。還可以根據(jù)uri限流,同hostname限流是一樣的。例如以ip限流為例,在gateway模塊中添加以下實(shí)現(xiàn):


public class HostAddrKeyResolver implements KeyResolver {

    @Override
    public Mono<String> resolve(ServerWebExchange exchange) {
        return Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
    }

    public HostAddrKeyResolver hostAddrKeyResolver() {
        return new HostAddrKeyResolver();
    }
}

把該類(lèi)注入到spring容器中:


@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }

    @Bean
    public HostAddrKeyResolver hostAddrKeyResolver(){
        return new HostAddrKeyResolver();
    }
}

基于上述配置,可以對(duì)請(qǐng)求基于ip的訪問(wèn)進(jìn)行限流。

08 自定義Gatewayfilter

Spring Cloud Gateway內(nèi)置了過(guò)濾器,能夠滿足很多場(chǎng)景的需求。當(dāng)然,也可以自定義過(guò)濾器。在Spring Cloud Gateway自定義過(guò)濾器,過(guò)濾器需要實(shí)現(xiàn)GatewayFilter和Ordered這兩個(gè)接口。

下面的例子實(shí)現(xiàn)了Gatewayfilter,它可以以log日志的形式記錄每次請(qǐng)求耗費(fèi)的時(shí)間,具體實(shí)現(xiàn)如下:

public class RequestTimeFilter implements GatewayFilter, Ordered {
    private static final Log log = LogFactory.getLog(GatewayFilter.class);
    private static final String REQUEST_TIME_BEGIN = "requestTimeBegin";
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        exchange.getAttributes().put(REQUEST_TIME_BEGIN, System.currentTimeMillis());
        return chain.filter(exchange).then(
                Mono.fromRunnable(() -> {
                    Long startTime = exchange.getAttribute(REQUEST_TIME_BEGIN);
                    if (startTime != null) {
                        log.info("請(qǐng)求路徑:"+exchange.getRequest().getURI().getRawPath() + "消耗時(shí)間: " + (System.currentTimeMillis() - startTime) + "ms");
                    }
                })
        );
    }
    @Override
    public int getOrder() {
        return 0;
    }
}

上述代碼中定義了自己實(shí)現(xiàn)的過(guò)濾器。Ordered的int getOrder()方法是來(lái)給過(guò)濾器定優(yōu)先級(jí)的,值越大優(yōu)先級(jí)越低。還有一個(gè)filter(ServerWebExchange exchange, GatewayFilterChain chain)方法,在該方法中,先記錄了請(qǐng)求的開(kāi)始時(shí)間,并保存在ServerWebExchange中,此處是一個(gè)“pre”類(lèi)型的過(guò)濾器。然后再chain.filter()的內(nèi)部類(lèi)中的run()方法中相當(dāng)于"post"過(guò)濾器,在此處打印了請(qǐng)求所消耗的時(shí)間。

接下來(lái)將該過(guò)濾器注冊(cè)到router中,代碼如下。


 @Bean
    public RouteLocator customerRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route(r -> r.path("/user/**")
                        .filters(f -> f.filter(new RequestTimeFilter())
                                .addResponseHeader("X-Response-Default-Foo", "Default-Bar"))
                        .uri("http://localhost:8504/user/info")
                        .order(0)
                        .id("customer_filter_router")
                )
                .build();
    }

除了上述代碼的方式配置我們自定義的過(guò)濾器的方式之外,也可以在application.yml文件中直接配置,這里不再贅述。

啟動(dòng)程序,通過(guò)curl http://localhost:8098/user/info控制臺(tái)會(huì)打印出請(qǐng)求消耗時(shí)間,日志如下:


....
2019-05-22 15:13:31.221  INFO 19780 --- [ctor-http-nio-4] o.s.cloud.gateway.filter.GatewayFilter   : 請(qǐng)求路徑:/user/info消耗時(shí)間: 54ms
...
2019-05-22 16:46:23.785  INFO 29928 --- [ctor-http-nio-1] o.s.cloud.gateway.filter.GatewayFilter   : 請(qǐng)求路徑:/user/info3消耗時(shí)間: 5ms
……

09 自定義GlobalFilter

Spring Cloud Gateway根據(jù)作用范圍分為GatewayFilter和GlobalFilter,二者區(qū)別如下:

  • GatewayFilter : 需要通過(guò)spring.cloud.routes.filters 配置在具體路由下,只作用在當(dāng)前路由上或通過(guò)spring.cloud.default-filters配置在全局,作用在所有路由上。

  • GlobalFilter:全局過(guò)濾器,不需要在配置文件中配置,作用在所有的路由上,最終通過(guò)GatewayFilterAdapter包裝成GatewayFilterChain可識(shí)別的過(guò)濾器,它為請(qǐng)求業(yè)務(wù)以及路由的URI轉(zhuǎn)換為真實(shí)業(yè)務(wù)服務(wù)的請(qǐng)求地址的核心過(guò)濾器,不需要配置,系統(tǒng)初始化時(shí)加載,并作用在每個(gè)路由上。

在上一小節(jié)中定義的是Gatewayfilter,下面實(shí)現(xiàn)的是Globalfilter:

public class TokenFilter implements GlobalFilter, Ordered {
    Logger logger= LoggerFactory.getLogger( TokenFilter.class );
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        if (token == null || token.isEmpty()) {
            logger.info( "token 為空,無(wú)法進(jìn)行訪問(wèn)." );
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

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

上述代碼實(shí)現(xiàn)了Globalfilter,具體邏輯是判斷請(qǐng)求中是否含參數(shù)token,如果沒(méi)有,則校驗(yàn)不通過(guò),對(duì)所有請(qǐng)求都有效。如果含有token則轉(zhuǎn)發(fā)到具體后端服務(wù)上,如果沒(méi)有則校驗(yàn)不通過(guò)。

通過(guò)curl http://localhost:8098/user/info進(jìn)行訪問(wèn),因?yàn)槁窂街胁缓袇?shù)token,則無(wú)法通過(guò)校驗(yàn),打印日志如下:


2019-05-22 15:27:11.078  INFO 5956 --- [ctor-http-nio-1] com.song.gateway.TokenFilter             : token 為空,無(wú)法進(jìn)行訪問(wèn).
...

通過(guò)curl http://localhost:8098/user/info?token=123進(jìn)行訪問(wèn)時(shí),則可以獲取到后端服務(wù)返回結(jié)果。

本文由博云研究院原創(chuàng)發(fā)表,轉(zhuǎn)載請(qǐng)注明出處。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)cdcxhl.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性?xún)r(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

網(wǎng)頁(yè)題目:微服務(wù)網(wǎng)關(guān)實(shí)戰(zhàn)——SpringCloudGateway-創(chuàng)新互聯(lián)
分享地址:http://muchs.cn/article2/ceegic.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站制作、企業(yè)網(wǎng)站制作、網(wǎng)站收錄、網(wǎng)站排名、移動(dòng)網(wǎng)站建設(shè)外貿(mào)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)