第二章 Spring Cloud Eureka
Netflix Eureka是Netflix开源的一款基于REST提供服务注册和发现的产品,它提供了完整的Service Registry和Service Discovery实现。从2012年9月再Github上发布1.1.2版本依赖,目前已经发布了239个Release版本,目前最新版本是2019年6月14日发布的v1.9.12版本。期间Netflix也有进行2.x版本的开发,不过由于各种各样的原因已经冻结开发,目前还是以1.x版本为主。Spring Cloud Netflix Eureka是为了将NetFlix Eureka整合进入Spring Cloud生态而提供的版本。
先介绍一下NetFlix这家公司:
Netflix(Nasdaq NFLX) 成立于1997年,是一家在线影片租赁提供商,主要提供Netflix超大数量的DVD并免费递送,总部位于美国加利福尼亚州洛斯盖图。
Netflix已经连续五次被评为顾客最满意的网站。可以通过PC、TV及iPad、iPhone收看电影、电视节目,可通过Wii,Xbox360,PS3等设备连接TV。Netflix大奖赛从2006年10月份开始,Netflix公开了大约1亿个1-5的匿名影片评级,数据集仅包含了影片名称。评价星级和评级日期,没有任何文本评价的内容。比赛要求参赛者预测Netflix的客户分别喜欢什么影片,要把预测的效率提高10%以上。
Netflix的开源框架组件已经在Netflix的大规模分布式微服务环境中经过多年的生产实战验证,正逐步被社区接受为构造微服务框架的标准组件。Spring Cloud开源产品,主要是基于对Netflix开源组件的进一步封装,方便Spring开发人员构建微服务基础框架。
本章内容以Spring Cloud Greenwich.SR2版本展开,对应Netflix Eureka版本为v1.9.12,将系统全面的介绍服务中心(注册中心)的由来以及由入门到进阶再到实战循序渐进的帮助开发者学习Eureka这个组件。
2.1 Spring Cloud Eureka 入门
2.1.1 服务中心(注册中心)概述
在微服务的架构中,服务中心(注册中心)是核心的基础服务之一。在微服务架构流行之前,服务中心就已经开始出现在分布式架构的系统之中了。例如 Dubbo :它是一个在国内比较流行的分布式框架,被大量的中小型互联网公司所采用, Dubbo 是一个非常实用的框架,提供了比较完善的服务治理功能,而服务治理的实现主要依靠的就是注册中心。
当然服务中心或是注册中心的名字不是凭空而来,其演进过程与软件开发架构的方式有着密切的关联,大致如下:
-
单体架构(垂直架构)
早期的互联网开发多使用此方案,所有的服务自成一体,包括淘宝最开始是购买的PHP+Mysql程序,一台PHP服务器,一台Mysql服务器就构成了最早期的淘宝,对于依赖的外部服务,会采用配置域名的方式进行调用,比如要调用外部供应商的接口来发短信。
-
分布式架构
随着互联网的发展,使用的用户越来越多,团队参与的开发人员越来越多,一份代码在版本管理上越来越复杂,每天大量的人力投在版本管理上,开发效率越来越低下,这里还可以用淘宝来举个例子,淘宝在最巅峰的时期所有的代码都在一个项目下,一个war包超过200MB,每次发布都需要耗费大量的人力去拆分版本,保证所有上线的代码都是正确的,但是人力终有尽时,还是出现过好多次生产事故。
这时,软件开发开始从单体架构拆分为颗粒度较粗的服务化架构,这时产生一个问题,原来在同一个项目中,接口的调用直接引用调用就行,现在拆分成不同的服务了,产生了物理上的隔离,如何进行内部服务间的调用呢?
以基于HTTP的服务调用为例,假设服务A部署在3台单独的虚拟机上,这三个服务有自己的独立内网IP,此时服务B要调用服务A,有以下这么几种调用方式:
方式一:
服务端B已知A所有的地址,自行在A的三个服务地址中做负载均衡,如图2-1:
这种方式最大的一个弊端是服务B和服务A的耦合性太强,服务B耦合了服务A的服务细节,如果服务A有扩充或者IP地址有变化的时候,服务B都需要去修改这些对应的IP,可能还会需要重启服务才能恢复正常访问。
方式二:
为了解耦可以在服务A的前面加一台Nginx来隐藏A的服务细节(IP地址),服务B只需要配置这台Nginx的域名,就可以完成对服务A的调用,不需要知道服务A具体的IP地址,如图2-2:
这时,如果需要修改服务A的IP地址,只需要修改更改Nginx的配置即可,实现了服务细节对服务B的隐藏。
-
微服务时代
在微服务时代,底层运维方式发生了巨变,随着容器的盛行,业务不再部署在固定的虚拟机上,也不会再有固定的IP,这时前面的解决方案就已经捉襟见肘了。针对这个问题,可能会有不同的解决方案,本书这里列举几个:
方案一:
以Nginx为例,在没有引入服务中心(注册中心)的时候,通过手工或者脚本的形式,在部署新的服务的时候去更新Nginx的配置文件,然后reload,这里有一个缺点是Nginx需要reload才能生效。或者使用ngx_http_dyups_module模块通过rest api的方式在Nginx运行时直接更新upstream而不需要reload。方案二:
将服务中心(注册中心)作为一个标准的分布式组件,网关、Nginx等组件都从这里获取相关的服务配置信息,实现动态路由。比如consul+Nginx的方案,结合nginx的主动健康检查模块nginx_upstream_check_module和服务发现模块nginx-upsync-module,实现一套服务动态发现机制。nginx的upstream不再通过手动配置,而是定时向consul发送请求,获取consul数据中心的配置文件,动态更新upstream地址池。由此可见,随着服务架构模式以及运维方式的转变,服务中心(注册中心)逐步成为分布式系统中一个不可或缺的中间件。
2.1.2 Eureka简介
Eureka是一种基于REST(Representational State Transfer)的服务,用于定位服务,以实现中间层服务器的负载平衡和故障转移。我们将此服务称为Eureka Server。Eureka还附带了一个基于Java的客户端组件Eureka Client,它使与服务的交互变得更加容易。客户端还有一个内置的负载均衡器,可以进行基本的循环负载均衡。如图2-3:
Eureka最初是针对AWS不提供中间服务层的负载均衡而设计研发的,AWS Elastic Load Balancer是面向客户端或者终端用户的负载均衡的解决方案,而Eureka是用来对中间层的服务做服务发现,配合其他组件提供负载均衡服务的。
Netflix为什么要设计Eureka而不是使用AWS Elastic Load Balancer或者AWS Route 53呢?官方文档做出了如下说明:
理论上是可以使用AWS Elastic Load Balancer对内部进行负载均衡,但是这样服务就会暴露在外网,存在安全性的问题,另外AWS Elastic Load Balancer是传统的基于代理的负载均衡解决方案,无法直接基于服务元数据信息定制负载均衡算法。因此,Netflix设计制作了Eureka,一方面用作内部的服务发现,另一方面配合其他组件如Ribbon提供个性化的负载均衡。
而AWS Route53是一种命名服务,可以给中间层提供服务发现功能,但是他是基于DNS的服务的,传统的基于DNS的负载均衡技术存在更新延时等问题,另外无法对服务的健康状态进行检查,因此Netflix设计制作了Eureka。
2.1.3 服务中心技术选型
下表选用目前市面上几种常见的产品级的服务中心进行对比:
名称 | 语言 | 健康检查 | 一致性算法 | CAP原则 | 依赖 | Spring Cloud |
---|---|---|---|---|---|---|
Eureka | Java | 可配、支持 | raft | AP | JVM | 支持 |
ZooKeeper | Java | (弱)长连接、keepalive | paxos | CP | JVM | 支持 |
Consul | Go | 服务状态、内存、硬盘等 | raft | CP | 支持 | |
etcd | Go | 连接心跳 | raft | CP | 支持 |
从列表来看,有很多服务中心是可以选择的,针对CAP原则,本书主要选取了Eureka和Zookeeper为代表来进行阐述。
首先,介绍一下什么是CAP原则。
CAP原则又称CAP定理,指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。
-
Zookeeper保证CP
当向服务中心查询服务列表时,我们可以容忍服务中心返回的是几分钟以前的注册信息,但不能接受服务直接down掉不可用。也就是说,服务注册功能对可用性的要求要高于一致性。但是Zookeeper会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个Zookeeper集群都是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因网络问题使得Zookeeper集群失去master节点是较大概率会发生的事,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。
-
Eureka保证AP
Eureka Server采用的是P2P复制模式,但它不保证复制一定成功。Eureka Server各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册或如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性)。
那么,基于什么因素考虑我们选用Eureka呢,主要有以下几点:
- 选择AP而不是CP,这一点会在后面的章节阐述
- 技术团队是Java体系的,偏好Java语言的开发,技术体系上比较统一,出现问题也好排查修复,对组件的掌控力较强,方便扩展和维护。
- 更重要的是Eureka是Netflix套件的一部分,跟Netflix其他组件如Zuul、Ribbon等整合的比较好,使用方便。
2.1.4 入门案例
下面我们体验一下Eureka的入门工程,这里需要用到的组件是Spring Cloud Netflix Eureka。
- 创建Maven父级pom工程
在父级工程中,需要配置好父级工程依赖,目的是方便配置和简化管理,具体pom.xml文件如下:
<?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>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.springcloud</groupId>
<artifactId>ch2_1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ch2_1</name>
<description>ch2_1</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR2</spring-cloud.version>
</properties>
<modules>
<module>ch2_1_eureka_server</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
<modules>
:需配置所有子工程,每次添加子工程需检查这里是否正常添加,如未自动添加,需手动添加。<properties>
:当前配置文件一些配置,可以看到Java的版本是1.8,springcloud的版本是Greenwich.SR1,编码格式是UTF-8,输出格式也是UTF-8。<dependencyManagement>
:这里是声明依赖,并不实现引入,如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version
和scope
都读取自父pom
;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。这里我们定义引入的Spring Cloud版本为Greenwich.SR2
。<build>
:在build中声明了当前使用的插件,spring-boot-maven-plugin,主要功能:能够将Spring Boot应用打包为可执行的jar或war文件,然后以通常的方式运行Spring Boot应用。
- 创建Eureka Server工程
配置Eureka Server工程的pom.xml文件如下,只需要添加spring-cloud-starter-netflix-eureka-server依赖即可。
<?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">
<parent>
<artifactId>ch2_1</artifactId>
<groupId>com.springcloud</groupId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ch2_1_eureka_server</artifactId>
<name>ch2_1_eureka_server</name>
<description>ch2_1_eureka_server</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR2</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
<parent>
:指定父级工程,注意<relativePath>
需配置父级依赖的相对路径,否则可能会找不到父级配置而报错,创建子工程时,这里是默认路径,如果报错,需手动修改。<dependencies>
:当前项目依赖的组件。
子工程启动主类Ch21EurekaServerApplication.java,这里是程序的入口
package com.springcloud.book;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* Created with IntelliJ IDEA.
*
* @Date: 2019/7/20
* @Time: 22:13
* @email: inwsy@hotmail.com
* Description:
*/
@SpringBootApplication
@EnableEurekaServer
public class Ch21EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(Ch21EurekaServerApplication.class, args);
}
}
- 添加注解
@EnableEurekaServer
子工程Eureka Server配置文件:
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
server:
enable-self-preservation: false
wait-time-in-ms-when-sync-empty: 0
默认的配置文件是在resource下面的application.properties,在springboot的项目中,目前支持两种配置文件的形式,还有一种是yaml,本书使用的所有配置均为yaml形式。
server.port
:服务端口。eureka.client.register-with-eureka
:表示是否注册自身到eureka服务器,因为当前这个应用就是eureka服务器,没必要注册自身,所以关闭自己注册自己。eureka.client.fetch-registry
:此客户端是否获取eureka服务器注册表上的注册信息。eureka.client.service-url.defaultZone
:默认访问路径。eureka.server.wait-time-in-ms-when-sync-empty
:在Eureka服务器获取不到集群里对等服务器上的实例时,需要等待的时间,单位为毫秒。eureka.server.enable-self-preservation
:自我保护模式,当出现出现网络分区、eureka在短时间内丢失过多客户端时,会进入自我保护模式,即一个服务长时间没有发送心跳,eureka也不会将其删除,默认为true,因为这里我们是演示,防止由于Eureka的机制导致Client被错误显示在线,自我保护模式无需开启,此项请在生产环境开启,以防网络波动,会直接将服务下线。
- 创建Eureka Client 工程
配置Eureka Server工程的pom.xml文件如下,只需要添加spring-cloud-starter-netflix-eureka-client依赖即可。
<?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">
<parent>
<artifactId>ch2_1</artifactId>
<groupId>com.springcloud</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ch2_1_eureka_client</artifactId>
<name>ch2_1_eureka_client</name>
<description>ch2_1_eureka_client</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
子工程启动主类Ch21EurekaClientApplication.java
package com.springcloud.book;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* Created with IntelliJ IDEA.
*
* @Date: 2019/7/21
* @Time: 0:37
* @email: inwsy@hotmail.com
* Description:
*/
@SpringBootApplication
@EnableDiscoveryClient
public class Ch21EurekaClientApplication {
public static void main(String[] args) {
SpringApplication.run(Ch21EurekaClientApplication.class, args);
}
}
- 添加注解
@EnableDiscoveryClient
子工程Eureka Client配置文件:
server:
port: 8080
spring:
application:
name: eureka-client
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
spring.application.name
:这里必须配置,否则会在Eureka Server界面显示为UNKNOWN
至此,入门案例已经完成。
- 测试
分别启动eureka-service和eureka-client,然后访问http://localhost:8761/,结果如图2-4展示:
- 红字的意思是提醒我们健康模式已经关闭,无需关注。
这里可以看到application那一栏我们的eureka-client已经正常注册在Eureka Server上。
我们访问Eureka的rest api接口,如:http://localhost:8761/eureka/apps,返回结果如下:
<applications>
<versions__delta>1</versions__delta>
<apps__hashcode>UP_1_</apps__hashcode>
<application>
<name>EUREKA-CLIENT</name>
<instance>
<instanceId>host.docker.internal:eureka-client:8080</instanceId>
<hostName>host.docker.internal</hostName>
<app>EUREKA-CLIENT</app>
<ipAddr>192.168.0.102</ipAddr>
<status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="true">8080</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<leaseInfo>
<renewalIntervalInSecs>30</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1563641232344</registrationTimestamp>
<lastRenewalTimestamp>1563641502331</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1563641232345</serviceUpTimestamp>
</leaseInfo>
<metadata>
<management.port>8080</management.port>
</metadata>
<homePageUrl>http://host.docker.internal:8080/</homePageUrl>
<statusPageUrl>http://host.docker.internal:8080/actuator/info</statusPageUrl>
<healthCheckUrl>http://host.docker.internal:8080/actuator/health</healthCheckUrl>
<vipAddress>eureka-client</vipAddress>
<secureVipAddress>eureka-client</secureVipAddress>
<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1563641232345</lastUpdatedTimestamp>
<lastDirtyTimestamp>1563641232302</lastDirtyTimestamp>
<actionType>ADDED</actionType>
</instance>
</application>
</applications>
2.1.5 Eureka Server REST API
Eureka同时也提供REST API来供非Java应用使用,Eureka在Github上专门有一篇wiki《Eureka REST operations》来介绍相关的接口,具体路径:https://github.com/Netflix/eureka/wiki/Eureka-REST-operations 。
传入参数格式要求为JSON/XML,提供的请求头必须定义传入数据类型application/xml
或application/json
。
操作 | HTTP请求 | 描述 |
---|---|---|
注册新的应用实例 | POST /eureka/apps/{appID} | 输入格式JSON/XML ,成功响应204 |
注销应用实例 | DELETE /eureka/apps/{appID}/{instanceID} | 成功响应200 |
向应用实例发送心跳检测 | PUT /eureka/apps/{appID}/{instanceID} | 成功响应200,未找到对应 instanceID 响应404 |
查询所有应用实例 | GET /eureka/apps | 成功响应200,并输出JSON/XML |
根据appID 查询应用实例 | GET /eureka/apps/{appID} | 成功响应200,并输出JSON/XML |
根据appID 和instanceID 查询应用实例 | GET /eureka/apps/{appID}/{instanceID} | 成功响应200,并输出JSON/XML |
根据instanceID 查询应用实例 | GET /eureka/instances/{instanceID} | 成功响应200,并输出JSON/XML |
暂停服务实例 | PUT /eureka/apps/{appID}/{instanceID}/status?value=OUT_OF_SERVICE | 成功响应200,失败响应500 |
恢复应用实例 | DELETE /eureka/apps/{appID}/{instanceID}/status?value=UP (参数value=UP 是可选的, 它被建议用作删除覆盖失败而导致的回退状态) | 成功响应200,失败响应500 |
更新元数据 | PUT /eureka/apps/{appID}/{instanceID}/metadata?key=value | 成功响应200,失败响应500 |
根据vip地址查询所有应用实例 | GET /eureka/vips/{vipAddress} | 成功响应200,vip地址未找到响应404,输出JSON/XML |
根据svip地址查询所有应用实例 | GET /eureka/svips/{svipAddress} | 成功响应200,svip地址未找到响应404,输出JSON/XML |
2.1.6 REST API 实战
我们可以借助工具Postman来测试Eureka的REST API,需设置请求头Content-Type:application/xml
。
- 查询所有应用实例
GET http://localhost:8761/eureka/apps
<applications>
<versions__delta>1</versions__delta>
<apps__hashcode>UP_1_</apps__hashcode>
<application>
<name>EUREKA-CLIENT</name>
<instance>
<instanceId>host.docker.internal:eureka-client:8080</instanceId>
<hostName>host.docker.internal</hostName>
<app>EUREKA-CLIENT</app>
<ipAddr>192.168.0.102</ipAddr>
<status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="true">8080</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<leaseInfo>
<renewalIntervalInSecs>30</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1563691948498</registrationTimestamp>
<lastRenewalTimestamp>1563693118633</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1563691948498</serviceUpTimestamp>
</leaseInfo>
<metadata>
<management.port>8080</management.port>
</metadata>
<homePageUrl>http://host.docker.internal:8080/</homePageUrl>
<statusPageUrl>http://host.docker.internal:8080/actuator/info</statusPageUrl>
<healthCheckUrl>http://host.docker.internal:8080/actuator/health</healthCheckUrl>
<vipAddress>eureka-client</vipAddress>
<secureVipAddress>eureka-client</secureVipAddress>
<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1563691948498</lastUpdatedTimestamp>
<lastDirtyTimestamp>1563691948494</lastDirtyTimestamp>
<actionType>ADDED</actionType>
</instance>
</application>
</applications>
- 根据
appID
查询应用实例
GET http://localhost:8761/eureka/apps/EUREKA-CLIENT
<application>
<name>EUREKA-CLIENT</name>
<instance>
<instanceId>host.docker.internal:eureka-client:8080</instanceId>
<hostName>host.docker.internal</hostName>
<app>EUREKA-CLIENT</app>
<ipAddr>192.168.0.102</ipAddr>
<status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="true">8080</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<leaseInfo>
<renewalIntervalInSecs>30</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1563691948498</registrationTimestamp>
<lastRenewalTimestamp>1563693478678</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1563691948498</serviceUpTimestamp>
</leaseInfo>
<metadata>
<management.port>8080</management.port>
</metadata>
<homePageUrl>http://host.docker.internal:8080/</homePageUrl>
<statusPageUrl>http://host.docker.internal:8080/actuator/info</statusPageUrl>
<healthCheckUrl>http://host.docker.internal:8080/actuator/health</healthCheckUrl>
<vipAddress>eureka-client</vipAddress>
<secureVipAddress>eureka-client</secureVipAddress>
<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1563691948498</lastUpdatedTimestamp>
<lastDirtyTimestamp>1563691948494</lastDirtyTimestamp>
<actionType>ADDED</actionType>
</instance>
</application>
- 根据
appID
和instanceID
查询应用实例
GET http://localhost:8761/eureka/apps/EUREKA-CLIENT/host.docker.internal:eureka-client:8080
<instance>
<instanceId>host.docker.internal:eureka-client:8080</instanceId>
<hostName>host.docker.internal</hostName>
<app>EUREKA-CLIENT</app>
<ipAddr>192.168.0.102</ipAddr>
<status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="true">8080</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<leaseInfo>
<renewalIntervalInSecs>30</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1563691948498</registrationTimestamp>
<lastRenewalTimestamp>1563693568690</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1563691948498</serviceUpTimestamp>
</leaseInfo>
<metadata>
<management.port>8080</management.port>
</metadata>
<homePageUrl>http://host.docker.internal:8080/</homePageUrl>
<statusPageUrl>http://host.docker.internal:8080/actuator/info</statusPageUrl>
<healthCheckUrl>http://host.docker.internal:8080/actuator/health</healthCheckUrl>
<vipAddress>eureka-client</vipAddress>
<secureVipAddress>eureka-client</secureVipAddress>
<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1563691948498</lastUpdatedTimestamp>
<lastDirtyTimestamp>1563691948494</lastDirtyTimestamp>
<actionType>ADDED</actionType>
</instance>
- 根据instanceID查询应用实例
GET http://localhost:8761/eureka/instances/host.docker.internal:eureka-client:8080
<instance>
<instanceId>host.docker.internal:eureka-client:8080</instanceId>
<hostName>host.docker.internal</hostName>
<app>EUREKA-CLIENT</app>
<ipAddr>192.168.0.102</ipAddr>
<status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="true">8080</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<leaseInfo>
<renewalIntervalInSecs>30</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1563691948498</registrationTimestamp>
<lastRenewalTimestamp>1563693688705</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1563691948498</serviceUpTimestamp>
</leaseInfo>
<metadata>
<management.port>8080</management.port>
</metadata>
<homePageUrl>http://host.docker.internal:8080/</homePageUrl>
<statusPageUrl>http://host.docker.internal:8080/actuator/info</statusPageUrl>
<healthCheckUrl>http://host.docker.internal:8080/actuator/health</healthCheckUrl>
<vipAddress>eureka-client</vipAddress>
<secureVipAddress>eureka-client</secureVipAddress>
<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1563691948498</lastUpdatedTimestamp>
<lastDirtyTimestamp>1563691948494</lastDirtyTimestamp>
<actionType>ADDED</actionType>
</instance>
- 注册新的应用实例
POST http://localhost:8761/eureka/apps/DEMO-CLIENT
<instance>
<instanceId>demo-client:8081</instanceId>
<hostName>127.0.0.1</hostName>
<app>DEMO-CLIENT</app>
<ipAddr>127.0.0.1</ipAddr>
<status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="true">11101</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<metadata class="java.util.Collections$EmptyMap"/>
<vipAddress>demo-client</vipAddress>
<secureVipAddress>demo-client</secureVipAddress>
<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1563693897000</lastUpdatedTimestamp>
<lastDirtyTimestamp>1563693897000</lastDirtyTimestamp>
</instance>
正常响应状态码204,代表注册成功,刷新下本地Eureka Serve服务,看到服务DEMO-CLIENT正常被注册。
- 注销应用实例
DELETE http://localhost:8761/eureka/apps/DEMO-CLIENT/demo-client:8081
正常响应状态码200,代表上面刚注册的DEMO-CLIENT被成功注销,刷新下本地Eureka Serve服务,看到服务DEMO-CLIENT已经消失不见。
- 暂停服务实例
PUT http://localhost:8761/eureka/apps/EUREKA-CLIENT/host.docker.internal:eureka-client:8080/status?value=OUT_OF_SERVICE
正常响应状态码200,刷新Eureka Service的页面可以看到服务EUREKA-CLIENT在状态栏已经标记了一行红字OUT_OF_SERVICE (1)
,代表当前服务不可用。
- 恢复应用实例
DELETE http://localhost:8761/eureka/apps/EUREKA-CLIENT/host.docker.internal:eureka-client:8080/status?value=UP
正常响应状态码200,刷新Eureka Service的页面可以看到服务EUREKA-CLIENT的服务状态已经恢复正常。
- 向应用实例发送心跳检测
PUT http://localhost:8761/eureka/apps/EUREKA-CLIENT/host.docker.internal:eureka-client:8080
正常响应状态码200
- 更新元数据
PUT http://localhost:8761/eureka/apps/EUREKA-CLIENT/host.docker.internal:eureka-client:8080/metadata?test=clientA
设置metadata元数据,其中key为test,value为clientA
- 根据vip地址查询所有应用实例
GET http://localhost:8761/eureka/vips/eureka-client
<applications>
<versions__delta>-1</versions__delta>
<apps__hashcode>UP_1_</apps__hashcode>
<application>
<name>EUREKA-CLIENT</name>
<instance>
<instanceId>host.docker.internal:eureka-client:8080</instanceId>
<hostName>host.docker.internal</hostName>
<app>EUREKA-CLIENT</app>
<ipAddr>192.168.0.102</ipAddr>
<status>UP</status>
<overriddenstatus>UP</overriddenstatus>
<port enabled="true">8080</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<leaseInfo>
<renewalIntervalInSecs>30</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1563694776499</registrationTimestamp>
<lastRenewalTimestamp>1563694948849</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1563691948498</serviceUpTimestamp>
</leaseInfo>
<metadata>
<test>clientA</test>
<management.port>8080</management.port>
</metadata>
<homePageUrl>http://host.docker.internal:8080/</homePageUrl>
<statusPageUrl>http://host.docker.internal:8080/actuator/info</statusPageUrl>
<healthCheckUrl>http://host.docker.internal:8080/actuator/health</healthCheckUrl>
<vipAddress>eureka-client</vipAddress>
<secureVipAddress>eureka-client</secureVipAddress>
<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1563694776499</lastUpdatedTimestamp>
<lastDirtyTimestamp>1563691948494</lastDirtyTimestamp>
<actionType>ADDED</actionType>
</instance>
</application>
</applications>
- 根据svip地址查询所有应用实例
GET http://localhost:8761/eureka/svips/eureka-client
<applications>
<versions__delta>-1</versions__delta>
<apps__hashcode>UP_1_</apps__hashcode>
<application>
<name>EUREKA-CLIENT</name>
<instance>
<instanceId>host.docker.internal:eureka-client:8080</instanceId>
<hostName>host.docker.internal</hostName>
<app>EUREKA-CLIENT</app>
<ipAddr>192.168.0.102</ipAddr>
<status>UP</status>
<overriddenstatus>UP</overriddenstatus>
<port enabled="true">8080</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<leaseInfo>
<renewalIntervalInSecs>30</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1563694776499</registrationTimestamp>
<lastRenewalTimestamp>1563695038861</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1563691948498</serviceUpTimestamp>
</leaseInfo>
<metadata>
<test>clientA</test>
<management.port>8080</management.port>
</metadata>
<homePageUrl>http://host.docker.internal:8080/</homePageUrl>
<statusPageUrl>http://host.docker.internal:8080/actuator/info</statusPageUrl>
<healthCheckUrl>http://host.docker.internal:8080/actuator/health</healthCheckUrl>
<vipAddress>eureka-client</vipAddress>
<secureVipAddress>eureka-client</secureVipAddress>
<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1563694776499</lastUpdatedTimestamp>
<lastDirtyTimestamp>1563691948494</lastDirtyTimestamp>
<actionType>ADDED</actionType>
</instance>
</application>
</applications>