Eureka文档翻译(下)

REST接口

下面的REST接口让非Java应用也可以使用Eureka。 appID:应用名 instanceID:实例的唯一ID(AWS中是实例的id,在其他环节是实例的hostname)。JSON、XML协议分别应使用对应的Content-type:application/json、application/xml。



































































Operation HTTP action Description
Register new application instance POST /eureka/v2/apps/appID Input: JSON/XML payload HTTP Code: 204 on success
De-register application instance DELETE /eureka/v2/apps/appID/instanceID HTTP Code: 200 on success
Send application instance heartbeat PUT /eureka/v2/apps/appID/instanceID HTTP Code:
200 on success 404 if instanceID doesn’t exist
Query for all instances GET /eureka/v2/apps HTTP Code: 200 on success Output: JSON/XML
Query for all appID instances GET /eureka/v2/apps/appID HTTP Code: 200 on success Output: JSON/XML
Query for a specific appID/instanceID GET /eureka/v2/apps/appID/instanceID HTTP Code: 200 on success Output: JSON/XML
Query for a specific instanceID GET /eureka/v2/instances/instanceID HTTP Code: 200 on success Output: JSON/XML
Take instance out of service PUT /eureka/v2/apps/appID/instanceID/status?value=OUT_OF_SERVICE HTTP Code:
200 on success 500 on failure
Put instance back into service (remove override) DELETE /eureka/v2/apps/appID/instanceID/status?value=UP (The value=UP is optional, it is used as a suggestion for the fallback status due to removal of the override) HTTP Code:
200 on success 500 on failure
Update metadata PUT /eureka/v2/apps/appID/instanceID/metadata?key=value HTTP Code:
200 on success 500 on failure
Query for all instances under a particular vip address GET /eureka/v2/vips/vipAddress HTTP Code: 200 on success Output: JSON/XML 404 if the vipAddress does not exist.
Query for all instances under a particular secure vip address GET /eureka/v2/svips/svipAddress HTTP Code: 200 on success Output: JSON/XML 404 if the svipAddress does not exist.

注册

注册时,你需要发送一个符合下面XSD的XML(或JSON)的包体。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xsd:element name="instance">
<xsd:complexType>
<xsd:all>
<!-- hostName in ec2 should be the public dns name, within ec2 public dns name will
always resolve to its private IP -->
<xsd:element name="hostName" type="xsd:string" />
<xsd:element name="app" type="xsd:string" />
<xsd:element name="ipAddr" type="xsd:string" />
<xsd:element name="vipAddress" type="xsd:string" />
<xsd:element name="secureVipAddress" type="xsd:string" />
<xsd:element name="status" type="statusType" />
<xsd:element name="port" type="xsd:positiveInteger" minOccurs="0" />
<xsd:element name="securePort" type="xsd:positiveInteger" />
<xsd:element name="homePageUrl" type="xsd:string" />
<xsd:element name="statusPageUrl" type="xsd:string" />
<xsd:element name="healthCheckUrl" type="xsd:string" />
<xsd:element ref="dataCenterInfo" minOccurs="1" maxOccurs="1" />
<!-- optional -->
<xsd:element ref="leaseInfo" minOccurs="0"/>
<!-- optional app specific metadata -->
<xsd:element name="metadata" type="appMetadataType" minOccurs="0" />
</xsd:all>
</xsd:complexType>
</xsd:element>
<xsd:element name="dataCenterInfo">
<xsd:complexType>
<xsd:all>
<xsd:element name="name" type="dcNameType" />
<!-- metadata is only required if name is Amazon -->
<xsd:element name="metadata" type="amazonMetdataType" minOccurs="0"/>
</xsd:all>
</xsd:complexType>
</xsd:element>
<xsd:element name="leaseInfo">
<xsd:complexType>
<xsd:all>
<!-- (optional) if you want to change the length of lease - default if 90 secs -->
<xsd:element name="evictionDurationInSecs" minOccurs="0" type="xsd:positiveInteger"/>
</xsd:all>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="dcNameType">
<!-- Restricting the values to a set of value using 'enumeration' -->
<xsd:restriction base = "xsd:string">
<xsd:enumeration value = "MyOwn"/>
<xsd:enumeration value = "Amazon"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="statusType">
<!-- Restricting the values to a set of value using 'enumeration' -->
<xsd:restriction base = "xsd:string">
<xsd:enumeration value = "UP"/>
<xsd:enumeration value = "DOWN"/>
<xsd:enumeration value = "STARTING"/>
<xsd:enumeration value = "OUT_OF_SERVICE"/>
<xsd:enumeration value = "UNKNOWN"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="amazonMetdataType">
<!-- From <a class="jive-link-external-small" href="http://docs.amazonwebservices.com/AWSEC2/latest/DeveloperGuide/index.html?AESDG-chapter-instancedata.html" target="_blank">http://docs.amazonwebservices.com/AWSEC2/latest/DeveloperGuide/index.html?AESDG-chapter-instancedata.html</a> -->
<xsd:all>
<xsd:element name="ami-launch-index" type="xsd:string" />
<xsd:element name="local-hostname" type="xsd:string" />
<xsd:element name="availability-zone" type="xsd:string" />
<xsd:element name="instance-id" type="xsd:string" />
<xsd:element name="public-ipv4" type="xsd:string" />
<xsd:element name="public-hostname" type="xsd:string" />
<xsd:element name="ami-manifest-path" type="xsd:string" />
<xsd:element name="local-ipv4" type="xsd:string" />
<xsd:element name="hostname" type="xsd:string"/>
<xsd:element name="ami-id" type="xsd:string" />
<xsd:element name="instance-type" type="xsd:string" />
</xsd:all>
</xsd:complexType>
<xsd:complexType name="appMetadataType">
<xsd:sequence>
<!-- this is optional application specific name, value metadata -->
<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="skip"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

心跳

Request: PUT /eureka/v2/apps/MYAPP/i-6589ef6
Response:
 Status: 200 (on success)
 404 (eureka doesn’t know about you, Register yourself first)
 500 (failure)

注销

如果Eureka在指定时间内没有收到节点的心跳包,则节点会被自动注销
Request: DELETE /eureka/v2/apps/MYAPP/i-6589ef6
Response:
 Status: 200 (on success)
 500 (failure)

节点互通

Eureka Client优先尝试与同分区内的Server节点通信,如果失败,则尝试其他分区。

一旦节点开始提供服务,节点上所有的操作信息都会被复制到互通的其他节点上。如果某个操作失败了,下一个心跳需要同步的信息也会被复制到其他节点。

当一个Server节点启动时,会尝试从相邻节点获取所有实例的注册信息。如果获取失败,或挨个尝试所有其他节点直到失败。如果获取成功,他会根据拿到的信息设置好心跳间隔。任何时候,如果心跳失败比例低于配置值(15分钟内低于85%),Eureka Server会保证该实例的注册信息不会过期。

在Netflix,上述保护措施被称为自我保护模式,主要用于保护Client集群与Server之间网络不稳定的情况。在这种情况下,Server会尽量保护已经注册的信息。但是在有大量连接中断的情况下,可能会导致Client拿到已经不存在的服务实例。Client必须保证对Eureka Server返回的无效或不存在的实例有容错能力。这种情况下,最好的保护措施是快速超时并重试其他服务器。

当一个Server节点不能从相邻节点中获得注册信息时,它会等待几分钟(约5分钟)让客户端可以注册上来。Server会尽量保证不会只提供部分实例的信息,以免造成负载不均衡的问题。

Eureka Server节点之间的互通与Server和Client之间的互通一样。

针对Server节点之间的通信也有一些值得注意的配置项

当节点之间网络中断时发生了什么?

当发生节点之间的网络中断时,可能出现如下情况:

  • 节点之间的心跳失败,Server进入自我保护模式(self-preservation)保护当前状态。
  • 注册操作可能发生在某个孤立的Server上,导致部分客户端可以拿到新的注册信息,部分拿不到。
  • 当网络恢复到稳定状态后,状态会自我修复到正确状态。一旦节点之间可以互通,注册信息会自动完成节点之间的同步。

原则是,当发生网络中断时,Eureka Server会尽可能保持可用可恢复状态,但在这期间客户端拿到信息可能不同。

修改默认配置

Eureka的默认配置适用于大部分情况,但是如果你想修改默认配置,这里有3种配置方式可以参考。

你可以继承下面的默认配置类来实现自定义的配置。

Important:不要使用interfaces,它们只是作为文档使用,并且将来可能被修改。

注意以上内容同时作为(即)Eureka中配置默认值的文档说明。

在注册信息中增加自定义数据

有时候你可能想要在注册信息中增加一些自定义的信息用于环境部署。例如,你可能想要传递一个特定环境需要用到的自定义environment id。Eureka提供了增加标准注册数据以外的自定义KV数据的能力,有两种方法:

获取数据

1
String myValue = instanceInfo.getMetadata().get("myKey");

第一种:静态配置

所有eureka.metadata.mykey=myvalue的KV数据都会被添加到注册数据中。

第二种:动态代码

首先你需要根据需求自己实现EurekaInstanceConfig接口,然后重载public Map<String, String> getMetadataMap()方法来返回你想要的数据。可以参考PropertiesInstanceConfig的实现。

FAQ

当节点之间网络中断时发生了什么?

当发生节点之间的网络中断时,可能出现如下情况:

  • 节点之间的心跳失败,Server进入自我保护模式(self-preservation)保护当前状态。
  • 注册操作可能发生在某个孤立的Server上,导致部分客户端可以拿到新的注册信息,部分拿不到。
  • 当网络恢复到稳定状态后,状态会自我修复到正确状态。一旦节点之间可以互通,注册信息会自动完成节点之间的同步。

原则是,当发生网络中断时,Eureka Server会尽可能保持可用可恢复状态,但在这期间客户端拿到信息可能不同。

为什么不用HA proxy做负载均衡?

由于AWS固有的原因,实例总会频繁出现上下线。ASG可以根据流量来扩展或撤下实例。假如你使用HAProxy,就需要知道如何自己处理对这种动态。而这恰恰是Eureka所做的事。

有一种情况,当需要作为有状态中间件的代理时,可以用HAProxy配合Eureka使用。但是通常情况下我们的中间件服务是无状态的,所以没有理由在多增加网络一跳情况下来使用这个proxy。还有一个原因是Eureka Client会缓存拿到的注册表信息,使得系统更有弹性。而使用HAProxy就会有这个不足,系统没有自恢复能力。

为什么不用Curator/Zookeeper做服务注册?

Zookeeper和Eureka确实提供了某些有共同的功能,特别是在复制注册信息这点上。Eureka也可以用Zookeeper做注册信息缓存和同步,但这仅仅是Eureka提供的其中一小部分功能。

Eureka还提供了信息同步以外的许多功能:

  • 提供注册、心跳、注销操作等的REST接口。
  • 在负载的弹性IP绑定环境中,保持信息及时更新,以及部署回滚,自动扩展和自恢复能力等。
  • 针对网络不稳定情况的容灾能力和自恢复能力。

Zookeeper的强大之处在于它的leader election(选举),ordered updates,distributed synchronization along with its consistency guarantees (保证分布式的一致性)。

除了注册表复制以外,其他特性都不适用解决如下问题:

  • 需要找到一个方法像Eureka一样来为zookeeper分配弹性IP。
  • 处理当Zookeeper失效的情况。

另外,Eureka设计中特别注意不去强依赖第三方组件。

  • 大部分服务依赖Eureka启动
  • 降低复杂度
  • 避免出现另一个故障点