什么是Eureka?
Eureka是基于REST(具像状态传输)的服务,主要用于AWS云中定位服务,以实现中间层服务器的负载平衡和故障转移。我们将此服务称为Eureka服务器。Eureka还附带了一个基于java的客户端组件Eureka客户端,这使得与服务的交互更加容易。客户机还有一个内置的负载均衡器,它执行基本的循环负载平衡。在Netflix,一个更加复杂的负载均衡器封装了Eureka,根据流量、资源使用、错误条件等因素提供加权负载平衡,从而提供更好的弹性。
Eureka需要什么?
在AWS云中,由于其固有的特性,服务器来来去去。与使用已知IP地址和主机名的服务器的传统负载平衡器不同,在AWS中,负载平衡需要在动态地使用负载平衡器注册和注销服务器时更加复杂。由于AWS还没有提供中间层负载平衡器,Eureka填补了中间层负载平衡领域的一个巨大空白。
Eureka和AWS的不同?
AWS弹性负载均衡器是面向最终用户web流量的边缘服务的负载平衡解决方案。Eureka满足了中间层负载平衡的需求。虽然理论上您可以将中间层服务放在AWS ELB之后,但在EC2经典中,您将通过失去AWS安全组的所有有用性而将其公开给外部世界。
AWS ELB也是一种传统的基于代理的负载平衡解决方案,而与Eureka不同的是,负载平衡发生在实例/服务器/主机级别。客户机实例知道它们需要与哪些服务器通信的所有信息。这是福是祸取决于你怎么看它。如果您正在寻找AWS现在提供的基于粘性用户会话的负载平衡,Eureka没有提供开箱即用的解决方案。在Netflix,我们希望我们的服务是无状态的(非粘性的)。这有助于更好的可伸缩性模型,Eureka非常适合解决这个问题。
将基于代理的负载平衡与使用Eureka的负载平衡区分开来的另一个重要方面是,您的应用程序可以对负载平衡器的中断具有弹性,因为关于可用服务器的信息缓存在客户机上。这确实需要少量内存,但是可以获得更好的弹性。
Eureka和Zookeeper的区别?
著名的CAP理论指出,一个分布式系统不可能同时满足C(一致性)、A(可用性)和P(分区容错性)。由于分区容错性在是分布式系统中必须要保证的,因此我们只能在A和C之间进行权衡。在此Zookeeper保证的是CP, 而Eureka则是AP。
-
Zookeeper保证CP:
当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接down掉不可用。也就是说,服务注册功能对可用性的要求要高于一致性。但是zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。 -
Eureka保证AP:
Eureka看明白了这一点,因此在设计时就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
- Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务
- Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)
- 当网络稳定时,当前实例新的注册信息会被同步到其它节点中
搭建Eureka服务端?
Eureka服务端也可以说是微服务的注册中心。
- 创建一个maven工程
- 修改maven工程的pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lc</groupId>
<artifactId>springcloud-eureka-server1</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.source.Encoding>UTF-8</project.build.source.Encoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<!-- 热部署工具 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
<!-- 依赖管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.9.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
- 在application.yml进行相关的配置修改
server:
port: 7001
eureka:
instance:
hostname: localhost #eureka 服务端实例名称
client:
register-with-eureka: false #false 表示不向注册中心中注册自己
fetch-registry: false #false 表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置与 Eureka Server 交互的地址查询服务和注册服务都需要依赖这个地址(服务暴露的地址)
- 在启动类上添加
@EnableEurekaServer
注解
@SpringBootApplication
@EnableEurekaServer
public class EurekaApp2 {
public static void main(String[] args) {
SpringApplication.run(EurekaApp2.class,args);
}
}
搭建Eureka集群
- 创建两个Eureka工程
- 修改Maven工程的pom文件与上面一致
- 在application.yml中添加相关的配置
Eureka工程1:
eureka:
instance:
hostname: eureka7001.com #eureka的服务名称
client:
register-with-eureka: false #表示不想服务器中注册自己
fetch-registry: false #表示自己端就是注册中心,不需要去检索服务
service-url:
defaultZone: http://eureka7002.com:7002/eureka/ #将7001和7002配置成集群环境
server:
port: 7001
Eureka工程2:
eureka:
instance:
hostname: eureka7002.com #eureka的服务名称
client:
register-with-eureka: false #表示不想服务器中注册自己
fetch-registry: false #表示自己端就是注册中心,不需要去检索服务
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
#将7002和7001配置成集群环境
server:
port: 7002
- 编写启动类(启动类和上面的一样:注意添加
@EnableEurekaServer
注解)
上面分别讲述了如何搭建Eureka服务端和Eureka集群。但是,有一点我们需要注意的就是,我们搭建好服务端后通过地址和端口就能进入到Eureka自带的默认管理也,这样对我们的服务管理非常的不安全,因此我们需要登录成功后才能进入到Eureka的管理页面,那该怎么做呢?
Eureka身份认证
- 添加Spring-Security相关的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
- 在Eureka服务进行配置
eureka:
instance:
hostname: eureka7002.com #eureka的服务名称
client:
register-with-eureka: false #表示不想服务器中注册自己
fetch-registry: false #表示自己端就是注册中心,不需要去检索服务
service-url:
defaultZone: http://${security.user.name}:${security.user.password}@eureka7001.com:7001/eureka/
server:
port: 7002
security:
user:
name: jak
password: 12345678
关于7001的配置也是一样的.就不再做多的说明啦
到这一步登录Eureka服务端就需要输入用户和密码进行身份认证才能进去啦!当然Eureka服务端进行了密码的配置,当然客户端也同样需要拥有密码才能把服务注册到Eureka容器,或者从Eureka容器中获取服务。
- 修改客户端进行身份认证
eureka:
client:
service-url:
defaultZone: http://${security.user.name}:${security.user.password}@eureka7001.com:7001/eureka/
instance:
instance-id: provider01
prefer-ip-address: true
spring:
application:
name: Eureka-Provider1
security:
user:
name: jak
password: 123456
这样就成功啦!