本文讲解了服务发现机制在分布式系统中存在的必要性,并对Eureka做了入门介绍,演示了如何下载Eureka源码、编译项目,为进一步学习源码做好环境准备。
一 为什么需要服务发现机制
1.1 没有服务发现机制
使用微服务构建的分布式系统,服务间通过网络交互。当服务A调用服务B的接口时,我们称服务A为消费者,服务B为提供者。
服务间调用时,服务消费者如何获得服务提供者的地址呢?如下面示例中硬编码吗?
User user = restTemplate.getForObject("http://168.10.37.121:8091/user/" + id, User.class)
或者将服务提供者配置到yaml中,使用LoadBalancerClient实现负责均衡。
# 消费者配置服务提供者
user-center:
ribbon:
listOfServers: 168.10.37.121:8091,168.10.37.25:8091
ServiceInstance serviceInstance = loadBalancerClient.choose("user-center");
String uri = "/user/" + 1;
String address = serviceInstance.getHost() + ":" + serviceInstance.getPort();
User user = restTemplate.getForObject("http://" + address + uri, User.class);
但是,以上方式都有很大局限:
- 如果服务提供者的网络地址发生变化,将不得不修改服务消费者的代码或配置,重新发布;
- 服务提供者往往集群部署,当某些节点宕机了,服务消费者无法感知,继续访问已宕机节点而报错。
- 服务提供者动态增减节点时,硬编码时无法适应。
1.2 服务发现机制
硬编码维护服务提供者的网络地址,存在很多问题。
我们需要一套服务发现机制:即消费者获取服务提供者的网络地址,同时能适应提供者动态扩容缩容。
这就是独立于业务应用的服务发现组件:
- 各服务启动时,将自己的网络地址等信息注册到发现组件,保存到注册表中;
- 消费者从发现组组件中查询服务提供者的网络地址,进而发起调用;
- 各服务定期向发现组件上报节点状态(up或down),如通过周期性心跳,对于长时间没有上报的节点,将其从注册表中剔除(认为它已下线)
可见,组件涉及服务端、客户端的双向交互。客户端即业务应用,主动发起注册、心跳、查询请求。
SpringCloud提供了多种服务发现组件的支持,如Eureka、Consul和Zookeeper等。
二 Eureka引入
Eureka是美国Netflix公司开源的服务发现组件,本身是一个基于RESTful (Representational State Transfer)的服务。它包含Server和Client两部分。主要用于AWS云中,实现服务发现、负载平衡和故障转移功能。
2.1 一些概念
- Register:服务注册
当Eureka客户端向Eureka Server发起注册,提供自身的元数据,比如IP地址、端口,运行状况等; - Renew:服务续约
Eureka客户会每隔30秒(默认)发送一次心跳来续约。 通过续约来告知Eureka Server该Eureka客户端仍然存在线。 - Fetch Registries:获取注册列表信息
Eureka客户端从服务器获取注册表信息,并将其缓存在本地。客户端会使用注册表查找其他服务地址,从而进行远程调用。该注册列表信息定期(每30秒钟)更新一次。在默认的情况下Eureka客户端使用压缩JSON格式来获取注册列表的信息。 - Cancel:服务下线
Eureka客户端在程序关闭时向Eureka服务器发送取消请求。 发送请求后,该客户端实例信息将从服务器的实例注册表中删除。 - Eviction 服务剔除
在默认的情况下,当Eureka客户端连续90秒没有向Eureka服务器发送服务续约,即心跳,Eureka服务器会将该服务实例从服务注册列表删除。
2.2 架构设计
图中有2个角色,即Eureka Server和Eureka Client:
- Eureka Client又分为Applicaton Service和Application Client,即服务提供者和服务消费者。
- us-east-1c、us-east-1d等都是Available Zone(可理解为机房);每个机房都有一个Eureka Server,多个机房一同构成Eureka集群。
- Eureka集群中,各节点是互联的,进行注册表同步。
us-east-1是Region名。Region表示AWS元中的地址位置,每个Region有多个Available Zone。在非AWS环境下,可以将Available Zone理解为机房。
三 eureka源码导入
3.1 拉取源码
从github上拉取源码,用idea打开项目。eureka使用gradle构建项目,idea将主动下载gradle-3.0-bin.zip。
git clone https://github.com/Netflix/eureka.git
git checkout v1.7.x
3.2 下载gradle
先配置本地gradle仓库地址。
在gradle/wrapper/gradle-wrapper.properties中,distributionUrl指向国外网站。如果下载速度很慢的话,可以替换为国内镜像地址。
3.3 配置依赖下载源
等idea自动下载完gradle,进入gradle的init.d文件夹(在Gradle user home绑定的目录下)。
创建一个
init.gradle文件,内容如下,使用阿里云的Maven仓地址:
allprojects {
repositories {
mavenLocal()
maven { name "Alibaba" ; url "https://maven.aliyun.com/repository/public" }
maven { name "Bstek" ; url "https://nexus.bsdn.org/content/groups/public/" }
mavenCentral()
}
buildscript {
repositories {
maven { name "Alibaba" ; url 'https://maven.aliyun.com/repository/public' }
maven { name "Bstek" ; url 'https://nexus.bsdn.org/content/groups/public/' }
maven { name "M2" ; url 'https://plugins.gradle.org/m2/' }
}
}
}
3.4 加载项目
点击reload按钮,idea将自动下载依赖,需要一点时间。
项目构建完成,可以看到依赖的包都被引入了。