当前位置: 首页 > news >正文

Eureka 学习笔记3:EurekaHttpClient

版本 awsVersion = ‘1.11.277’

EurekaTransport 用于客户端和服务端之间进行通信,封装了以下接口的实现:

  1. ClosableResolver 接口实现
  2. TransportClientFactory 接口实现
  3. EurekaHttpClient 接口实现及其对应的 EurekaHttpClientFactory 接口实现
private static final class EurekaTransport {// 服务端集群解析器,用于获取服务端列表private ClosableResolver bootstrapResolver;// 底层工厂,用于创建具体通信协议的实现private TransportClientFactory transportClientFactory;// EurekaHttpClient实现,用于注册实例、取消注册、续约private EurekaHttpClient registrationClient;// 上层工厂,用于创建registrationClientprivate EurekaHttpClientFactory registrationClientFactory;// EurekaHttpClient实现,用于全量拉取、增量拉取服务列表private EurekaHttpClient queryClient;// 上层工厂,用于创建queryClientprivate EurekaHttpClientFactory queryClientFactory;
}

EurekaHttpClientFactory 是上层工厂接口(A top level factory interface),用于创建 EurekaHttpClientDecorator 对象(to create http clients for application/eurekaClient use)。

public interface EurekaHttpClientFactory {EurekaHttpClient newClient();void shutdown();
}

例如 DiscoveryClient # scheduleServerEndpointTask 方法:

newRegistrationClientFactory = EurekaHttpClients.registrationClientFactory(eurekaTransport.bootstrapResolver,eurekaTransport.transportClientFactory,transportConfig);
newRegistrationClient = newRegistrationClientFactory.newClient();

TransportClientFactory 是底层工厂接口(A low level client factory interface),用于创建 JerseyApplicationClient(Eureka 原生实现)、Jersey2ApplicationClient(Eureka 原生实现)、RestTemplateEurekaHttpClient(SpringCloud 实现)等具体协议相关的实现。底层工厂创建的对象不建议直接使用(Not advised to be used by top level consumers),需要经过上层工厂加工。

public interface TransportClientFactory {EurekaHttpClient newClient(EurekaEndpoint serviceUrl);void shutdown();
}

例如 DiscoveryClient # scheduleServerEndpointTask 方法:

TransportClientFactories transportClientFactories = argsTransportClientFactories == null? new Jersey1TransportClientFactories(): argsTransportClientFactories;

EurekaHttpClient 接口,用于客户端和服务端之间进行通信,封装了注册、取消注册、续约、拉取服务列表等一系列操作。

public interface EurekaHttpClient {// 注册实例(服务注册)EurekaHttpResponse<Void> register(InstanceInfo info);// 取消注册(服务下线)EurekaHttpResponse<Void> cancel(String appName, String id);// 发送心跳(服务续约)EurekaHttpResponse<InstanceInfo> sendHeartBeat(String appName, String id, InstanceInfo info, InstanceStatus overriddenStatus);// 更新实例的服务状态InstanceStatus(服务状态更新)EurekaHttpResponse<Void> statusUpdate(String appName, String id, InstanceStatus newStatus, InstanceInfo info);// 删除实例的覆盖状态,overriddenStatus将变成UNKNOWNEurekaHttpResponse<Void> deleteStatusOverride(String appName, String id, InstanceInfo info);// 获取指定区域regions的注册表(全量获取)EurekaHttpResponse<Applications> getApplications(String... regions);// 获取指定区域regions的注册列表(增量获取)EurekaHttpResponse<Applications> getDelta(String... regions);EurekaHttpResponse<Applications> getVip(String vipAddress, String... regions);EurekaHttpResponse<Applications> getSecureVip(String secureVipAddress, String... regions);// 获取指定应用的实例列表EurekaHttpResponse<Application> getApplication(String appName);// 获取指定实例EurekaHttpResponse<InstanceInfo> getInstance(String appName, String id);// 获取指定实例EurekaHttpResponse<InstanceInfo> getInstance(String id);void shutdown();
}

EurekaHttpClient
HttpReplicationClient 用于服务端和服务端之间进行通信,在 EurekaHttpClient 的基础上封装了更新服务端实例状态、批量同步数据等操作。

public interface HttpReplicationClient extends EurekaHttpClient {// 更新服务端实例的状态EurekaHttpResponse<Void> statusUpdate(String asgName, ASGStatus newStatus);// 向其他服务端批量同步数据EurekaHttpResponse<ReplicationListResponse> submitBatchUpdates(ReplicationList replicationList);
}

Eureka 服务端集群节点是对等节点(peerNode),对等节点之间进行数据同步会产生循环问题和数据冲突问题。

  • 对于循环问题,Eureka 使用 Http 请求头 x-netflix-discovery-replication 表示是否是服务端同步数据操作,如果是服务端同步数据,就不会再继续向其他服务端进行同步数据。
// com.netflix.eureka.resources.InstanceResource
@PUT
public Response renewLease(@HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication,@QueryParam("overriddenstatus") String overriddenStatus,@QueryParam("status") String status,@QueryParam("lastDirtyTimestamp") String lastDirtyTimestamp) {boolean isFromReplicaNode = "true".equals(isReplication);boolean isSuccess = registry.renew(app.getName(), id, isFromReplicaNode);// ...
}// com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl
private void replicateToPeers(Action action,String appName,String id,InstanceInfo info /* optional */,InstanceStatus newStatus /* optional */,boolean isReplication) {// ...// If it is a replication already,// do not replicate again as this will create a poison replicationif (peerEurekaNodes == Collections.EMPTY_LIST || isReplication) {return;}// ...
}
  • 对于数据冲突问题,Eureka 通过比较 ReplicationInstance 类的 lastDirtyTimestamp 属性解决。lastDirtyTimestamp 是服务实例 InstanceInfo 的属性,表示服务实例最近一次变更时间。

例如 Server A 向 Server B 同步数据:

  1. 如果 Server A 的数据比 Server B 的新,Server B 返回 Status.NOT_FOUND,Server A 重新将该服务实例注册到 Server B
  2. 如果 Server A 的数据比 Server B 的旧,Server B 返回 Status.CONFLICT,要求 Server A 同步 Server B 的数据
// com.netflix.eureka.resources.InstanceResource # renewLease
private Response validateDirtyTimestamp(Long lastDirtyTimestamp,boolean isReplication) {InstanceInfo appInfo = registry.getInstanceByAppAndId(app.getName(), id, false);if (appInfo != null) {if ((lastDirtyTimestamp != null) && (!lastDirtyTimestamp.equals(appInfo.getLastDirtyTimestamp()))) {Object[] args = {id,appInfo.getLastDirtyTimestamp(),lastDirtyTimestamp,isReplication};if (lastDirtyTimestamp > appInfo.getLastDirtyTimestamp()) {logger.debug("Time to sync, " + "since the last dirty timestamp differs - " + "ReplicationInstance id : {}," + "Registry: {} Incoming: {} Replication: {}",args);return Response.status(Status.NOT_FOUND).build();} else if (appInfo.getLastDirtyTimestamp() > lastDirtyTimestamp) {// In the case of replication, // send the current instance info in the registry // for the replicating node to sync itself with this one.if (isReplication) {logger.debug("Time to sync, " + "since the last dirty timestamp differs - " + "ReplicationInstance id : {}," + "Registry: {} Incoming: {} Replication: {}",args);return Response.status(Status.CONFLICT).entity(appInfo).build();} else {return Response.ok().build();}}} // end if ((lastDirtyTimestamp != null)}// end if (appInfo != null)return Response.ok().build();
}

抽象类 EurekaHttpClientDecorator 使用装饰者模式为 EurekaHttpClient 添加新的功能。

EurekaHttpClientDecorator

  • SessionedEurekaHttpClient 为 EurekaHttpClient 设置随机的会话时间,超过会话时间则调用 EurekaHttpClientFactory 的 newClient 方法创建一个新的 EurekaHttpClient 执行请求。随机的会话时间在配置 sessionedClientReconnectIntervalSeconds0.5-1.5 之间。

  • RetryableEurekaHttpClient 为 EurekaHttpClient 提供重试功能,默认重试 3 次。当服务端响应异常时,将服务端添加到 quarantineSet 中,并从 ClusterResolver 解析得到的服务端列表中移除 quarantineSet ,选择其他的服务端创建一个新的 EurekaHttpClient 执行请求,超过重试次数则抛出 TransportException 异常。

  • RedirectingEurekaHttpClient 为 EurekaHttpClient 提供重定向功能,默认可重定向次数 10 次。当服务端响应 302 时,获取响应中的 targetUrl,创建一个新的 EurekaHttpClient 执行请求,超过重定向次数则抛出 TransportException 异常。

  • MetricsCollectingEurekaHttpClient 为 EurekaHttpClient 提供指标收集功能,用于集成 Netflix Servo 监控组件,统计各类型请求的耗时以及不同响应码和异常的计数。

相关文章:

Eureka 学习笔记3:EurekaHttpClient

版本 awsVersion ‘1.11.277’ EurekaTransport 用于客户端和服务端之间进行通信&#xff0c;封装了以下接口的实现&#xff1a; ClosableResolver 接口实现TransportClientFactory 接口实现EurekaHttpClient 接口实现及其对应的 EurekaHttpClientFactory 接口实现 private …...

Android Framework 之 启动流程

Android 系统的启动流程 Android 系统的启动流程可以分为以下几个主要步骤&#xff1a; 引导加载器&#xff08;Bootloader&#xff09;启动&#xff1a;当你打开一个 Android 设备时&#xff0c;首先启动的是引导加载器。引导加载器负责启动 Android 的核心操作系统。 Linux…...

Qt、C/C++环境中内嵌LUA脚本、实现LUA函数的调用执行

Qt、C/C环境中内嵌LUA脚本、实现LUA函数的调用执行 Chapter1. Qt、C/C环境中内嵌LUA脚本、实现LUA函数的调用执行1、LUA简介2、LUA脚本的解释器和编译器3、C环境中内嵌LUA执行LUA函数调用4、Qt内嵌LUA执行LUA函数调用5、运行结果6、内嵌LUA脚本在实际项目中的案例应用 Chapter1…...

超详细 | 模拟退火算法及其MATLAB实现

模拟退火算法(simulated annealing&#xff0c;SA)是20世纪80年代初期发展起来的一种求解大规模组合优化问题的随机性方法。它以优化问题的求解与物理系统退火过程的相似性为基础&#xff0c;利用Metropolis算法并适当地控制温度的下降过程实现模拟退火&#xff0c;从而达到求解…...

在线餐饮油烟实时监测系统的设计与实现

安科瑞 华楠 摘 要&#xff1a;为了解决传统油烟检测方法中成本高、效率低、实时性差等问题&#xff0c;设计开发了一种在线油烟实时监测系统&#xff1b;系统由采集、通讯、服务器和用户交互四个模块组成&#xff1b;采集模块采集油烟数据&#xff0c;通过GPRS通讯技术将数据发…...

7-2 凯撒密码 (20分)

7-2 凯撒密码 (20分) 为了防止信息被别人轻易窃取&#xff0c;需要把电码明文通过加密方式变换成为密文。输入一个以回车符为结束标志的字符串&#xff08;少于80个字符&#xff09;&#xff0c;再输入一个整数offset&#xff0c;用凯撒密码将其加密后输出。恺撒密码是一种简单…...

LeetCode_贪心算法_中等_763.划分字母区间

目录 1.题目2.思路3.代码实现&#xff08;Java&#xff09; 1.题目 给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段&#xff0c;同一字母最多出现在一个片段中。注意&#xff0c;划分结果需要满足&#xff1a;将所有划分结果按顺序连接&#xff0c;得到的字符串仍…...

【算法提高:动态规划】1.5 状态压缩DP TODO

文章目录 状态压缩DP例题列表棋盘式1064. 小国王⭐&#x1f402;&#xff08;好题&#xff01;&#xff09;做题套路总结 327. 玉米田&#xff08;好题&#xff01;&#x1f402; 和1064. 小国王差不多的题目&#xff09;292. 炮兵阵地&#xff08;和上面两道题差不多&#xff…...

建网站一般使用Windows还是liunx好?

建网站一般使用Windows还是liunx好&#xff1f; 1&#xff1b;服务器配置比较低时&#xff0c;最好使用linux系统。 对于一个电脑新手&#xff0c;刚开始做网站时&#xff0c;都会选择入门级的服务器&#xff0c;我刚开始做网站时&#xff0c;就是这样的。我购买了一台入门级服…...

NodeJs后端项目使用docker打包部署

docker安装看之前的文章 默认已经安装好docker并且配置没有问题 拉取项目 https://gitee.com/coder-msc/docker-node 本地跑一个看看 pnpm install pnpm start 本地访问 http://localhost:1301/getname?name%E5%93%88%E5%88%A9%E6%B3%A2%E7%89%B9项目整个上传服务器 查看…...

ARM单片机中断处理过程解析

前言 中断&#xff0c;在单片机开发中再常见不过了。当然对于中断的原理和执行流程都了然于胸&#xff0c;那么对于ARM单片机中断的具体处理行为&#xff0c;你真的搞清楚了吗&#xff1f; 今天来简单聊一聊&#xff0c;ARM单片机中断处理过程中的具体行为是什么样的&#xf…...

关于SEDEX会员与平台的相关问题汇总

【关于SEDEX会员与平台的相关问题汇总】 01.会员资格有效期是多久&#xff1f; Sedex会员资格有效期为12个月&#xff0c;您也可以选择更长期的会员资格。您支付会员年费时&#xff0c;在“订阅信息”框下的“延长订阅期限”中输入年数&#xff0c;即可获得更长的会员资格时效。…...

解读Spring-context的property-placeholder

在spring中&#xff0c;如果要给程序定义一些参数&#xff0c;可以放在application.properties中&#xff0c;通过<context:property-placeholder>加载这个属性文件&#xff0c;然后就可以通过value给我们的变量自动赋值&#xff0c;如果你们的程序可能运行在多个环境中&…...

【Rust】枚举类型创建单链表以及常见的链表操作方法

目录 单链表 用枚举表达链表 枚举enum Box容器 创建节点 1. 创建并打印 2. match 匹配 3. 节点初始化 4.节点嵌套 追加节点 1. 尾插法 2. 链表追加方法 3. 头插法 4. 改写成单链表方法 遍历链表 1. 递归法 2. 递推法 3. 改写成单链表方法 自定义Display tr…...

Excel 两列数据中相同的数据进行同行显示

一、要求 假设您有两个列&#xff0c;分别是A列和B列&#xff0c;需要在C列中找出A列对应的B列的值。 二、方案 方法1&#xff1a;寻常思路 凸显重复项对A列单独进行筛选–按颜色进行排序&#xff0c;然后升序对B列重复上述操作即可 方法2&#xff1a;两个公式 VLOOKUP 纵向查找…...

Windows本地安装配置Qcadoo MES系统

简介 Qcadoo MES是一款功能强大且灵活的开源MES&#xff08;制造执行系统&#xff09;&#xff0c;旨在为制造业务提供全面的管理和监控解决方案。本篇博客将教您如何在Windows操作系统上安装和配置Qcadoo MES系统&#xff0c;以便您能够轻松管理和监控制造过程。 环境要求 …...

涛思数据与拾贝云达成战略合作,携手赋能工业数字化转型

2023 年 7 月 27 日&#xff0c;北京涛思数据科技有限公司&#xff08;以下简称“涛思数据”&#xff09;与广州拾贝云科技有限公司&#xff08;以下简称“拾贝云”&#xff09;于广州签署战略合作协议。双方围绕电力行业的需求与痛点展开积极讨论&#xff0c;就如何量身打造最…...

nginx 配置多域名多站点 Ubuntu

nginx 配置多域名多站点 Ubuntu 一、安装 nginx apt install nginx二、配置文件说明 nginx 的配置文件在 /etc/nginx 目录下&#xff0c;它的默认内容是这样的 root2bd0:/etc/nginx# ll total 72 drwxr-xr-x 8 root root 4096 Jul 31 15:21 ./ drwxr-xr-x 104 root root …...

Docker实践:使用Docker搭建个人开发环境(极简版)

文章目录 说明教程1. 编写 Dockerfile2. 编写 docker-compose.yml3. 使用容器创建容器启动容器进入容器命令行VSCode 4. 关闭容器5. 备份容器导出导入 6. 重置容器 相关资料文章合集详细了解本文在个人电脑上安装 Docker容器使用 NVIDIA 显卡托管镜像运行GUI程序 说明 本文是在…...

SQL从三个表中根据时间分别查询并汇总数量一行展示

需求&#xff1a;如果您要从三个表中根据时间分别查询并汇总数量&#xff0c;然后将结果以时间和数量一行展示&#xff0c;可以使用子查询和条件聚合。 入库主表 入库明细表 出库主表 出库明细表 退货主表 退货明细表 SQL代码 SELECT time,sum(a.inQty) as inQty,sum(a.outQty…...

突破透明动画性能瓶颈:VAP引擎实现移动端高效视觉体验

突破透明动画性能瓶颈&#xff1a;VAP引擎实现移动端高效视觉体验 【免费下载链接】vap VAP是企鹅电竞开发&#xff0c;用于播放特效动画的实现方案。具有高压缩率、硬件解码等优点。同时支持 iOS,Android,Web 平台。 项目地址: https://gitcode.com/gh_mirrors/va/vap …...

Qwen3-Embedding国产化部署

从单一型人才到AI带领下的复合型人才 1.1 传统职能的终结 传统软件公司怎么干的&#xff1f; 销售、售前、交付、研发、市场、运维——各司其职&#xff0c;职能清晰。看起来很专业&#xff0c;但实际上是什么&#xff1f;一堆冗余的角色在等活干。 这不是高效&#xff0c;这是…...

UniHacker:跨平台支持的开源工具快速部署方案

UniHacker&#xff1a;跨平台支持的开源工具快速部署方案 【免费下载链接】UniHacker 为Windows、MacOS、Linux和Docker修补所有版本的Unity3D和UnityHub 项目地址: https://gitcode.com/GitHub_Trending/un/UniHacker UniHacker作为一款专业的开源工具&#xff0c;凭借…...

使用 HashMap 优化嵌套循环:Java 对象数组转换

本文旨在提供使用 HashMap 优化 Java 嵌套循环的有效方法&#xff0c;特别是当循环涉及对象数组并进行相等检查时。通过将内部循环转换为 HashMap 查询可以显著降低时间复杂性&#xff0c;提高代码性能。本文将提供详细的步骤和示例代码&#xff0c;以帮助读者理解和应用此优化…...

别再一条条Update了!MyBatis批量更新数据,用这个Case When写法性能翻倍

MyBatis批量更新性能优化实战&#xff1a;告别低效循环&#xff0c;拥抱CASE WHEN 每次看到代码里用循环一条条执行update语句&#xff0c;我的数据库性能监控图表就会剧烈波动——这简直是DBA的噩梦。上周排查一个后台任务卡死问题&#xff0c;发现同事在处理5万条数据更新时&…...

【Matlab】MATLAB教程:数据插值interp1(案例:interp1(x,y,xi,‘linear‘);应用:数据补全、插值)

MATLAB教程:数据插值interp1(案例:interp1(x,y,xi,linear);应用:数据补全、插值) 在科研实验、工程监测、信号采集等各类数据获取场景中,受限于设备精度、测试条件、环境干扰等因素,采集到的原始数据往往存在**数据点稀疏、采样间隔不均、局部数据缺失**等问题,直接使…...

从SuperGlue到LoFTR:无检测器特征匹配是如何“卷”出来的?技术演进深度解读

从SuperGlue到LoFTR&#xff1a;无检测器特征匹配的技术革命与范式迁移 在计算机视觉领域&#xff0c;特征匹配一直是三维重建、SLAM、图像配准等任务的核心基础。传统方法如SIFT、ORB等基于手工设计的特征检测与描述算法&#xff0c;在过去二十年里主导了这一领域。然而&#…...

GIS开发必备:5分钟搞定EPSG3857转WGS84坐标转换(附proj4.js完整代码)

GIS开发实战&#xff1a;从原理到代码实现EPSG3857与WGS84的高效坐标转换 刚接触WebGIS开发的工程师们&#xff0c;常常会被各种坐标系搞得晕头转向。为什么高德地图上显示的位置和GPS设备采集的数据对不上&#xff1f;为什么Leaflet、OpenLayers这些库加载的瓦片地图坐标数值大…...

用STM32+物联网做个智能药盒:手把手教你搞定毕设硬件选型与代码框架

基于STM32的智能药盒开发实战&#xff1a;从硬件选型到云端联调 在老龄化社会加速和慢性病管理需求激增的背景下&#xff0c;智能医疗设备正从医院走向家庭。作为嵌入式开发者&#xff0c;将STM32与物联网技术结合打造智能药盒&#xff0c;不仅能解决实际用药管理痛点&#xff…...

Vue3项目救星:我是如何用Cursor的‘项目规则’功能,让团队新人一天上手的

Vue3团队协作革命&#xff1a;用Cursor项目规则实现代码规范的自动化治理 当新成员加入你的Vue3项目时&#xff0c;是否经历过这样的场景&#xff1f;新人提交的代码里混杂着选项式API和组合式API&#xff0c;路由命名忽而短横线忽而大驼峰&#xff0c;样式文件里散落着各种魔…...