是官方文档的总结html
http://spring.io/projects/spring-cloud-netflix#overviewjava
讲解基于2.0.2版本官方文档git
https://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/2.0.2.RELEASE/single/spring-cloud-netflix.htmlgithub
Netflix提供了如下功能:web
1、服务发现:Eureka客户端spring
服务发现是基于微服务的体系结构的核心原则之一。尝试手工配置每一个客户端或某种形式的约定可能很困难,并且很脆弱。Eureka是Netflix服务发现服务器和客户端。能够将服务器配置和部署为高度可用,每一个服务器都将注册服务的状态复制给其余服务器。apache
1.一、包含依赖后端
group ID:org.springframework.cloud缓存
artifact ID:spring-cloud-starter-netflix-eureka-client安全
具体版本能够查看http://spring.io/projects/spring-cloud,查看对应Spring Cloud版本匹配的Eureka客户端版本
1.二、注册到Eureka中
当客户端向Eureka注册时,它会提供关于本身的元数据,例如主机、端口、健康指示符URL、主页和其余详细信息。Eureka从属于服务的每一个实例接收心跳消息。若是心跳在可配置的时间表上失败,则一般从注册表中删除该实例。
@SpringBootApplication @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应用,只要classpath中包含了spring-cloud-starter-netflix-eureka-client,应用就会自动注册到Eureka服务器
要求经过配置来指向Eureka服务器
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
defaultZone:当客户端没有明确指向一个Eureka服务器时,会采用这个默认URL。
默认应用程序名称(即服务ID)、虚拟主机和非安全端口(从环境获取)分别为${Spring.application.name}、${Spring.application.name}和${server.port}。
当classpath中包含了spring-cloud-starter-netflix-eureka-client时,使这个应用既是一个Eureka实例(把本身注册到Eureka服务器中),也是一个Eureka客户端(他能够查询Eureka服务器定位其它服务)。
实例行为能够经过eureka.instance.*的属性来配置,也能够经过设置spring.application.name(做为Eureka服务的ID或VIP)并做为实例行为的默认值。
更多配置属性的信息,查看这2个Bean:EurekaInstanceConfigBean、EurekaClientConfigBean
https://github.com/spring-cloud/spring-cloud-netflix/tree/master/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java
https://github.com/spring-cloud/spring-cloud-netflix/blob/master/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientConfigBean.java
禁止使用Eureka客户端,能够设置eureka.client.enabled为false
1.三、经过Eureka服务器的验证
在eureka.client.serviceUrl.defaultZone的路径中嵌入一个凭证(http://user:password@localhost:8761/eureka),会自动为你提供一个HTTP basic认证。
若是须要更加复杂的需求,能够建立一个DiscoveryClientOptionalArgs的Bean,并为他注入一个ClientFilter实例,用于客户端请求服务器时使用。
因为Eureka中的限制,不可能支持每一个服务器的basic认证凭据,所以只使用了找到的第一组。
1.四、状态页面和健康指标
默认路径是Spring Boot中Actuator下的/info和/health地址,
若是你使用非默认上下文路径或非默认servlet路径,则须要修改他们。
eureka:
instance:
statusPageUrlPath: ${server.servletPath}/info
healthCheckUrlPath: ${server.servletPath}/health
在Dalston版本中,还要求在更改管理上下文路径时设置状态和健康检查URL。从Edgware开始,这一要求就被删除了。
1.五、注册一个安全的应用
若是应用须要经过HTTPS传输,能够设置2个属性
eureka.instance.[nonSecurePortEnabled]=[false]
eureka.instance.[securePortEnabled]=[true]
设置了以后,Eureka客户端会返回https的地址。Eureka的实例信息也会有一个安全的健康检查URL
因为Eureka的设计,status页、home页并不会由于这个设置变成安全连接,须要手动更改。
eureka:
instance:
statusPageUrl: https://${eureka.hostname}/info
healthCheckUrl: https://${eureka.hostname}/health
homePageUrl: https://${eureka.hostname}/
${eureka.hostname}是一个本地占位符,最新版本的Eureka才支持;也可使用Spring占位符${eureka.instance.hostName}
If your application runs behind a proxy, and the SSL termination is in the proxy (for example, if you run in Cloud Foundry or other platforms as a service), then you need to ensure that the proxy “forwarded” headers are intercepted and handled by the application. If the Tomcat container embedded in a Spring Boot application has explicit configuration for the 'X-Forwarded-\*` headers, this happens automatically. The links rendered by your app to itself being wrong (the wrong host, port, or protocol) is a sign that you got this configuration wrong.
1.六、Eureka健康检查
默认状况下,Eureka使用心跳机制决定一个客户端是否在线。
除非特殊设置,Eureka客户端不会经过Actuator来传递应用的健康信息。
能够开启Eureka健康检查,
。。待补充
1.七、Eureka实例和客户端的元数据
使用eureka.instance.metadataMap能够添加元数据,这些元数据能够在远程客户端中获取。
通常元数据不会改变客户端的行为,除了那些客户端能识别到这些元数据的含义,有些元数据Spring Cloud已经在使用。
这个是用于部署在云平台,而后能够获取平台的一些数据?
1.八、使用Eureka客户端
Eureka客户端,能够经过Eureka服务器来发现其余服务的实例。
可使用com.netflix.discovery.EurekaClient
@Autowired private EurekaClient discoveryClient; public String serviceUrl() { InstanceInfo instance = discoveryClient.getNextServerFromEureka("STORES", false); return instance.getHomePageUrl(); }
Do not use the EurekaClient
in a @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 a higher phase.
1.8.一、禁用Jersey
默认状况下Eureka客户端使用Jersey进行HTTP通讯。
能够经过排除依赖禁用他,而后Spring Cloud会经过Spring RestTemplate来进行HTTP通讯。
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <exclusions> <exclusion> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> </exclusion> <exclusion> <groupId>com.sun.jersey</groupId> <artifactId>jersey-core</artifactId> </exclusion> <exclusion> <groupId>com.sun.jersey.contribs</groupId> <artifactId>jersey-apache-client4</artifactId> </exclusion> </exclusions> </dependency>
1.九、本地Netflix Eureka客户端的替代方案
通常不会使用上面的EurekaClient来获取真正的物理地址。
Spring Cloud提供了一个Feign和Spring RestTemplate,能够经过Eureka服务的识别码(如服务ID或VIP)来访问服务,而不是经过物理地址。
若是要用一个固定服务器物理地址列表来配置Ribbon,能够经过设置<client>.ribbon.listOfServers,使用一个逗号分隔的物理地址(或hostnames),<client>是客户端的ID
也可使用org.springframework.cloud.client.discovery.DiscoveryClient,包含针对服务发现客户端(不只是Netflix)的一些API
@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; }
1.十、为何注册一个服务这么慢?
Being an instance also involves a periodic heartbeat to the registry (through the client’s serviceUrl
) with a default duration of 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 by setting eureka.instance.leaseRenewalIntervalInSeconds
. Setting it to a value of less than 30 speeds up the process of getting clients connected to other services. In production, it is probably better to stick with the default, because of internal computations in the server that make assumptions about the lease renewal period.
做为一个实例,还涉及到注册表的周期性心跳(经过客户端的serviceUrl),默认持续时间为30秒。直到实例、服务器和客户端在其本地缓存中都有相同的元数据(所以可能须要3次心跳),客户端才能发现服务。能够经过设置eureka.instance.leaseRenewalIntervalInSeconds.更改期间将其设置为小于30的值能够加快将客户端链接到其余服务的过程。在生产中,可能最好仍是坚持默认的作法,由于服务器中的内部计算会对租约续订期作出假设。
1.十一、分区
若是你的Eureka客户端分开了几个区域,而且但愿调用服务时,先在相同区域调用服务,而后才调用其它区域的服务。
这就须要进行正确的配置。
首先,要吧Eureka服务器部署到每个区域,而且他们之间是对等服务器
而后,你须要告诉Eureka服务器,你的服务是在哪个区域,能够经过修改metadataMap属性来实现
//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
2、Eureka服务器
2.一、如何包含Eureka服务器
group ID:org.springframework.cloud
artifact ID:spring-cloud-starter-netflix-eureka-server
具体版本能够查看http://spring.io/projects/spring-cloud,查看对应Spring Cloud版本匹配的Eureka客户端版本
2.二、运行一个Eureka服务器
@SpringBootApplication @EnableEurekaServer public class Application { public static void main(String[] args) { new SpringApplicationBuilder(Application.class).web(true).run(args); } }
服务器有一个首页和一些HTTP API端点在/eureka/*下
有几个Eureka的讨论网站?
https://github.com/cfregly/fluxcapacitor/wiki/NetflixOSS-FAQ#eureka-service-discovery-load-balancer
https://groups.google.com/forum/?fromgroups#!topic/eureka_netflix/g3p2r7gHnN0
Due to Gradle’s dependency resolution rules and the lack of a parent bom feature, depending on spring-cloud-starter-netflix-eureka-server
can cause failures on application startup. To remedy this issue, add the Spring Boot Gradle plugin and import the Spring cloud starter parent bom as follows:
build.gradle.
buildscript {
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:{spring-boot-docs-version}")
}
}
apply plugin: "spring-boot" dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:{spring-cloud-version}" } }
2.三、高可用,分区与区域(High Availability, Zones and Regions)
Eureka没有后端存储,可是服务实例必须保持发送心跳消息来保持他们的注册是最新的(在内存中实现)。
客户端也有一个对Eureka注册服务的内存缓存,这使得不用每一次调用服务,都去查找一次注册的服务。
默认状况下,每一个Eureka服务器也是Eureka客户端,须要(至少一个)服务URL来定位对等服务器。若是你不提供,服务也能运行,只是在日志中会增长大量没法向服务器注册的信息。
2.四、单例模式
经过2个缓存(服务器、客户端)以及心跳机制,使得只要提供一些监控或者运行时弹性(如Cloud Foundry)保持一个Eureka服务器持续运行,他就有很强的抗错误弹性。
在单例模式下,你能够考虑关闭掉客户端行为,就不会一直尝试注册到不存在的服务器路径失败
关闭掉客户端
server: port: 8761 eureka: instance: hostname: localhost client: registerWithEureka: false fetchRegistry: false serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
注意defaultZone指向本地Eureka实例
2.五、同伴意识
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/
在前面的示例中,咱们有一个YAML文件,经过在不一样的Spring profiles中运行该文件,能够在两个主机(peer 1和peer 2)上运行相同的服务器。您可使用此配置来经过操做/etc/host来解析主机名来测试单个主机上的对等感知(在生产中这样作没有多大价值)。实际上,若是在知道本身主机名的机器上运行(默认状况下,使用java.net.InetAddress查找),则不须要eureka.instance.hostname。
你能够添加多个同伴到一个系统中,只要他们互相经过至少一个链接而相连,他们之间的注册实例就会互相同步。若是这些同伴是物理隔离的,那么这个系统就有能力抵抗脑裂(split-brain)失败。
eureka: client: serviceUrl: defaultZone: http://peer1/eureka/,http://peer2/eureka/,http://peer3/eureka/ --- spring: profiles: peer1 eureka: instance: hostname: peer1 --- spring: profiles: peer2 eureka: instance: hostname: peer2 --- spring: profiles: peer3 eureka: instance: hostname: peer3
2.六、何时使用IP地址
在某些状况下,Eureka最好是公布服务的IP地址,而不是主机名。
设置eureka.instance.preferIpAddress为true,程序注册到Eureka中的时候,会使用IP地址二不是hostname
若是主机名不能由Java肯定,则将IP地址发送给Eureka。唯一明确设置主机名的方法是设置eureka.instance.hostname属性。能够经过使用环境变量(例如eureka.instance.hostname=${host_name})在运行时设置主机名。
2.七、保护Eureka服务器
您只需经过spring-boot-starter-security将Spring Security添加到服务器的类路径中,就能够保护您的Eureka服务器。默认状况下,当Spring Security在类路径上时,它将要求在向应用程序的每一个请求中发送一个有效的CSRF令牌。Eureka客户端一般不会拥有有效的跨站点请求伪造(CSRF)令牌,您须要对/eureka/*端点禁用此要求。例如:
@EnableWebSecurity class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().ignoringAntMatchers("/eureka/**"); super.configure(http); } }