局域⽹中就有⽹關(翻譯過來就叫作GateWay)這個概念,局域⽹接收或者發送數據出去經過這個⽹關,⽐如⽤Vmware虛擬機軟件搭建虛擬機集羣的時候,每每咱們須要選擇IP段中的⼀個IP做爲⽹關地址。
咱們學習的GateWay(Spring Cloud GateWay),它只是衆多⽹關解決⽅案中的⼀種,是微服務架構中的重要組成部分java
Spring Cloud GateWay是Spring Cloud的⼀個全新項⽬,⽬標是取代Netflix Zuul,它基於
Spring5.0+SpringBoot2.0+WebFlux(基於⾼性能的Reactor模式響應式通訊框架Netty,異步⾮阻塞模型)等技術開發,性能⾼於Zuul,官⽅測試, GateWay是Zuul的1.6倍,旨在爲微服務架構提供⼀種簡單有效的統⼀的API路由管理⽅式。
Spring Cloud GateWay不只提供統⼀的路由⽅式(反向代理)而且基於 Filter(定義過濾器對請求過濾,完成⼀些功能) 鏈的⽅式提供了⽹關基本的功能,例如:鑑權、流量控制、熔斷、路徑重寫、⽇志監控等。git
新建GateWay網關項目,因爲gateway不須要引⼊starter-web模塊,須要引⼊web-flux,而我們以前的父工程裏面有web組件,因此咱們不能以lagou-parent爲父工程創建gateway。web
<!--GateWay ⽹關--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--引⼊webflux--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency>
application.yml中作一些關於路由規則的配置:spring
Spring: application: name: lagou-cloud-gateway cloud: gateway: routes: # 路由能夠有多個 - id: service-autodeliver-router # 咱們⾃定義的路由 ID,保持惟⼀ uri: http://127.0.0.1:8090 # ⽬標服務地址 ⾃動投遞微服務(部署多實例) #動態路由: uri配置的應該是⼀個服務名稱,⽽不該該是⼀個具體的服務實例的地址 # gateway⽹關從服務註冊中⼼獲取實例信息而後負載後路由 predicates: # 斷⾔:路由條件, Predicate 接受⼀個輸⼊參數,返回⼀個布爾值結果。該接⼝包含多種默認⽅法來將 Predicate 組合成其餘複雜的邏輯(⽐如:與,或,⾮)。 - Path=/autodeliver/** - id: service-resume-router # 咱們⾃定義的路由 ID,保持惟⼀ uri: http://127.0.0.1:8081 # ⽬標服務地址 #http://localhost:9002/resume/openstate/1545132 #http://127.0.0.1:8081/openstate/1545132 predicates: # 斷⾔:路由條件, Predicate 接受⼀個輸⼊參數,返回⼀個布爾值結果。該接⼝包含多種默 認⽅法來將Predicate 組合成其餘複雜的邏輯(⽐如:與,或,⾮)。 - Path=/resume/** filters: - StripPrefix=1
正常訪問服務消費者8090的地址是
http://localhost:8090/autodeliver/checkStateTimeoutFallBack/1545132
經過網關配置代理以後的地址:
http://localhost:9002/autodeliver/checkStateTimeoutFallBack/1545132
架構
上面咱們是直接寫死了目標服務的請求地址,這樣對於咱們集羣部署多個服務是不行的,咱們應該改形成從eureka服務註冊中心獲取服務列表並進行訪問,即所謂的動態路由。
動態路由配置方式:url: lb://在eureka註冊的服務名稱
lb表示從註冊中心獲取服務,後面是須要轉發的服務名稱。
例如:app
uri: lb://lagou-service-resume
由於須要從註冊中心獲取服務列表,因此須要在pom.xml中添加eureka的客戶端依賴。
測試:負載均衡
能夠看到網關分發請求到不一樣的服務,實現了動態路由。框架
從過濾器⽣命週期(影響時機點)的⻆度來講,主要有兩個pre和post:異步
生命週期時機點 | 做用 |
---|---|
pre | 這種過濾器在請求被路由以前調⽤。咱們可利⽤這種過濾器實現身份驗證、在集羣中選擇 請求的微服務、記錄調試信息等 |
post | 這種過濾器在路由到微服務之後執⾏。這種過濾器可⽤來爲響應添加標準的 HTTPHeader、收集統計信息和指標、將響應從微服務發送給客戶端等。 |
從過濾器類型的⻆度, Spring Cloud GateWay的過濾器分爲GateWayFilter和GlobalFilter兩種:ide
過濾器類型 | 影響範圍 |
---|---|
GateWayFilter | 應用到單個路由上 |
GlobalFilter | 應用到全部路由上 |
好比GateWayFilter能夠去掉url中的佔位後再轉發路由,以下:
- id: service-resume-router # 咱們⾃定義的路由 ID,保持惟⼀ #uri: http://127.0.0.1:8081 # ⽬標服務地址 uri: lb://lagou-service-resume # ⽬標服務地址 #http://localhost:9002/resume/openstate/1545132 #http://127.0.0.1:8081/openstate/1545132 predicates: # 斷⾔:路由條件, Predicate 接受⼀個輸⼊參數,返回⼀個布爾值結果。該接⼝包含多種默 認⽅法來將Predicate 組合成其餘複雜的邏輯(⽐如:與,或,⾮)。 - Path=/resume/** filters: - StripPrefix=1
和前面的動態路由相比,主要是添加了下面的參數:
filters: - StripPrefix=1
StripPrefix這個參數的意思是去掉訪問url的第一個參數,再進行匹配。
好比http://localhost:9002/resume/openstate/1545132
這個請求,會匹配目標服務的http://127.0.0.1:8081/openstate/1545132
。
思路:請求過來時,判斷髮送請求的客戶端的ip,若是在⿊名單中,拒絕訪問.
⾃定義GateWay全局過濾器時,咱們實現Global Filter接⼝便可,經過全局過濾器能夠實現⿊⽩名單、限流等功能。
在網關服務中自定義全局過濾器:
@Slf4j @Component public class BlackListFilter implements GlobalFilter, Ordered { private static List<String> blackList=new ArrayList<>(); static { blackList.add("0:0:0:0:0:0:0:1");//模擬本機地址 } /** * 過濾器核⼼⽅法 * @param exchange 封裝了request和response對象的上下⽂ * @param chain ⽹關過濾器鏈(包含全局過濾器和單路由過濾器) * @return */ @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 思路:獲取客戶端ip,判斷是否在⿊名單中,在的話就拒絕訪問,不在的話就放⾏ // 從上下⽂中取出request和response對象 ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); // 從request對象中獲取客戶端ip String clientIp = request.getRemoteAddress().getHostString(); // 拿着clientIp去⿊名單中查詢,存在的話就拒絕訪問 if(blackList.contains(clientIp)){ //// 拒絕訪問,返回 response.setStatusCode(HttpStatus.UNAUTHORIZED); log.debug("------>Ip:"+clientIp+" 在黑名單中,被拒絕訪問!"); String data="Request be denied!!"; DataBuffer wrap = response.bufferFactory().wrap(data.getBytes()); return response.writeWith(Mono.just(wrap)); } // 合法請求,放⾏,執⾏後續的過濾器 return chain.filter(exchange); } /** * 返回值表示當前過濾器的順序(優先級),數值越⼩,優先級越⾼ * @return */ @Override public int getOrder() { return 0; } }
效果:
⽹關做爲⾮常核⼼的⼀個部件,若是掛掉,那麼全部請求均可能⽆法路由處理,所以咱們須要作
GateWay的⾼可⽤。
GateWay的⾼可⽤很簡單: 能夠啓動多個GateWay實例來實現⾼可⽤,在GateWay的上游使⽤Nginx等負載均衡設備進⾏負載轉發以達到⾼可⽤的⽬的。
舉例:
啓動多個GateWay實例(假如說兩個,⼀個端⼝9002,⼀個端⼝9003),剩下的就是使⽤Nginx等完成負載代理便可。示例以下:
upstream gateway { server 127.0.0.1:9002; server 127.0.0.1:9003; } location / { proxy_pass http://gateway; }
gateway案例源碼地址:gateway案例源碼地址
歡迎訪問個人博客:https://www.liuyj.top