Spring Cloud 系列之 Gateway 服務網關(一)

什麼是 Spring Cloud Gateway

Spring Cloud Gateway 作爲 Spring Cloud 生態系統中的網關,目標是替代 Netflix Zuul,其不僅提供統一的路由方式,並且還基於 Filter 鏈的方式提供了網關基本的功能。目前最新版 Spring Cloud 中引用的還是 Zuul 1.x 版本,而這個版本是基於過濾器的,是阻塞 IO,不支持長連接。

Zuul 2.x 版本一直跳票,2019 年 5 月,Netflix 終於開源了支持異步調用模式的 Zuul 2.0 版本,真可謂千呼萬喚始出來。但是 Spring Cloud 已經不再集成 Zuul 2.x 了,那麼是時候瞭解一下 Spring Cloud Gateway 了。

Spring Cloud Gateway 是基於 Spring 生態系統之上構建的 API 網關,包括:Spring 5,Spring Boot 2 和 Project Reactor。Spring Cloud Gateway 旨在提供一種簡單而有效的方法來路由到 API,併爲它們提供跨領域的關注點,例如:安全性,監視/指標,限流等。由於 Spring 5.0 支持 Netty,Http2,而 Spring Boot 2.0 支持 Spring 5.0,因此 Spring Cloud Gateway 支持 Netty 和 Http2 順理成章。

什麼是服務網關

API Gateway(APIGW / API 網關),顧名思義,是出現在系統邊界上的一個面向 API 的、串行集中式的強管控服務,這裏的邊界是企業 IT 系統的邊界,可以理解爲企業級應用防火牆,主要起到隔離外部訪問與內部系統的作用。在微服務概念的流行之前,API 網關就已經誕生了,例如銀行、證券等領域常見的前置機系統,它也是解決訪問認證、報文轉換、訪問統計等問題的。

API 網關的流行,源於近幾年來移動應用與企業間互聯需求的興起。移動應用、企業互聯,使得後臺服務支持的對象,從以前單一的Web應用,擴展到多種使用場景,且每種使用場景對後臺服務的要求都不盡相同。這不僅增加了後臺服務的響應量,還增加了後臺服務的複雜性。隨着微服務架構概念的提出,API網關成爲了微服務架構的一個標配組件

API 網關是一個服務器,是系統對外的唯一入口。API 網關封裝了系統內部架構,爲每個客戶端提供定製的 API。所有的客戶端和消費端都通過統一的網關接入微服務,在網關層處理所有非業務功能。API 網關並不是微服務場景中必須的組件,如下圖,不管有沒有 API 網關,後端微服務都可以通過 API 很好地支持客戶端的訪問。

但對於服務數量衆多、複雜度比較高、規模比較大的業務來說,引入 API 網關也有一系列的好處:

  • 聚合接口使得服務對調用者透明,客戶端與後端的耦合度降低
  • 聚合後臺服務,節省流量,提高性能,提升用戶體驗
  • 提供安全、流控、過濾、緩存、計費、監控等 API 管理功能

爲什麼要使用網關

  • 單體應用:瀏覽器發起請求到單體應用所在的機器,應用從數據庫查詢數據原路返回給瀏覽器,對於單體應用來說是不需要網關的。
  • 微服務:微服務的應用可能部署在不同機房,不同地區,不同域名下。此時客戶端(瀏覽器/手機/軟件工具)想要請求對應的服務,都需要知道機器的具體 IP 或者域名 URL,當微服務實例衆多時,這是非常難以記憶的,對於客戶端來說也太複雜難以維護。此時就有了網關,客戶端相關的請求直接發送到網關,由網關根據請求標識解析判斷出具體的微服務地址,再把請求轉發到微服務實例。這其中的記憶功能就全部交由網關來操作了。

總結

如果讓客戶端直接與各個微服務交互:

  • 客戶端會多次請求不同的微服務,增加了客戶端的複雜性
  • 存在跨域請求,在一定場景下處理相對複雜
  • 身份認證問題,每個微服務需要獨立身份認證
  • 難以重構,隨着項目的迭代,可能需要重新劃分微服務
  • 某些微服務可能使用了防火牆/瀏覽器不友好的協議,直接訪問會有一定的困難

因此,我們需要網關介於客戶端與服務器之間的中間層,所有外部請求率先經過微服務網關,客戶端只需要與網關交互,只需要知道網關地址即可。這樣便簡化了開發且有以下優點:

  • 易於監控,可在微服務網關收集監控數據並將其推送到外部系統進行分析
  • 易於認證,可在微服務網關上進行認證,然後再將請求轉發到後端的微服務,從而無需在每個微服務中進行認證
  • 減少了客戶端與各個微服務之間的交互次數

網關解決了什麼問題

網關具有身份認證與安全、審查與監控、動態路由、負載均衡、緩存、請求分片與管理、靜態響應處理等功能。當然最主要的職責還是與“外界聯繫”。

總結一下,網關應當具備以下功能:

  • 性能:API 高可用,負載均衡,容錯機制。
  • 安全:權限身份認證、脫敏,流量清洗,後端簽名(保證全鏈路可信調用),黑名單(非法調用的限制)。
  • 日誌:日誌記錄,一旦涉及分佈式,全鏈路跟蹤必不可少。
  • 緩存:數據緩存。
  • 監控:記錄請求響應數據,API 耗時分析,性能監控。
  • 限流:流量控制,錯峯流控,可以定義多種限流規則。
  • 灰度:線上灰度部署,可以減小風險。
  • 路由:動態路由規則。

常用網關解決方案

Nginx + Lua

Nginx 是由 IgorSysoev 爲俄羅斯訪問量第二的 Rambler.ru 站點開發的,一個高性能的 HTTP 和反向代理服務器。Ngnix 一方面可以做反向代理,另外一方面做可以做靜態資源服務器。

  • Nginx 適合做門戶網關,是作爲整個全局的網關,對外的處於最外層的那種;而 Gateway 屬於業務網關,主要用來對應不同的客戶端提供服務,用於聚合業務。各個微服務獨立部署,職責單一,對外提供服務的時候需要有一個東西把業務聚合起來。

  • Gateway 可以實現熔斷、重試等功能,這是 Nginx 不具備的。

Kong

Kong 是 Mashape 提供的一款 API 管理軟件,它本身是基於 Ngnix + Lua 的,但比 Nginx 提供了更簡單的配置方式,數據採用了 ApacheCassandra/PostgreSQL 存儲,並且提供了一些優秀的插件,比如驗證,日誌,調用頻次限制等。Kong 非常誘人的地方就是提供了大量的插件來擴展應用,通過設置不同的插件可以爲服務提供各種增強的功能。

優點:基於 Nginx 所以在性能和穩定性上都沒有問題。Kong 作爲一款商業軟件,在 Nginx 上做了很擴展工作,而且還有很多付費的商業插件。Kong 本身也有付費的企業版,其中包括技術支持、使用培訓服務以及 API 分析插件。

缺點:如果你使用 Spring Cloud,Kong 如何結合目前已有的服務治理體系?

Traefik

Traefik 是一個開源的 GO 語言開發的爲了讓部署微服務更加便捷而誕生的現代HTTP反向代理、負載均衡工具。 它支持多種後臺 (Docker, Swarm, Kubernetes, Marathon, Mesos, Consul, Etcd, Zookeeper, BoltDB, Rest API, file…) 來自動化、動態的應用它的配置文件設置。Traefik 擁有一個基於 AngularJS 編寫的簡單網站界面,支持 Rest API,配置文件熱更新,無需重啓進程。高可用集羣模式等。

相對 Spring Cloud 和 Kubernetes 而言,目前比較適合 Kubernetes。

Spring Cloud Netflix Zuul

Zuul 是 Netflix 公司開源的一個 API 網關組件,Spring Cloud 對其進行二次基於 Spring Boot 的註解式封裝做到開箱即用。目前來說,結合 Sring Cloud 提供的服務治理體系,可以做到請求轉發,根據配置或者默認的路由規則進行路由和 Load Balance,無縫集成 Hystrix。

雖然可以通過自定義 Filter 實現我們想要的功能,但是由於 Zuul 本身的設計是基於單線程的接收請求和轉發處理,是阻塞 IO,不支持長連接。目前來看 Zuul 就顯得很雞肋,隨着 Zuul 2.x 一直跳票(2019 年 5 月發佈了 Zuul 2.0 版本),Spring Cloud 推出自己的 Spring Cloud Gateway。

大意就是:Zuul 已死,Spring Cloud Gateway 永生(手動狗頭)。

Zuul 1.0

Zuul 2.0

Spring Cloud Gateway

本文主角。

環境準備

gateway-demo 聚合工程。SpringBoot 2.2.4.RELEASESpring Cloud Hoxton.SR1

  • eureka-server:註冊中心
  • eureka-server02:註冊中心
  • product-service:商品服務,提供了根據主鍵查詢商品接口 http://localhost:7070/product/{id}
  • order-service:訂單服務,提供了根據主鍵查詢訂單接口 http://localhost:9090/order/{id} 且訂單服務調用商品服務。

Nginx 實現 API 網關

點擊鏈接觀看:Nginx 實現 API 網關(獲取更多請關注公衆號「哈嘍沃德先生」)

之前的課程中我們已經詳細的講解過 Nginx 關於反向代理、負載均衡等功能的使用,這裏不再贅述。這裏主要通過 Nginx 來實現 API 網關方便大家更好的學習和理解 Spring Cloud Gateway 的使用。

下載

官網:http://nginx.org/en/download.html 下載穩定版。爲了方便學習,請下載 Windows 版本。

安裝

解壓文件後直接運行根路徑下的 nginx.exe 文件即可。

Nginx 默認端口爲 80,訪問:http://localhost:80/ 看到下圖說明安裝成功。

配置路由規則

進入 Nginx 的 conf 目錄,打開 nginx.conf 文件,配置路由規則:

http {

	...

    server {
        listen       80;
        server_name  localhost;

        ...

        # 路由到商品服務
        location /api-product {
            proxy_pass http://localhost:7070/;
        }

        # 路由到訂單服務
        location /api-order {
            proxy_pass http://localhost:9090/;
        }

        ...
    }
    
    ...
    
}

訪問

之前我們如果要訪問服務,必須由客戶端指定具體服務地址訪問,現在統一訪問 Nginx,由 Nginx 實現網關功能將請求路由至具體的服務。

訪問:http://localhost/api-product/product/1 結果如下:

訪問:http://localhost/api-order/order/1 結果如下:

Gateway 實現 API 網關

點擊鏈接觀看:Gateway 網關核心概念(獲取更多請關注公衆號「哈嘍沃德先生」)

官網文檔:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/

核心概念

路由(Route):路由是網關最基礎的部分,路由信息由 ID、目標 URI、一組斷言和一組過濾器組成。如果斷言路由爲真,則說明請求的 URI 和配置匹配。

斷言(Predicate):Java8 中的斷言函數。Spring Cloud Gateway 中的斷言函數輸入類型是 Spring 5.0 框架中的 ServerWebExchange。Spring Cloud Gateway 中的斷言函數允許開發者去定義匹配來自於 Http Request 中的任何信息,比如請求頭和參數等。

過濾器(Filter):一個標準的 Spring Web Filter。Spring Cloud Gateway 中的 Filter 分爲兩種類型,分別是 Gateway Filter 和 Global Filter。過濾器將會對請求和響應進行處理。

工作原理

如上圖所示,客戶端向 Spring Cloud Gateway 發出請求。再由網關處理程序 Gateway Handler Mapping 映射確定與請求相匹配的路由,將其發送到網關 Web 處理程序 Gateway Web Handler。該處理程序通過指定的過濾器鏈將請求發送到我們實際的服務執行業務邏輯,然後返回。過濾器由虛線分隔的原因是,過濾器可以在發送代理請求之前和之後運行邏輯。所有 pre 過濾器邏輯均被執行。然後發出代理請求。發出代理請求後,將運行 post 過濾器邏輯。

搭建網關服務

點擊鏈接觀看:Gateway 實現 API 網關(獲取更多請關注公衆號「哈嘍沃德先生」)

創建項目

gateway-demo 聚合工程下創建 gateway-server 項目。

添加依賴

添加 spring cloud gateway 依賴。

<?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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>gateway-server</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- 繼承父依賴 -->
    <parent>
        <groupId>com.example</groupId>
        <artifactId>gateway-demo</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

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

</project>

配置文件

application.yml

server:
  port: 9000 # 端口

spring:
  application:
    name: gateway-server # 應用名稱

啓動類

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GatewayServerApplication {

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

}

配置路由規則

spring:
  application:
    name: gateway-server # 應用名稱
  cloud:
    gateway:
      # 路由規則
      routes:
        - id: product-service           # 路由 ID,唯一
          uri: http://localhost:7070/   # 目標 URI,路由到微服務的地址
          predicates:                   # 斷言(判斷條件)
            - Path=/product/**          # 匹配對應 URL 的請求,將匹配到的請求追加在目標 URI 之後
  • 請求 http://localhost:9000/product/1 將會路由至 http://localhost:7070/product/1

訪問:http://localhost:9000/product/1 結果如下:

本篇文章先讓大家簡單認識一下 Gateway 網關,下一篇我們講解 Gateway 網關的多種路由規則、動態路由規則(配合服務發現的路由規則),記得關注噢~

本文采用 知識共享「署名-非商業性使用-禁止演繹 4.0 國際」許可協議

大家可以通過 分類 查看更多關於 Spring Cloud 的文章。


🤗 您的點贊轉發是對我最大的支持。

📢 掃碼關注 哈嘍沃德先生「文檔 + 視頻」每篇文章都配有專門視頻講解,學習更輕鬆噢 ~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章