Spring Cloud - 網關

老張正準備下班,路太小齊的位置,發現他正在閱讀Spring Cloud Gataway的官方文檔html

看了看時間,等公交車還有一下子,順便就和小齊交流一下,便問道:「你在學習Spring Cloud網關嗎?」前端

小齊聽到聲音後轉過身來,便看到老張拉了一把椅子坐下。正好本身有一些疑惑的地方,也想找人交流學習一下。程序員

「是啊,我最近不是在學習微服務這部分知識嗎,如今學到網關這部分了。其實我不是特別明白,爲何咱們的微服務須要網關呢?」web

什麼是網關

老張神祕一笑,說道:「我給你看兩張圖你就明白了。」而後在小齊的電腦上搜出了這篇文章裏面的兩張圖。面試

「咱們假設你如今要作一個電商應用,前端是移動端的APP,後端是各類微服務。那你可能某個頁面須要調用多個服務的數據來展現。若是沒有網關,你的系統看起來就是這個樣子的:」spring

沒有網關
沒有網關

「而若是加上了網關,你的系統就會變成這個樣子:」編程

有網關
有網關

「嗯,這看起來是一個‘高內聚,低耦合’的思想,若是不使用網關,可能有什麼壞處呢?」小齊問道。後端

「這個其實從剛剛的第一張圖你就看得出來,若是沒有網關,你的客戶端就會變得很是麻煩。對每個微服務,可能都要作權限認證、負載均衡等工做;並且後端的微服務可能還使用了不一樣的消息通訊協議;最重要的是,若是你想對微服務進行重構,好比拆分或者合併爲服務器,那也必須得修改客戶端,增長了複雜性。」跨域

網關的技術選型

小齊:「那看來網關確實是相當重要,如今市面上有哪些微服務網關呢?」緩存

「咱們在實現網關的時候,須要考慮到的是它的性能和可擴展性。對於現成的產品來講,NGINX Plus是一個很不錯的選擇,NGINX Plus 提供了一個成熟的、可擴展的、高性能 web 服務器和一個易於部署的、可配置可編程的反向代理。NGINX Plus 能夠管理身份驗證、訪問控制、負載均衡請求、緩存響應,並提供應用程序可感知的健康檢查和監控。除此以外,你還可使用Node.js或者Netty根據本身的需求去本身寫一個網關。並且Spring Cloud也提供了一些已經寫好的微服務網關框架,你知道有哪些嗎?」

「我查了一下,好像Spring Cloud Gataway和Netflix的Zuul都挺不錯的。但Netflix的套件暫停開發了,因此我如今主要在看Spring Cloud Gateway。」

老張點點頭,道:「是的,Netflix不少組件到中止開發了。前兩天咱們討論的Hystrix也是,可是Hystrix的替代產品還在孵化中。但網關方面,Spring Cloud Gateway已經孵化完成了,能夠用來替代Zuul。那你知道Spring Cloud Gateway的原理嗎?」

Spring Cloud Gateway

小齊把剛剛本身正在看的官方文檔打開,而後給老張看了官網文檔的這個圖,一邊說道:「Spring Cloud Gateway是基於Spring Boot 2.0, Spring WebFlux, Reactor項目構建的,底層是Netty。它的流程其實和Zuul很類似,使用一系列的過濾器去處理請求,達到咱們本身想要的定製化。」

原理圖
原理圖

老張問:「那裏剛剛看完了官方文檔,能夠跟我總結一下它有哪些功能嗎?」

「Spring Cloud Gateway幾乎能夠知足絕大多數網關的需求。它主要有下面一些功能:」

斷言 Predicate

斷言能夠指定在什麼狀況下能夠匹配某個路由。斷言是基於Java 8提供的Predicate接口。Gateway(如下簡稱Spring Cloud Gateway爲Gateway)提供了一些默認的斷言。你能夠在官方文檔查看具體有哪些斷言以及它們的用法。

支持時間、Cookie、Header、Host、HTTP Method、相對路徑、URL查詢語句、遠程IP等來作斷言。好比:

spring:
 cloud:  gateway:  routes:  - id: method_route  uri: https://example.org  predicates:  - Method=GET 複製代碼

網關過濾器 GatewayFilter

Gateway也提供了一些已經寫好的過濾器。能夠查看官方文檔。主要有重寫request或者response的header、parameter、body、session、安全、重寫路徑、重試以及對熔斷的一些支持。

全局過濾器 Global Filters

全局過濾器與網關過濾器相似,只是默認會給全部的請求都添加上全局過濾器。固然,也能夠本身定義全局過濾器。過濾器的順序能夠經過@Order註解來指定:

@Bean
@Order(-1) public GlobalFilter a() {  return (exchange, chain) -> {  log.info("first pre filter");  return chain.filter(exchange).then(Mono.fromRunnable(() -> {  log.info("third post filter");  }));  }; }  @Bean @Order(0) public GlobalFilter b() {  return (exchange, chain) -> {  log.info("second pre filter");  return chain.filter(exchange).then(Mono.fromRunnable(() -> {  log.info("second post filter");  }));  }; }  @Bean @Order(1) public GlobalFilter c() {  return (exchange, chain) -> {  log.info("third pre filter");  return chain.filter(exchange).then(Mono.fromRunnable(() -> {  log.info("first post filter");  }));  }; } 複製代碼

其它功能

Gateway還提供了其它不少功能,好比說SSL方面的配置、基於netty的access log、跨域、actuator端點等等。具體的用法能夠參考官方文檔。

尤爲是actuator端點,它可讓咱們使用HTTP請求去動態地獲取、新增、刪除路由。具體的使用方法和參數查看官方文檔

定製化

除此之外,Gateway提供了一些接口和抽象類。用戶還能夠本身定製化斷言、Filter、路由等,實現更個性化的要求。參考文檔在這裏,可是目前文檔還不完善,能夠本身看看源碼。

與註冊中心配合

老張:「嗯,上面基本上把Spring Cloud Gateway的功能總結全了。它還能夠與Spring Cloud的註冊中心無縫集成。」

小齊接着老張的話,說道:「是的,Gateway能夠很方便地與註冊中心配合起來使用,默認使用Ribbon實現了負載均衡。你只須要加入某個註冊中心的依賴,好比consul-discovery,而後把配置打開就好了:」

spring.cloud.gateway.discovery.locator.enabled=true
複製代碼

「這樣你就能夠請求Gataway的/service-id/path來訪問服務名叫service-id的某個微服務的/path路徑了。好比:」

http://gateway:8080/service-user/hello

->

http://service-user:8080/hello

也能夠對某個微服務作個性化的配置,參考文檔

網關自己的負載均衡

說完後,小齊問道:「那全部微服務就只有一個網關,萬一併發量上去了,網關承受不住怎麼辦?」

老張笑道:「正如你上面所說,Spring Cloud Gateway底層是Netty的,它自己就能承受比較大的併發。若是仍是承受不了併發量,那能夠註冊多個Gateway實例,而後在前面弄一個Nginx或者F5等負載均衡器。大概圖是這樣:」

網關負載均衡
網關負載均衡

老張看了看時間,差很少該去趕車了。「今天就到這吧,下次再交流~」

關於做者

微信公衆號:編了個程

我的網站:https://yasinshaw.com

筆名Yasin,一個有深度,有態度,有溫度的程序員。工做之餘分享編程技術和生活,若是喜歡個人文章,能夠順手關注一下公衆號,也歡迎轉發分享給你的朋友~

在公衆號回覆「面試」或者「學習」能夠領取相應的資源哦~

公衆號
公衆號
相關文章
相關標籤/搜索