所有文章

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

正文

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

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

ApplicationsResource

@GET
public Response getContainers(@PathParam("version") String version,
@HeaderParam(HEADER_ACCEPT) String acceptHeader,
@HeaderParam(HEADER_ACCEPT_ENCODING) String acceptEncoding,
@HeaderParam(EurekaAccept.HTTP_X_EUREKA_ACCEPT) String eurekaAccept,
@Context UriInfo uriInfo,
@Nullable @QueryParam("regions") String regionsStr) { // ... Key cacheKey = new Key(Key.EntityType.Application,
ResponseCacheImpl.ALL_APPS,
keyType, CurrentRequestVersion.get(), EurekaAccept.fromString(eurekaAccept), regions
); Response response;
if (acceptEncoding != null && acceptEncoding.contains(HEADER_GZIP_VALUE)) {
response = Response.ok(responseCache.getGZIP(cacheKey))
.header(HEADER_CONTENT_ENCODING, HEADER_GZIP_VALUE)
.header(HEADER_CONTENT_TYPE, returnMediaType)
.build();
} else {
response = Response.ok(responseCache.get(cacheKey))
.build();
}
return response;
}

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

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

@Inject
ApplicationsResource(EurekaServerContext eurekaServer) {
this.serverConfig = eurekaServer.getServerConfig();
this.registry = eurekaServer.getRegistry();
this.responseCache = registry.getResponseCache();
}

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

String get(final Key key, boolean useReadOnlyCache) {
Value payload = getValue(key, useReadOnlyCache);
if (payload == null || payload.getPayload().equals(EMPTY_PAYLOAD)) {
return null;
} else {
return payload.getPayload();
}
}

继续跟进getValue

Value getValue(final Key key, boolean useReadOnlyCache) {
Value payload = null;
try {
if (useReadOnlyCache) {
final Value currentPayload = readOnlyCacheMap.get(key);
if (currentPayload != null) {
payload = currentPayload;
} else {
payload = readWriteCacheMap.get(key);
readOnlyCacheMap.put(key, payload);
}
} else {
payload = readWriteCacheMap.get(key);
}
} catch (Throwable t) {
logger.error("Cannot get value for key : {}", key, t);
}
return payload;
}

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

this.readWriteCacheMap = CacheBuilder.newBuilder().initialCapacity(serverConfig.getInitialCapacityOfResponseCache())
.expireAfterWrite(serverConfig.getResponseCacheAutoExpirationInSeconds(), TimeUnit.SECONDS)
.removalListener(new RemovalListener<Key, Value>() {
@Override
public void onRemoval(RemovalNotification<Key, Value> notification) {
Key removedKey = notification.getKey();
if (removedKey.hasRegions()) {
Key cloneWithNoRegions = removedKey.cloneWithoutRegions();
regionSpecificKeys.remove(cloneWithNoRegions, removedKey);
}
}
})
.build(new CacheLoader<Key, Value>() {
@Override
public Value load(Key key) throws Exception {
if (key.hasRegions()) {
Key cloneWithNoRegions = key.cloneWithoutRegions();
regionSpecificKeys.put(cloneWithNoRegions, key);
}
Value value = generatePayload(key);
return value;
}
});

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

我们跟进generatePayload

private Value generatePayload(Key key) {
Stopwatch tracer = null;
try {
String payload;
switch (key.getEntityType()) {
case Application:
boolean isRemoteRegionRequested = key.hasRegions();
// 获取所有Application
if (ALL_APPS.equals(key.getName())) {
if (isRemoteRegionRequested) {
tracer = serializeAllAppsWithRemoteRegionTimer.start();
payload = getPayLoad(key, registry.getApplicationsFromMultipleRegions(key.getRegions()));
} else {
tracer = serializeAllAppsTimer.start();
payload = getPayLoad(key, registry.getApplications());
}
} else if (ALL_APPS_DELTA.equals(key.getName())) {
// ...
} else {
tracer = serializeOneApptimer.start();
// 获取某个Application
payload = getPayLoad(key, registry.getApplication(key.getName()));
}
break;
// ...
}
return new Value(payload);
} finally { }
}

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

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

private String getPayLoad(Key key, Applications apps) {
EncoderWrapper encoderWrapper = serverCodecs.getEncoder(key.getType(), key.getEurekaAccept());
String result;
try {
result = encoderWrapper.encode(apps);
} catch (Exception e) {
return "";
}
return result;
}

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

总结

获取服务信息列表其实就是从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. LoadRunner11下载、安装与破解

    目前LoadRunner最新版本已经更新到LR12了,但是只有试用版本,最多只支持50人的并发,所以我们还是只能用LR11的破解版,毕竟商用 版是真的很贵,一般企业怕是都不会去购买. 1.LoadRu ...

  2. List三个子类的特点

    List的三个子类的特点 ArrayList: 底层数据结构是数组,查询快,增删慢. 线程不安全,效率高. Vector: 底层数据结构是数组,查询快,增删慢. 线程安全,效率低. Vector相对A ...

  3. ELK 二进制安装并收集nginx日志

    对于日志来说,最常见的需求就是收集.存储.查询.展示,开源社区正好有相对应的开源项目:logstash(收集).elasticsearch(存储+搜索).kibana(展示),我们将这三个组合起来的技 ...

  4. 使用一般处理程序生成 JSON

    在 .NET 3.5 之后,定义在命名空间 System.Runtime.Serialization.Json 中的 DataContractJsonSerializer 可以帮助我们直接将一个对象格 ...

  5. 《CNCF × Alibaba云原生技术公开课》知识点自测(二):容器基本概念

    (单选)1.已运行 docker run -d -t —name demo ubuntu top 和 docker run --name demo-x --pid container:demo ubu ...

  6. Flutter JSON解析与复杂模型转换技巧及实例

    其实转换成model类是有好处的,转换后可以减少上线后APP崩溃和出现异常,所以我们从这节课开始,要制作model类模型,然后用model的形式编辑UI界面. 类别json的分析 比如现在从后台得到了 ...

  7. vue中添加less配置,用于计算div高度

    需求:左边垂直的菜单栏高度设置为 100% - 导航栏的高度(3.6rem) 首先,从vue-cli脚手架里的安装的webpack模板中并没有less的依赖配置,得自己手动添加安装 安装命令::npm ...

  8. vector iterators incompatible

    字面翻译迭代器类型不兼容 今天同事遇到的这个问题算是一个习惯性写法的问题.描述一下代码: struct Track{}; class BaseTrack { - std::vector<Trac ...

  9. 判断scrollView的滑动方向(二)

    在上一篇文章<判断scrollView的滑动方向>中谈到的第二种方法是根据滑动速率来判断的. 今天将通过滑动过程中的坐标差来判断 - (void)scrollViewDidScroll:( ...

  10. IO-file-07 递归

    package com.bwie.io; /** * 递归: * 方法自己调用自己 * 递归头:何时结束递归 * 递归体:重复调用 * @author Allen17805272076 * */ pu ...