白話SpringCloud | 第九章:路由網(wǎng)關(Zuul)的使用

第九章:路由網(wǎng)關(Zuul)的使用

前言

介紹完分布式配置中心,結合前面的文章。我們已經(jīng)有了一個微服務的框架了,可以對外提供api接口服務了。但現(xiàn)在試想一下,在微服務框架中,每個對外服務都是獨立部署的,對外的api或者服務地址都不是不盡相同的。對于內(nèi)部而言,很簡單,通過注冊中心自動感知即可。但我們大部分情況下,服務都是提供給外部系統(tǒng)進行調(diào)用的,不可能同享一個注冊中心。同時一般上內(nèi)部的微服務都是在內(nèi)網(wǎng)的,和外界是不連通的。而且,就算我們每個微服務對外開放,對于調(diào)用者而言,調(diào)用不同的服務的地址或者參數(shù)也是不盡相同的,這樣就會造成消費者客戶端的復雜性,同時想想,可能微服務可能是不同的技術棧實現(xiàn)的,有的是http、rpc或者websocket等等,也會進一步加大客戶端的調(diào)用難度。所以,一般上都有會有個api網(wǎng)關,根據(jù)請求的url不同,路由到不同的服務上去,同時入口統(tǒng)一了,還能進行統(tǒng)一的身份鑒權、日志記錄、分流等操作。接下來,我們就來了解今天要講解的路由服務:zuul。

一點知識

為什么要使用微服務網(wǎng)關

簡單來說,微服務網(wǎng)關是微服務架構中一個不可或缺的部分。通過服務網(wǎng)關統(tǒng)一向外系統(tǒng)提供REST API的過程中,除了具備服務路由、均衡負載功能之外,它還具備了權限控制等功能。

在未加入網(wǎng)關時,一般上會在服務外網(wǎng)架設一個負載均衡,如nginx等。此時,微服務的組成為:

image

此時,對于Open Service而言可能需要提供權限控制等和業(yè)務無關的能力,這樣本身就破壞了微服務服務單一的原則。所以,一般上在Open Service之上,還有一層服務提供諸如通用的權限校驗、參數(shù)校驗等功能,此服務就是網(wǎng)關了。之后,對于內(nèi)部微服務而言,只需要關系各自微服務提供的業(yè)務功能即可,無需去關心其他非業(yè)務相關的功能。

API網(wǎng)關是什么

API網(wǎng)關可以提供一個單獨且統(tǒng)一的API入口用于訪問內(nèi)部一個或多個API。簡單來說嘛就是一個統(tǒng)一入口,比如現(xiàn)在的支付寶或者微信的相關api服務一樣,都有一個統(tǒng)一的api地址,統(tǒng)一的請求參數(shù),統(tǒng)一的鑒權。

客戶端和服務端直連的弊端

  • 客戶端會對此請求不同的微服務,增加客戶端復雜性
  • 存在跨域請求時,需要進行額外處理
  • 認證服務,每個服務需要獨立認證
  • UI端和微服務耦合

網(wǎng)關的優(yōu)缺點

優(yōu)點

  • 減少api請求次數(shù)
  • 限流
  • 緩存
  • 統(tǒng)一認證
  • 降低微服務的復雜度
  • 支持混合通信協(xié)議(前端只和api通信,其他的由網(wǎng)關調(diào)用)
  • ……

缺點:

  • 網(wǎng)關需高可用,可能產(chǎn)生單點故障
  • 管理復雜

網(wǎng)關的選擇

現(xiàn)在市場上有很多的網(wǎng)關可供選擇:

  • Spring Cloud Zuul:本身基于Netflix開源的微服務網(wǎng)關,可以和Eureka,Ribbon,Hystrix等組件配合使用。
  • Kong : 基于OpenResty的 API 網(wǎng)關服務和網(wǎng)關服務管理層。
  • Spring Cloud Gateway:是由spring官方基于Spring5.0,Spring Boot2.0,Project Reactor等技術開發(fā)的網(wǎng)關,提供了一個構建在Spring Ecosystem之上的API網(wǎng)關,旨在提供一種簡單而有效的途徑來發(fā)送API,并向他們提供交叉關注點,例如:安全性,監(jiān)控/指標和彈性。目的是為了替換Spring Cloud Netfilx Zuul的。

Spring cloud體系中,一般上選擇zuul或者Gateway。當然,也可以綜合自己的業(yè)務復雜性,自研一套或者改在一套符合自身業(yè)務發(fā)展的api網(wǎng)關的,最簡單做法是做個聚合api服務,通過SpringBoot構建對外的api接口,實現(xiàn)統(tǒng)一鑒權、參數(shù)校驗、權限控制等功能,說白了就是一個rest服務。

Zuul介紹和使用

何為Zuul

ZuulNetflix開源的微服務網(wǎng)關,可以和Eureka、RibbonHystrix等組件配合使用,Spring CloudZuul進行了整合與增強,Zuul的主要功能是路由轉(zhuǎn)發(fā)過濾器。

zuul

Zuul基于JVM的路由器和服務器端負載均衡器。同時,Zuul的規(guī)則引擎允許規(guī)則和過濾器基本上用任何JVM語言編寫,內(nèi)置支持JavaGroovy。這個功能,就可以實現(xiàn)動態(tài)路由的功能了。當需要添加某個新的對外服務時,一般上不停機更新是通過數(shù)據(jù)緩存配置或者使用Groovy進行動態(tài)路由的添加的。

Zuul的核心一系列的過濾器:

  • 身份認證與安全:識別每個資源的驗證要求,并拒絕那些與要求不符的請求。
  • 審查與監(jiān)控:在邊緣位置追蹤有意義的數(shù)據(jù)和統(tǒng)計結果,從而帶來精確的生產(chǎn)視圖。
  • 動態(tài)路由:動態(tài)地將請求路由到不同的后端集群。
  • 壓力測試:逐漸增加指向集群的流量,以了解性能。
  • 負載分配:為每一種負載類型分配對應容量,并啟用超出限定值的請求。
  • 靜態(tài)響應處理:在邊緣位置直接建立部分相應,從而避免其轉(zhuǎn)發(fā)到內(nèi)部集群。

加入Zuul網(wǎng)關后:

加入Zuul后

Zuul實踐

創(chuàng)建工程:spring-cloud-zuul
這里直接加入了注冊中心進行服務化模式。

0.加入pom依賴。

        <!-- zuul 依賴 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>        
        <!-- eureka client 依賴 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

注意:這里的Eureka不是必須的。在沒有注冊中心的情況下,也是可以進行zuul使用的。

1.配置文件,配置注冊中心相關信息、路由規(guī)則等。

spring.application.name=zuul-server
server.port=8888

# 注冊中心地址 -此為單機模式
eureka.client.service-url.defaultZone=http://127.0.0.1:1000/eureka
# 啟用ip配置 這樣在注冊中心列表中看見的是以ip+端口呈現(xiàn)的
eureka.instance.prefer-ip-address=true
# 實例名稱  最后呈現(xiàn)地址:ip:15678
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}

## 路由規(guī)則
## 傳統(tǒng)路由配置:不依賴服務發(fā)現(xiàn)。
## 所有以myapi開頭的url路由至http://127.0.0.1:2000/下
## 如http://127.0.0.1:8888/myapi/hello --> http://127.0.0.1:2000/hello
zuul.routes.myApi.path=/myapi/**
zuul.routes.myApi.url=http://127.0.0.1:2000

#forward模式 直接轉(zhuǎn)發(fā)至zuul提供的rest服務
zuul.routes.myDemo.path=/myDemo/**
zuul.routes.myDemo.url=forward:/demo

## 服務發(fā)現(xiàn)模式
# 路由地址
zuul.routes.myEureka.path=/eureka/**
#為具體服務的名稱
zuul.routes.myEureka.service-id=eureka-client

友情提示:
默認情況下:Zuul代理所有注冊到EurekaServer的微服務,路由規(guī)則:
http://ZUUL_HOST:ZUUL_PORT/微服務實例名(serverId)/**
轉(zhuǎn)發(fā)至serviceId對應的微服務。

如:http://127.0.0.1:8888/eureka-client/hello?name=oKong
最后就是轉(zhuǎn)發(fā)至:http://127.0.0.1:2000//hello?name=oKong

2.啟動類加入@EnableZuulProxy注解,聲明一個Zuul代理。

/**
 * zuul 示例
 * 
 * @author oKong
 *
 */
@SpringBootApplication
@EnableZuulProxy
@EnableDiscoveryClient
@Slf4j
public class SpringCloudZuulApplication {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(SpringCloudZuulApplication.class, args);
        log.info("spring-cloud-zuul啟動!");
    }

}

3.編寫一個控制類,測試forward功能。


/**
 * zuul 內(nèi)部提供對外服務示例
 * @author oKong
 *
 */
@RestController
@RequestMapping("/demo")
public class DemoController {

    @GetMapping("/hello")
    public String hello(String name) {
        return "hi," + name + ",this is zuul api! ";
    }
}

4.啟動spring-cloud-eureka-serverspring-cloud-eureka-client服務,之后再啟動spring-cloud-zuul服務。

此時,我們來訪問zuul內(nèi)部服務:http://127.0.0.1:8888/demo/hello?name=oKong

zuul內(nèi)部服務

然后訪問:http://127.0.0.1:8888/myDemo/hello?name=oKong 效果和上面直接方式是一樣的,最后都是訪問/demo/**api地址的。

訪問:http://127.0.0.1:8888/myapi/hello?name=oKonghttp://127.0.0.1:8888/eureka/hello?name=oKong 最后效果都是一樣的,都是訪問http://127.0.0.1:2000/hello?name=oKong 。

eureka服務
非eureka服務

直接以默認形式訪問:http://127.0.0.1:8888/eureka-client/hello?name=oKong 最后效果也是一樣的。

默認形式

其實,從控制臺輸出日志也是可以一窺究竟的:

控制臺輸出

路由規(guī)則說明

簡單說明下關于路由規(guī)則的一些說明:

傳統(tǒng)路由配置:不依賴服務發(fā)現(xiàn),如nginx

  • 單例實例配置:通過zuul.routes.<route>.pathzuul.routes.<route>.url參數(shù)對的方式來配置
# 傳統(tǒng)路由配置
zuul.routes.server-provide.path=/server-provide/**
zuul.routes.server-provide.url=http://127.0.0.1:1001/

  • 多實例配置:通過一組zuul.routes.<route>.pathzuul.routes.<route>.serviceId參數(shù)對的方式配置
# 多實例
zuul.routes.server-provide.path=/user-service/**
zuul.routes.server-provide.serviceId=user-service
ribbon.eureka.enabled=false
server-provide.ribbon.listOfServers=http://127.0.0.1:1001/,http://127.0.0.1:1001/

服務路由配置:依賴服務發(fā)現(xiàn),結合Eureka

  • 默認規(guī)則:http://ZUUL_HOST:ZUUL_PORT/微服務實例名(serverId)/** ,轉(zhuǎn)發(fā)至serviceId對應的微服務。

  • 自定義路由規(guī)則:通過一組zuul.routes.<route>.pathzuul.routes.<route>.serviceId參數(shù)對的方式配置

# 自定義路由
zuul.routes.server-provide.path=/server-api/**
zuul.routes.server-provide.serviceId=server-provide

比如:

例子

而且,要注意,這些過濾器是path進行最佳路徑匹配的,所以,一般上在一些歷史系統(tǒng)上,我們會在最后后面加上一個路徑/**的匹配規(guī)則,以保證歷史api可以使用,做到最大兼容性,避免類似404的異常。

zuul.routes.legacy.path=/**

參考資料

  1. https://cloud.spring.io/spring-cloud-static/Finchley.SR1/single/spring-cloud.html#_router_and_filter_zuul

總結

本章節(jié)主要簡單介紹了關于Zuul的一些簡單使用以及一些路由規(guī)則的簡單說明。開頭也說過了,Zuul的核心是一系列的過濾器。介于篇幅問題,關于過濾器的介紹、自定義過濾器、異常處理、熔斷降級等放在下一章節(jié)來講解。而相關的其他配置,大家可以去官網(wǎng)進行查看,或者自行搜索下,也可以查看下:org.springframework.cloud.netflix.zuul.filters.ZuulProperties類,相關配置信息都在里面了。

最后

目前互聯(lián)網(wǎng)上大佬都有分享SpringCloud系列教程,內(nèi)容可能會類似,望多多包涵了。原創(chuàng)不易,碼字不易,還希望大家多多支持。若文中有錯誤之處,還望提出,謝謝。

老生常談

  • 個人QQ:499452441
  • 微信公眾號:lqdevOps
公眾號

個人博客:http://blog.lqdev.cn

源碼示例:https://github.com/xie19900123/spring-cloud-learning

原文地址:http://blog.lqdev.cn/2018/10/14/SpringCloud/chapter-nine/

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

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

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,595評論 19 139
  • 目錄 一、SpringCloud微服務技術簡介 1.1 微服務的功能主要體現(xiàn)在以下兒個方面。 1.2 微服務具有以...
    AI視界尼奧閱讀 3,414評論 0 1
  • (git上的源碼:https://gitee.com/rain7564/spring_microservices_...
    sprainkle閱讀 17,255評論 3 32
  • 我在北京,離你的城市1345.62公里。 今年這兒沒有想象里暗無天日的霾,空氣很好,下完雨之后,泥土還能...
    跌宕行僧閱讀 326評論 0 0
  • 男孩,13歲,初二。 在我看來,這幅圖的主題是尋找母愛。 案主其實是一個外向躁動的大男孩兒,但內(nèi)心卻極力掩飾并隱藏...
    皮皮爸爸時代閱讀 269評論 0 0

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