Spring Cloud系列之gateway

Spring Cloud系列之Eureka
Spring Cloud系列之配置中心Config
Spring Cloud系列之gateway
Spring Cloud系列之Feign
Spring Cloud系列之Hystrix
Spring Cloud系列之鏈路追蹤

網(wǎng)關的角色是作為一個 API 架構(gòu),用來保護、增強和控制對于 API 服務的訪問。從面向?qū)ο笤O計的角度看,它與外觀模式類似。API網(wǎng)關封裝了系統(tǒng)內(nèi)部架構(gòu),為每個客戶端提供一個定制的API。它可能還具有其它職責,如身份驗證、日志、黑白名單、監(jiān)控、負載均衡、緩存、請求分片與管理、靜態(tài)響應處理。API網(wǎng)關方式的核心要點是,所有的客戶端和消費端都通過統(tǒng)一的網(wǎng)關接入微服務,在網(wǎng)關層處理所有的非業(yè)務功能。通常,網(wǎng)關也是提供REST/HTTP的訪問API。 下面我們來看一張網(wǎng)關所處的架構(gòu)圖

微服務-API網(wǎng)關-架構(gòu).jpg

從這張圖上看到有四個層次,最上層是我們用戶層,第二層是我們的負載均衡器,第三層就是我們的網(wǎng)關,最后是我們內(nèi)部的微服務,在接入網(wǎng)關的時候為什么需要在上面需要一個負載均衡器,因為我們想讓網(wǎng)關無狀態(tài),無狀態(tài)的網(wǎng)關有一個好處,可以部署很多,不會有單點,即使掛了一臺,其他的網(wǎng)關還在,這個對整個系統(tǒng)的穩(wěn)定性起來非常重要的作用。一般的系統(tǒng)會有一個LB,然后對應多個網(wǎng)關。網(wǎng)關能起到的作用很多:

  • 最重要的一個重要反向路由,當外面的請求進來之后,怎么找到內(nèi)部具體的微服務,這個是網(wǎng)關起來重要職責,將外部的調(diào)用轉(zhuǎn)化為內(nèi)部的服務服務,這個就是反向路由

  • 第二個是認證安全,網(wǎng)關像是一個門衛(wèi),有一些訪問是正常的訪問,有一些是惡意的訪問,例如說爬蟲,甚至是一些黑客行為,網(wǎng)關需要將其攔截在外部- 第三個重要職責是限流熔斷,比方說,有一個門,外面有流量進來,正常來說流量是比較穩(wěn)定的,但也有可能有突發(fā)流量,有可能網(wǎng)站在搞促銷,這個時候可能就有流量的洪峰闖進來,如果說內(nèi)部沒有好的限流熔斷措施,可能造成內(nèi)部整個服務的服務器癱瘓,網(wǎng)關就要承擔限流熔斷的職責。

  • 網(wǎng)關要承擔日志監(jiān)控的職責,外部的訪問所有的流量都要經(jīng)過網(wǎng)關,那么可以在網(wǎng)關上可以對所有的流量做訪問的審計,把它作為日志保存起來,另外可以通過分析日志,知道性能的調(diào)用情況,能夠?qū)φ麄€流量情況進行監(jiān)控

zuul快被springcloud家族拋棄了,在這里我們著重介紹下SpringCloud Gateway

SpringCloud Gateway

簡介

SpringCloud Gateway 是 Spring Cloud 的一個全新項目,該項目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技術開發(fā)的網(wǎng)關,它旨在為微服務架構(gòu)提供一種簡單有效的統(tǒng)一的 API 路由管理方式。

SpringCloud Gateway 作為 Spring Cloud 生態(tài)系統(tǒng)中的網(wǎng)關,目標是替代 Zuul,在Spring Cloud 2.0以上版本中,沒有對新版本的Zuul 2.0以上最新高性能版本進行集成,仍然還是使用的Zuul 2.0之前的非Reactor模式的老版本。而為了提升網(wǎng)關的性能,SpringCloud Gateway是基于WebFlux框架實現(xiàn)的,而WebFlux框架底層則使用了高性能的Reactor模式通信框架Netty。

Spring Cloud Gateway 的目標,不僅提供統(tǒng)一的路由方式,并且基于 Filter 鏈的方式提供了網(wǎng)關基本的功能,例如:安全,監(jiān)控/指標,和限流。

Spring Cloud Gateway 底層使用了高性能的通信框架Netty。

核心概念
  • 路由(route):網(wǎng)關配置的基本組成模塊,和Zuul的路由配置模塊類似。一個Route模塊由一個 ID,一個目標 URI,一組斷言和一組過濾器定義。如果斷言為真,則路由匹配,目標URI會被訪問。

  • 斷言(Predicate):參考了 Java 8 的 Predicate,可以使用它來匹配來自 HTTP 請求的任何內(nèi)容,例如 headers 或請求參數(shù)。斷言的輸入類型是一個 ServerWebExchange。類似于nginx中的location匹配一樣

    spring cloud gateway幫我們內(nèi)置了很多Predicate功能,實現(xiàn)了各種路由匹配規(guī)則(通過header、請求參數(shù)等作為條件)匹配到相應的路由

    斷言體系包含:

    • 時間類斷言

    • cookie類斷言

    • header請求頭斷言

    • host請求主機類斷言

    • method請求方式類斷言

    • path請求路徑斷言

    • queryparam請求參數(shù)類斷言

    • remoteaddr遠程地址類斷言

  • 過濾器(Filter):和Zuul的過濾器在概念上類似,可以使用它攔截和修改請求,并且對上游的響應,進行二次處理。過濾器為org.springframework.cloud.gateway.filter.GatewayFilter類的實例。

下面是其官網(wǎng)中對工作過程描述圖,如下:

[圖片上傳失敗...(image-a26eae-1640333180160)]

總結(jié)下:

客戶端想gateway發(fā)出請求,然后在gateway handler mapping中找到與請求相匹配的路由,將其發(fā)送到gateway web handler,handler再通過指定的過濾鏈路來將請求發(fā)送到我們實際的服務并執(zhí)行業(yè)務邏輯,然后返回,其中過濾器用虛線分隔,是因為過濾器可能會在發(fā)送代理請求之前(pre)或者之后(post)執(zhí)行業(yè)務邏輯;

Filter在pre前我們可以做請求的合法性校驗、權(quán)限校驗、流量監(jiān)控、日志輸出、協(xié)議轉(zhuǎn)換等等,在post之后我們也可以做響應內(nèi)容的修改、日志輸出、流量監(jiān)控等等。

入門
  • 引入依賴:
<dependencies>

    <!--spring cloud gateway依賴-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>

    <!--網(wǎng)關也是一個eureka客戶端-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

</dependencies>

注意:gateway不需要引入web模塊,他引入的是webflux

  • 配置文件
server:
  port: 10003
spring:
  application:
    name: gateway
  zipkin:
    # zipkin server的請求地址
    base-url: http://localhost:10005/
    sender:
      type: web
  sleuth:
    sampler:
      probability: 1
  cloud:
    gateway:
      routes:
      # 路由id,可以隨意寫
        - id: user-api-route
      # 代理的服務地址;lb表示從eureka中獲取具體服務
          uri: lb://user-api
      # 路由斷言,可以配置映射路徑
          predicates:
            - Path=/user/**
          filters: # 表示過濾1個路徑,2表示兩個路徑,以此類推
            - StripPrefix=1
    config:
      enabled: true
      # 與遠程倉庫中的配置文件的application保持一致
      name: gateway
      # 遠程倉庫中的配置文件的profile保持一致
      profile: dev
      # 遠程倉庫中的 分支 版本保持一致
      label: master
      # config server地址
      uri: http://localhost:10002/
      # 配置的用戶名密碼
      username: root
      password: root  
#eureka 參數(shù)配置
eureka:
  # 此實例注冊到eureka服務端的唯一的實例ID,其組成為${spring.application.name}:${spring.application.instance_id:${random.value}}
  instance:
    #  與此實例相關聯(lián)的主機名,是其他實例可以用來進行請求的準確名稱
    hostname: localhost
    # 獲取實例的ip地址
    prefer-ip-address: true
    #  eureka客戶需要多長時間發(fā)送心跳給eureka服務器,表明它仍然活著,默認為30 秒
    lease-renewal-interval-in-seconds: 10
    #  Eureka服務器在接收到實例的最后一次發(fā)出的心跳后,需要等待多久才可以將此實例刪除,默認為90秒
    lease-expiration-duration-in-seconds: 30
  client:
    # 注冊自己
    register-with-eureka: true
    # 不拉取服務
    fetch-registry: true
    # 配置服務地址
    service-url:
      # eureka 服務地址,如果是集群的話;需要指定其它集群eureka地址  ,如果是多臺eureka server 地址以逗號隔開
      defaultZone: http://127.0.0.1:10001/eureka
  • 啟動類
/**
 * @Description:
 * @author: dy
 */
@EnableDiscoveryClient //開啟Eureka客戶端發(fā)現(xiàn)功能
@SpringBootApplication
public class GateWayApplication {

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

}

基礎功能這樣配置就夠了,運行結(jié)果訪問接口:

gateway運行結(jié)果.png
gateway過濾器

從過濾器的生命周期角度來說,分為兩個pre和post:

  • pre前我們可以做請求的合法性校驗、權(quán)限校驗、流量監(jiān)控、日志輸出、協(xié)議轉(zhuǎn)換等等

  • post之后我們也可以做響應內(nèi)容的修改、日志輸出、流量監(jiān)控等等。

過濾器類型“

  • gatewayFilter 應用到單個路由上

  • globalfilter 應用到全部路由上

下面我們就以全局過濾器來實現(xiàn)一個功能:

比如實現(xiàn)校驗用戶是否登錄,判斷用戶請求頭里面是否有token,代碼如下:

/**
 * @Description:
 * @author: dy
 */
@Component  //讓容器掃描到就等同于注冊了
public class TokenGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("-----------------全局過濾器MyGlobalFilter------------------- --");
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        if (StringUtils.isBlank(token)) {
            //沒有登錄拒絕訪問,返回
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        //合法請求放行、執(zhí)行后續(xù)的過濾器
        return chain.filter(exchange);
    }

    /**
     * 過濾器的執(zhí)行順序
     * @return
     */
    @Override
    public int getOrder() {
        //值越小越先執(zhí)行
        return 1;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容