4 Spring Cloud Netflix
Spring Cloud 通過自動配置和綁定到Spring環境和其他Spring編程模型慣例,為Spring Boot應用程序提供Netflix OSS集成。 通過幾個簡單的注釋,可以快速啟用和配置應用程序中的常見功能模塊,並使用久經考驗的Netflix組件構建大型分布式系統。 提供的功能模塊包括服務發現(Eureka),斷路器(Hystrix),智能路由(Zuul)和客戶端負載均衡(Ribbon)。
4.1 服務發現:Eureka客戶端
服務發現是microservice基礎架構的關鍵原則之一。Eureka是Netflix服務發現的一種服務和客戶端。
4.1.1 注冊到Eureka
當一個客戶端注冊到Eureka,它提供關於自己的元數據(諸如主機和端口,健康指標URL,首頁等)Eureka通過一個服務從各個實例接收心跳信息。如果心跳接收失敗超過配置的時間,實例將會正常從注冊里面移除。
可以使用@EnableEurekaClient
或@EnableDiscoveryClient
注解。
配置eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
屬性,注意修改URL地址。
確保spring.application.name
有默認值。
注:@EnableEurekaClient
只能用於Eureka,@EnableDiscoveryClient
能用於zookeeper等其他注冊組件。
@EnableEurekaClient
使其成為Eureka實例(被其他服務發現)和客戶端(能發現其他服務)注冊到應用里面。可通過eureka.instance.*
進行相關配置的修改。
4.1.2 對Eureka服務的身份驗證
如果其中一個eureka.client.serviceUrl.defaultZone
的url已經把憑證嵌入到它里面,那么HTTP基本的身份驗證將會被自動添加到你的eureka客戶端(curl風格,如http://user:password@localhost:8761/eureka
)。 對於更復雜的需求,可以創建一個帶“@Bean”注解的“DiscoveryClientOptionalArgs”類型並且為它注入“ClientFilter”實例。
4.1.3 健康指標和狀態頁面
健康指標和狀態頁面分別對應一個Eureka實例的“/health”和“/info”。
4.1.4 注冊一個安全應用
若要用HTTPS,需要設置兩個標記,分別是EurekaInstanceConfig
,即eureka.instance.[nonSecurePortEnabled,securePortEnabled]=[false,true]
。
4.1.5 Eureka 健康檢查
默認情況下,Eureka使用客戶端心跳來確定一個客戶端是否活着(狀態為“UP”)。
4.1.6 Eureka給客戶端和實例的元數據
有標准的元數據,如主機名、IP地址、端口號、狀態頁面和健康檢查。額外的元數據可以被添加到實例注冊在eureka.instance.metadataMap
里面。
在 Cloudfoundry 使用 Eureka
Cloudfoundry有總的路由,所有在同個應用的實例有相同的主機名。
在AWS上使用Eureka
定制EurekaInstanceConfigBean
修改Eureka實例ID
通過eureka.instance.instanceId
進行配置。
4.1.7 使用EurekaClient
使用@EnableDiscoveryClient
(或@EnableEurekaClient
),使它從Eureka Server發現服務實例。
注:不要在@PostConstruct
方法或@Scheduled
方法使用EurekaClient(或任何ApplicationContext還沒被啟動的地方)。
4.1.8 代替原生的Netflix EurekaClient
Spring Cloud已經支持Feign(一個REST客戶端構建)跟Spring RestTemplate(使用邏輯Eureka服務標識符(VIPs)代替物理的URL)。
4.1.9 為什么注冊一個服務這么慢?
實例默認與注冊中心持續30秒的周期心跳(通過客戶的serviceUrl
)。當實例、服務端和客戶端全都在它們的緩存里面擁有相同的元數據(這可能還需要3次心跳),那么服務對於客戶端的discovery將變為不可用。可通過eureka.instance.leaseRenewalIntervalInSeconds
這個修改配置,可以加快這一進程的客戶端連接到其他服務。
4.2 服務發現: Eureka Server
例子,添加依賴spring-cloud-starter-eureka-server
@SpringBootApplication
@EnableEurekaServer
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
服務端有一個帶UI的首頁,HTTP API端點在/eureka/*
下提供標准的Eureka功能。
4.2.1 高可用
Eureka服務端沒有后台存儲,但是服務實例在注冊里面全都得發送心跳去保持注冊更新(在內存里操作)客戶端們也有一份內存緩存着eureka的注冊信息。
4.2.2 標准模式
eureka.client.registerWithEureka=false
eureka.client.fetchRegistry=false
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
4.2.3 節點感知
運行多個Eureka Servers。
Eureka甚至可以更有彈性和可用的運行多個實例,並讓他們互相注冊。事實上,這也是默認的行為,因此所有你需要讓它工作的,只要添加一個有效的節點serviceUrl,例如:
---
spring:
profiles: peer1
eureka:
instance:
hostname: peer1
client:
serviceUrl:
defaultZone: http://peer2/eureka/
---
spring:
profiles: peer2
eureka:
instance:
hostname: peer2
client:
serviceUrl:
defaultZone: http://peer1/eureka/
然后通過不同的“profile”進行運行不同的Eureka Server。
4.2.4 IP偏好
設置eureka.instance.preferIpAddress=true
使應用注冊到eureka的是IP地址而不是主機名。
4.3 斷路器:Hystrix
Netflix創建了一個庫實現斷路器模式,名為Hystrix。一個低水平的服務群中一個服務掛掉會給用戶導致級聯失效的。當調用一個特定的服務達到一定閾值(在Hystrix里默認是5秒內20個失敗),斷路器開啟並且調用沒有成功的。開發人員能夠提供錯誤原因和開啟一個斷路由回調。
例子,需添加依賴org.springframework.cloud.spring-cloud-starter-hystrix
@SpringBootApplication
@EnableCircuitBreaker
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
@Component
public class StoreIntegration {
@HystrixCommand(fallbackMethod = "defaultStores")
public Object getStores(Map<String, Object> parameters) {
//do stuff that might fail
}
public Object defaultStores(Map<String, Object> parameters) {
return /* something useful */;
}
}
經測試,失敗就直接調用defaultStores()方法了。
4.3.1 傳播安全上下文或使用 Spring Scopes
如果你想一些線程的本地的上下文傳播到一個@HystrixCommand,默認聲明將不會工作,因為他在線程池里執行命令。(在超時的情況下)。你可以切換Hystrix去使用同個線程讓調用者使用一些配置,或直接在注解中,讓它去使用不同的“隔離策略”。舉例:
@HystrixCommand(fallbackMethod = "stubMyService",
commandProperties = {
@HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE")
}
)
...
如果你使用@SessionScope
或@RequestScope
同樣適用。你會知道你要這么做,因為一個runtime異常說他不能找到作用域上下文。
4.3.2 健康指標
連接的斷路器的狀態也暴露在應用程序的/health
端點中。
4.3.3 Hystrix 指標流
添加依賴org.springframework.boot.spring-boot-starter-actuator
,使/hystrix.stream
流作為一個管理端點。
4.4 斷路器: Hystrix儀表盤
Hystrix的主要作用是會采集每一個HystrixCommand的信息指標,把每一個斷路器的信息指標顯示的Hystrix儀表盤上。
環境需要
- 添加依賴
org.springframework.cloud.spring-cloud-starter-hystrix-dashboard
- 主類上注解
@EnableHystrixDashboard
- 訪問
/hystrix
- 填寫鏈接
http://host:port/hystrix.stream
4.4.1 Turbine
略
4.4.2 Turbine Stream
略
4.5 客戶端負載均衡器:Ribbon
Ribbon是一個客戶端負載均衡器,有很多控制HTTP和TCP客戶端的行為,可使用@FeignClient
注解。
4.5.1 自定義Ribbon客戶端
略
4.5.2 在Eureka中使用Ribbon
略
4.5.3 示例: 沒有Eureka時如何使用Ribbon
略
4.5.4 示例:禁用Eureka使用Ribbon
略
4.5.5 直接使用Ribbon的API
public class MyClass {
@Autowired
private LoadBalancerClient loadBalancer;
public void doStuff() {
ServiceInstance instance = loadBalancer.choose("stores");
URI storesUri = URI.create(String.format("http://%s:%s", instance.getHost(), instance.getPort()));
// ... do something with the URI
}
}
4.6 聲明REST客戶端:Feign
略
4.7 外部配置:Archaius
略
4.8 路由和過濾器:Zuul
Zuul是Netflix出品的一個基於JVM路由和服務端的負載均衡器。
- 認證
- Insights
- 壓力測試
- 金絲雀測試(Canary Testing)
- 動態路由
- 服務遷移
- 負載削減
- 安全
- 靜態響應處理
- 主動/主動交換管理
4.8.1 嵌入Zuul反向代理
Spring Cloud創建了一個嵌入式Zuul代理來緩和急需一個UI應用程序來代理調用一個或多個后端服務的通用需求,這個功能對於代理前端需要訪問的后端服務非常有用,避免了所有后端服務需要關心管理CORS和認證的問題。
。
在Spring Boot主函數上通過注解@EnableZuulProxy
來開啟。
4.8.2 Cookies和敏感HTTP頭
4.8.3 路由Endpoint
使用@EnableZuulProxy
同時引入了Spring Boot Actuator,默認將增加一個endpoint,提供http服務的/routes
。
4.8.4 窒息模式和本地跳轉
逐步替代舊的接口是一種通用的遷移現有應用程序或者API的方式,使用不同的具體實現逐步替換它們。Zuul代理是一種很有用的工具,因為你可以使用這種方式處理所有客戶端到舊接口的請求。只是重定向了一些請求到新的接口。
4.8.5 通過Zuul上傳文件
4.8.6 簡單的嵌入Zuul
4.8.7 關閉Zuul過濾器
4.8.8 通過Sidecar進行多語言支持
4.9 RxJava with Spring MVC
Spring Cloud Netflix 包含 RxJava。
Spring Cloud Netflix提供並支持從Spring MVC Controllers返回rx.Single
對象,還支持使用rx.Observable
對象。
4.10 指標:Spectator, Servo, and Atlas
略