老張正準備下班,路太小齊的位置,發現他正在閱讀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 Boot 2.0, Spring WebFlux, Reactor項目構建的,底層是Netty。它的流程其實和Zuul很類似,使用一系列的過濾器去處理請求,達到咱們本身想要的定製化。」
老張問:「那裏剛剛看完了官方文檔,能夠跟我總結一下它有哪些功能嗎?」
「Spring Cloud Gateway幾乎能夠知足絕大多數網關的需求。它主要有下面一些功能:」
斷言能夠指定「在什麼狀況下」能夠匹配某個路由。斷言是基於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 複製代碼
Gateway也提供了一些已經寫好的過濾器。能夠查看官方文檔。主要有重寫request或者response的header、parameter、body、session、安全、重寫路徑、重試以及對熔斷的一些支持。
全局過濾器與網關過濾器相似,只是默認會給全部的請求都添加上全局過濾器。固然,也能夠本身定義全局過濾器。過濾器的順序能夠經過@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,一個有深度,有態度,有溫度的程序員。工做之餘分享編程技術和生活,若是喜歡個人文章,能夠順手「關注」一下公衆號,也歡迎「轉發」分享給你的朋友~
在公衆號回覆「面試」或者「學習」能夠領取相應的資源哦~