Zuul:智能路由和过滤(译)
2019獨角獸企業重金招聘Python工程師標準>>>
Zuul:智能路由和過濾(譯) 博客分類: spring 微服務 ?Router and Filter: Zuul
路由是微服務架構的不可或缺的一部分。例如:”/” 可能映射到你應用主頁,/api/users映射到用戶服務,/api/shop映射到購物服務。Zuul。Zuul是Netflix出品的一個基于JVM路由和服務端的負載均衡器。
Netflix uses Zuul?for the following:?
* Authentication?
* Insights?
* Stress Testing?
* Canary Testing?
* Dynamic Routing?
* Service Migration?
* Load Shedding?
* Security?
* Static Response handling?
* Active/Active traffic management
Zuul的規則和過濾器允許使用各種基于JVM的語言,支持基于Java和Groovy。
注意:zuul.max.host.connections已經被兩個新的屬性替代:zuul.host.maxTotalConnections 和 zuul.host.maxPerRouteConnections,默認分別為200和20.
注意:默認所有routes的Hystrix隔離模式(ExecutionIsolationStrategy)是SEMAPHORE zuul.ribbonIsolationStrategy可以改為THREAD,如果這個隔離模式更好。
How to Include Zuul
org.springframework.cloud and artifact id?spring-cloud-starter-zuul。See the?Spring Cloud Project page?for details。
Embedded Zuul Reverse Proxy
當一個UI應用想要代理調用一個或者多個后臺服務的時候,Sping cloud創建了一個嵌入的Zuul proxy很方便的開發一個簡單的案例。這個功能對于代理前端需要訪問的后端服務非常有用,避免了所有后端服務需要關心管理CORS和認證的問題.
在Spring Boot主函數上通過注解 @EnableZuulProxy 來開啟, 這樣可以讓本地的請求轉發到適當的服務. 按照約定, 一個ID為”users”的服務會收到 /users 請求路徑的代理請求(前綴會被剝離). Zuul使用Ribbon定位服務注冊中的實例, 并且所有的請求都在hystrix的command中執行, 所以失敗信息將會展現在Hystrix metrics中, 并且一旦斷路器打開, 代理請求將不會嘗試去鏈接服務.
注意:Zuul starter沒有包含服務發現的客戶端, 所以對于路由你需要在classpath中提供一個根據service IDs做服務發現的服務.(例如, eureka是一個不錯的選擇)
去忽略一個自動添加的服務,可以在服務ID表達式列表中設置 zuul.ignored-services。如果一個服務匹配到了要忽略的列表, 但是它也明確的配置在路由列表中, 將不會被忽略, 例如:
application.yml zuul:ignoredServices: '*'routes:users: /myusers/**在這個例子中,所有的服務都會被忽略,除了“users”。
增加或改變代理路由規則, 你可以添加類似下面的外部配置:
application.ymlzuul:routes:users: /myusers/**這表示,HTTP調用 “/myusers” 會轉到 “user” 服務(例如:”/myusers/101”跳轉到”/101”)。
為了更細粒度的控制一個路由, 你可以獨立指定配置路徑和服務ID:
application.ymlzuul:routes:users:path: /myusers/**serviceId: users_service這表示,HTTP調用 “/myuser”會跳轉到”users_servie”服務。路由必須配置一個可以被指定為”ant路徑匹配原則”的”path”,所以“/myusers/”只能匹配一個層級, 但”/myusers/*“可以匹配多級.(附注:Ant path 匹配原則)
后端的配置既可以是”serviceId”(對于服務發現中的服務), 也可以是”url”(物理地址), 例如:
application.ymlzuul:routes:users:path: /myusers/**url: http://example.com/users_serviceurl-routes的方式不會執行 HystrixCommand 也不會通過Ribbon負載多個URLS。要實現這些,需給這個serviceid指定一個service-route并配置一個Ribbon client(這個必須在Ribbon中禁用Eureka: see?above for more information)。
application.yml zuul:routes:users:path: /myusers/**serviceId: usersribbon:eureka:enabled: falseusers:ribbon:listOfServers: example.com,google.com你可以使用regexmapper提供serviceId和routes之間的綁定. 它使用正則表達式組來從serviceId提取變量, 然后注入到路由表達式中.
@Bean public PatternServiceRouteMapper serviceRouteMapper() {return new PatternServiceRouteMapper("(?<name>^.+)-(?<version>v.+$)","${version}/${name}"); }這表示serviceId “myusers-v1” 將會被映射到 “/v1/myusers/“.任何正則表達式都可以,但是所有的命名組都必須在servicePattern和routePattern中存在。如果servicePattern沒有匹配到一個serviceId,默認的行為會被啟用。在上面的例子中,serviceId”myusers”將會映射到”/myusers/“(沒有發現版本)這個特性默認是禁用的,而且只用于發現的服務。
給所有映射添加前綴,可以設置 zuul.prefix 一個值,比如/api。這個前綴默認會刪除,在請求跳轉之前。(通過 zuul.stripPrefix=false 可以關閉這個功能)。你也可以在單個服務中關閉這個功能, 例如:
application.ymlzuul:routes:users:path: /myusers/**stripPrefix: falsezuul.stripPrefix只使用于使用了zuul.prefix配置情況下。在一個定義好了的 route’s path中不會有任何影響。
在這個例子中,”users”service的請求”/myusers/101”將會跳轉到”/myusers/101”。
zuul.routes 實際上綁定到類型為 ZuulProperties 的對象上. 如果你查看這個對象你會發現一個叫”retryable”的字段, 設置為”true”會使Ribbon客戶端自動在失敗時重試(如果你需要修改重試參數, 可以使用Ribbon client configuration)
X-Forwarder-Host請求頭默認添加到轉發請求中。設置zuul.addProxyHeaders=false禁用它。路徑前綴默認被刪除,?
到后臺服務的請求會添加一個 “X-Forwarded-Prefix”(“/myusers”在上面的例子中)。
一個@EnableZuulProxy的應用可以作為單機使用如果你設置了一個默認路由(”/”),例如zuul.route.home: / 會把所有的請求(”/**”)轉到home服務。
如果需要更細粒度的忽略配置,你可以指定特殊的表達式來配置忽略規則.這些表達式從route location的開始進行匹配,意味著前綴應該被包括在匹配表達式中. 忽略表達式影響所有服務和取代任何路由的特殊配置.
application.ymlzuul:ignoredPatterns: /**/admin/**routes:users: /myusers/**這個的意思是所有請求, 比如”/myusers/101”的請求會跳轉到”users”服務的”/101”, 但包含”/admin/”的請求將不被處理.
Zuul Http Client
默認的zull的Http clietn現在是Apach HTTP Client,替代了已過期的Ribbon RestClient。想使用RestClient或使用okhttp3.OKHttpClient,可以設置ribbon.restclient.enable=true或者ribbon.okhttp.enable=true。
Cookies and Sensitive Headers
在同一個系統的多個服務之間中分享headers是可以的,但是你可能不想把一些敏感headers泄露到下游服務器。你可以指定一批忽略的headers列表在路由配置中。Cookies扮演了一個特殊的角色, 因為他們很好的在瀏覽器中定義, 而且他們總是被認為是敏感的. 如果代理的客戶端是瀏覽器, 則對于下游服務來說對用戶, cookies會引起問題, 因為他們都混在一起。(所有下游服務看起來認為他們來自同一個地方)。
如果你對于你的服務設計很細心,比如,如果只有一個下游的服務設置了cookies,你可能會讓它從后端服務一直追溯到前端調用者,如果你的代理設置了cookies而且所有你的后端服務都是同一系統的一部分,它可以很自然的共享(比如使用spring session去聯系一些共享狀態)。除此之外,任何下游服務設置的cookies可以能不會對前端調用者產生作用。所以建議對不屬于你的域名的部分在routes里將 “Set-Cookie”和“Cookie”添加到敏感headers。 即使是屬于你的域名的路由, 嘗試仔細思考在允許cookies流傳在它們和代理之間意味著什么。
每個路由中的敏感頭部信息配置按照逗號分隔, 例如:
application.ymlzuul:routes:users:path: /myusers/**sensitiveHeaders: Cookie,Set-Cookie,Authorizationurl: https://downstream敏感headers也支持全局設置 zuul.sensitiveHeaders. 如果在單個路由中設置 sensitiveHeaders 會覆蓋全局 sensitiveHeaders 設置.
注意: 這是sensitiveHeaders 的默認值, 你無需設置除非你需要不同的配置. 注意. 這是Spring Cloud Netflix 1.1的新功能(在1.0中, 用戶無法直接控制請求頭和所有cookies).
Ignored Headers
除了每個route敏感頭以外, 你可以設置一個全局的 zuul.ignoredHeaders 在下游相互調用間去丟棄這些值(包括請求和響應). 如果沒有將Spring Security 添加到運行路徑中, 他們默認是空的, 否則他們會被Spring Secuity初始化一批安全頭(例如 緩存相關). 在這種情況下, 假設下游服務也可能添加這些頭信息, 我希望從代理獲取值.
The Routes Endpoint
如果你使用 @EnableZuulProxy 同時引入了Spring Boot Actuator, 你將默認增加一個endpoint, 提供http服務的 /routes. 一個GET請求將返回路由匹配列表. 一個POST請求將強制刷新已存在的路由.(比如, 在服務catalog變化的場景中)
注意:路由列表應該自動應答服務登記變化, 但是POST是一種強制立即更新的方案.
窒息模式和本地跳轉(Strangulation Patterns and Local Forwards)
一個常見的遷移舊應用或者舊接口的方式,就是逐步的替換它的實現。 Zuul代理是一種很有用的工具, 因為你可以使用這種方式處理所有客戶端到舊接口的請求. 只是重定向了一些請求到新的接口.
實例配置:
application.ymlzuul:routes:first:path: /first/**url: http://first.example.comsecond:path: /second/**url: forward:/secondthird:path: /third/**url: forward:/3rdlegacy:path: /**url: http://legacy.example.com在這個例子中,我們替換了 “legacy” ,它映射到所有的請求,但是沒有匹配到其他任何一個請求。路徑 /first/* 指向了一個額外的URL. 并且路徑 /second/*?是一個本地跳轉. 比如, 帶有Spring注解的 @RequestMapping . 路徑 /third/** 也是一個本地跳轉, 但是屬于一個不同的前綴. (比如 /third/foo 跳轉到 /3rd/foo )。
注意:忽略表達式并不是完全的忽略請求, 只是配置這個代理不處理這些請求(所以他們也是跳轉執行本地處理)。
Uploading Files through Zuul
如果你使用 @EnableZuulProxy , 你可以使用代理路徑上傳文件, 對于小文件可以正常使用. 對于大文件有可選的路徑”/zuul/“繞過Spring DispatcherServlet (避免處理multipart). 比如對于 zuul.routes.customers=/customers/*?, 你可以使用 “/zuul/customers/*” 去上傳大文件. Servlet路徑通過 zuul.servletPath 指定. 如果使用Ribbon負載均衡器的代理路由, 在 處理非常大的文件時, 仍然需要提高超時配置. 比如:
application.yml hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000 ribbon:ConnectTimeout: 3000ReadTimeout: 60000注意: 對于大文件的上傳流, 你應該在請求中使用塊編碼. (有些瀏覽器默認不這么做). 比如在命令行中:
$ curl -v -H "Transfer-Encoding: chunked" \ -F "file=@mylarge.iso" localhost:9999/zuul/simple/filePlain Embedded Zuul
你可以運行一個沒有代理功能的Zuul服務, 或者有選擇的開關部分代理功能, 如果你使用 @EnableZuulServer (替代 @EnableZuulProxy ). 你添加的任何 ZuulFilter 類型 實體類都會被自動加載, 和使用 @EnableZuulProxy 一樣, 但不會自動加載任何代理過濾器.
在以下例子中, Zuul服務中的路由仍然是按照 “zuul.routes.*”指定, 但是沒有服務發現和代理, 因此”serviceId”和”url”配置會被忽略. 比如:
application.ymlzuul:routes:api: /api/**匹配所有的 “/api/**” 給Zuul過濾器鏈.
Disable Zuul Filters
在代理和服務模式下, 對于Spring Cloud, Zuul默認加入了一批 ZuulFilter 類. 查閱?the zuul filters package?去獲取可能開啟的過濾器. 如果你想關閉其中一個, 可以簡單的設置 zuul...disable=true . 按照約定, 在 filter 后面的包是Zuul過濾器類. 比如關閉 org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter , 可設置zuul.SendResponseFilter.post.disable=true.
?
http://blog.csdn.net/chenqipc/article/details/53322830
轉載于:https://my.oschina.net/xiaominmin/blog/1599765
總結
以上是生活随笔為你收集整理的Zuul:智能路由和过滤(译)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: elasticsearch query
- 下一篇: 牛客练习赛9 B - 珂朵莉的值域连续段