从REST和Instance角度理解Netfix Eureka

前言

最近项目开始使用到spring cloud作为项目的微服架构,在开发中遇
到很多问题,相信很多多人也遇到,写这篇博客也是谈谈我关于spring cloud中的eureka的一些认识,当中有误的地方还请各位留言指出,多多交流。

首先看看官方对eureka的定义

Eureka是一个基于REST(Representational State Transfer)服务,主要是用于云服务为目的的中间层服务器的负载平衡和故障转移。Eureka还附带了一个基于java的客户端组件,Eureka客户机使得交互与服务更加容易。客户端也有一个基于循环负载平衡内置的负载均衡器。当然在Netflix中,还提供很多更加能满足复杂要求的负载均衡器,它们基于交通、资源使用、错误条件等因素提供更好的弹性。

这个我根据官方的介绍翻译的原文链接在这https://github.com/Netflix/eureka/wiki/Eureka-at-a-glance/当中有翻译不对的还请留言指出。

从官方的文档中我们能得到这些重要的信息:

  1. Eureka是基于REST服务的,也就意味着它是基于http协议的
  2. 它分为服务端(java语言实现)和 客服端(可以是java也可以是非Java语言,因为Eureka提供的是 rest服务,当然官方也有提供部分其他语言的官方包)。
  3. Eureka的作用是实现为服务间的负载均衡和故障转移。
Eureka的服务端和客服端

Eureka的服务端来管理所有的微服,微服内的所有服务需要依赖Eureka客户端的依赖包,并在application上添加@EnableEurekaClient注解来实现Eureka客户端。

<dependency>
  <groupId>com.netflix.eureka</groupId>
  <artifactId>eureka-client</artifactId>
  <version>1.1.16</version>
</dependency>

@EnableEurekaClient
public class ServiceHiApplication {

public static void main(String[] args) {
    SpringApplication.run(ServiceHiApplication.class, args);
}

}

当然还有配置文件需要添加相关的配置,具体的可以参考官方文档https://github.com/Netflix/eureka/wiki/Configuring-Eureka/
,现在网上也有很多相关的博客,这里我就不详细写了。

Eureka的客服端则是通过rest服务通知Eureka的服务端该客服端的健康状况,事实是每个客服端的具体信息保存在InstanceInfo类中,通过ConcurrentHashMap<String, Map<String,Lease<InstanceInfo>>>
的双层Map结构来管理所有的的客服端。更重要的是其实在每个客服端在以心跳的模式定时通知服务端客户端的实时状态时,客户端也会获得到一份最新的服务端的InstanceInfo列表清单,没错其实每个客服端也能获得微服的所有客服端的健康状况。具体客服端获得服务信息的方法如下:

@Qualifier("eurekaClient")
@Autowired
private EurekaClient eurekaClient;

public String  serviceUrl(){
    InstanceInfo instance = eurekaClient.getNextServerFromEureka("service-hi", false);
    return instance.getHomePageUrl();
}

@Autowired
private DiscoveryClient discoveryClient;
//获得对应服务名下所有的服务实力信息列表,服务如果有做集群,则返回的是该服务集群下的所有实力的列表
List<ServiceInstance> list = discoveryClient.getInstances("service-hi");
if (list != null && list.size() > 0 ) {
    String aa = list.get(0).getUri().getAuthority();
}
    
//获得微服下所有的服务名
List<String> servicesNames = discoveryClient.getServices();
StringBuilder sb = new StringBuilder();
for (String s:servicesNames) {
    sb.append(s+"\t");
}
Eureka的REST服务

上面说过服务端和客户端是通过rest服务实现通信的,也就是说如果我现在想知道服务端下所有客服端的具体信息和健康状况只需要通过一个http请求就可以完成,答案是肯定的,当然本身eureka服务本身就提供了管理界面来查看客户端的具体信息如下:


image

但是这样获得的信息并不完全,所有如果你想获得更加详细的信息,或则你想使用其他编程语言实现客服端的话可以通过Eureka服务提供的接口文档实现注册、取消注册、更新、获得所有InstanceInfo信息等操作,文档如下:

操作 接口地址 描述
注册服务 POST /eureka/v2/apps/appID Input: JSON/XML payload HTTP Code: 204 on success
取消服务注册 DELETE /eureka/v2/apps/appID/instanceID HTTP Code: 200 on success
发送一个服务的心跳 PUT /eureka/v2/apps/appID/instanceID HTTP Code: 200 on success 404 if instanceID doesn’t exist
查询所有服务信息 GET /eureka/v2/apps HTTP Code: 200 on success Output: JSON/XML
查询所有服务的服务id GET /eureka/v2/apps/appID HTTP Code: 200 on success Output: JSON/XML
根据具体服务id查询服务信息 GET /eureka/v2/apps/appID/instanceID HTTP Code: 200 on success Output: JSON/XML
对于一个具体的实例查询 GET /eureka/v2/instances/instanceID HTTP Code: 200 on success Output: JSON/XML
停止实力服务 PUT /eureka/v2/apps/appID/instanceID/status?value=OUT_OF_SERVICE HTTP Code: 200 on success 500 on failure
把实例重新放入服务中 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
更新 metadata中的数据 PUT /eureka/v2/apps/appID/instanceID/metadata?key=value HTTP Code: 200 on success 500 on failure
查询特定vipaddress地址下的所有实例 GET /eureka/v2/vips/vipAddress HTTP Code: 200 on success Output: JSON/XML 404 if the vipAddress does not exist.
查询特定安全vipaddress下的所有实例 GET /eureka/v2/svips/svipAddress HTTP Code: 200 on success Output: JSON/XML 404 if the svipAddress does not exist.

官方文档的链接在这:https://github.com/Netflix/eureka/wiki/Eureka-REST-operations/
已获取所有InstanceInfo列表信息为例,我在postman上的请求结果如下:

<applications>
<versions__delta>1</versions__delta>
<apps__hashcode>UP_3_</apps__hashcode>
<application>
    <name>SERVICE-HI-APPNAME 8763</name>
    <instance>
        <instanceId>service-hi</instanceId>
        <hostName>DESKTOP-CKLCJ5F</hostName>
        <app>SERVICE-HI-APPNAME 8763</app>
        <ipAddr>192.168.1.8</ipAddr>
        <status>UP</status>
        <overriddenstatus>UNKNOWN</overriddenstatus>
        <port enabled="true">8763</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>1510988885998</registrationTimestamp>
            <lastRenewalTimestamp>1511102494467</lastRenewalTimestamp>
            <evictionTimestamp>0</evictionTimestamp>
            <serviceUpTimestamp>1510988822454</serviceUpTimestamp>
        </leaseInfo>
        <metadata>
            <testkey4>testValue4</testkey4>
            <testkey3>testValue3</testkey3>
            <testkey2>testValue2</testkey2>
            <testkey1>testValue1</testkey1>
        </metadata>
        <homePageUrl>http://DESKTOP-CKLCJ5F:8763/</homePageUrl>
        <statusPageUrl>http://DESKTOP-CKLCJ5F:8763/info</statusPageUrl>
        <healthCheckUrl>http://DESKTOP-CKLCJ5F:8763/health</healthCheckUrl>
        <vipAddress>service-hi</vipAddress>
        <secureVipAddress>service-hi</secureVipAddress>
        <isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
        <lastUpdatedTimestamp>1510988885998</lastUpdatedTimestamp>
        <lastDirtyTimestamp>1510988885942</lastDirtyTimestamp>
        <actionType>ADDED</actionType>
    </instance>
</application>
<application>
    <name>SERVICE-RIBBON</name>
    <instance>
        <instanceId>DESKTOP-CKLCJ5F:service-ribbon:8764</instanceId>
        <hostName>DESKTOP-CKLCJ5F</hostName>
        <app>SERVICE-RIBBON</app>
        <ipAddr>192.168.1.8</ipAddr>
        <status>UP</status>
        <overriddenstatus>UNKNOWN</overriddenstatus>
        <port enabled="true">8764</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>1510993263471</registrationTimestamp>
            <lastRenewalTimestamp>1511102494632</lastRenewalTimestamp>
            <evictionTimestamp>0</evictionTimestamp>
            <serviceUpTimestamp>1510988934957</serviceUpTimestamp>
        </leaseInfo>
        <metadata class="java.util.Collections$EmptyMap"/>
        <homePageUrl>http://DESKTOP-CKLCJ5F:8764/</homePageUrl>
        <statusPageUrl>http://DESKTOP-CKLCJ5F:8764/info</statusPageUrl>
        <healthCheckUrl>http://DESKTOP-CKLCJ5F:8764/health</healthCheckUrl>
        <vipAddress>service-ribbon</vipAddress>
        <secureVipAddress>service-ribbon</secureVipAddress>
        <isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
        <lastUpdatedTimestamp>1510993263471</lastUpdatedTimestamp>
        <lastDirtyTimestamp>1510993263422</lastDirtyTimestamp>
        <actionType>ADDED</actionType>
    </instance>
</application>
<application>
    <name>SERVICE-HI-APPNAME 8765</name>
    <instance>
        <instanceId>service-hi</instanceId>
        <hostName>DESKTOP-CKLCJ5F</hostName>
        <app>SERVICE-HI-APPNAME 8765</app>
        <ipAddr>192.168.1.8</ipAddr>
        <status>UP</status>
        <overriddenstatus>UNKNOWN</overriddenstatus>
        <port enabled="true">8765</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>1511100242138</registrationTimestamp>
            <lastRenewalTimestamp>1511102492656</lastRenewalTimestamp>
            <evictionTimestamp>0</evictionTimestamp>
            <serviceUpTimestamp>1511100242138</serviceUpTimestamp>
        </leaseInfo>
        <metadata>
            <testkey4>testValue4</testkey4>
            <testkey3>testValue3</testkey3>
            <testkey2>testValue2</testkey2>
            <testkey1>testValue1</testkey1>
        </metadata>
        <homePageUrl>http://DESKTOP-CKLCJ5F:8765/</homePageUrl>
        <statusPageUrl>http://DESKTOP-CKLCJ5F:8765/info</statusPageUrl>
        <healthCheckUrl>http://DESKTOP-CKLCJ5F:8765/health</healthCheckUrl>
        <vipAddress>service-hi</vipAddress>
        <secureVipAddress>service-hi</secureVipAddress>
        <isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
        <lastUpdatedTimestamp>1511100242138</lastUpdatedTimestamp>
        <lastDirtyTimestamp>1511100242050</lastDirtyTimestamp>
        <actionType>ADDED</actionType>
    </instance>
</application>
</applications>

上面的信息更加详细,如IP地址、服务的健康状况、instanceId、hostName等信息都可以查到,方便我们在开发中发现问题。

总结

相信讲到这大家对Eureka是如何管理微服务已经有了一定的认识,管理Eureka下的服务其实是管理每个InstanceInfo,而负载均衡,错误故障转移都是基于每个InstanceInfo实现的。后面我会单独对InstanceInfo做更具体的讲解,欢迎大家评论。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容