SpringCloud無廢話入門05:Spring Cloud Gateway路由、filter、熔斷

1.什么是路由網(wǎng)關

? ? ? ??截至目前為止的例子中,我們創(chuàng)建了一個service,叫做:HelloService,然后我們把它部署到了兩臺服務器(即提供了兩個provider),然后我們又使用ribbon將其做了負載均衡。目前為止這一切都看上運作的很好,我們通過地址訪問地址http://localhost:9291/hello,實際是路由到了http://localhost:9191/hello和http://localhost:9192/hello兩個服務器上。

? ? ? ??緊接著,隨著業(yè)務更進一步,我們又創(chuàng)建了UserService,又創(chuàng)建了ProductService,我們提供的服務器也越來越多,但是我們發(fā)現(xiàn)一個問題,即:即提供一種服務,前端程序員都需要通過IP+端口的形式去訪問,很快URL地址就多的爆炸了,而且,甚至某些別有用心的同學因為知道了這些目標地址,開始采用非常規(guī)的手段去做些壞事。所以,我們必須做些手段來規(guī)避這些糟糕的事情。

? ? ? ??路由網(wǎng)關出現(xiàn)了。

? ? ? ??當我們輸入URL,比如zuikc.com/hello或者zuikc.com/user的時候,路由網(wǎng)關會去分析這個地址,并且根據(jù)地址的pattern,

? ? ? ??1:去決定到底是訪問helloservice還是userservice;

? ? ? ??2:到eureka注冊中心拿到該服務的id;

? ? ? ??3:通過ribbon去訪問該服務id中的一臺provider;

? ? ? ??4:拿到response,返回給調用者;

? ? ? ??并且,由于路由網(wǎng)關能做這些事情,還有額外的一些事情,比如權限驗證(shiro,springsecurity等),就天然的適合放到路由網(wǎng)關也一并實現(xiàn)了。

? ? ? ??關于路由網(wǎng)關,以前有zuul,但是zuul已經(jīng)停止更新了,Spring Cloud Gateway被Spring Cloud官方推出來,作為第二代網(wǎng)關框架,取代Zuul網(wǎng)關。

? ? ? ??總結一下,路由網(wǎng)關的作用就是:路由轉發(fā)、權限校驗、限流控制。

2.路由網(wǎng)關原理

? ? ? ??來看Spring Cloud Gateway官方提供的架構圖,

? ? ? ??客戶端向Spring Cloud Gateway發(fā)出請求。 Gateway Handler Mapping匹配路徑并將其發(fā)送到Gateway web handler處理。 Gateway web handler處理請求,將其發(fā)送給過濾器鏈。

? ? ? ??過濾器鏈主要分兩大類:pre和post。“pre”過濾器一般進行權限、限流、日志輸出等功能,以及請求頭的更改、協(xié)議的轉換;“post”過濾器是在收到響應后,可以對響應數(shù)據(jù)做統(tǒng)一修改,比如響應頭、協(xié)議的轉換等。

3.實現(xiàn)

? ? ? ??現(xiàn)在,讓我們用代碼實現(xiàn)一下吧。

? ? ? ??首先,創(chuàng)建子模塊,在我們的例子中,創(chuàng)建完畢后,解決方案像如下這樣,

? ? ? ??現(xiàn)在,導入依賴如下:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

? ? ? ? ?xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

? ? <parent>

? ? ? ? <artifactId>springcloud.parent</artifactId>

? ? ? ? <groupId>com.zuikc</groupId>

? ? ? ? <version>1.0-SNAPSHOT</version>

? ? </parent>

? ? <modelVersion>4.0.0</modelVersion>

? ? <packaging>war</packaging>

? ? <name>gateway</name>

? ? <artifactId>gateway</artifactId>

? ? <dependencyManagement>

? ? ? ? <dependencies>

? ? ? ? ? ? <dependency>

? ? ? ? ? ? ? ? <groupId>org.springframework.cloud</groupId>

? ? ? ? ? ? ? ? <artifactId>spring-cloud-dependencies</artifactId>

? ? ? ? ? ? ? ? <version>Greenwich.RELEASE</version>

? ? ? ? ? ? ? ? <type>pom</type>

? ? ? ? ? ? ? ? <scope>import</scope>

? ? ? ? ? ? </dependency>

? ? ? ? </dependencies>

? ? </dependencyManagement>

? ? <dependencies>

? ? ? ? <dependency>

? ? ? ? ? ? <groupId>org.springframework.cloud</groupId>

? ? ? ? ? ? <artifactId>spring-cloud-starter-gateway</artifactId>

? ? ? ? </dependency>

? ? </dependencies>

</project>

? ? ? ??先創(chuàng)建一個最簡單的application.yml,

server:

? port: 8880

? ? ? ??然后,讓我們創(chuàng)建application類,

package com.zuikc;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.gateway.route.RouteLocator;

import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;

import org.springframework.context.annotation.Bean;

import org.springframework.web.bind.annotation.RestController;

/**

?* @ClassName GatewayApplication

?* @Description 我們提供咨詢和培訓服務,關于本文有任何困惑,請關注并聯(lián)系“碼農(nóng)星球”

?* @Author 碼農(nóng)星球

?**/

@SpringBootApplication

@RestController

public class GatewayApplication {

? ? public static void main(String[] args) {

? ? ? ? SpringApplication.run(GatewayApplication.class, args);

? ? }

? ? @Bean

? ? public RouteLocator myRoutes(RouteLocatorBuilder builder) {

? ? ? ? return builder.routes()

? ? ? ? ? ? ? ? .route("host_route", r -> r.path("/hello/**").filters(f -> f.stripPrefix(1)).uri("http://localhost:9291"))

? ? ? ? ? ? ? ? .route("host_route", r -> r.path("/user/**").filters(f -> f.stripPrefix(1)).uri("http://localhost:9391"))

? ? ? ? ? ? ? ? .build();

? ? }

}

? ? ? ??在這個類中,我們將“域名/hello”下的所有請求轉發(fā)到了HelloService所在ribbon服務器中,將“域名/user”下所有的請求轉到User所在的ribbon下。

? ? ? ??然后,啟動application。這個時候,讓我們輸入地址:http://localhost:8880/hello/hello,可以看到結果類似如下:

? ? ? ??服務將在兩個provider中切換。注意,上述url中,第一個hello,是指路由到helloservice中,第二個hello,是具體的服務。

? ? ? ??接下來,讓我們試一下,http://localhost:8880/user/something。由于我們目前并沒有開發(fā)UserService,所以就出現(xiàn)errorpage了~~

4.使用配置實現(xiàn)

? ? ? ??我們也可以使用配置來實現(xiàn)路由。

? ? ? ??在上面的代碼中,我們首先去掉application中的bean,

package com.zuikc;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.gateway.route.RouteLocator;

import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;

import org.springframework.context.annotation.Bean;

import org.springframework.web.bind.annotation.RestController;

/**

?* @ClassName GatewayApplication

?* @Description 我們提供咨詢和培訓服務,關于本文有任何困惑,請關注并聯(lián)系“碼農(nóng)星球”

?* @Author 碼農(nóng)星球

?**/

@SpringBootApplication

@RestController

public class GatewayApplication {

? ? public static void main(String[] args) {

? ? ? ? SpringApplication.run(GatewayApplication.class, args);

? ? }

}

? ? ? ??然后,修改application.yml,

server:

? port: 8880

spring:

? cloud:

? ? gateway:

? ? ? routes:

? ? ? - id: host_route

? ? ? ? uri: http://localhost:9291

? ? ? ? predicates:

? ? ? ? - Path=/hello/**

? ? ? ? filters:

? ? ? ? - StripPrefix=1

? ? ? - id: host_route

? ? ? ? uri: http://localhost:9391

? ? ? ? predicates:

? ? ? ? - Path=/user/**

? ? ? ? filters:

? ? ? ? - StripPrefix=1

? ? ? ??然后,重啟application,得到的效果是一樣一樣滴。

5.通過filters使用Hystrix

? ? ? ??如果注意上文中的http://localhost:8880/user/something,我們發(fā)現(xiàn)原來在gateway中也是可以指定熔斷器fallback的。

? ? ? ??那就好辦了,首先,讓我們引入hystrix,

? ? ? ? <dependency>

? ? ? ? ? ? <groupId>org.springframework.cloud</groupId>

? ? ? ? ? ? <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>

? ? ? ? </dependency>

? ? ? ??其次,創(chuàng)建一個fallback,

package com.zuikc;

import org.springframework.stereotype.Component;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

/**

?* @ClassName FallBack

?* @Description 我們提供咨詢和培訓服務,關于本文有任何困惑,請關注并聯(lián)系“碼農(nóng)星球”

?* @Author 碼農(nóng)星球

?**/

@RestController

@RequestMapping("/fallback")

public class FallBack {

? ? @RequestMapping("")

? ? public String fallback(){

? ? ? ? return "error";

? ? }

}

? ? ? ??再次,修改我們的配置文件,

server:

? port: 8880

spring:

? cloud:

? ? gateway:

? ? ? routes:

? ? ? - id: host_route

? ? ? ? uri: http://localhost:9291

? ? ? ? predicates:

? ? ? ? - Path=/hello/**

? ? ? ? filters:

? ? ? ? - StripPrefix=1

? ? ? - id: host_route

? ? ? ? uri: http://localhost:9391

? ? ? ? predicates:

? ? ? ? - Path=/user/**

? ? ? ? filters:

? ? ? ? - StripPrefix=1

? ? ? ? - name: Hystrix

? ? ? ? ? args:

? ? ? ? ? ? name: fallbackcmd

? ? ? ? ? ? fallbackUri: forward:/fallback

? ? ? ??重啟application。

? ? ? ??這個時候,再次訪問http://localhost:8880/user/something,頁面輸出為error。

? ? ? ??感謝關注“碼農(nóng)星球”。本文版權屬于“碼農(nóng)星球”。我們提供咨詢和培訓服務,關于本文有任何困惑,請關注并聯(lián)系我們。

本文參考:https://spring.io/guides/gs/gateway/

一些官方的例子在:

http://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.0.0.RELEASE/single/spring-cloud-gateway.html

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容