Spring Cloud 系列之 Gateway 服務(wù)網(wǎng)關(guān)(一)

什么是 Spring Cloud Gateway

Spring Cloud Gateway 作為 Spring Cloud 生態(tài)系統(tǒng)中的網(wǎng)關(guān),目標(biāo)是替代 Netflix Zuul,其不僅提供統(tǒng)一的路由方式,并且還基于 Filter 鏈的方式提供了網(wǎng)關(guān)基本的功能。目前最新版 Spring Cloud 中引用的還是 Zuul 1.x 版本,而這個(gè)版本是基于過(guò)濾器的,是阻塞 IO,不支持長(zhǎng)連接。

Zuul 2.x 版本一直跳票,2019 年 5 月,Netflix 終于開(kāi)源了支持異步調(diào)用模式的 Zuul 2.0 版本,真可謂千呼萬(wàn)喚始出來(lái)。但是 Spring Cloud 已經(jīng)不再集成 Zuul 2.x 了,那么是時(shí)候了解一下 Spring Cloud Gateway 了。

Spring Cloud Gateway 是基于 Spring 生態(tài)系統(tǒng)之上構(gòu)建的 API 網(wǎng)關(guān),包括:Spring 5,Spring Boot 2 和 Project Reactor。Spring Cloud Gateway 旨在提供一種簡(jiǎn)單而有效的方法來(lái)路由到 API,并為它們提供跨領(lǐng)域的關(guān)注點(diǎn),例如:安全性,監(jiān)視/指標(biāo),限流等。由于 Spring 5.0 支持 Netty,Http2,而 Spring Boot 2.0 支持 Spring 5.0,因此 Spring Cloud Gateway 支持 Netty 和 Http2 順理成章。

什么是服務(wù)網(wǎng)關(guān)

API Gateway(APIGW / API 網(wǎng)關(guān)),顧名思義,是出現(xiàn)在系統(tǒng)邊界上的一個(gè)面向 API 的、串行集中式的強(qiáng)管控服務(wù),這里的邊界是企業(yè) IT 系統(tǒng)的邊界,可以理解為企業(yè)級(jí)應(yīng)用防火墻,主要起到隔離外部訪問(wèn)與內(nèi)部系統(tǒng)的作用。在微服務(wù)概念的流行之前,API 網(wǎng)關(guān)就已經(jīng)誕生了,例如銀行、證券等領(lǐng)域常見(jiàn)的前置機(jī)系統(tǒng),它也是解決訪問(wèn)認(rèn)證、報(bào)文轉(zhuǎn)換、訪問(wèn)統(tǒng)計(jì)等問(wèn)題的。

API 網(wǎng)關(guān)的流行,源于近幾年來(lái)移動(dòng)應(yīng)用與企業(yè)間互聯(lián)需求的興起。移動(dòng)應(yīng)用、企業(yè)互聯(lián),使得后臺(tái)服務(wù)支持的對(duì)象,從以前單一的Web應(yīng)用,擴(kuò)展到多種使用場(chǎng)景,且每種使用場(chǎng)景對(duì)后臺(tái)服務(wù)的要求都不盡相同。這不僅增加了后臺(tái)服務(wù)的響應(yīng)量,還增加了后臺(tái)服務(wù)的復(fù)雜性。隨著微服務(wù)架構(gòu)概念的提出,API網(wǎng)關(guān)成為了微服務(wù)架構(gòu)的一個(gè)標(biāo)配組件。

API 網(wǎng)關(guān)是一個(gè)服務(wù)器,是系統(tǒng)對(duì)外的唯一入口。API 網(wǎng)關(guān)封裝了系統(tǒng)內(nèi)部架構(gòu),為每個(gè)客戶端提供定制的 API。所有的客戶端和消費(fèi)端都通過(guò)統(tǒng)一的網(wǎng)關(guān)接入微服務(wù),在網(wǎng)關(guān)層處理所有非業(yè)務(wù)功能。API 網(wǎng)關(guān)并不是微服務(wù)場(chǎng)景中必須的組件,如下圖,不管有沒(méi)有 API 網(wǎng)關(guān),后端微服務(wù)都可以通過(guò) API 很好地支持客戶端的訪問(wèn)。

但對(duì)于服務(wù)數(shù)量眾多、復(fù)雜度比較高、規(guī)模比較大的業(yè)務(wù)來(lái)說(shuō),引入 API 網(wǎng)關(guān)也有一系列的好處:

  • 聚合接口使得服務(wù)對(duì)調(diào)用者透明,客戶端與后端的耦合度降低
  • 聚合后臺(tái)服務(wù),節(jié)省流量,提高性能,提升用戶體驗(yàn)
  • 提供安全、流控、過(guò)濾、緩存、計(jì)費(fèi)、監(jiān)控等 API 管理功能

為什么要使用網(wǎng)關(guān)

  • 單體應(yīng)用:瀏覽器發(fā)起請(qǐng)求到單體應(yīng)用所在的機(jī)器,應(yīng)用從數(shù)據(jù)庫(kù)查詢數(shù)據(jù)原路返回給瀏覽器,對(duì)于單體應(yīng)用來(lái)說(shuō)是不需要網(wǎng)關(guān)的。
  • 微服務(wù):微服務(wù)的應(yīng)用可能部署在不同機(jī)房,不同地區(qū),不同域名下。此時(shí)客戶端(瀏覽器/手機(jī)/軟件工具)想要請(qǐng)求對(duì)應(yīng)的服務(wù),都需要知道機(jī)器的具體 IP 或者域名 URL,當(dāng)微服務(wù)實(shí)例眾多時(shí),這是非常難以記憶的,對(duì)于客戶端來(lái)說(shuō)也太復(fù)雜難以維護(hù)。此時(shí)就有了網(wǎng)關(guān),客戶端相關(guān)的請(qǐng)求直接發(fā)送到網(wǎng)關(guān),由網(wǎng)關(guān)根據(jù)請(qǐng)求標(biāo)識(shí)解析判斷出具體的微服務(wù)地址,再把請(qǐng)求轉(zhuǎn)發(fā)到微服務(wù)實(shí)例。這其中的記憶功能就全部交由網(wǎng)關(guān)來(lái)操作了。

總結(jié)

如果讓客戶端直接與各個(gè)微服務(wù)交互:

  • 客戶端會(huì)多次請(qǐng)求不同的微服務(wù),增加了客戶端的復(fù)雜性
  • 存在跨域請(qǐng)求,在一定場(chǎng)景下處理相對(duì)復(fù)雜
  • 身份認(rèn)證問(wèn)題,每個(gè)微服務(wù)需要獨(dú)立身份認(rèn)證
  • 難以重構(gòu),隨著項(xiàng)目的迭代,可能需要重新劃分微服務(wù)
  • 某些微服務(wù)可能使用了防火墻/瀏覽器不友好的協(xié)議,直接訪問(wèn)會(huì)有一定的困難

因此,我們需要網(wǎng)關(guān)介于客戶端與服務(wù)器之間的中間層,所有外部請(qǐng)求率先經(jīng)過(guò)微服務(wù)網(wǎng)關(guān),客戶端只需要與網(wǎng)關(guān)交互,只需要知道網(wǎng)關(guān)地址即可。這樣便簡(jiǎn)化了開(kāi)發(fā)且有以下優(yōu)點(diǎn):

  • 易于監(jiān)控,可在微服務(wù)網(wǎng)關(guān)收集監(jiān)控?cái)?shù)據(jù)并將其推送到外部系統(tǒng)進(jìn)行分析
  • 易于認(rèn)證,可在微服務(wù)網(wǎng)關(guān)上進(jìn)行認(rèn)證,然后再將請(qǐng)求轉(zhuǎn)發(fā)到后端的微服務(wù),從而無(wú)需在每個(gè)微服務(wù)中進(jìn)行認(rèn)證
  • 減少了客戶端與各個(gè)微服務(wù)之間的交互次數(shù)

網(wǎng)關(guān)解決了什么問(wèn)題

網(wǎng)關(guān)具有身份認(rèn)證與安全、審查與監(jiān)控、動(dòng)態(tài)路由、負(fù)載均衡、緩存、請(qǐng)求分片與管理、靜態(tài)響應(yīng)處理等功能。當(dāng)然最主要的職責(zé)還是與“外界聯(lián)系”。

總結(jié)一下,網(wǎng)關(guān)應(yīng)當(dāng)具備以下功能:

  • 性能:API 高可用,負(fù)載均衡,容錯(cuò)機(jī)制。
  • 安全:權(quán)限身份認(rèn)證、脫敏,流量清洗,后端簽名(保證全鏈路可信調(diào)用),黑名單(非法調(diào)用的限制)。
  • 日志:日志記錄,一旦涉及分布式,全鏈路跟蹤必不可少。
  • 緩存:數(shù)據(jù)緩存。
  • 監(jiān)控:記錄請(qǐng)求響應(yīng)數(shù)據(jù),API 耗時(shí)分析,性能監(jiān)控。
  • 限流:流量控制,錯(cuò)峰流控,可以定義多種限流規(guī)則。
  • 灰度:線上灰度部署,可以減小風(fēng)險(xiǎn)。
  • 路由:動(dòng)態(tài)路由規(guī)則。

常用網(wǎng)關(guān)解決方案

Nginx + Lua

Nginx 是由 IgorSysoev 為俄羅斯訪問(wèn)量第二的 Rambler.ru 站點(diǎn)開(kāi)發(fā)的,一個(gè)高性能的 HTTP 和反向代理服務(wù)器。Ngnix 一方面可以做反向代理,另外一方面做可以做靜態(tài)資源服務(wù)器。

  • Nginx 適合做門戶網(wǎng)關(guān),是作為整個(gè)全局的網(wǎng)關(guān),對(duì)外的處于最外層的那種;而 Gateway 屬于業(yè)務(wù)網(wǎng)關(guān),主要用來(lái)對(duì)應(yīng)不同的客戶端提供服務(wù),用于聚合業(yè)務(wù)。各個(gè)微服務(wù)獨(dú)立部署,職責(zé)單一,對(duì)外提供服務(wù)的時(shí)候需要有一個(gè)東西把業(yè)務(wù)聚合起來(lái)。

  • Gateway 可以實(shí)現(xiàn)熔斷、重試等功能,這是 Nginx 不具備的。

Kong

Kong 是 Mashape 提供的一款 API 管理軟件,它本身是基于 Ngnix + Lua 的,但比 Nginx 提供了更簡(jiǎn)單的配置方式,數(shù)據(jù)采用了 ApacheCassandra/PostgreSQL 存儲(chǔ),并且提供了一些優(yōu)秀的插件,比如驗(yàn)證,日志,調(diào)用頻次限制等。Kong 非常誘人的地方就是提供了大量的插件來(lái)擴(kuò)展應(yīng)用,通過(guò)設(shè)置不同的插件可以為服務(wù)提供各種增強(qiáng)的功能。

優(yōu)點(diǎn):基于 Nginx 所以在性能和穩(wěn)定性上都沒(méi)有問(wèn)題。Kong 作為一款商業(yè)軟件,在 Nginx 上做了很擴(kuò)展工作,而且還有很多付費(fèi)的商業(yè)插件。Kong 本身也有付費(fèi)的企業(yè)版,其中包括技術(shù)支持、使用培訓(xùn)服務(wù)以及 API 分析插件。

缺點(diǎn):如果你使用 Spring Cloud,Kong 如何結(jié)合目前已有的服務(wù)治理體系?

Traefik

Traefik 是一個(gè)開(kāi)源的 GO 語(yǔ)言開(kāi)發(fā)的為了讓部署微服務(wù)更加便捷而誕生的現(xiàn)代HTTP反向代理、負(fù)載均衡工具。 它支持多種后臺(tái) (Docker, Swarm, Kubernetes, Marathon, Mesos, Consul, Etcd, Zookeeper, BoltDB, Rest API, file…) 來(lái)自動(dòng)化、動(dòng)態(tài)的應(yīng)用它的配置文件設(shè)置。Traefik 擁有一個(gè)基于 AngularJS 編寫的簡(jiǎn)單網(wǎng)站界面,支持 Rest API,配置文件熱更新,無(wú)需重啟進(jìn)程。高可用集群模式等。

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

Spring Cloud Netflix Zuul

Zuul 是 Netflix 公司開(kāi)源的一個(gè) API 網(wǎng)關(guān)組件,Spring Cloud 對(duì)其進(jìn)行二次基于 Spring Boot 的注解式封裝做到開(kāi)箱即用。目前來(lái)說(shuō),結(jié)合 Sring Cloud 提供的服務(wù)治理體系,可以做到請(qǐng)求轉(zhuǎn)發(fā),根據(jù)配置或者默認(rèn)的路由規(guī)則進(jìn)行路由和 Load Balance,無(wú)縫集成 Hystrix。

雖然可以通過(guò)自定義 Filter 實(shí)現(xiàn)我們想要的功能,但是由于 Zuul 本身的設(shè)計(jì)是基于單線程的接收請(qǐng)求和轉(zhuǎn)發(fā)處理,是阻塞 IO,不支持長(zhǎng)連接。目前來(lái)看 Zuul 就顯得很雞肋,隨著 Zuul 2.x 一直跳票(2019 年 5 月發(fā)布了 Zuul 2.0 版本),Spring Cloud 推出自己的 Spring Cloud Gateway。

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

Zuul 1.0

Zuul 2.0

Spring Cloud Gateway

本文主角。

環(huán)境準(zhǔn)備

gateway-demo 聚合工程。SpringBoot 2.2.4.RELEASE、Spring Cloud Hoxton.SR1。

  • eureka-server:注冊(cè)中心
  • eureka-server02:注冊(cè)中心
  • product-service:商品服務(wù),提供了根據(jù)主鍵查詢商品接口 http://localhost:7070/product/{id}
  • order-service:訂單服務(wù),提供了根據(jù)主鍵查詢訂單接口 http://localhost:9090/order/{id} 且訂單服務(wù)調(diào)用商品服務(wù)。

Nginx 實(shí)現(xiàn) API 網(wǎng)關(guān)

點(diǎn)擊鏈接觀看:Nginx 實(shí)現(xiàn) API 網(wǎng)關(guān)視頻(獲取更多請(qǐng)關(guān)注公眾號(hào)「哈嘍沃德先生」)

之前的課程中我們已經(jīng)詳細(xì)的講解過(guò) Nginx 關(guān)于反向代理、負(fù)載均衡等功能的使用,這里不再贅述。這里主要通過(guò) Nginx 來(lái)實(shí)現(xiàn) API 網(wǎng)關(guān)方便大家更好的學(xué)習(xí)和理解 Spring Cloud Gateway 的使用。

下載

官網(wǎng):http://nginx.org/en/download.html 下載穩(wěn)定版。為了方便學(xué)習(xí),請(qǐng)下載 Windows 版本。

安裝

解壓文件后直接運(yùn)行根路徑下的 nginx.exe 文件即可。

Nginx 默認(rèn)端口為 80,訪問(wèn):http://localhost:80/ 看到下圖說(shuō)明安裝成功。

配置路由規(guī)則

進(jìn)入 Nginx 的 conf 目錄,打開(kāi) nginx.conf 文件,配置路由規(guī)則:

http {

    ...

    server {
        listen       80;
        server_name  localhost;

        ...

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

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

        ...
    }
    
    ...
    
}

訪問(wèn)

之前我們?nèi)绻L問(wèn)服務(wù),必須由客戶端指定具體服務(wù)地址訪問(wèn),現(xiàn)在統(tǒng)一訪問(wèn) Nginx,由 Nginx 實(shí)現(xiàn)網(wǎng)關(guān)功能將請(qǐng)求路由至具體的服務(wù)。

訪問(wèn):http://localhost/api-product/product/1 結(jié)果如下:

訪問(wèn):http://localhost/api-order/order/1 結(jié)果如下:

Gateway 實(shí)現(xiàn) API 網(wǎng)關(guān)

點(diǎn)擊鏈接觀看:Gateway 網(wǎng)關(guān)核心概念視頻(獲取更多請(qǐng)關(guān)注公眾號(hào)「哈嘍沃德先生」)

官網(wǎng)文檔:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/

核心概念

路由(Route):路由是網(wǎng)關(guān)最基礎(chǔ)的部分,路由信息由 ID、目標(biāo) URI、一組斷言和一組過(guò)濾器組成。如果斷言路由為真,則說(shuō)明請(qǐng)求的 URI 和配置匹配。

斷言(Predicate):Java8 中的斷言函數(shù)。Spring Cloud Gateway 中的斷言函數(shù)輸入類型是 Spring 5.0 框架中的 ServerWebExchange。Spring Cloud Gateway 中的斷言函數(shù)允許開(kāi)發(fā)者去定義匹配來(lái)自于 Http Request 中的任何信息,比如請(qǐng)求頭和參數(shù)等。

過(guò)濾器(Filter):一個(gè)標(biāo)準(zhǔn)的 Spring Web Filter。Spring Cloud Gateway 中的 Filter 分為兩種類型,分別是 Gateway Filter 和 Global Filter。過(guò)濾器將會(huì)對(duì)請(qǐng)求和響應(yīng)進(jìn)行處理。

工作原理

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

搭建網(wǎng)關(guān)服務(wù)

點(diǎn)擊鏈接觀看:Gateway 實(shí)現(xiàn) API 網(wǎng)關(guān)視頻(獲取更多請(qǐng)關(guān)注公眾號(hào)「哈嘍沃德先生」)

創(chuàng)建項(xiàng)目

gateway-demo 聚合工程下創(chuàng)建 gateway-server 項(xiàng)目。

添加依賴

添加 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>

    <!-- 項(xiàng)目依賴 -->
    <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 # 應(yīng)用名稱

啟動(dòng)類

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);
    }

}

配置路由規(guī)則

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

訪問(wèn):http://localhost:9000/product/1 結(jié)果如下:

本篇文章先讓大家簡(jiǎn)單認(rèn)識(shí)一下 Gateway 網(wǎng)關(guān),下一篇我們講解 Gateway 網(wǎng)關(guān)的多種路由規(guī)則、動(dòng)態(tài)路由規(guī)則(配合服務(wù)發(fā)現(xiàn)的路由規(guī)則),記得關(guān)注噢~

本文采用 知識(shí)共享「署名-非商業(yè)性使用-禁止演繹 4.0 國(guó)際」許可協(xié)議

大家可以通過(guò) 分類 查看更多關(guān)于 Spring Cloud 的文章。


?? 您的點(diǎn)贊轉(zhuǎn)發(fā)是對(duì)我最大的支持。

?? 關(guān)注公眾號(hào) 哈嘍沃德先生「文檔 + 視頻」每篇文章都配有專門視頻講解,學(xué)習(xí)更輕松噢 ~


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

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

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