5.6 PrefixPath GatewayFilter Factory
PrefixPath過濾器工廠類的實現類是PrefixPathGatewayFilterFactory,這個類只需要配置一個prefix參數,它可以給請求的URI添加prefix前綴。如下面配置所示:
spring: cloud: gateway: routes: - id: prefixpath_route uri: http://example.org filters: - PrefixPath=/mypath
這樣的話這個過濾器就會給所示匹配的請求URI添加一個前綴,比如上面的配置,如果收到的請求URI是/hello,那么經過此過濾器之后URI就變為/mypath/hello了。
5.7 PreserveHostHeader GatewayFilter Factory
PreserveHostHeader過濾器工廠的實現類是PreserveHostHeaderGatewayFilterFactory,它表示在Spring Cloud Gateway轉發請求的時候,保持客戶端的Host信息不變,會將這些信息攜帶到后面的服務實例上面。默認為開啟這個過濾器的。要不然后面的實例服務接收到的Host信息就是新的Http Client的Host信息,而不是真實的客戶端的Host信息了。配置如下所示:
spring: cloud: gateway: routes: - id: preserve_host_route uri: http://example.org filters: - PreserveHostHeader
5.8 RequestRateLimiter GatewayFilter Factory
RequestRateLimiter過濾器工廠的實現類是RequestRateLimiterGatewayFilterFactory , 這是一個請求速率限制器,它使用RateLimiter的具體規則決定是否允許處理當前的請求。如果不允許,將返回一個默認的狀態碼 HTTP 429 - Too Many Requests (請求太頻繁)。
另外,這個過濾器使用一個可選擇的參數:keyResolver,這些具體的keyResolver決定了速率限制的規則。 keyResolver是一個實現了KeyResolver接口的Bean類,在配置中,可以使用SpEl表達式引用這個Bean的名字。例如#{@myKeyResolver}就是一個SpEL表達式,它引用了一個名字叫myKeyResolver的Bean。KeyResolver接口如下面代碼所示:
public interface KeyResolver { Mono<String> resolve(ServerWebExchange exchange); }
使用KeyResolver接口可以靈活的配置速率限制器的使用的key,這個key是指限流器限制的依據,可以從exchange中獲取key的具體值,比如根據ip限流,根據某個userId限流等,在未來的計划中,將會添加更多的KeyResolver實現。默認的KeyResolver實現是PrincipalNameKeyResolver,它允許從ServerWebExchange中獲取Principal,並調用Principal.getName();具體的用法可以參考下面Redis RateLimiter的使用.
一般來說,如果KeyResolver找不到一個key,本次請求將會被拒絕,這個行為可以通過配置進行調整:spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key(true 或false)和 spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code (拒絕請求時返回的狀態碼)
注意,RequestRateLimiter不支持快捷方式配置,如下面的配置是錯誤的:
# INVALID SHORTCUT CONFIGURATION
spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}
5.8.1 Redis RateLimiter
這是一個基於redis實現的限流器,Stripe公司(國外一家做支付的公司)目前正在使用這一方式。它需要用到一個Spring boot starter : spring-boot-starter-data-redis-reactive。
如下面配置所示:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
此流量限制方式使用的是令牌桶算法(Token Bucket Algorithm)。這個限流器有兩個重要的參數:
- redis-rate-limiter.replenishRate:這個是令牌產生的速率,表示每秒鍾產生多少個令牌放入到令牌桶中,在沒有任務請求被丟棄的情況下,所有的令牌被使用,用戶在一秒內正好發送這么多請求。這也是對請求的速率進行限制。
- redis-rate-limiter.burstCapacity:這個表示的是令牌桶的容量,表示在這個令牌中最多有這么多令牌,也即表示,一個用戶同時允許最多發送的請求數。這個是上面產生速率的一種限制,因為令牌是被以固定的速率放入到令牌桶中的,如果這一秒內放的令牌沒有被使用,下一秒還會以此速度放入令牌,直到達到令牌桶的容量限制。
比如replenishRate配置的是2,burstCapacity配置是6,那么就表示一秒內,一個用戶最多發送6個請求(令牌桶滿的時候),之后如果請求不斷,也是最多以2次請求/每秒的速率處理請求。
如果replenishRate和burstCapacity的值相關,這就會使網關以一個固定的速率處理請求,如果burstCapacity配置為0,則會阻塞所有的請求。burstCapacity的值設置的比replenishRate大一些,表示可以允許臨時的大速率處理請求。
如下面配置的例子所示:
spring: cloud: gateway: routes: - id: requestratelimiter_route uri: http://example.org filters: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 10 redis-rate-limiter.burstCapacity: 20
@Bean KeyResolver userKeyResolver() { return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user")); //根據參數進行限流 }
這個限流器配置示表,限制每個用戶每秒鍾發送10次請求,最多20次,在某個時間內,允許的請求在可以在10到20之間。如果連續兩次發送10次請求,就會導致請求被丟棄,返回Http狀態碼 HTTP 429 - Too Many Requests 。上面Java中配置的Bean類:KeyResolver,表示獲取限流的key,它是從請求參數中獲取的,生產環境不建議這樣使用,因為如果每次請求這個值不一樣,是起不到限流作用的。
繼承RateLimiter 接口也可以實現自定義的限流器,在配置中,使用SpEL表達式來引用一個限流器的Bean。比如#{@myRateLimiter}就是一個SpEL表達式,表示引用一個bean,它的名字是myRateLimiter。如下面配置所示:
spring: cloud: gateway: routes: - id: requestratelimiter_route uri: http://example.org filters: - name: RequestRateLimiter args: rate-limiter: "#{@myRateLimiter}" key-resolver: "#{@userKeyResolver}"
可以參考源碼項目中的配置方式:

對就的Bean配置如下所示:
@Configuration public class RateLimiterConfig { @Bean public KeyResolver ipKeyResolver() { return exchange-> Mono.just(exchange.getRequest().getRemoteAddress().getHostString()); } @Bean public RedisRateLimiter myRateLimiter() { return new RedisRateLimiter(2, 4); } }
源碼地址:https://gitee.com/wgslucky/SpringCloud
5.9 RedirectTo GatewayFilter Factory
這個跳轉的過濾器的實現類是:RedirectToGatewayFilterFactory,它需要兩個參數,一個是狀態碼,一個是重定向要跳轉到的Url,這個Url必須是可訪問的,它會被添加到此請求返回的消息中的Location Header里面,客戶端會從Location Header中獲取這個Url並發送請求。這個狀態碼必須是30x系列,要不然程序會報錯,常用的狀態碼有301和302
- 301:在請求的URL已被移除時使用。響應的Location首部中應該包含資源現在所處的URL。
- 302:與301狀態碼類似,但是,客戶端應該使用Location首部給出的URL來零食定位資源,將來的請求仍然使用老的URL。
官方的比較簡潔的說明:
- 301 redirect: 301 代表永久性轉移(Permanently Moved)
- 302 redirect: 302 代表暫時性轉移(Temporarily Moved )
盡量使用301跳轉!301和302狀態碼都表示重定向,就是說瀏覽器在拿到服務器返回的這個狀態碼后會自動跳轉到一個新的URL地址,這個地址可以從響應的Location首部中獲取(用戶看到的效果就是他輸入的地址A瞬間變成了另一個地址B)——這是它們的共同點。他們的不同在於。301表示舊地址A的資源已經被永久地移除了(這個資源不可訪問了),搜索引擎在抓取新內容的同時也將舊的網址交換為重定向之后的網址;302表示舊地址A的資源還在(仍然可以訪問),這個重定向只是臨時地從舊地址A跳轉到地址B,搜索引擎會抓取新的內容而保存舊的網址。重定向是客戶端行為。
在application.yml中配置如下所示:
spring: cloud: gateway: routes: - id: prefixpath_route uri: http://localhost:8080 predicates: - Path=/redirect_test filters: - RedirectTo=301,http://www.xinyues.com
啟動源碼中的網關服務,請求http://localhost:8080/redirect_test ,將會跳轉到http://www.xinyues.com
5.10 RemoveNonProxyHeaders GatewayFilter Factory
原文檔如下所示:
The RemoveNonProxyHeaders GatewayFilter Factory removes headers from forwarded requests. The default list of headers that is removed comes from the IETF. The default removed headers are: Connection Keep-Alive Proxy-Authenticate Proxy-Authorization TE Trailer Transfer-Encoding Upgrade To change this, set the spring.cloud.gateway.filter.remove-non-proxy-headers.headers property to the list of header names to remove.
但是在spring-cloud-gateway-core-2.1.0.RELEASE.jar版本的jar並沒有找到此過濾器工作,也沒有spring.cloud.gateway.filter.remove-non-proxy-headers.headers的配置,但是找到spring.cloud.gateway.filter.remove-hop-by-hop.headers的配置。如果要指定移除的Header,可以在這里面配置。默認移除的Header有:
public static final Set<String> HEADERS_REMOVED_ON_REQUEST = new HashSet<>(Arrays.asList( "connection", "keep-alive", "transfer-encoding", "te", "trailer", "proxy-authorization", "proxy-authenticate", "x-application-context", "upgrade" // these two are not listed in https://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-14#section-7.1.3 //"proxy-connection", // "content-length", ));
5.11 RemoveRequestHeader GatewayFilter Factory
這個過濾器的實現類是:RemoveRequestHeaderGatewayFilterFactory,它可以從Header中移除指定的包頭中的參數,但是這個版本中只能配置一個參數。在application.yml中配置如下所示:
spring: cloud: gateway: routes: - id: removerequestheader_route uri: http://example.org filters: - RemoveRequestHeader=X-Request-Foo
在向后面的執行流發送請求之前,它會移除包頭中名字為X-Request-Foo的值。
5.12 RemoveResponseHeader GatewayFilter Factory
這個過濾器的實現類是RemoveResponseHeaderGatewayFilterFactory,它用來從響應的包頭中移除指定的參數,如下面配置所示:
spring: cloud: gateway: routes: - id: removeresponseheader_route uri: http://example.org filters: - RemoveResponseHeader=X-Response-Foo
在返回客戶端之后,它會從響應消息的包頭中移除X-Response-Foo參數的值。
