Spring Cloud Eureka 实现服务注册与发现

时间:2023-02-15 08:22:59

微服务 是一种架构模式,跟具体的语言实现无关,微服务架构将业务逻辑分散到了各个服务当中,服务间通过网络层进行通信共同协作;这样一个应用就可以划分为多个服务单独来维护发布。构建一个可靠微服务系统是需要具体看场景去衡量的,网络通信必然会带来过多的网络延迟,设计的时候就要尽量减少服务与服务间的通信,采用什么通信协议等。和单应用架构不同,微服务架构是由一系列职责单一的细粒度服务构成的分布式网状结构,服务之间通过轻量机制进行通信来实现。微服务背后一个重要的理念就是持续集成、快速交付,而在服务内部使用一个统一的技术框架,显然比把分散的技术组合到一起更有效率。

Spring Cloud 微服务框架

Spring Cloud 是基于 Spring Boot 提供了一套微服务解决方案,是一系列框架的有序集合,包括服务注册与发现,配置中心,全链路监控,服务网关,负载均衡,熔断器等组件等,其中主要通过整合 Netflix (Netflix 是一家成功实践微服务架构的互联网公司,几年前,Netflix 就把它的几乎整个微服务框架栈开源贡献给了社区)的相关产品来实现这方面的功能(Spring Cloud Netflix),包括用于服务注册和发现的 Eureka,调用断路器 Hystrix,调用端负载均衡 Ribbon,Rest 客户端 Feign,智能服务路由 Zuul 等(Feign 和 RxJava 并不是 Netiflix 的产品,只是被整合到 Spring Cloud Netflix 中了)。

结构图

Spring Cloud Eureka 实现服务注册与发现

组件架构图

服务设施中用到了 Spring Cloud Config、Netflix Eureka、Netflix Hystrix、Netflix Zuul、Netflix Ribbon、Netflix Feign 等组件,这也正是Spring Cloud分布式开发中最核心的组件(转载)。

Spring Cloud Eureka 实现服务注册与发现

  • 账户服务通过远程客户端(Feign)调用统计服务及通知服务,通过Ribbon实现负载均衡,并在调用过程中增加了断路器(Hystrix)的功能;

  • 由于服务发现后才能调用,因此账户服务、统计服务、通知服务通过注册中心(Eureka)实现互相发现;

  • API Gateway(Zuul)提供对外统一的服务网关,首先从注册中心(Eureka)处获取相应服务,再根据服务调用各个服务的真实业务逻辑;

  • 服务调用过程通过聚合器(Turbine)统一所有断路信息;

  • 整个业务过程中所有服务的配置文件通过Spring Cloud Config来管理,即起什么端口、配置什么参数等;

  • 认证机制通过Auth service实现,提供基本认证服务;

  • Spring Cloud Config、Eureka、Ribbon、Hystrix、Feign以及Turbine均为标准组件,与业务之间没有强关系,不涉及到业务代码,仅需简单配置即可工作。

Eureka 注册发现服务

CAP 理论

Eureka 是 Netflix 开源的一款提供服务注册和发现组件,Spring Cloud  将它集成在自己的子项目 Spring Cloud Netflix 中。原生的 Eureka 会包含 AWS 定制功能,这也正是 Spring Cloud 中最核心的组件。另外服务注册与发现开源组件很多,比如 Consul(CA)和 Zookeeper (CP),但这并不是一个最佳选择。

在分布式系统领域有个著名的CAP定理:C——数据一致性,A——服务可用性,P——服务对网络分区故障的容错性。这三个特性在任何分布式系统中不能同时满足,最多同时满足两个。

Zookeeper 是著名 Hadoop 的一个子项目,很多场景下Zookeeper也作为Service发现服务解决方案。Zookeeper 保证的是 CP,即任何时刻对Zookeeper的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性,但是它不能保证每次服务请求的可用性。从实际情况来分析,在使用 Zookeeper 获取服务列表时,如果zookeeper正在选主,或者Zookeeper集群中半数以上机器不可用,那么将就无法获得数据了。所以说,Zookeeper不能保证服务可用性。

诚然,对于大多数分布式环境,尤其是涉及到数据存储的场景,数据一致性应该是首先被保证的,这也是zookeeper设计成CP的原因。但是对于服务发现场景来说,情况就不太一样了:针对同一个服务,即使注册中心的不同节点保存的服务提供者信息不尽相同,也并不会造成灾难性的后果。因为对于服务消费者来说,能消费才是最重要的——拿到可能不正确的服务实例信息后尝试消费一下,也好过因为无法获取实例信息而不去消费。所以,对于服务发现而言,可用性比数据一致性更加重要——AP 胜过 CP。而 Spring Cloud Netflix 在设计 Eureka 时遵守的就是AP原则。转载

  • 根据 CAP 理论指出,CAP 永远不可能同时满足,最多只能同时满足两个,提高其中任意两者的同时,必然要牺牲第三者。分布式系统不可能同时满足C(Consistency一致性)、A(Availablity可用性)和P(Partition Tolerance分区容错性)。由于分区容错性在是分布式系统中必须要保证的,因此我们需要权衡A和C。在此 Zookeeper 保证的是CP, 而Eureka则是 AP。
  • Eureka更合适处理范围更广的网络分割故障。Eureka 内置了心跳服务用于淘汰一些“濒死”的服务,节点会进入“自我保护模式”,同时保留那些“心跳死亡”的服务注册信息不过期,当宕机的服务器重新恢复后,Eureka 会再次将其纳入到服务器集群管理之中。ZooKeeper 下节点断开了,那么会将它们都从自己管理范围中剔除出去,外界就不能访问到这些节点了,即便这些节点本身是“健康”的,可以正常提供服务的,所以导致到达这些节点的服务请求被丢失了。Zookeeper 在网络被分割严重时,可能会出现多个Leader的情况。
  • Eureka 客户端缓存功能使得即便 Eureka 集群中所有节点都失效,或者不能访问任何一台  Eureka 服务器,依然可以通过客户端缓存来获取现有的服务注册信息。
  • ZooKeeper 的一致性使得请求能得到一致的数据结果。在热部署或更新了服务配置之后,Eureka 每个节点之间的更新会出现一定的时间差,使得部分外部访问到的是新的服务,而部分是老的服务。
  • 由于 ZooKeeper 的 CP 机制,Leader 节点的选取或者事务日志机制,使得设置与维护 ZooKeeper 服务相对比较困难,同时正确的设置与维护 ZooKeeper 服务本身也比较折腾,容易出错。相对而言Eureka更容易设置和维护,系统运行时健壮性更强。

配置单机版 Eureka Server

Eureka 由 Eureka Server(服务的注册中心,负责维护注册的服务列表) 和 Eureka Client 组成,我们将 Eureka Client 再分为 Service Provider(服务提供方,作为一个Eureka Client,向Eureka Server做服务注册、续约和下线等操作,注册的主要数据包括服务名、机器ip、端口号、域名等) 与 Service Consumer(服务消费方,作为一个Eureka Client,向Eureka Server获取Service Provider 的注册信息,并通过远程调用与 Service Provider 进行通信),另外 Service Provider 和 Service Consumer 不是严格的概念,Service Consumer 也可以随时向 Eureka Server 注册,来让自己变成一个 Service Provider,Eureka Server 也可以自注册,但是一般单机版的服务这样做没有意义。

Maven 配置

        <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-security</artifactId>-->
<!--</dependency>—>

YML 配置文件

spring:
application:
name: microsrv-eureka-server server:
port: 8000 eureka:
instance:
hostname: localhost
#prefer-ip-address: true
#ip-address: 192.168.1.1 client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

程序的入口Application类加上@EnableEurekaServer 注解

@SpringBootApplication
@EnableEurekaServer
public class MicrosrvEurekaServerApplication { public static void main(String[] args) {
SpringApplication.run(MicrosrvEurekaServerApplication.class, args);
}
}

配置高可用集群 Eureka Server

我们可以创建三个注册中心节点,每个节点进行两两相互注册,达到集群的最高可用性,任何一个节点挂掉都不会影响服务的注册与发现。如果某台 Eureka Server 宕机,Eureka Client 的请求会自动切换到新的 Eureka Server 节点,当宕机的服务器重新恢复后,Eureka 会再次将其纳入到服务器集群管理之中。当节点开始接受客户端请求时,所有的操作都会进行 replicateToPeer(节点间复制)操作,将请求复制到其他Eureka Server当前所知的所有节点中。一个新的 Eureka Server 节点启动后,会首先尝试从邻近节点获取所有实例注册表信息,完成初始化。Eureka Server 通过getEurekaServiceUrls()方法获取所有的节点,并且会通过心跳续约的方式定期更新。默认配置下,如果 Eureka Server 在一定时间内没有接收到某个服务实例的心跳,Eureka Server 将会注销该实例(默认为90秒,通过 eureka.instance.lease-expiration-duration-in-seconds 配置)。当 Eureka Server 节点在短时间内丢失过多的心跳时(比如发生了网络分区故障),那么这个节点就会进入自我保护模式。

修改 host文件

vi /etc/hosts 增加如下信息

10.255.131.162       microsrv-eureka-server-peer1
10.255.131.163 microsrv-eureka-server-peer2
10.255.131.164 microsrv-eureka-server-peer3

YUM 文件配置(---分割每个节点的内容,等同于创建了三个文件的效果)

### HOST 方式
spring:
application:
name: microsrv-eureka-server
profiles:
active: peer1
#logging:
# level:
# com.netflix.eureka: 'off'
# com.netflix.discovery: 'off' ---
spring:
profiles: peer1
server:
port: 8000
eureka:
instance:
hostname: microsrv-eureka-server-peer1
client:
registerWithEureka: true
fetchRegistry: true
service-url:
defaultZone: http://microsrv-eureka-server-peer2:${server.port}/eureka/,http://microsrv-eureka-server-peer3:${server.port}/eureka/ ---
spring:
profiles: peer2
server:
port: 8000
eureka:
instance:
hostname: microsrv-eureka-server-peer2
client:
registerWithEureka: true
fetchRegistry: true
service-url:
defaultZone: http://microsrv-eureka-server-peer1:${server.port}/eureka/,http://microsrv-eureka-server-peer3:${server.port}/eureka/ ---
spring:
profiles: peer3
server:
port: 8000
eureka:
instance:
hostname: microsrv-eureka-server-peer3
client:
registerWithEureka: true
fetchRegistry: true
service-url:
defaultZone: http://microsrv-eureka-server-peer1:${server.port}/eureka/,http://microsrv-eureka-server-peer2:${server.port}/eureka/
最后依次启动服务
java -jar microsrv-eureka-server-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer1
java -jar microsrv-eureka-server-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer2
java -jar microsrv-eureka-server-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer3

Spring Cloud Eureka 实现服务注册与发现

有时候我们觉得使用 Host 的方式显示并不是太友好,也可以修改成 IP 的方式实现(配置 eureka.instance.prefer-ip-address=true 属性),配置如下:

## IP 的方式
spring:
application:
name: microsrv-eureka-server
profiles:
active: peer1
#logging:
# level:
# com.netflix.eureka: 'off'
# com.netflix.discovery: 'off' ---
spring:
profiles: peer1
server:
port: 8000
eureka:
instance:
prefer-ip-address: true
ip-address: 10.255.131.162
client:
registerWithEureka: true
fetchRegistry: true
service-url:
defaultZone: http://10.255.131.163:${server.port}/eureka/,http://10.255.131.164:${server.port}/eureka/ ---
spring:
profiles: peer2
server:
port: 8000
eureka:
instance:
prefer-ip-address: true
ip-address: 10.255.131.163
client:
registerWithEureka: true
fetchRegistry: true
service-url:
defaultZone: http://10.255.131.162:${server.port}/eureka/,http://10.255.131.164:${server.port}/eureka/ ---
spring:
profiles: peer3
server:
port: 8000
eureka:
instance:
prefer-ip-address: true
ip-address: 10.255.131.164
client:
registerWithEureka: true
fetchRegistry: true
service-url:
defaultZone: http://10.255.131.162:${server.port}/eureka/,http://10.255.131.163:${server.port}/eureka/

创建 Service Provider 服务提供者

Service Provider 本质是一个 Eureka Client。启动时,会调用服务注册方法向 Eureka Server 注册自己的信息。Eureka Server 会维护一个已注册服务的列表。

创建  Service Consumer 消费者

Service Consumer 本质也是一个 Eureka Client(它也会向 Eureka Server 注册,只是这个注册信息无关紧要)。它启动后,会从 Eureka Server 上获取所有实例的注册信息,包括IP地址、端口等,并缓存到本地。这些信息默认每30秒更新一次。前文提到过,如果与 Eureka Server 通信中断,Service Consumer 仍然可以通过本地缓存与 Service Provider 通信。

注意:Eureka 2.0 开源工作宣告停止

其他问题

Liunx 服务器运行报 java.net.UnknownHostException:Name or service not known

2018-06-28 17:27:06.970  INFO 1292 --- [           main] c.n.d.provider.DiscoveryJerseyProvider   : Using XML decoding codec XStreamXml
2018-06-28 17:27:07.027 WARN 1292 --- [ main] c.n.e.transport.JerseyReplicationClient : Cannot find localhost ip java.net.UnknownHostException: iZuf6i3b97wsrn5x2oic17Z: iZuf6i3b97wsrn5x2oic17Z: Name or service not known
at java.net.InetAddress.getLocalHost(InetAddress.java:1505) ~[na:1.8.0_151]
at com.netflix.eureka.transport.JerseyReplicationClient.createReplicationClient(JerseyReplicationClient.java:170) ~[eureka-core-1.9.2.jar!/:1.9.2]

解决办法,配置主机名

echo `hostname`
vi /etc/hosts
127.0.0.1 hostname localhost
自我保护模式
当注册服务因为网络或其他原因出现故障而关停时,Eureka不会剔除服务注册,而是等待其修复,可以通过如下配置剔除不健康节点,这是AP的一种实现。
server:
eureka.server.enable-self-preservation//(设为false,关闭自我保护)
eureka.server.eviction-interval-timer-in-ms //清理间隔(单位毫秒,默认是60*1000)
client:
eureka.client.healthcheck.enabled = true //开启健康检查(需要spring-boot-starter-actuator依赖)
eureka.instance.lease-renewal-interval-in-seconds =30 //租期更新时间间隔(默认30秒)
eureka.instance.lease-expiration-duration-in-seconds =90 //租期到期时间(默认90秒)
server:
eureka:
server:
enableSelfPreservation: false
evictionIntervalTimerInMs: 3000
client:
eureka:
instance:
leaseRenewalIntervalInSeconds:30
leaseExpirationDurationInSeconds: 90

如果 Eureka Server 每分钟收到心跳续约的数量低于一个阈值(instance的数量*(60/每个instance的心跳间隔秒数)*自我保护系数),并且持续15分钟,就会触发自我保护。在自我保护模式中,Eureka Server会保护服务注册表中的信息,不再注销任何服务实例。当它收到的心跳数重新恢复到阈值以上时,该Eureka Server节点就会自动退出自我保护模式。它的设计哲学前面提到过,那就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。该模式可以通过 eureka.server.enable-self-preservation = false 来禁用,同时 eureka.instance.lease-renewal-interval-in-seconds可以用来更改心跳间隔,eureka.server.renewal-percent-threshold 可以用来修改自我保护系数(默认0.85)。

Eureka Server 中的 Region、Zone 概念

Region 与 Zone 均是 AWS 的概念。在非 AWS 环境下,我们可以先简单地将 region 理解为 Eureka集 群,zone 理解成机房。

REFER:
https://github.com/Microsoft/api-guidelines
http://projects.spring.io/spring-cloud/
微服务架构初探
http://www.iteye.com/news/32932

Spring Cloud Eureka 实现服务注册与发现的更多相关文章

  1. 服务注册发现Eureka之一:Spring Cloud Eureka的服务注册与发现

    Spring Cloud简介 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全局锁 ...

  2. Spring Cloud Alibaba &vert; Nacos服务注册与发现

    目录 Spring Cloud Alibaba | Nacos服务注册与发现 1. 服务提供者 1.1 pom.xml项目依赖 1.2 配置文件application.yml 1.3 启动类Produ ...

  3. spring cloud 学习之 服务注册和发现&lpar;Eureka&rpar;

    一:服务注册和发现(Eureka) 1:采用Eureka作为服务注册和发现组件 2:Eureka 项目中 主要在启动类加上 注解@EnableEurekaServer @SpringBootAppli ...

  4. Spring Cloud Consul 实现服务注册和发现

    Spring Cloud 是一个基于 Spring Boot 实现的云应用开发工具,它为基于 JVM 的云应用开发中涉及的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全局锁.决策竞选.分布 ...

  5. Spring Cloud实践之服务注册与发现Eureka

    一.简述: 服务提供者producer与服务消费者consumer都注册到eureka server,然后服务consumer在其应用内直接调用producer的服务名来调用服务,而不是像之前一样调用 ...

  6. Spring Cloud&lpar;一&rpar;:服务注册与发现

    Spring Cloud是什么 Spring Cloud是一系列框架的有序集合.它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册.配置中心.消息总线.负载均 ...

  7. Spring Cloud Consul使用——服务注册与发现&lpar;注册中心&rpar;

    整理自该文章 一.Consul 服务端接下来我们开发 Consul 的服务端,创建一个 spring-cloud-consul-producer 项目 1.添加依赖包 <dependencies ...

  8. Spring Cloud Alibaba 的服务注册与发现

    Spring Cloud Alibaba 服务发现例子 一.需求 1.提供者完成的功能 2.消费者完成的功能 3.可以附加的额外配置 二.实现步骤 1.总的依赖引入 2.服务提供者和发现者,引入服务发 ...

  9. Spring Cloud 系列之 Eureka 实现服务注册与发现

    如果你对 Spring Cloud 体系还不是很了解,可以先读一下 Spring Cloud 都有哪些模块 Eureka 是 Netflix 开源的服务注册发现组件,服务发现可以说是微服务架构的核心功 ...

随机推荐

  1. Syncfusion的社区许可及免费电子书和白皮书

    今晚由于要忙于其他事情,就简单的给大家推荐一个第三方组件库.特别注明:这是我义务为这家公司打广告.毕竟我从他们公司收获了很多知识. Syncfusion是一家微软生态下的第三方组件/控件供应商,算是后 ...

  2. 第一章 Collections 类、泛型类和Timing类概述

    摘抄<数据结构与算法(C#语言描述)> 删除很多废话 1.1群集(collection)的定义 群集是一种结构化的数据类型.存储数据,并且提供数据的添.删.改操作,以及对群集不同属性值的设 ...

  3. poj 2362

    回溯加剪枝 #include <cstdio> #include <cstdlib> #include <cmath> #include <map> # ...

  4. And Then There Was One(约瑟夫问题变形)

    题目链接:http://poj.org/problem?id=3517 And Then There Was One Time Limit: 5000MS   Memory Limit: 65536K ...

  5. C&num;中DBNull&period;Value和Null的用法和区别

    DBNull.Value,, 是适用于向数据库的表中插入空值.而 null,是指在程序中表示空引用. 或者对象为空.就是没有实例化. row[column]的值为DBNull.Value的话,至少说明 ...

  6. C语言--static修饰变量

    Static在C语言里面有两个作用,第一个是修饰变量,第二个是修饰函数. 1.Static修饰变量 按照作用范围的不同,变量分为局部变量和全局变量.如果用static修饰变量,不论这个变量是全局的还是 ...

  7. ado&period;net 使用:ExecuteReader 无法获取输出参数

    解决方法: 要获取到输出参数.需要连接关闭之后才行. 一般都是用using把打开数据库连接的reader包起来

  8. vscode快捷键

    vscode快捷键 按 ctrl+shift+p 查找设置文件Ctrl + W 关闭编辑器 设置定位到终端的快捷键:打开键盘配置文件,搜索focus terminal,找到聚焦到终端的命令,添加ctr ...

  9. Linux系统网络文件配置

    /etc  一.修改配置文档(需要重启网络配置,永远生效) 1.修改IP地址[MariaDB@db1]$ vi /etc/sysconfig/network-scripts/ifcfg-eth0DEV ...

  10. 关于form表单onsubmi提交

    表单允许客户端的用户以标准格式向服务器提交数据.表单的创建者为了收集所需数据,使用了各种控件设计表单如 INPUT 或 SELECT.查看表单的用户只需填充数据并单击提交按钮即可向服务器发送数据.服务 ...