在前面的文章中,咱們前後使用了eureka/ribbon/feign/hystrix搭建了一個看似完美的微服務了,那是否還有值得繼續優化的地方呢?答案確定是有的,若是從整個微服務內部來看,基本已經完整了,可是咱們的微服務不可避免的須要對外部提供服務,此時,咱們將關注點聚焦在對外提供服務這一塊.前端
假若有一個外部服務,須要調用咱們的整個微服務中許多不一樣的服務,好比用戶服務,訂單服務,物流服務等等,思考一下,直接調用微服務會有什麼問題?
1.首先,外部服務必須知道咱們的微服務在eureka註冊中心的應用名,根據應用名去調用(若是不走eureka註冊中心而直接調用服務就失去了微服務的意義),而咱們並不想對外部服務暴露這些信息.言下之意,咱們既想要對外屏蔽咱們的內部信息,又能在屏蔽信息的狀況下對外提供服務.
2.其次,微服務採用restful API的架構風格,外部服務直接訪問微服務內部的服務,勢必要在各個微服務內新增權限校驗的邏輯,而這偏偏破壞了restful API無狀態的特色.
3.外部服務屢次調用微服務內部的不一樣服務,增長了外部服務的複雜性,不以利後期的維護.git
所以,爲了解決這些問題,咱們須要將權限控制這樣的東西從咱們的服務中抽離出去,而最適合這些邏輯的地方就是處於對外訪問最前端的地方,這就是API網關.而spring cloud中的API網關就是zuul,接下來,讓咱們來了解一下zuul.github
zuul就是spring cloud中的API網關,相似於設計模式裏面的Facade門面模式:
他的存在就像是整個微服務的門面,全部的外部客戶端訪問都須要通過它來進行轉發與過濾,它的核心是一系列的過濾器,它的主要做用包括:
1.身份驗證和安全性:肯定每一個資源的身份驗證要求並拒毫不知足這些要求的請求
2.監控和統計:監控和統計數據,爲咱們提供準確的生產視圖.
3.動態路由:相似於Nginx,根據須要動態地將請求路由到後端不一樣的微服務.spring
接下來,讓咱們來用代碼演示一下zuul,首先新增一個module:
而後老規矩,三個步驟,首先配置maven依賴:
而後配置文件:
主要是端口號,以及eureka-server的地址,因爲網關確定是須要從eureka中發現服務的,因此須要配置eureka-server的信息,前後啓動eureka-server,producer-hystrix(該服務須要密碼驗證)以及user-hystrix(該服務無需密碼驗證):
而後啓動zuul網關訪問試一下,咱們先訪問一下無需密碼訪問的user:
而後再試一下須要密碼訪問的producer:
發現須要帳號密碼登陸,由於咱們的producer啓用了security,有安全驗證,所以咱們須要在header中配置驗證信息.以前咱們說過,zuul的核心是一系列的過濾器,其各類功能都是經過過濾器實現的,所以咱們須要經過過濾器實現該功能,zuul的過濾器有以下幾種類型:
很明顯,咱們須要pre類型的過濾器,實現zuul過濾器的方式是繼承ZuulFilter而且覆蓋相應的方法,其中最重要的方法是run方法,該方法是咱們處理業務邏輯的實現方法.
建立該過濾器後,必須建立一個bean才能生效:
而後再訪問試一試:
嗯?爲何仍是這樣?咱們配置的過濾器未生效?是代碼有問題嗎?其實不是的,這是spring cloud的一個大坑,這是由於spring cloud zuul 對2.0.0.RELEASE 以上的高版本支持很差,這也是zuul一直被人詬病的地方,所以spring cloud官方從2.0.0.RELEASE開始,也是推出了本身的微服務網關spring-cloud-starter-gateway,目的也是想替代zuul,有興趣的童鞋能夠去研究一下gateway,咱們說了,要解決這個問題,是由於zuul版本過高,對springboot 支持不太好形成的,還記得以前咱們的zuul配置嗎?
咱們的springboot和cloud都是用的2.1.2版本,只要咱們把版本下降就能解決這個問題了:
springboot咱們使用2.0.7版本,而zuul咱們使用2.0.0版本,而後在重啓一下zuul服務訪問:
能夠發現,咱們的過濾器已經生效了,在header中設置了帳號密碼信息,經過了producer的security驗證.可是還有一個問題,前面咱們說到,因爲是對外服務,咱們並不想過多暴露咱們內部服務的相關信息,好比路徑中的微服務的應用名,所以咱們還須要進行配置:
前面兩條,用於告訴zuul,凡是訪問/producer-proxy/的路徑,所有轉發到dhp-micro-service-producer服務,第三條告訴zuul忽略全部服務,這樣,再想經過直接訪問微服務名的方式就沒法訪問了,只能經過指定的/producer-proxy/這個代理地址來訪問:
能夠看到,再經過應用名的方式來訪問直接報404,而經過咱們設置的代理地址,則能正常訪問.後端
做爲全部微服務訪問的統一入口,zuul也是能夠進行加密訪問的,同理是使用spring security:
則訪問的時候就須要進行安全驗證:
驗證成功後就能正常訪問了:
設計模式
在以前的文章中,咱們使用了feign來簡化代碼開發,如今咱們集成了網關zuul,全部的服務都走zuul,所以,咱們以前的代碼也須要進行改造,使用feign集成zuul來訪問微服務.
咱們說feign是經過eureka-server拉取服務,所以要使feign集成zuul,首先zuul也須要註冊到eureka:
而後新增一個使用feign訪問zuul的service(本文直接在consumer中完成,實際生產環境可能因爲有多個服務會須要調用,所以能夠單獨抽一個module出來):
讀過我以前文章的童鞋們應該明白,首先表示我這個接口使用feign代理,而且關注的服務是DHP-MICRO-SERVICE-ZUUL-GATEWAY,因爲全部服務都有安全驗證,所以有一個FeignClientConfig配置驗證信息:
若是調用服務失敗,咱們還須要服務降級,所以有一個ZuulProxyServiceFallbackFactory:
此時,相關準備工做已經就緒,開始使用,首先在consumer-feign中新增maven依賴:
而後編碼實現:
而後依次啓動eureka-server,producer,user,zuul,consumer訪問試一試:
能夠看到,咱們成功經過zuul訪問到了producer和user.但這還不夠,咱們如今是經過消費者經過zuul代理訪問服務方,此時zuul從功能上相似於Nginx,主要是轉發,假如zuul轉發到的服務掛了,會直接顯示錯誤頁面,好比咱們如今把producer停掉再訪問一下:
這顯然是不行的,所以zuul自己也須要進行降級處理,新增一個降級處理的類:
該降級處理類的主要做用是構建一個請求失敗的http相應信息.此時再重啓zuul試一下:
能夠發現咱們的zuul降級已經成功了,這樣不會所以zuul代理的服務不可用而致使拋出異常了.api
下一篇文章,咱們繼續介紹spring cloud 分佈式配置中心config,敬請期待!安全
本文的github地址springboot
本文由博客一文多發平臺 OpenWrite 發佈!restful