Netflix是一家在線影片租賃提供商。java
Netflix 開源軟件git
NetflixOSS github
Spring Cloud Netflix 經過自動配置以及綁定Spring環境中的其餘模塊的方式將Netflix OSS與Spring Boot 應用進行整合。web
經過簡單的註解就能夠快速在應用中開啓一個標準配置的大型分佈式及高可用的Netflix組件。spring
標準配置 包括:服務發現(
Eureka
);斷路器(Hystrix
);智能路由(Zuul
);客戶端負載均衡(Ribbon
)bootstrap
服務發現是微服務架構中重要的一個概念。通常來講,在每一個客戶端進行配置或者某種形式的約定來進行服務調用是很麻煩的,並且須要頻繁修改。
Eureka
是Netflix服務發現服務以及客戶端的實現。服務可以以一種高可用的方式進行配置和部署,對於每一個註冊的服務彼此間都會進行狀態複製。緩存
當一個註冊器客戶端經過Eureka進行註冊時,它會帶上一些描述本身狀況的元數據,如:地址、端口、健康指示器地址、主頁等等。Eureka會接收每個服務實例發送的心跳包。若是心跳包超過配置的間隔時間,那這個服務實例就會被移除。安全
Eureka客戶端代碼示例:網絡
@Configuration @ComponentScan @EnableAutoConfiguration @EnableEurekaClient @RestController public class Application { @RequestMapping("/") public String home() { return "Hello world"; } public static void main(String[] args) { new SpringApplicationBuilder(Application.class).web(true).run(args); } }
可見,這就是一個普通的Spring Boot 應用。例子中使用了
@EnableEurekaClient
,當Eureka可用時,也可使用@EnableDiscoveryClient
。此外還須要在本地配置一個Eureka服務。例如:架構
application.yml
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/
這裏的
defaultZone
,表示任何處理任何沒有匹配上的url請求。(默認請求處理地址)
默認應用名(服務ID)、虛擬地址和端口,會從
Environment
中獲取:${spring.application.name}
、${spring.application.name}
、${server.port}
。
@EnableEurekaClient
會讓應用既作爲一個Eurake實例,同時也做爲一個Eurake的客戶端(可以經過這個客戶端,查詢到註冊的本地其餘服務)。Eurake實例能夠經過eureka.instance.*
相關配置項進行配置。默認狀況下使用spring.application.name
做爲註冊服務的service ID 和 虛擬IP
具體配置相能夠參見 EurekaInstanceConfigBean 和 EurekaClientConfigBean
若是
eureka.client.serviceUrl.defaultZone
的URL中嵌入了帳號信息則Eurake客戶端會自動使用HTTP basic 認證。(如:http://user:password@localhost:8761/eureka
)
若是須要更爲複雜的認證方式,能夠本身實現一個
DiscoveryClientOptionalArgs
而後注入一個ClientFilter
實例,這樣客戶端與服務端的調用都會通過這個Filter。
注意: 因爲Eurake的限制,不可能爲每個服務配置單獨的認證,所以第一個被發現的認證方式會被使用。
一個Eurake實例的狀態頁和健康指示器默認爲:
/info
和/health
,這兩個是由Spring Boot Actuator應用提供的訪問端點。能夠經過如下方式進行修改:
application.yml
eureka: instance: statusPageUrlPath: ${management.context-path}/info healthCheckUrlPath: ${management.context-path}/health
這些地址將會被用於客戶端元數據的獲取,以及必要的檢測時使用。所以,這些端點是頗有用的。
若是你想讓應用之間經過HTTPS通信,那能夠在
EurekaInstanceConfig
中配置兩個開關:eureka.instance.[nonSecurePortEnabled,securePortEnabled]=[false,true]
。 這樣Eureka
就會經過安全方式發佈實例信息。 這樣的話,Spring Cloud 的DiscoveryClient
將會爲已註冊的服務返回一個https://…
URI, 同時Eureka
實例信息將會提供一個安全的健康檢查URL。
因爲
Eureka
的內部機制,使得還會爲狀態和主頁提供一個非安全的URL,固然,這也是能夠經過額外的配置關閉掉。
application.yml
eureka: instance: statusPageUrl: https://${eureka.hostname}/info healthCheckUrl: https://${eureka.hostname}/health homePageUrl: https://${eureka.hostname}/
注意:
${eureka.hostname}
是一個Eureka
的原生佔位符,之後的版本纔可用。因此,可使用spring的佔位符來替代,如:${eureka.instance.hostName}
注意: 若是你運行在代理的網絡狀況,那SSL可能被代理清理掉。並且,代理可能致使你得到的來源端口、地址不正確
默認狀況下,Eureka經過客戶端心跳包來檢測客戶端狀態。沒有額外配置的狀況下
Discovery
客戶端不會爲每個Spring Boot 應用發起額外的健康檢查。這樣,也就意味着,一旦服務註冊成功後,Eureka
總會認爲應用是在線狀態。 固然,也能夠開啓Eureka的健康檢查,這樣應用狀態就能夠轉播給Eureka了。
application.yml
eureka: client: healthcheck: enabled: true
警告:
eureka.client.healthcheck.enabled=true
只能在application.yml
中設置,若是在bootstrap.yml
中設置,會致使Eureka在註冊時獲得一個UNKNOWN
的狀態
若是須要更多的健康檢查控制,能夠本身實現一個
com.netflix.appinfo.HealthCheckHandler
.
花些時間去了解Eureka的元數據是值得的,你能夠在這個過程當中對本身平臺有更清楚的認識。標準的元數據例如:主機名,IP地址,端口號,狀態頁,健康檢查。這些會在服務註冊以及客戶端直連服務端時被髮布出來。對於實例註冊時,能夠經過
eureka.instance.metadataMap
配置額外的元數據信息,這樣不會對客戶端有啥影響,除非客戶端能本身處理某些特殊元數據。後面還會繼續說明元數據在Spring Cloud 中的意義。
Cloudfoundry提供了針對全部實例中相同主機名相同應用的全局路由功能。相似一個小型PaaS平臺。這個不是Eureka必要的功能,但仍是建議開啓此功能。開啓時,須要明確指定主機名和端口號。能夠經過設置實例的元數據來讓客戶端區分不一樣的實例,默認經過
eureka.instance.instanceId
和vcap.application.instance_id
來區分。例如:
application.yml
eureka: instance: hostname: ${vcap.application.uris[0]} nonSecurePort: 80
經過這種方式來設置Cloudfoundry實例的安全規則,你能夠註冊並使用虛擬主機的IP地址進行服務之間的調用。這個特性還不能在PWS(Pivotal Web Services)環境下使用。
若是須要在AWS中部署Eureka,能夠定製一個
EurekaInstanceConfigBean
:
@Bean @Profile("!default") public EurekaInstanceConfigBean eurekaInstanceConfig() { EurekaInstanceConfigBean b = new EurekaInstanceConfigBean(); AmazonInfo info = AmazonInfo.Builder.newBuilder().autoBuild("eureka"); b.setDataCenterInfo(info); return b; }
普通的Netflix Eureka實例註冊時使用主機名做爲實例ID。Spring Cloud Eureka提供了一個更爲合理的ID策略:
${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}}}
例如:myhost:myappname:8080
使用Spring Cloud時,能夠覆蓋這個值,經過
eureka.instance.instanceId
這個配置。例如:
application.yml
eureka: instance: instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
若是多個服務實例部署在同一個主機上,那這個元數據會加上一個隨機數,保證明例惟一性。 在一個Spring Boot 應用中,Cloudfoundry的
vcap.application.instance_id
會被自動賦值,不須要隨機數。
一旦在應用中使用了
@EnableDiscoveryClient
或者@EnableEurekaClient
,那你就能夠從Eureka Server中使用服務發現功能。 還有一種方法就是直接使用原生的com.netflix.discovery.EurekaClient
(對應Spring Cloud的DiscoveryClient
)。例如:
@Autowired private EurekaClient discoveryClient; public String serviceUrl() { InstanceInfo instance = discoveryClient.getNextServerFromEureka("STORES", false); return instance.getHomePageUrl(); }
提示:不要在@PostConstruct
方法以及@Scheduled
中(或者任何ApplicationContext
還沒初始完成的地方)使用EurekaClient
。其須要等待SmartLifecycle
(phase=0
)初始化完成才能夠
一般來講,不須要直接使用原始的Netflix 的
EurekaClient
,由於,提供了不少更方便使用的包裝器。 Spring Cloud支持Feign(一個REST客戶端)以及Spring本身的RestTemplate
來使用Eureka服務的邏輯標識符,而不是經過物理URL。 能夠爲物理服務簡單的配置一個固定列表集合:<client>.ribbon.listOfServers
用逗號分割物理地址或者主機名,<client>指的是客戶端ID。
你也可使用
org.springframework.cloud.client.discovery.DiscoveryClient
,這個客戶端提供了一套簡單的API來操做客戶端,不須要專門去使用Netflix。例如:
@Autowired private DiscoveryClient discoveryClient; public String serviceUrl() { List<ServiceInstance> list = discoveryClient.getInstances("STORES"); if (list != null && list.size() > 0 ) { return list.get(0).getUri(); } return null; }
做爲一個實例涉及到一個心跳機制去註冊(經過
serviceUrl
),默認持續30秒。直到實例自身,服務端,客戶端各自元數據本地緩存同步完成後,服務纔可用(至少須要3次心跳週期)。 能夠經過eureka.instance.leaseRenewalIntervalInSeconds
修改這個週期,改善客戶端連接到服務的速度。不過,考慮到短時間的波動以及服務續期等狀況,在生產環境最好仍是用默認設定。