官方文檔地址爲:http://cloud.spring.io/spring-cloud-static/Dalston.SR2/#_spring_cloud_netflixios
文中例子我作了一些測試在:http://git.oschina.net/dreamingodd/spring-cloud-preparationgit
This project provides Netflix OSS integrations for Spring Boot apps through autoconfiguration and binding to the Spring Environment and other Spring programming model idioms. With a few simple annotations you can quickly enable and configure the common patterns inside your application and build large distributed systems with battle-tested Netflix components. The patterns provided include Service Discovery (Eureka), Circuit Breaker (Hystrix), Intelligent Routing (Zuul) and Client Side Load Balancing (Ribbon).web
這個項目經過自動配置以及Spring環境和Spring通用編程模型綁定,爲Spring Boot提供Netflix OSS集成。開發人員只須要一些簡單的註解,就能利用battletested Netflix 組件,在開發者的軟件中實現和配置通用模式,以及創建大型的分佈式系統。 這些通用模式包括服務發現(Eureka),斷路器(Hystrix),智能路由(Zuul),客戶端負載均衡(Ribbon)。spring
@EnableDiscoveryClient
Service Discovery is one of the key tenets of a microservice based architecture. Trying to hand configure each client or some form of convention can be very difficult to do and can be very brittle. Eureka is the Netflix Service Discovery Server and Client. The server can be configured and deployed to be highly available, with each server replicating state about the registered services to the others.express
服務發現 是微服務架構的核心原則之一。使用手動配置或一些約定方式來處理多服務多實例的方式是很是困難,而且十分脆弱的。Eureka同時是Netflix服務發現的服務端和客戶端。服務端能夠經過配置和部署實現高可用,實現方式是每一個服務端對註冊的服務複製他們的狀態到其餘的服務端。編程
To include Eureka Client in your project use the starter with group org.springframework.cloud and artifact id spring-cloud-starter-eureka. See the Spring Cloud Project page for details on setting up your build system with the current Spring Cloud Release Train.bootstrap
When a client registers with Eureka, it provides meta-data about itself such as host and port, health indicator URL, home page etc. Eureka receives heartbeat messages from each instance belonging to a service. If the heartbeat fails over a configurable timetable, the instance is normally removed from the registry.緩存
當一個客戶端使用Eureka註冊,它提供主機和端口,健康指標URL,主頁等元數據給Eureka。Eureka會接收到一個服務的每個實例的心跳信息。若是心跳數據接收失敗(心跳時間可配置時間表),通常來講這個實例就會被刪除。安全
Example eureka client: @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); } }
(i.e. utterly normal Spring Boot app). In this example we use @EnableEurekaClient explicitly, but with only Eureka available you could also use @EnableDiscoveryClient. Configuration is required to locate the Eureka server. Example: (這是一個很是普通的Spring Boot App)。在本例中咱們顯式使用了@EnableEurekaClient。而後,咱們還須要配置去定位Eureka服務端。例如:
application.yml
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/
where "defaultZone" is a magic string fallback value that provides the service URL for any client that doesn’t express a preference (i.e. it’s a useful default).
其中defalutZone爲不表示首選項的客戶端提供默認的服務URL,是一個魔術字符串,一個後備值。(反正有用就是了)
The default application name (service ID), virtual host and non-secure port, taken from the Environment, are ${spring.application.name}, ${spring.application.name} and ${server.port} respectively.
從環境中取得的默認的服務名(服務ID),虛擬主機和非安全端口分別是${spring.application.name}, ${spring.application.name} and ${server.port}。
@EnableEurekaClient makes the app into both a Eureka "instance" (i.e. it registers itself) and a "client" (i.e. it can query the registry to locate other services). The instance behaviour is driven by eureka.instance.* configuration keys, but the defaults will be fine if you ensure that your application has a spring.application.name (this is the default for the Eureka service ID, or VIP).
@EnableEurekaClient把應用變成一個Eureka「實例」(即自注冊)和一個「客戶端」(便可以查詢註冊器來定位其餘的服務)。eureka.instance.*的配置能夠用來控制實例的行爲,不過若是你有一個spring.application.name(默認的Eureka服務ID),默認的配置就OK。
See EurekaInstanceConfigBean and EurekaClientConfigBean for more details of the configurable options.
瞭解更多能夠看看下面的 EurekaInstanceConfigBean,EurekaClientConfigBean。
HTTP basic authentication will be automatically added to your eureka client if one of the eureka.client.serviceUrl.defaultZone URLs has credentials embedded in it (curl style, like http://user:password@localhost:8761/eureka). For more complex needs you can create a @Bean of type DiscoveryClientOptionalArgs and inject ClientFilter instances into it, all of which will be applied to the calls from the client to the server.
服務器端加入spring-cloud-starter-security依賴便可使用基於HTTP的認證機制。而後把客戶端請求的defaultZone改爲相似http://user:password@localhost:8761/eureka的形式。更深刻的細節須要建立一個DiscoveryClientOptionalArgs的Bean並注入ClientFilter實例,當客戶端請求服務器的時候會用到這些東西。
NOTE Because of a limitation in Eureka it isn’t possible to support per-server basic auth credentials, so only the first set that are found will be used.
The status page and health indicators for a Eureka instance default to "/info" and "/health" respectively, which are the default locations of useful endpoints in a Spring Boot Actuator application. You need to change these, even for an Actuator application if you use a non-default context path or servlet path (e.g. server.servletPath=/foo) or management endpoint path (e.g. management.contextPath=/admin). Example:
狀態和健康頁面分別是/info和/health,他們是Spring Actuator支持的URL。由於你通常不會使用默認的context path或servlet path,最好修改一下默認值,以下:
application.yml
eureka:
instance:
statusPageUrlPath: ${management.context-path}/info healthCheckUrlPath: ${management.context-path}/health
These links show up in the metadata that is consumed by clients, and used in some scenarios to decide whether to send requests to your application, so it’s helpful if they are accurate.
這些連接是client之間互相消費的元數據,在一些情境下決定了是否發出請求,因此要儘可能將他們設置正確。
If your app wants to be contacted over HTTPS you can set two flags in the EurekaInstanceConfig, viz eureka.instance.[nonSecurePortEnabled,securePortEnabled]=[false,true] respectively. This will make Eureka publish instance information showing an explicit preference for secure communication. The Spring Cloud DiscoveryClient will always return an https://…; URI for a service configured this way, and the Eureka (native) instance information will have a secure health check URL.
若是你但願系統使用HTTPS協議進行交互,須要如下兩個配置:eureka.instance.[nonSecurePortEnabled,securePortEnabled]=[false,true]。它們將使Eureka發佈實例信息時明確首選安全通訊。服務發現將一直返回https://...;Eureka實例也將得到一個安全的健康檢查URL。
Because of the way Eureka works internally, it will still publish a non-secure URL for status and home page unless you also override those explicitly. You can use placeholders to configure the eureka instance urls, e.g.
因爲Eureka內部不可見,它仍將發佈不安全的URL,除非你顯式重寫配置。例如:
applicatio.yml
eureka: instance: statusPageUrl: https://${eureka.hostname}/info healthCheckUrl: https://${eureka.hostname}/health homePageUrl: https://${eureka.hostname}/
(Note that ${eureka.hostname} is a native placeholder only available in later versions of Eureka. You could achieve the same thing with Spring placeholders as well, e.g. using ${eureka.instance.hostName}.)
(注意一下${eureka.hostname}爲Eureka後續版本的佔位符,之前版本是${eureka.instance.hostName})。
NOTE If your app is running behind a proxy, and the SSL termination is in the proxy (e.g. if you run in Cloud Foundry or other platforms as a service) then you will need to ensure that the proxy "forwarded" headers are intercepted and handled by the application. An embedded Tomcat container in a Spring Boot app does this automatically if it has explicit configuration for the 'X-Forwarded-*` headers. A sign that you got this wrong will be that the links rendered by your app to itself will be wrong (the wrong host, port or protocol).
By default, Eureka uses the client heartbeat to determine if a client is up. Unless specified otherwise the Discovery Client will not propagate the current health check status of the application per the Spring Boot Actuator. Which means that after successful registration Eureka will always announce that the application is in 'UP' state. This behaviour can be altered by enabling Eureka health checks, which results in propagating application status to Eureka. As a consequence every other application won’t be sending traffic to application in state other then 'UP'.
通常來講,Eureka使用客戶端心跳來確認客戶端的在線狀態。但SpringCloud默認指定了服務發現的客戶端再也不經過Actuator傳播應用的當前狀態。這意味着在初次註冊以後,Eureka將一直顯示此應用爲「UP」狀態。這裏須要開發人員配置啓用Eureka健康檢查,使服務能廣播本身的應用狀態。而後,其餘的應用才能在狀態爲「UP」的時候發送請求。具體配置以下:
application.yml
eureka: client: healthcheck: enabled: true
WARNING eureka.client.healthcheck.enabled=true should only be set in application.yml. Setting the value in bootstrap.yml will cause undesirable side effects like registering in eureka with an UNKNOWN status.
WARNING eureka.client.healthcheck.enabled=true這個配置項只能寫在application.yml中。下載bootstratp.yml中爲致使不良反作用-註冊Eureka的時候UNKNOWN狀態。
If you require more control over the health checks, you may consider implementing your own com.netflix.appinfo.HealthCheckHandler.
若是須要對健康檢查作更多控制,能夠考慮實現本身的com.netflix.appinfo.HealthCheckHandler。
It’s worth spending a bit of time understanding how the Eureka metadata works, so you can use it in a way that makes sense in your platform. There is standard metadata for things like hostname, IP address, port numbers, status page and health check. These are published in the service registry and used by clients to contact the services in a straightforward way. Additional metadata can be added to the instance registration in the eureka.instance.metadataMap, and this will be accessible in the remote clients, but in general will not change the behaviour of the client, unless it is made aware of the meaning of the metadata. There are a couple of special cases described below where Spring Cloud already assigns meaning to the metadata map.
爲了在平臺中合理使用Eureka,花點時間理解Eureka元數據的工做原理是值得的。標準的元數據包括hostname,IP地址,端口號,狀態頁,健康檢查。客戶端簡單地使用這些發佈在註冊機中的元數據去調用服務。能夠在服務註冊時加入其餘元數據到eureka.instance.metadataMap中,遠程客戶端能夠訪問到,除非改變元數據的意義,不然整體上不會改變客戶端行爲。後面會描述了幾個特殊狀況,Spring Cloud已經指定的元數據集合的意義。(這段理解不能)
Cloudfoundry has a global router so that all instances of the same app have the same hostname (it’s the same in other PaaS solutions with a similar architecture). This isn’t necessarily a barrier to using Eureka, but if you use the router (recommended, or even mandatory depending on the way your platform was set up), you need to explicitly set the hostname and port numbers (secure or non-secure) so that they use the router. You might also want to use instance metadata so you can distinguish between the instances on the client (e.g. in a custom load balancer). By default, the eureka.instance.instanceId is vcap.application.instance_id. For example:
application.yml
eureka:
instance:
hostname: ${vcap.application.uris[0]} nonSecurePort: 80
Depending on the way the security rules are set up in your Cloudfoundry instance, you might be able to register and use the IP address of the host VM for direct service-to-service calls. This feature is not (yet) available on Pivotal Web Services (PWS).
If the application is planned to be deployed to an AWS cloud, then the Eureka instance will have to be configured to be AWS aware and this can be done by customizing the EurekaInstanceConfigBean the following way:
@Bean @Profile("!default") public EurekaInstanceConfigBean eurekaInstanceConfig(InetUtils inetUtils) { EurekaInstanceConfigBean b = new EurekaInstanceConfigBean(inetUtils); AmazonInfo info = AmazonInfo.Builder.newBuilder().autoBuild("eureka"); b.setDataCenterInfo(info); return b; }
A vanilla Netflix Eureka instance is registered with an ID that is equal to its host name (i.e. only one service per host). Spring Cloud Eureka provides a sensible default that looks like this: ${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}}}. For example myhost:myappname:8080.
Using Spring Cloud you can override this by providing a unique identifier in eureka.instance.instanceId. For example:
application.yml
eureka: instance: instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
With this metadata, and multiple service instances deployed on localhost, the random value will kick in there to make the instance unique. In Cloudfoundry the vcap.application.instance_id will be populated automatically in a Spring Boot application, so the random value will not be needed.
Once you have an app that is @EnableDiscoveryClient (or @EnableEurekaClient) you can use it to discover service instances from the Eureka Server. One way to do that is to use the native com.netflix.discovery.EurekaClient (as opposed to the Spring Cloud DiscoveryClient), e.g.
當你有一個@EnableDiscoveryClient(或@EnableEurekaClient)的APP時,你就能夠用它從Eureka服務器來發現服務實例了。下面介紹一個使用原生com.netflix.discovery.EurekaClient(對應Spring Cloud DiscoveryClient)的實現方法:
@Autowired private EurekaClient discoveryClient; public String serviceUrl() { InstanceInfo instance = discoveryClient.getNextServerFromEureka("STORES", false); return instance.getHomePageUrl(); }
TIP Don’t use the EurekaClient in @PostConstruct method or in a @Scheduled method (or anywhere where the ApplicationContext might not be started yet). It is initialized in a SmartLifecycle (with phase=0) so the earliest you can rely on it being available is in another SmartLifecycle with higher phase.
提示 不要在@PostConstruct,@Scheduled方法中(或者任何應用上下文尚未啓動的時刻)。那時候EurekaClient極可能尚未被初始化。
You don’t have to use the raw Netflix EurekaClient and usually it is more convenient to use it behind a wrapper of some sort. Spring Cloud has support for Feign (a REST client builder) and also Spring RestTemplate using the logical Eureka service identifiers (VIPs) instead of physical URLs. To configure Ribbon with a fixed list of physical servers you can simply set <client>.ribbon.listOfServers to a comma-separated list of physical addresses (or hostnames), where <client> is the ID of the client.
一般,開發人員沒必要使用Netflix原生的EurekaClient,使用包裝好的更爲便利。Spring Cloud擁有Feign(一個Rest客戶端Builder)的支持,使用邏輯Eureka服務定位器的Spring RestTemplate代替物理地址URL。用固定的物理服務器列表只須要簡單配置配置Ribbon,設置<client>.ribbon.listOfServers用逗號分隔物理地址列表(或主機名),<client>就是客戶端的ID。
@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; }
Being an instance also involves a periodic heartbeat to the registry (via the client’s serviceUrl) with default duration 30 seconds. A service is not available for discovery by clients until the instance, the server and the client all have the same metadata in their local cache (so it could take 3 heartbeats). You can change the period using eureka.instance.leaseRenewalIntervalInSeconds and this will speed up the process of getting clients connected to other services. In production it’s probably better to stick with the default because there are some computations internally in the server that make assumptions about the lease renewal period.
一個Eureka客戶端實例一樣包含一個默認30秒週期性心跳通知註冊機(經過客戶端serviceUrl)。一個服務須要實例,服務器和客戶端都在本地緩存中有相同的元數據纔可用(故可能須要3次心跳-多是server、provider、consumer)。經過eureka.instance.leaseRenewalIntervalInSeconds配置能夠修改心跳週期,它能加快客戶端連接到服務端的速度。但在生產環境中最好使用默認值,由於服務器內部有一些對更新週期的預期的計算。
If you have deployed Eureka clients to multiple zones than you may prefer that those clients leverage services within the same zone before trying services in another zone. To do this you need to configure your Eureka clients correctly.
若是開發人員將Eureka部署到了多個地區,並想在使用時優先使用一個區。那麼就須要正確配置Eureka的客戶端。
First, you need to make sure you have Eureka servers deployed to each zone and that they are peers of each other. See the section on **zones and regions** for more information.
首先開發人員須要保證不一樣地區的Eureka服務端都是彼此的節點。更多信息請見 **zones and regions**。
Next you need to tell Eureka which zone your service is in. You can do this using the metadataMap property. For example if service 1 is deployed to both zone 1 and zone 2 you would need to set the following Eureka properties in service 1
其次,開發人員須要通知Eureka你的服務在哪一個地區。使用metadataMap屬性來實現。例如,服務1註冊在地區1和地區2,須要像下文這樣配置:
Service 1 in Zone 1
eureka.instance.metadataMap.zone = zone1 eureka.client.preferSameZoneEureka = true
Service 1 in Zone 2
eureka.instance.metadataMap.zone = zone2 eureka.client.preferSameZoneEureka = true
dreamingodd原創文章,如轉載請註明出處。