路由是微服務架構中必須(integral )的一部分,比如,“/” 可能映射到你的WEB程序上,”/api/users
“可能映射到你的用戶服務上,“/api/shop”可能映射到你的商品服務商。(注解:我理解這里的這幾個映射就是說通過Zuul這個網關把服務映射到不同的服務商去處理,從而變成了微服務!)
Zuul是Netflix出品的一個基於JVM路由和服務端的負載均衡器.
Zuul功能:
- 認證
- 壓力測試
- 金絲雀測試
- 動態路由
- 負載削減
- 安全
- 靜態響應處理
- 主動/主動交換管理
Zuul的規則引擎允許通過任何JVM語言來編寫規則和過濾器, 支持基於Java和Groovy的構建。
配置屬性 zuul.max.host.connections
已經被兩個新的配置屬性替代, zuul.host.maxTotalConnections
(總連接數)和 zuul.host.maxPerRouteConnections
,(每個路由連接數) 默認值分別是200和20.
一 . Zuul做反向代理
當一個UI應用調用一個或更多的后端服務的時候,我們可以用Spring Cloud創建一個Zuul代理減少開發是非常常見的例子。使用代理服務來避免必須的跨域資源共享(Cross-Origin Resource Sharing)和所有的后端需要分別認證的問題。
在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", 其他所有服務都被忽略了.
這個意味着http請求"/myusers"將被轉發到"users"服務(比如 "/myusers/101" 將跳轉到 "/101")
為了更細致的控制一個路由, 你可以直接配置路徑和服務ID:
zuul:
routes:
users: path: /myusers/** serviceId: users_service
這個意味着 HTTP 調用"/myusers"被轉發到"users_service"服務. 路由必須配置一個可以被指定為ant風格表達式的"path", 所以“/myusers/*”只能匹配一個層級,
但"/myusers/**"可以匹配多級.
后端的配置既可以是"serviceId"(對於服務發現中的服務而言), 也可以是"url"(對於物理地址), 例如:
zuul:
routes:
users:
path: /myusers/**
url: http://example.com/users_service
這個簡單的"url-routes"不會按照 HystrixCommand
執行, 也無法通過Ribbon負載均衡多個URLs. 為了實現這一指定服務路由和配置Ribbon客戶端(這個必須在
Ribbon中禁用Eureka: 具體參考更多信息), 例如:
zuul:
routes:
users:
path: /myusers/**
serviceId: users
ribbon:
eureka:
enabled: false
users:
ribbon:
listOfServers: example.com,google.com //所使用的Ribbon列表
你可以使用regexmapper提供serviceId和routes之間的綁定. 它使用正則表達式組來從serviceId提取變量, 然后注入到路由表達式中.
ApplicationConfiguration.java
@Bean
public PatternServiceRouteMapper serviceRouteMapper() {
return new PatternServiceRouteMapper(
"(?<name>^.+)-(?<version>v.+$)",
"${version}/${name}");
}
這個意思是說"myusers-v1"將會匹配路由"/v1/myusers/**". 任何正則表達式都可以, 但是所有組必須存在於servicePattern和routePattern之中.
如果servicePattern不匹配服務ID,則使用默認行為. 在上面例子中,一個服務ID為“myusers”將被映射到路徑“/ myusers/**”(沒有版本被檢測到)
,這個功能默認是關閉的,並且僅適用於服務注冊的服務。
設置 zuul.prefix
可以為所有的匹配增加前綴, 例如 /api,代理前綴默認會從請求路徑中移除(通過 zuul.stripPrefix=false
可以關閉這個功能).
- #反響代理配置
- #這里的配置類似nginx的反響代理
- #當請求/api/**會直接交給listOfServers配置的服務器處理
- #當stripPrefix=true的時候 (http://127.0.0.1:8181/api/user/list -> http://192.168.1.100:8080/user/list)
- #當stripPrefix=false的時候(http://127.0.0.1:8181/api/user/list -> http://192.168.1.100:8080/api/user/list)
- zuul.routes.api.path=/api/**
- zuul.routes.api.stripPrefix=false
- api.ribbon.listOfServers=192.168.1.100:8080,192.168.1.101:8080,192.168.1.102:8080
你也可以在指定服務中關閉這個功能:
zuul:
routes:
users:
path: /myusers/**
stripPrefix: false
在這個例子中, 請求"/myusers/101"將被跳轉到"users"服務的"/myusers/101"上.zuul.routes的鍵值隊
實際上綁定到類型為ZuulProperties
的對象上. 如果你查看這個對象你會發現一個叫"retryable"的字段, 設置為"true"會
使Ribbon
客戶端自動在失敗時重試(如果你需要修改重試參數, 直接使用Ribbon客戶端的配置)X-Forwarded-Host
請求頭默認在跳轉時添加. 通過設置zuul.addProxyHeaders = false
關閉它. 前綴路徑默認剝離, 並且對於后端的請求通過請
求頭"X-Forwarded-Prefix"獲取(上面的例子中是"/myusers")
通過@EnableZuulProxy
應用程序可以作為一個獨立的服務, 如果你想設置一個默認路由("/"), 比如zuul.route.home: /
將路由所有的請求(例如: "/**")
到"home"服務.