Eureka三级缓存架构

Eureka Server缓存机制概述

Eureka是Netflix开源的服务发现框架,它具有高可用、可扩展、易于部署等优点,被广泛应用于微服务架构中。其中一个重要的组件就是Eureka Server,它负责维护服务注册表,以及向客户端提供服务注册信息。

在Eureka Server中,缓存机制是一个非常重要的优化点,它可以显著提升服务注册表的性能和可靠性。本文将深入剖析Eureka Server的缓存机制,并通过源码分析,探讨其实现原理和优化策略。

三级缓存

一级缓存:只读缓存 readOnlyCacheMap,数据结构 ConcurrentHashMap。相当于数据库。

二级缓存:读写缓存 readOnlyCacheMap,Guava Cache。相当于 Redis 主从架构中主节点,既可以进行读也可以进行写。

三级缓存:本地注册表 registry,数据结构 ConcurentHashMap。相当于 Redis 主从架构的从节点,只负责读。

多级缓存的意义

这里为什么要设计多级缓存呢?原因很简单,就是当存在大规模的服务注册和更新时,如果只是修改一个ConcurrentHashMap数据,那么势必因为锁的存在导致竞争,影响性能。

而Eureka又是AP模型,只需要满足最终可用就行。所以它在这里用到多级缓存来实现读写分离。注册方法写的时候直接写内存注册表,写完表之后主动失效读写缓存。

获取注册信息接口先从只读缓存取,只读缓存没有再去读写缓存取,读写缓存没有再去内存注册表里取(不只是取,此处较复杂)。并且,读写缓存会更新回写只读缓存

  • responseCacheUpdateIntervalMs :readOnlyCacheMap 缓存更新的定时器时间间隔,默认为30秒

  • responseCacheAutoExpirationInSeconds : readWriteCacheMap 缓存过期时间,默认为 180 秒 。

Eureka Server内存缓存实现原理

Eureka Server的内存缓存机制是通过EurekaRegistry类实现的。EurekaRegistry类是Eureka Server中最核心的组件之一,它负责维护服务注册表,并提供服务注册、注销、查询等接口。在EurekaRegistry类中,内存缓存主要通过以下两个类实现:ReadOnlyClusterRegistry和PeerAwareInstanceRegistry。

ReadOnlyClusterRegistry类是EurekaRegistry的一个内部类,它主要用于向客户端提供服务注册信息。当客户端向Eureka Server发起查询请求时,Eureka Server会从ReadOnlyClusterRegistry中获取服务注册信息,并返回给客户端。同时,ReadOnlyClusterRegistry还负责监控服务注册表的变化,并及时更新缓存中的服务注册信息。

PeerAwareInstanceRegistry类则是EurekaRegistry的另一个内部类,它主要用于维护服务注册表。当Eureka Server收到客户端的服务注册请求时,PeerAwareInstanceRegistry会将服务注册信息添加到内存缓存中。当客户端发起注销请求时,PeerAwareInstanceRegistry会将服务注册信息从内存缓存中删除。同时,PeerAwareInstanceRegistry还负责定时从其他Eureka Server节点获取服务注册信息,并更新本地内存缓存。

PeerAwareInstanceRegistry的内存缓存是通过ConcurrentHashMap实现的。ConcurrentHashMap是Java中线程安全的HashMap实现,它可以支持多个线程同时对同一个HashMap进行操作,从而保证线程安全。在PeerAwareInstanceRegistry中,ConcurrentHashMap主要用于存储服务注册信息。当服务注册信息发生变化时,PeerAwareInstanceRegistry会通过ConcurrentHashMap的put、remove等方法更新内存缓存中的服务注册信息。

下面是一段示例代码,演示了如何使用Eureka Server的内存缓存机制:

public class EurekaServerDemo {public static void main(String[] args) throws Exception {// 创建Eureka Server实例EurekaServerContext serverContext = EurekaServerContextHolder.getInstance().getServerContext();EurekaServerConfig serverConfig = serverContext.getServerConfig();EurekaServer eurekaServer = new EurekaServer(serverConfig);// 启动Eureka ServereurekaServer.start();// 获取Eureka Server的内存缓存PeerAwareInstanceRegistry registry = serverContext.getRegistry();// 添加服务注册信息InstanceInfo instanceInfo = InstanceInfo.Builder.newBuilder().setAppName("demo").setInstanceId("demo-1").setHostName("localhost").setIPAddr("127.0.0.1").setPort(8080).build();registry.register(instanceInfo);// 查询服务注册信息Applications applications = registry.getApplications();Application application = applications.getRegisteredApplications("demo");InstanceInfo registeredInstance = application.getInstances().get(0);// 输出服务注册信息System.out.println("Registered instance: " + registeredInstance);// 关闭Eureka ServereurekaServer.shutdown();}
}

Eureka客户端缓存实现原理

Eureka客户端的缓存机制是通过DiscoveryClient类实现的。DiscoveryClient类是Eureka客户端中最核心的组件之一,它负责向Eureka Server发起查询请求,并将获取到的服务注册信息缓存到内存中,以便后续快速访问。

在DiscoveryClient中,内存缓存主要通过以下两个类实现:Applications和InstanceInfo。

Applications类是Eureka客户端缓存的服务注册表,它包含了所有已注册的服务信息。当DiscoveryClient向Eureka Server发起查询请求时,Eureka Server会返回完整的服务注册表信息,并由DiscoveryClient将其缓存到Applications中。同时,DiscoveryClient还会定时从Eureka Server获取服务注册表的增量信息,并更新Applications中的缓存。

InstanceInfo类则是服务注册信息的抽象表示,它包含了服务的基本信息,例如应用名、实例ID、主机名、IP地址、端口号等。当DiscoveryClient从Eureka Server获取服务注册信息时,会将其转换成InstanceInfo,并缓存到内存中。此外,InstanceInfo还包含了服务的健康状态、元数据信息等,这些信息也会被缓存到内存中,以便后续快速访问。

下面是一段示例代码,演示了如何使用Eureka客户端的缓存机制:

public class EurekaClientDemo {public static void main(String[] args) throws Exception {// 创建Eureka客户端实例DiscoveryClientConfig clientConfig = new DefaultEurekaClientConfig();EurekaClient eurekaClient = new DiscoveryClient(new MyInstanceConfig(), clientConfig);// 获取服务注册信息List<ServiceInstance> instances = eurekaClient.getInstancesById("demo");ServiceInstance instance = instances.get(0);// 输出服务注册信息System.out.println("Service instance: " + instance);// 关闭Eureka客户端eurekaClient.shutdown();}private static class MyInstanceConfig extends MyDataCenterInstanceConfig {@Overridepublic String getAppname() {return "demo-client";}}
}

Eureka缓存优化策略

Eureka缓存机制的性能和可靠性对于微服务架构的稳定运行至关重要。为了提升缓存的性能和可靠性,Eureka Server采用了以下优化策略:

  1. 客户端缓存时间:Eureka客户端会将从Eureka Server获取的服务注册表信息缓存在本地内存中。为了避免本地缓存的信息过期,Eureka客户端会定时从Eureka Server获取服务注册表的增量信息,以更新本地缓存。这个定时更新的时间间隔可以通过配置项eureka.client.registryFetchIntervalSeconds来设置,默认为30秒。

  2. 服务端缓存时间:Eureka Server会将服务注册信息缓存在内存中,以便快速响应客户端的查询请求。为了避免缓存的信息过期,Eureka Server会定时清理过期的缓存信息,并从其他Eureka Server节点获取最新的服务注册信息。这个定时清理的时间间隔可以通过配置项eureka.server.responseCacheAutoExpirationInSeconds来设置,默认为180秒。

  3. 客户端缓存大小:Eureka客户端缓存的大小对于性能和可靠性都有很大的影响。如果缓存太小,会影响客户端的查询性能;如果缓存太大,会占用过多的内存资源。Eureka客户端的缓存大小可以通过配置项eureka.client.fetchRegistry=true和eureka.client.registryRefreshSingleVipAddress来设置。

  4. 服务端缓存大小:Eureka Server缓存的大小也对于性能和可靠性有很大的影响。如果缓存太小,会影响服务端的响应性能;如果缓存太大,会占用过多的内存资源。Eureka Server的缓存大小可以通过配置项eureka.server.responseCacheMaxSize来设置,默认为1000。

缓存同步

ResponseCacheImpl这个类的构造实现中,初始化了一个定时任务,这个定时任务每个

ResponseCacheImpl(EurekaServerConfig serverConfig, ServerCodecs serverCodecs, AbstractInstanceRegistry registry) {//省略...if (shouldUseReadOnlyResponseCache) {timer.schedule(getCacheUpdateTask(),new Date(((System.currentTimeMillis() / responseCacheUpdateIntervalMs) * responseCacheUpdateIntervalMs)+ responseCacheUpdateIntervalMs),responseCacheUpdateIntervalMs);}
}

默认每30s从readWriteCacheMap更新有差异的数据同步到readOnlyCacheMap中

private TimerTask getCacheUpdateTask() {return new TimerTask() {@Overridepublic void run() {logger.debug("Updating the client cache from response cache");for (Key key : readOnlyCacheMap.keySet()) { //遍历只读集合if (logger.isDebugEnabled()) {logger.debug("Updating the client cache from response cache for key : {} {} {} {}",key.getEntityType(), key.getName(), key.getVersion(), key.getType());}try {CurrentRequestVersion.set(key.getVersion());Value cacheValue = readWriteCacheMap.get(key);Value currentCacheValue = readOnlyCacheMap.get(key);if (cacheValue != currentCacheValue) { //判断差异信息,如果有差异,则更新readOnlyCacheMap.put(key, cacheValue);}} catch (Throwable th) {logger.error("Error while updating the client cache from response cache for key {}", key.toStringCompact(), th);} finally {CurrentRequestVersion.remove();}}}};
}

缓存失效

在AbstractInstanceRegistry.register这个方法中,当完成服务信息保存后,会调用invalidateCache失效缓存

public void register(InstanceInfo registrant, int leaseDuration, boolean isReplication) {//....invalidateCache(registrant.getAppName(), registrant.getVIPAddress(), registrant.getSecureVipAddress());//....
}

最终调用ResponseCacheImpl.invalidate方法,完成缓存的失效机制

public void invalidate(Key... keys) {for (Key key : keys) {logger.debug("Invalidating the response cache key : {} {} {} {}, {}",key.getEntityType(), key.getName(), key.getVersion(), key.getType(), key.getEurekaAccept());readWriteCacheMap.invalidate(key);Collection<Key> keysWithRegions = regionSpecificKeys.get(key);if (null != keysWithRegions && !keysWithRegions.isEmpty()) {for (Key keysWithRegion : keysWithRegions) {logger.debug("Invalidating the response cache key : {} {} {} {} {}",key.getEntityType(), key.getName(), key.getVersion(), key.getType(), key.getEurekaAccept());readWriteCacheMap.invalidate(keysWithRegion);}}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/36660.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FreeBSD虚拟化解决之道:高效、安全、灵活的虚拟解决方案全览

FreeBSD下的虚拟化技术 虚拟化软件可让一台计算机同时运行多个操作系统。这种用于个人电脑的系统软件通常涉及一个运行虚拟化软件的宿主机&#xff08;host&#xff09;操作系统&#xff0c;并支持任何数量的客户机&#xff08;guest&#xff09;操作系统。 FreeBSD下的虚拟解…

基于Java的地方废物回收机构管理系统

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;Java技术&#xff0c;MIS的总体思想&#xff0c;MySQL数据库 工具&#xff1a;Eclipse&#xff0c;…

【数据结构】详解二叉树之堆

失败只是暂时停止成功&#xff0c;假如我不能&#xff0c;我就一定要&#xff1b;假如我要&#xff0c;我就一定能&#xff01;&#x1f493;&#x1f493;&#x1f493; 目录 ✨说在前面 &#x1f34b;知识点一&#xff1a;树的概念和结构 • &#x1f330;1.什么是树&#x…

【漏洞复现】学分制系统GetTimeTableData SQL注入

0x01 产品简介 学分制系统由上海鹏达计算机系统开发有限公司研发&#xff0c;是基于对职业教育特点和需求的深入理解&#xff0c;结合教育部相关文件精神&#xff0c;并广泛吸纳专家、学者意见而开发的一款综合性管理系统。系统采用模块化的设计方法&#xff0c;方便学校根据自…

新奥集团校招面试经验分享、测评笔试题型分析

一、走进新奥集团 新奥集团成立于1989年&#xff0c;总部位于河北廊坊&#xff0c;是中国领先的清洁能源企业集团。业务涵盖城市燃气、能源化工、环保科技等多个领域&#xff0c;致力于构建现代能源体系&#xff0c;提升生活品质。 二、新奥集团校招面试经验分享 新奥集团的…

浔川AI3款产品同步上线——浔川AI社

第一款&#xff1a;浔川AI翻译v3.0 正式代码&#xff1a; # -*- coding: utf-8 -*- import tkinter as tk import tkinter.messagebox import pickle import random# 窗口 window tk.Tk() window.title(AI翻译登录界面) window.geometry(450x200) # 画布放置图片 # canvastk…

小程序驾校预约系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;学员管理&#xff0c;教练管理&#xff0c;驾校信息管理&#xff0c;驾校车辆管理&#xff0c;教练预约管理&#xff0c;考试信息管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;驾校信息&a…

一个简单的文件下载服务

背景&#xff1a;我需要一个简单的文件下载功能&#xff0c;例如&#xff1a;输入 /Users/Documents//filedownload/src/main/resources/a.txt会下载文件到本地 准备&#xff1a;新建一个简单的 springboot 服务&#xff0c;直接上代码&#xff0c;如有需要 pom.xml 放在最后 …

ROS2创建自定义接口

ROS2提供了四种通信方式&#xff1a; 话题-Topics 服务-Services 动作-Action 参数-Parameters 查看系统自定义接口命令 使用ros2 interface package sensor_msgs命令可以查看某一个接口包下所有的接口 除了参数之外&#xff0c;话题、服务和动作(Action)都支持自定义接口&am…

【智能算法】决策树算法

目录 一、基本概念 二、工作原理 三、决策树算法优点和缺点 3.1 决策树算法优点 3.2 决策树算法缺点 四、常见的决策树算法及matlab代码实现 4.1 ID3 4.1.1 定义 4.1.2 matlab代码实现 4.2 C4.5 4.2.1 定义 4.2.2 matlab代码实现 4.3 CART 4.3.1 定义 4.3.2 mat…

基于深度学习的人体骨架提取

1. 任务和目标 人体骨架提取的主要任务是从图像或视频中检测和重建人体的关键点&#xff08;关节点&#xff09;&#xff0c;以描述和理解人体的姿态和动作。关键点通常表示为连接成骨架结构的主要关节&#xff0c;例如头部、肩膀、肘部等。 2. 技术和方法 2.1 深度学习模型…

【代码随想录训练营】【Day 62】【单调栈-1】| Leetcode 739, 496, 503

【代码随想录训练营】【Day 62】【单调栈-1】| Leetcode 739, 496, 503 需强化知识点 单调栈&#xff1a;要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置 题目 739. 每日温度 单调栈的基本使用&#xff1a;注意要判断 while len(stack) > 0 class S…

android轮播图入门1——简单无限自动轮播图

目标 目标是实现一个简单的轮播图&#xff0c;特征如下&#xff1a; 只展示本地图片可以无限轮播&#xff0c;在第一帧时也可以向前轮播可以自动轮播 code 先上代码&#xff0c;需要事先准备几张本地图片当素材 MainActivity: package com.example.loopapplication;import…

【数据结构】——链表经典OJ(leetcode)

文章目录 一、 相交链表二、 反转链表三、 回文链表四、 环形链表五、 环形链表 II六、 合并两个有序链表七、 两数相加八、 删除链表的倒数第N个节点九、 随机链表的复制 一、 相交链表 双指针法 struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListN…

day02-Spark集群及参数

一、Spark运行环境变量问题(了解) 1-pycharm远程开发运行时&#xff0c;执行的是服务器的代码 2-通过本地传递指令到远程服务器运行代码时&#xff0c;会加载对应环境变量数据&#xff0c;加载环境变量文件是用户目录下的.bashrc文件 在/etc/bashrc 1-1 在代码中添加 使用os模块…

Python 算法交易实验74 QTV200第二步(改): 数据清洗并写入Mongo

说明 之前第二步是打算进入Clickhouse的&#xff0c;实测下来有一些bug 可以看到有一些分钟数据重复了。简单分析原因&#xff1a; 1 起异步任务时&#xff0c;还是会有两个任务重复的问题&#xff0c;这个在同步情况下是不会出现的2 数据库没有upsert模式。clickhouse是最近…

MT1568 学生成绩

题目 有3个学生&#xff0c;每个学生有3门课的成绩&#xff0c;从键盘输入数据&#xff0c;包括学号、姓名、三门课成绩&#xff0c;学号整型&#xff0c;姓名字符型&#xff0c;成绩实型&#xff0c;计算3门课程总平均成绩&#xff0c;以及平均分最高的学生信息。不考虑非法成…

【webrtc】webrtc 与h265

参考 webrtc 支持H265(三) 总结_webrtc h265-CSDN博客 enable-chromium-hevc-hardware-decoding/README.zh_CN.md at main StaZhu/enable-chromium-hevc-hardware-decoding GitHub 《WebRTC系列》实战 Web 端支持 h265 硬解_webrtc-streamer h265编码-CSDN博客 webrtc分块…

mysql GROUP_CONCAT函数详解

文章目录 概要使用技巧1. 建表、插入数据2.以id分组&#xff0c;把age字段的值拼成一行&#xff0c;逗号分隔(默认)3.以id分组&#xff0c;把age字段的值拼成 一行&#xff0c;分号分隔4.以id分组&#xff0c;把去冗余的age字段的值打印在一行5.以id分组&#xff0c;把age字段的…

算法:链表题目练习

目录 链表的技巧和操作总结 常用技巧&#xff1a; 链表中的常用操作 题目一&#xff1a;反转一个单链表 题目二&#xff1a;链表的中间结点 题目三&#xff1a;返回倒数第k个结点 题目四&#xff1a;合并两个有序链表 题目五&#xff1a;移除链表元素 题目六&#xff…