所有文章

https://www.cnblogs.com/lay2017/p/11908715.html

正文

eureka服务端维护了一个服务信息的列表,服务端节点之间相互复制服务信息。而作为eureka的客户端将会从eureka服务端请求这个服务信息列表,选择对应的实例。本文就来看看eureka服务端对客户端提供的获取服务信息列表的http接口。

eureka服务端基于jersey来提供http服务调用,所以我们先找到它的Resource。

ApplicationsResource

  1. @GET
  2. public Response getContainers(@PathParam("version") String version,
  3. @HeaderParam(HEADER_ACCEPT) String acceptHeader,
  4. @HeaderParam(HEADER_ACCEPT_ENCODING) String acceptEncoding,
  5. @HeaderParam(EurekaAccept.HTTP_X_EUREKA_ACCEPT) String eurekaAccept,
  6. @Context UriInfo uriInfo,
  7. @Nullable @QueryParam("regions") String regionsStr) {
  8.  
  9. // ...
  10.  
  11. Key cacheKey = new Key(Key.EntityType.Application,
  12. ResponseCacheImpl.ALL_APPS,
  13. keyType, CurrentRequestVersion.get(), EurekaAccept.fromString(eurekaAccept), regions
  14. );
  15.  
  16. Response response;
  17. if (acceptEncoding != null && acceptEncoding.contains(HEADER_GZIP_VALUE)) {
  18. response = Response.ok(responseCache.getGZIP(cacheKey))
  19. .header(HEADER_CONTENT_ENCODING, HEADER_GZIP_VALUE)
  20. .header(HEADER_CONTENT_TYPE, returnMediaType)
  21. .build();
  22. } else {
  23. response = Response.ok(responseCache.get(cacheKey))
  24. .build();
  25. }
  26. return response;
  27. }

这里从responseCache当中获取了Applications的序列号结果直接返回了,所以我们先看看ResponseCache是从哪里来的

可以看到ResponseCache是再ApplicationsResource构造的时候从Registry中获取的

  1. @Inject
  2. ApplicationsResource(EurekaServerContext eurekaServer) {
  3. this.serverConfig = eurekaServer.getServerConfig();
  4. this.registry = eurekaServer.getRegistry();
  5. this.responseCache = registry.getResponseCache();
  6. }

我们再看看ResponseCache的get方法做了什么

  1. String get(final Key key, boolean useReadOnlyCache) {
  2. Value payload = getValue(key, useReadOnlyCache);
  3. if (payload == null || payload.getPayload().equals(EMPTY_PAYLOAD)) {
  4. return null;
  5. } else {
  6. return payload.getPayload();
  7. }
  8. }

继续跟进getValue

  1. Value getValue(final Key key, boolean useReadOnlyCache) {
  2. Value payload = null;
  3. try {
  4. if (useReadOnlyCache) {
  5. final Value currentPayload = readOnlyCacheMap.get(key);
  6. if (currentPayload != null) {
  7. payload = currentPayload;
  8. } else {
  9. payload = readWriteCacheMap.get(key);
  10. readOnlyCacheMap.put(key, payload);
  11. }
  12. } else {
  13. payload = readWriteCacheMap.get(key);
  14. }
  15. } catch (Throwable t) {
  16. logger.error("Cannot get value for key : {}", key, t);
  17. }
  18. return payload;
  19. }

可以看到,其实只是从ReadWriteCacheMap当中获取对应的值,那么我们再看看ReadWriteCacheMap是怎么被构造的

  1. this.readWriteCacheMap = CacheBuilder.newBuilder().initialCapacity(serverConfig.getInitialCapacityOfResponseCache())
  2. .expireAfterWrite(serverConfig.getResponseCacheAutoExpirationInSeconds(), TimeUnit.SECONDS)
  3. .removalListener(new RemovalListener<Key, Value>() {
  4. @Override
  5. public void onRemoval(RemovalNotification<Key, Value> notification) {
  6. Key removedKey = notification.getKey();
  7. if (removedKey.hasRegions()) {
  8. Key cloneWithNoRegions = removedKey.cloneWithoutRegions();
  9. regionSpecificKeys.remove(cloneWithNoRegions, removedKey);
  10. }
  11. }
  12. })
  13. .build(new CacheLoader<Key, Value>() {
  14. @Override
  15. public Value load(Key key) throws Exception {
  16. if (key.hasRegions()) {
  17. Key cloneWithNoRegions = key.cloneWithoutRegions();
  18. regionSpecificKeys.put(cloneWithNoRegions, key);
  19. }
  20. Value value = generatePayload(key);
  21. return value;
  22. }
  23. });

从这里可以看出,调用ReadWriteCacheMap的get方法,将会触发这里的generatePayload方法

我们跟进generatePayload

  1. private Value generatePayload(Key key) {
  2. Stopwatch tracer = null;
  3. try {
  4. String payload;
  5. switch (key.getEntityType()) {
  6. case Application:
  7. boolean isRemoteRegionRequested = key.hasRegions();
  8. // 获取所有Application
  9. if (ALL_APPS.equals(key.getName())) {
  10. if (isRemoteRegionRequested) {
  11. tracer = serializeAllAppsWithRemoteRegionTimer.start();
  12. payload = getPayLoad(key, registry.getApplicationsFromMultipleRegions(key.getRegions()));
  13. } else {
  14. tracer = serializeAllAppsTimer.start();
  15. payload = getPayLoad(key, registry.getApplications());
  16. }
  17. } else if (ALL_APPS_DELTA.equals(key.getName())) {
  18. // ...
  19. } else {
  20. tracer = serializeOneApptimer.start();
  21. // 获取某个Application
  22. payload = getPayLoad(key, registry.getApplication(key.getName()));
  23. }
  24. break;
  25. // ...
  26. }
  27. return new Value(payload);
  28. } finally {
  29.  
  30. }
  31. }

我们看到这里payload主要构成元素是Application,也就是我们需要的服务列表信息。

最后,我们跟进getPayLoad方法,看看这些服务列表信息是怎么被序列号成payload的

  1. private String getPayLoad(Key key, Applications apps) {
  2. EncoderWrapper encoderWrapper = serverCodecs.getEncoder(key.getType(), key.getEurekaAccept());
  3. String result;
  4. try {
  5. result = encoderWrapper.encode(apps);
  6. } catch (Exception e) {
  7. return "";
  8. }
  9. return result;
  10. }

编码器的实现比较多种,这里就不展开了

总结

获取服务信息列表其实就是从registry当中获取Applications,然后做一次序列化,最后通过http响应回去。总体来说还是比较简单的。

三、eureka服务端获取服务列表的更多相关文章

  1. springcloud(三):Eureka服务端

    一. 因为使用一个注册中心服务器端,n个客户端:n个生产者客户端.n消费者客户端....,所有的客户端最好的方式就是通过对象传递参数,因此需要创建一个公共组件项目,为n个客户端传值提供方便 二.创建公 ...

  2. SpringCloud02 Eureka知识点、Eureka服务端和客户端的创建、Eureka服务端集群、Eureka客户端向集群的Eureka服务端注册

    1 Eureka知识点 按照功能划分: Eureka由Eureka服务端和Eureka客户端组成 按照角色划分: Eureka由Eureka Server.Service Provider.Servi ...

  3. eureka服务端和客户端的简单搭建

    本篇博客简单记录一下,eureka 服务端和 客户端的简单搭建. 目标: 1.完成单机 eureka server 和 eureka client 的搭建. 2.完成eureka server 的添加 ...

  4. ftpget 从Windows FTP服务端获取文件

    /********************************************************************************* * ftpget 从Windows ...

  5. Spring Cloud官方文档中文版-服务发现:Eureka服务端

    官方文档地址为:http://cloud.spring.io/spring-cloud-static/Dalston.SR3/#spring-cloud-eureka-server 文中例子我做了一些 ...

  6. SpringCloud系列四:Eureka 服务发现框架(定义 Eureka 服务端、Eureka 服务信息、Eureka 发现管理、Eureka 安全配置、Eureka-HA(高可用) 机制、Eureka 服务打包部署)

    1.概念:Eureka 服务发现框架 2.具体内容 对于服务发现框架可以简单的理解为服务的注册以及使用操作步骤,例如:在 ZooKeeper 组件,这个组件里面已经明确的描述了一个服务的注册以及发现操 ...

  7. eureka服务端的高可用

    eureka client的高可用这个很简单,只需要向eureka服务端上多注册几个实例即可,那么eureka server端如何实现高可用呢?其实eureka server 端也是可以做为一个客户端 ...

  8. IE8下服务端获取客户端文件的路径为C:/fakePath问题的解决方案

    上一篇文章上提到,IE8下服务端获取客户端文件的路径时,会变成C:/fakePath问题,于是乎通过文件路径去获得文件大小就失败了. 上网搜了一下,主要原因是IE8因为安全考虑,在上传文件时屏蔽了真实 ...

  9. Android从服务端获取json解析显示在客户端上面

    Android从服务端获取json解析显示在客户端上面 百度经验:jingyan.baidu.com 首先说一下Json数据的最基本的特点,Json数据是一系列的键值对的集合,和XML数据来比,Jso ...

随机推荐

  1. linux内核睡眠状态解析

    1. 系统睡眠状态 睡眠状态是整个系统的全局低功耗状态,在这种状态下,用户空间的代码不能被执行并且整个系统的活动明显被降低 1.1 被支持的睡眠状态 取决于所运行平台的能力和配置选项,Linux内核能 ...

  2. bat命令编写大全

    bat命令编写大全 摘自:https://blog.csdn.net/haibo19981/article/details/52161653 2016年08月09日 12:26:31 爱睡觉的猫L 阅 ...

  3. OpenStack社区中的GO语言之争

    1 背景介绍 Swift之前几乎所有的代码都是用Python实现的,但是性能一直不理想, 社区为了解决性能问题,尝试过很多方法,后来发现用Golang语言进行一部分代码重写, 性能得到了一定的提升,社 ...

  4. 利用Python获取cookie的方法,相比java代码简便不少

    1.通过urllib库,是python的标准库,不需要另外引入,直接看代码,注意代码的缩进: # coding=UTF-8import cookielibimport urllib2 class Ry ...

  5. git命令手册

    以下内容是我在学习和研究Git时,对Git操作的特性.重点和注意事项的提取.精练和总结,可以做为Git操作的字典,方便大家查阅: 备注:本文会不断更新完善: 目录 一. 语法格式描述 二. git环境 ...

  6. laravel构建联合查询

    参考:http://laravelacademy.org/post/126.html DB门面可以指定不同的数据库连接(通过connection方法) /** * @param $login_uid ...

  7. 【Leetcode_easy】744. Find Smallest Letter Greater Than Target

    problem 744. Find Smallest Letter Greater Than Target 题意:一堆有序的字母,然后又给了一个target字母,让求字母数组中第一个大于target的 ...

  8. idea的enable auto-import/内存设置

    设置pom.xml依赖的自动导入 设置idea的memory heap On the Help menu, click Edit Custom VM Options. Set the -Xmx opt ...

  9. WEB前端动态背景集

    本资源是我在源代码网站上发现的,内附几十种背景动态特效,我单独提取出来精品背景特效在此分享,文件里有20多种精品动态效果,本人觉得可用作于个人博客主页背景,登陆页面背景等,有20多个背景特效,非常漂亮 ...

  10. pod install安装第三方库异常

    使用pod install安装第三方插件时,可能会出现如下异常: Installing SDWebImage (3.7.3) [!] Error installing SDWebImage[!] /u ...