API網關是一個更爲智能的應用服務器,它的定義相似於面向對象設計模式中的Facade模式,它的存在就像是整個微服務架構系統的門面同樣,全部的外部客戶端訪問都須要通過它來進行調度和過濾。它除了要實現請求路由、負載均衡、校驗過濾等功能以外,還須要更多能力,好比與服務治理框架的結合、請求轉發時的熔斷機制、服務的聚合等一系列高級功能。設計模式
在Spring Cloud中提供了基於Netflix Zuul實現的API網關組件——Spring Cloud Zuul。api
首先,對於路由規則與服務實例的維護問題。Spring Cloud Zuul經過與Spring Cloud Eureka進行整合,將自身註冊爲Eureka服務治理下的應用,同時從Eureka中得到了全部其餘微服務的實例信息。這樣的設計很是巧妙地將服務治理體系中維護的實例信息利用起來,將維護服務實例的工做交給了服務治理框架自動完成,再也不須要人工介入。而對於路由規則的維護,Zuul默認會將經過以服務名做爲ContextPath的方式來建立路由映射,大部分狀況下,這樣的默認設置已經能夠實現咱們大部分的路由需求,除了一些特殊狀況(好比兼容一些老的URL)還須要作一些特別的配置。可是相比於以前架構下的運維工做量,經過引入Spring Cloud Zuul實現API網關後,已經可以大大減小了。瀏覽器
其次,對於相似簽名校驗、登陸校驗在微服務架構中冗餘問題。理論上來講,這些校驗邏輯在本質上與微服務應用自身的業務並無多大的關係,因此它們徹底能夠獨立成一個單獨的服務存在,只是它們被剝離和獨立出來以後,並非給各個微服務調用,而是在API網關服務上進行統一調用來對微服務接口作前置過濾,以實現對微服務接口的攔截和校驗。服務器
1. 首先,搭建幾個用於路由和過濾使用的微服務應用,但是使用以前的註冊中心和demo-member、demo-customer-feign,分別啓動三個應用。架構
2. 建立maven工程,骨架選擇quickstart,命名爲:demo-api-gateway。併發
3. 在pom.xml文件中引入相關依賴:app
4. 建立啓動類:負載均衡
5. 在src\main\resources目錄下建立application.yml文件:框架
6. 進入註冊中心,觀察啓動的服務:運維
7. 在demo-api-gateway的pom.xml文件中添加Eureka依賴,並在application.yml文件中指定Eureka位置和進行路由的配置:
8. 啓動demo-api-gateway服務,分別向網關發起下面請求:
◆http://localhost:5217/api-a/member:該url符合/api-a/**規則,由api-a路由負責轉發,該路由映射的serviceId爲member-service,全部最終/member請求會被髮送到member-service服務的某個實例上去。
◆http://localhost:5217/api-b/getMember:該url符合/api-b/**規則,由api-b路由負責轉發,該路由映射的serviceId爲customer-service-feign,全部最終/getMember請求會被髮送到customer-service-feign服務的某個實例上去。
經過面向服務的路由配置方式,咱們不須要再爲各個路由維護微服務應用的具體實例的位置,而是經過簡單的path與serviceId的映射組合,使得維護工做變得很是簡單。這徹底歸功於Spring Cloud Eureka的服務發現機制,它使得API網關服務能夠自動化完成服務實例清單的維護,完美地解決了對路由映射實例的維護問題。
Zuul容許開發者在API網關上經過定義過濾器來實現對請求的攔截與過濾,只須要繼承ZuulFilter抽象類並實現它定義的4個抽象方法就能夠完成對請求的攔截和過濾了。
下面實現一個簡單的Zuul過濾器,它實現了再請求被路由以前檢查HttpServletRequest中是否有token參數,如有就進行路由,若沒有就拒絕訪問,返回401 Unauthorized錯誤。
1. 定義AccessFilter類,集成ZuulFilter:
名詞解釋:
◆filterType:該方法須要返回一個字符串來表明過濾的類型,而這個類型就是在HTTP請求過程當中定義的各個階段。在Zuul中默認定義了4種不一樣的生命週期的過濾器類型:
■pre:能夠在請求被路由以前調用。
■routing:在路由請求時被調用。
■post:在routing和error過濾器以後被調用。
■error:處理請求時發生錯誤時被調用。
◆filterOrder:經過int值來定義過濾器的執行順序,數值越小優先級越高。
◆shouldFilter:返回一個boolea值來判斷該過濾器是否要執行。能夠經過此方法來指定過濾器的有效範圍。
◆run:過濾器的具體邏輯,在該方法中,能夠實現自定義的過濾邏輯,來肯定是否要攔截當前的請求,不對其進行後續的路由,或是在請求路由返回結果以後,對處理結果作一些加工等。
2. 實現了自定義過濾器以後,並不會直接生效,還須要爲其建立具體的Bean才能啓動該過濾器,在啓動類中添加以下內容:
3. 重啓網關項目,併發起以下請求,對上述定義的過濾器作一個驗證:
◆http://localhost:5217/api-a/member:返回401錯誤。
◆http://localhost:5217/api-a/member?token=123:正確路由到member-service的/member接口,並返回相應內容。
經過Eureka與Zuul的整合已經省去了維護服務實例清單的大量配置工做,剩下只須要再維護請求路徑的匹配表達式與服務名的映射關係便可。可是在實際運用過程當中會發現,大部分的路由配置規則幾乎都會採用服務名做爲外部請求的前綴,例如上述的member-seriver,而對應的服務名稱也是member-service
對於這樣具備規則性的配置內容,咱們老是但願能夠自動化地完成。Zuul正好默認實現了這樣的功能,當Spring Cloud Zuul構建API網關服務引入Spring Cloud Eureka以後,它爲Eureka中的每一個服務都自動建立一個默認路由規則,這些默認規則的path會使用serviceId配置的服務名做爲請求前綴,如上述的路由配置規則,能夠直接註釋掉:
重啓網關服務,就可使用服務名做爲前綴進行服務的調用:
對於版本的管理,當微服務有不一樣的版本的時候,例如memberservice-v1,固然能夠經過微服務名稱來區分不一樣的版本,從而調用各個版本的服務,可是這樣生成出來的表達式規則較爲單一,不利於經過路徑規則來進行管理。一般的作法是爲這些不一樣版本的微服務應用生成以版本代號做爲路由前綴定義的路由規則,好比/v1/meberservie/。這時候,經過這樣具備版本號前綴的URL路徑,咱們就能夠很容易地經過路徑表達式來歸類和管理這些具備版本新的微服務了。
具體操做方法是,首先中止member-service服務,並將其服務名稱改成memberservice-v1,而後啓動該服務。在網關服務的啓動類中,添加以下代碼:
從新啓動網關服務,在瀏覽器中訪問測試:
◆它做爲系統的統一入口,屏蔽了系統內部各個微服務的細節。
◆它能夠與服務治理框架結合,實現自動化的服務實例維護以及負載均衡的路由轉發。
◆它能夠實現接口權限校驗與微服務業務邏輯的解耦。
◆經過服務網關中的過濾器,在各生命週期中去校驗請求的內容,將本來在對外服務層作的校驗前移,保證了微服務的無狀態性,同時下降了微服務的測試難度,讓服務自己更集中關注業務邏輯的處理。