1 Eureka 闭源
在Euraka的GitHub上,宣布Eureka 2.x闭源。近这意味着如果开发者继续使用作为 2.x 分支上现有工作repo 一部分发布的代码库和工件,则将自负风险。
1.1 Eureka的替换方案
1.1.1 Zookeeper
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
1.1.2 Consul
consul是近几年比较流行的服务发现工具,工作中用到,简单了解一下。consul的三个主要应用场景:服务发现、服务隔离、服务配置。
1.1.3 Nacos
Nacos 是阿里巴巴推出来的一个新开源项目,这是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
1.2 Consul
Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其它分布式服务注册与发现的方案,Consul 的方案更“一站式”,内置了服务注册与发现框 架、分布一致性协议实现、健康检查、Key/Value 存储、多数据中心方案,不再需要依赖其它工具(比如 ZooKeeper 等)。使用起来也较 为简单。Consul 使用 Go 语言编写,因此具有天然可移植性(支持Linux、windows和Mac OS X);安装包仅包含一个可执行文件,方便部署,与 Docker 等轻量级容器可无缝配合。
1.3 Consul 的优势:
- 使用 Raft 算法来保证一致性, 比复杂的 Paxos 算法更直接. 相比较而言, zookeeper 采用的是Paxos, 而 etcd 使用的则是 Raft。
- 支持多数据中心,内外网的服务采用不同的端口进行监听。 多数据中心集群可以避免单数据中心的单点故障,而其部署则需要考虑网络延迟, 分片等情况等。 zookeeper 和 etcd 均不提供多数据中心功能的支持。
- 支持健康检查。 etcd 不提供此功能。
- 支持 http 和 dns 协议接口。 zookeeper 的集成较为复杂, etcd 只支持 http 协议。
- 官方提供 web 管理界面, etcd 无此功能。
综合比较, Consul 作为服务注册和配置管理的新星, 比较值得关注和研究。
特性:
- 服务发现
- 健康检查
- Key/Value 存储
- 多数据中心
1.4 consul与Eureka的区别
1.4.1 一致性
Consul强一致性(CP)
- 服务注册相比Eureka会稍慢一些。因为Consul的raft协议要求必须过半数的节点都写入成功才认为注册成功
- Leader挂掉时,重新选举期间整个consul不可用。保证了强一致性但牺牲了可用性。
Eureka保证高可用和最终一致性(AP)
- 服务注册相对要快,因为不需要等注册信息replicate到其他节点,也不保证注册信息是否replicate成功
- 当数据出现不一致时,虽然A, B上的注册信息不完全相同,但每个Eureka节点依然能够正常对外提供服务,这会出现查询服务信息时如果请求A查不到,但请求B就能查到。如此保证了可用性但牺牲了一致性。
1.4.2 开发语言和使用
- eureka就是个servlet程序,跑在servlet容器中
- Consul则是go编写而成,安装启动即可
1.5 下载
2 Consul 的基本使用
2.1 注册服务
3 案例
- 提供一个商品微服务
- 提供一个订单系统
3.1 把服务注册到 Consul
- product 子模块
<!-- 基于 consul 的服务发现-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!-- actuator 的健康检查-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
server:
port: 9081
spring:
application:
name: service-product #服务名称
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/springcloud_shop?useUnicode=true&characterEncoding=utf8
username: root
password: root
jpa:
database: MySQL
show-sql: true
open-in-view: true
autoconfigure:
exclude: org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration
# 配置 consul 的服务注册
cloud:
consul:
host: 127.0.0.1
port: 8500
discovery:
register: true
instance-id: ${spring.application.name}-1 # 注册的实例ID(唯一标志)
service-name: ${spring.application.name} # 服务的名称
port: ${server.port} # 服务的请求端口
prefer-ip-address: true # 指定开启 ip 地址注册
ip-address: ${spring.cloud.client.ip-address} # 当前服务的请求 IP
#eureka:
# client:
# service-url :
# defaultZone: http://localhost:9000/eureka/
# instance:
# prefer-ip-address: true # 使用 ip 地址注册
# instance-id: ${spring.cloud.client.ip-address}:${server.port} # 向注册中心注册服务的 id
# lease-renewal-interval-in-seconds: 5 # 发送心跳的间隔
# lease-expiration-duration-in-seconds: 10 # 续约到期时间
3.2 服务消费者从 consul 拉取所有的服务列表
- Order 子模块
<!--引入 EurekaClient-->
<!-- <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>-->
<!--请求重试-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<!-- 基于 consul 的服务发现-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!-- actuator 的健康检查-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
server:
port: 8082
spring:
application:
name: service-order #服务名称
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/springcloud_shop?useUnicode=true&characterEncoding=utf8
username: root
password: root
jpa:
database: MySQL
show-sql: true
open-in-view: true
# 配置 consul 的服务注册
cloud:
consul:
host: 127.0.0.1
port: 8500
discovery:
register: false
instance-id: ${spring.application.name}-1 # 注册的实例ID(唯一标志)
service-name: ${spring.application.name} # 服务的名称
port: ${server.port} # 服务的请求端口
prefer-ip-address: true # 指定开启 ip 地址注册
ip-address: ${spring.cloud.client.ip-address} # 当前服务的请求 IP