【系统架构理论】一篇文章精通:Spring Cloud Netflix Eureka
是官方文档的总结
http://spring.io/projects/spring-cloud-netflix#overview
讲解基于2.0.2版本官方文档
https://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/2.0.2.RELEASE/single/spring-cloud-netflix.html
Netflix提供了以下功能:
- 服务发现:可以注册Eureka实例,客户端可以使用Spring的beans来发现这些实例
- 服务发现:可以通过声明式Java配置来创建一个嵌入式Eureka服务器
- 断路器:可以通过简单的注解修饰方法来创建一个断路器客户端
- 断路器:使用声明式Java配置可以嵌入一个Hystrix仪表盘
- 客户端负载均衡器:Ribbon
- 外部配置:从Spring环境到Archaius的桥梁(允许使用SpringBoot约定对Netflix组件进行本地配置)
- 路由器和过滤器:Zuul过滤器的自动重新配置,和用于反向创建代理的配置方法的简单约定。
一、服务发现:Eureka客户端
服务发现是基于微服务的体系结构的核心原则之一。尝试手工配置每个客户端或某种形式的约定可能很困难,而且很脆弱。Eureka是Netflix服务发现服务器和客户端。可以将服务器配置和部署为高度可用,每个服务器都将注册服务的状态复制给其他服务器。
1.1、包含依赖
group ID:org.springframework.cloud
artifact ID:spring-cloud-starter-netflix-eureka-client
具体版本可以查看http://spring.io/projects/spring-cloud,查看对应Spring Cloud版本匹配的Eureka客户端版本
1.2、注册到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.3、通过Eureka服务器的验证
在eureka.client.serviceUrl.defaultZone的路径中嵌入一个凭证(http://user:password@localhost:8761/eureka),会自动为你提供一个HTTP basic认证。
如果需要更加复杂的需求,可以创建一个DiscoveryClientOptionalArgs的Bean,并为他注入一个ClientFilter实例,用于客户端请求服务器时使用。
由于Eureka中的限制,不可能支持每个服务器的basic认证凭据,因此只使用了找到的第一组。
1.4、状态页面和健康指标
默认路径是Spring Boot中Actuator下的/info和/health地址,
如果你使用非默认上下文路径或非默认servlet路径,则需要修改他们。
eureka:
instance:
statusPageUrlPath: ${server.servletPath}/info
healthCheckUrlPath: ${server.servletPath}/health
在Dalston版本中,还要求在更改管理上下文路径时设置状态和健康检查URL。从Edgware开始,这一要求就被删除了。
1.5、注册一个安全的应用
如果应用需要通过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.6、Eureka健康检查
默认情况下,Eureka使用心跳机制决定一个客户端是否在线。
除非特殊设置,Eureka客户端不会通过Actuator来传递应用的健康信息。
可以开启Eureka健康检查,
。。待补充
1.7、Eureka实例和客户端的元数据
使用eureka.instance.metadataMap可以添加元数据,这些元数据可以在远程客户端中获取。
一般元数据不会改变客户端的行为,除了那些客户端能识别到这些元数据的含义,有些元数据Spring Cloud已经在使用。
这个是用于部署在云平台,然后可以获取平台的一些数据?
1.8、使用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.1、禁用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.9、本地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.10、为什么注册一个服务这么慢?
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.11、分区
如果你的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
二、Eureka服务器
2.1、如何包含Eureka服务器
group ID:org.springframework.cloud
artifact ID:spring-cloud-starter-netflix-eureka-server
具体版本可以查看http://spring.io/projects/spring-cloud,查看对应Spring Cloud版本匹配的Eureka客户端版本
2.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.3、高可用,分区与区域(High Availability, Zones and Regions)
Eureka没有后端存储,但是服务实例必须保持发送心跳消息来保持他们的注册是最新的(在内存中实现)。
客户端也有一个对Eureka注册服务的内存缓存,这使得不用每一次调用服务,都去查找一次注册的服务。
默认情况下,每个Eureka服务器也是Eureka客户端,需要(至少一个)服务URL来定位对等服务器。如果你不提供,服务也能运行,只是在日志中会增加大量无法向服务器注册的信息。
2.4、单例模式
通过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.5、同伴意识
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.6、什么时候使用IP地址
在某些情况下,Eureka最好是公布服务的IP地址,而不是主机名。
设置eureka.instance.preferIpAddress为true,程序注册到Eureka中的时候,会使用IP地址二不是hostname
如果主机名不能由Java确定,则将IP地址发送给Eureka。惟一明确设置主机名的方法是设置eureka.instance.hostname属性。可以通过使用环境变量(例如eureka.instance.hostname=${host_name})在运行时设置主机名。
2.7、保护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);
}
}
【系统架构理论】一篇文章精通:Spring Cloud Netflix Eureka的更多相关文章
- Spring Cloud Netflix Eureka源码导读与原理分析
Spring Cloud Netflix技术栈中,Eureka作为服务注册中心对整个微服务架构起着最核心的整合作用,因此对Eureka还是有很大的必要进行深入研究. 本文主要分为四部分,一是对项目构建 ...
- Spring Cloud Netflix Eureka client源码分析
1.client端 EurekaClient提供三个功能: EurekaClient API contracts are:* - provide the ability to get Instance ...
- Spring Cloud Netflix Eureka(注册中心)
Eureka简介 Eureka是Netflix开发的一个Service Discovery组件,spring cloud将其整合用来做服务注册中心,Eureka包括两部分Eureka Server 和 ...
- Spring Cloud Netflix Eureka: 多网卡环境下Eureka服务注册IP选择问题
https://blog.csdn.net/neosmith/article/details/53126924 通过源码可以看出,该工具类会获取所有网卡,依次进行遍历,取ip地址合理.索引值最小且不在 ...
- Spring Cloud Netflix Eureka【服务治理】
一.简介 二.使用 一.源码分析
- 一起来学spring Cloud | 第一章:spring Cloud 与Spring Boot
目前大家都在说微服务,其实微服务不是一个名字,是一个架构的概念,大家现在使用的基于RPC框架(dubbo.thrift等)架构其实也能算作一种微服务架构. 目前越来越多的公司开始使用微服务架构,所以在 ...
- 几种常见的微服务架构方案——ZeroC IceGrid、Spring Cloud、基于消息队列、Docker Swarm
微服务架构是当前很热门的一个概念,它不是凭空产生的,是技术发展的必然结果.虽然微服务架构没有公认的技术标准和规范草案,但业界已经有一些很有影响力的开源微服务架构平台,架构师可以根据公司的技术实力并结合 ...
- 从架构演进的角度聊聊Spring Cloud都做了些什么?
Spring Cloud作为一套微服务治理的框架,几乎考虑到了微服务治理的方方面面,之前也写过一些关于Spring Cloud文章,主要偏重各组件的使用,本次分享主要解答这两个问题:Spring Cl ...
- 微服务架构的服务与发现-Spring Cloud
1 为什么需要服务发现 简单来说,服务化的核心就是将传统的一站式应用根据业务拆分成一个一个的服务,而微服务在这个基础上要更彻底地去耦合(不再共享DB.KV,去掉重量级ESB),并且强调DevOps和快 ...
随机推荐
- Visio 2016自定义模具与形状
Visio 2016自定义模具与形状 0. 什么是模具? 模具:一组形状的集合 1. 新建模具 打开Visio 2016,在空白的文件中选更多形状>>新建模具 2. 编辑模具 新建的模具已 ...
- 【linux】 mail/mutt 发送邮件
mail: 比较常用,缺点是发送附件要同时安装其他软件: mutt:功能强大,注意发送html需要升级到1.5+版本: 用mail发送邮件: echo "邮件正文" | mai ...
- apt-get updete以及apt-get upgrade的区别
You should first run update, then upgrade. Neither of them automatically runs the other. apt-get upd ...
- Learning OSG programing---osgAnimation(1)
osg::AnimationPath* createAnimationPath(const osg::Vec3& center,float radius,double looptime) { ...
- Arrays工具类使用与源码分析(1)
Arrays工具类主要是方便数组操作的,学习好该类可以让我们在编程过程中轻松解决数组相关的问题,简化代码的开发. Arrays类有一个私有的构造函数,没有对外提供实例化的方法,因此无法实例化对象.因为 ...
- Netty核心组件介绍及手写简易版Tomcat
Netty是什么: 异步事件驱动框架,用于快速开发高i性能服务端和客户端 封装了JDK底层BIO和NIO模型,提供高度可用的API 自带编码解码器解决拆包粘包问题,用户只用关心业务逻辑 精心设计的Re ...
- input限制小数点的位数
在做限制input小数点的时候,我本来想通过vue里面的的watch监听来实现, ---实现逻辑是,通过监听输入的内容,当出现"."(点)的时候,记录通过indexOf获取点的位置 ...
- 洛谷 P1049 装箱问题(01背包)
一道水题,但看到好久没有发博客了,再一看是一道noip普及组t4,就做了. 题目链接 https://www.luogu.org/problemnew/show/P1049 解题思路 一道裸的01背包 ...
- python读取ini文件时,特殊字符的读取
前言: 使用python在读取配置文件时,由于配置文件中存在特殊字符,读取时出现了以下错误: configparser.InterpolationSyntaxError: '%' must be fo ...
- Quartz实现数据库动态配置定时任务
项目实战 或许实现的方式跟之前的代码有点不一样的 1.定时任务的配置信息 @Configuration public class ScheduleConfigration { @Autowired p ...