SpringCloud Gateway的基本入門和注意點詳解
1.gateway和zuul
Spring Cloud Finchley版本的gateway比zuul 1.x系列的性能和功能整體要好,且使用 Gateway 做跨域相比應(yīng)用本身或是 Nginx 的好處是規(guī)則可以配置的更加靈活.
這兩者相同的地方就是都是作為網(wǎng)關(guān),處理前段的請求,可以進行路由到對應(yīng)的服務(wù)或者url,也可以針對權(quán)限做過濾處理,也可以對其他服務(wù)響應(yīng)的結(jié)果做處理
截至目前SpringCloud gateway最新版本是2.1.0 RC3,可見官方網(wǎng)站SpringCloud gateway,每個版本增加的功能都比較多,改動的地方也比較多,前幾個版本有比較坑的地方,建議使用最新版本
2.使用gateway的路由功能
1. 搭載springcloud gateway
準(zhǔn)備一個spring cloud工程,包括eureka-server注冊中心,service-client服務(wù)提供者,端口8090
service-client提供一個接口:
@RestController @Slf4j public class ProducerController { @RequestMapping("/hi") public String hi(@RequestParam String name) { log.info("[client服務(wù)] [hi方法]收到請求"); return "hi " + name + ",i am from service-client"; } }
再建一個spring cloud工程,service-gateway網(wǎng)關(guān),端口8088
pom的依賴:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.4.RELEASE</version> <relativePath/> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies>
application啟動類:
package com.zgd.springcloud.gateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; /** * service-gateway 客戶端 * @author zgd */ @EnableEurekaClient @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
這樣基本的框架就搭好了,先啟動eureka-server注冊中心,再啟動service-client和service-gateway
直接調(diào)用 localhost:8090/hi?name=zgd,可以收到
hi zgd,i am from service-client
2.簡單使用gateway
GateWay大體可以分為路由工廠Route Predicate Factories,網(wǎng)關(guān)過濾器工廠GatewayFilter Factories,全局過濾器工廠Global Filters處理請求。
對于路由轉(zhuǎn)發(fā),Spring Cloud gateway內(nèi)置了很多校驗條件謂語(predicate)來實現(xiàn)路由功能。
比如
- 根據(jù)時間來路由: After Route Predicate Factory某個時間點之后請求路由,Before Route Predicate Factory某個時間點之前請求路由,Between Route Predicate Factory兩者時間之間
- 通過請求路徑來路由: Path Route Predicate Factory
- 根據(jù)請求頭來路由
- 根據(jù)cookie來路由
- 根據(jù)域名來路由
有兩種方式配置,一種是配置文件application的方式,一種是代碼配置
1.application配置
a. 路由到其他地址
spring: cloud: gateway: #可以根據(jù)請求參數(shù),cookie,host,請求時間,請求頭等進行校驗判斷路由, 下面根據(jù)先后順序轉(zhuǎn)發(fā) routes: - id: host_route uri: http://httpbin.org:80/get predicates: - Path=/zzzgd/** # 請求地址攜帶zzzgd的,則轉(zhuǎn)發(fā)
在spring.cloud.gateway.routes中,我們可以根據(jù)不同的謂語配置不同的路由,根據(jù)配置的先后順序來跳轉(zhuǎn),越在前面優(yōu)先級越高.
其中id,區(qū)分不同的路由規(guī)則,不可重復(fù),uri,指需要跳轉(zhuǎn)的地址,Predicates就是上面說的謂語了,可以配置多個,使用正則匹配. 這里我們配置的是如果請求地址攜帶zzzgd則會跳轉(zhuǎn)到我們配置的uri
配置好gateway,重新啟動,然后我們調(diào)用localhost:8088(網(wǎng)關(guān)的地址和端口)/zzzgd/abc,這個地址是沒有任何匹配的接口的,按理來說會返回404,但是配置了網(wǎng)關(guān)就返回了這些信息,這個是我們配置的uri所返回的:
{ "args": { "name": "zgd" }, "headers": { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", "Accept-Encoding": "gzip, deflate, br", "Accept-Language": "zh-CN,zh;q=0.9", "Connection": "close", "Cookie": "SL_G_WPT_TO=zh; SL_GWPT_Show_Hide_tmp=undefined; SL_wptGlobTipTmp=undefined", "Forwarded": "proto=http;host=\"localhost:8088\";for=\"0:0:0:0:0:0:0:1:55782\"", "Host": "httpbin.org", "Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36", "X-Forwarded-Host": "localhost:8088" }, "origin": "0:0:0:0:0:0:0:1, 119.147.213.42", "url": "http://localhost:8088/get?name=zgd" }
上面的是根據(jù)地址來路由,還有下面多種路由配置:
根據(jù)域名來轉(zhuǎn)發(fā)路由:
routes: - id: host_route uri: http://httpbin.org:80/get predicates: - Host=**.csdn.** # 請求域名攜帶csdn的,則轉(zhuǎn)發(fā) - id: query_route uri: http://httpbin.org:80/get predicates: - Query=username, zzz* # 請求參數(shù)含有username,且值滿足zzz開頭的,則轉(zhuǎn)發(fā)(對值的匹配可以省略) - id: header_route uri: http://httpbin.org:80/get predicates: - Header=request, \d+ # 如果請求頭含有request,且為數(shù)字,則轉(zhuǎn)發(fā) - id: cookie_route uri: http://httpbin.org:80/get predicates: - Cookie=name, zzzgd # 如果攜帶cookie,參數(shù)名為name,值為zzzgd,則轉(zhuǎn)發(fā) - id: path_route uri: http://httpbin.org:80/get predicates: - Path=/zzzgd/** # 請求地址攜帶zzzgd的,則轉(zhuǎn)發(fā) # 路由到其他服務(wù),url需要用[lb://]+[serviceId] - id: service_client uri: lb://service-client predicates: - Path=/to_client/** # 如果請求地址滿足/to_client/**,則轉(zhuǎn)發(fā)到 service-client 服務(wù) filters: - StripPrefix=1 # 去除請求地址中的to_client - id: after_route uri: http://httpbin.org:80/get predicates: - After=2019-01-01T17:42:47.789-07:00[America/Denver] # 如果請求時間大于該時間,則轉(zhuǎn)發(fā)
b. 根據(jù)服務(wù)名路由到其他服務(wù)
我們知道,zuul是可以根據(jù)服務(wù)在eureka的serviceId,來將請求路由到不同的服務(wù)上,這也是網(wǎng)關(guān)最大的作用之一,gateway也可以
gateway可以通過開啟以下配置來打開根據(jù)服務(wù)的serviceId來匹配路由,默認(rèn)是大寫:
# 配置gateway路由 spring: cloud: gateway: discovery: locator: # 是否可以通過其他服務(wù)的serviceId來轉(zhuǎn)發(fā)到具體的服務(wù)實例。默認(rèn)為false # 為true,自動創(chuàng)建路由,路由訪問方式:http://Gateway_HOST:Gateway_PORT/大寫的serviceId/**,其中微服務(wù)應(yīng)用名默認(rèn)大寫訪問 enabled: true
開啟配置,重啟gateway,訪問 localhost:8088/SERVICE-CLIENT/hi?name=zgd,
正常返回了service-client的結(jié)果.
如果需要小寫serviceId,則配置spring.cloud.gateway.locator.lowerCaseServiceId:true
注意事項
不管小寫大寫,不能使用下劃線,否則會報:
org.springframework.cloud.gateway.support.NotFoundException: Unable to find instance for localhost
所以服務(wù)的spring.application.name 必須用中劃線而不是下劃線
如果開啟了lowerCaseServiceId,則只能用小寫,不能識別大寫,如果不開啟,只能識別大寫
除了上面這種自動設(shè)置路由服務(wù),也可以手動設(shè)置,在routes中配置
這里使用的是gateway的其中一個過濾器工廠,去除請求地址前綴的過濾器
# 路由到其他服務(wù),url需要用[lb://]+[serviceId] - id: service_client uri: lb://service-client predicates: - Path=/to_client/** # 如果請求地址滿足/to_client/**,則轉(zhuǎn)發(fā)到 service-client 服務(wù) filters: - StripPrefix=1 # 去除請求地址中的to_client
這里的uri不是一個具體的地址了,而是lb://開頭,加上serviceId
然后比如上面這個配置,我們 再調(diào)用 localhost:8088/to_client/hi?name=zgd
可以看到也正常收到了service-client的返回.說明我們調(diào)用到了這個服務(wù).
這里需要注意的一點,如果不加上filters.- StripPrefix=1,那么則無法請求到hi這個接口。因為這個to_client相當(dāng)于是服務(wù)名,只是為了網(wǎng)關(guān)的路由加上去的,對于服務(wù)提供者service-client來說,不需要這段地址,所以需要去掉
還有其他的predicate,可以參考官方文檔
過濾
這個filters也是gateway的一個重要功能,過濾.
gateway內(nèi)置的過濾器工廠有下面這些:
除了上面用到的
- 路徑前綴去除過濾器,還有
- 添加請求參數(shù)過濾器
- 添加請求頭過濾器
- 添加響應(yīng)頭過濾器
- 移除響應(yīng)頭過濾器
它可以修改我們請求的路徑,請求的參數(shù),增加請求頭,或者響應(yīng)頭等等
可以參考官方文檔
舉個例子,我們將application配置如下:
spring: cloud: gateway: routes: - id: query_route uri: http://httpbin.org:80/get predicates: - Query=username, zzz* # 請求參數(shù)含有username,且值滿足zzz開頭的,則轉(zhuǎn)發(fā)(對值的匹配可以省略) filters: - AddRequestHeader=X-Request-Foo, Bar - AddRequestParameter=age, 18
請求 localhost:8088/?username=zzzzzzz
它返回了它所受到的請求,將會看到返回數(shù)據(jù)中已經(jīng)添加了一個age=18的請求參數(shù),且請求頭也多了X-Request-Foo=Bar
b.代碼配置
為了方便在java開發(fā),gateway也提供了代碼的方式配置,比如我們注釋掉上面的application配置,然后建一個配置類
/** * @Author: zgd * @Date: 2019/1/8 19:09 * @Description: */ @Configuration public class GateWayConfig { @Bean public RouteLocator routeLocator(RouteLocatorBuilder builder) { return builder.routes() .route(r -> r.path("/fluent/**").and().query("name") .uri("http://httpbin.org:80/get")) .build(); } }
啟動,訪問
http://localhost:8088/fluent/1/?name=bb
成功!
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java中List使用stream流轉(zhuǎn)成map的幾種方式詳解
Stream是Java8中處理集合的關(guān)鍵抽象概念,它可以指定你希望對集合進行的操作,可以執(zhí)行非常復(fù)雜的查找、過濾和映射數(shù)據(jù)等操作,下面這篇文章主要給大家介紹了關(guān)于Java中List使用stream流轉(zhuǎn)成map的幾種方式,需要的朋友可以參考下2023-04-04使用jekins自動構(gòu)建部署java maven項目的方法步驟
這篇文章主要介紹了使用jekins自動構(gòu)建部署java maven項目的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01關(guān)于Spring MVC同名參數(shù)綁定問題的解決方法
Spring MVC中的參數(shù)綁定還是蠻重要的,最近在使用中遇到了同名參數(shù)綁定的問題,想著總結(jié)分享出來,下面這篇文章主要給大家介紹了關(guān)于Spring MVC同名參數(shù)綁定問題的解決方法,需要的朋友可以參考借鑒,下面來一起看看吧。2017-08-08