HydraRPC: RPC in the CXL Era——论文阅读
ATC 2024 Paper CXL论文阅读笔记整理
问题
远程过程调用(RPC)是分布式系统中的一项基本技术,它允许函数在远程服务器上通过本地调用执行来促进网络通信,隐藏底层通信过程的复杂性简化了客户端/服务器交互[15]。RPC已成为数据中心通信基础设施的重要组成部分,如Protobufs[21]、Thrift[40]和Finagle[20]。性能和可扩展性对于现代RPC实现至关重要。通信和(反)序列化的额外网络延迟和数据复制会阻碍性能,而硬件(网络)和软件(缓冲区管理)级别的拥塞会影响可扩展性。
现有RPC采用如图2所示的消息传递。沉重的网络堆栈给传统的基于TCP/IP的RPC(A)带来了负担,带来很高的CPU开销。利用RDMA来实现RPC可以提高性能,同时保持与现有应用程序的兼容性,现有方法可分为双边(B)和单边(C)方法。HERD[29]和FaSST[30]是双边操作,但需要额外的数据副本。RFP[41,46]提出单边操作,通过引用,服务器向客户端写入引用,客户端使用该引用通过RDMA Read获取,但需要额外的网络往返来发。
CXL(Compute Express Link)是一种行业支持的用于内存和设备缓存一致性互连,提供高速、高效和灵活的互连。这种环境促进了更复杂、更高效的RPC机制的开发,来增加的吞吐量和降低开销。通过内存共享功能,可以让多台机器访问相同的数据[4],从而取代繁重的网络通信。
挑战
现有基于消息传递的RPC面临三个挑战:
-
网络开销。如图2所示,每个RPC包含两个消息或RDMA操作,这至少比正常的内存访问贵10倍。即使使用RDMA,最佳的网络往返时间也在2μs左右,而在CXL HDM中,只需要300ns。
-
数据复制。现代分布式处理系统,如Ray[39],通常按引用传递来避免昂贵的数据复制(图2(A/B/C))。使用分布式存储来存储数据,只通过RPC传输这些数据的引用,从而减少了数据传输开销,提高了效率和性能。
-
可扩展性。多个RPC连接应建立其缓冲区,缓冲区共享应限制在同一台服务器上。但是,不平衡的RPC连接工作负载会导致高内存占用和较差QoS。从网络的角度来看,大量的RPC连接可能会导致网络拥塞。
传统RPC的实现基于消息传递,但CXL只提供共享内存抽象,通过CXL实现RPC需要考虑三个问题:
-
如何设计RPC的控制平面和RPC协议,以充分利用CXL HDM(主机管理设备内存)的潜在性能。
-
CXL HDM提供共享内存接口,没有消息传递接口,没有高效易用的机制来通知CPU请求/响应的到达。
-
如何在RPC场景中使用CXL HDM时管理它。
本文方法
本文提出了利用CXL HDM(主机管理设备内存)进行数据传输的HydraRPC。
-
利用在多台机器之间共享的CXL HDM来避免昂贵的网络轮询、内存复制和(反)序列化。多个客户端/服务器通过物理链路或CXL交换机连接到同一CXL HDM。每个RPC连接中,在CXL HDM有两个消息队列和数据区域,消息队列负责将引用作为请求/响应缓冲区传递,数据区存储请求/响应的原始数据。消息队列中的每个条目大小为64位,包括对数据区域的嵌入式引用(偏移)和1位到达标志。为了为请求/响应数据分配内存,采用了用户空间级内存分配器,通过映射设备内存区域来管理CXL HDM。
-
采用不可缓存的共享来绕过CPU缓存,而不是通用的load/store内存访问指令。
-
利用英特尔的内存类型范围寄存器(MTRR)技术[31],来控制物理内存区域的访问和缓存,在Intel和AMD CPU中都可用。通过优化CPU缓存特定范围内存地址的方式来提高系统性能,允许直写、写组合或回写缓存。有两个接口可以设置MTRR:一个是ASCII接口,允许在/proc/mtrr中读写。另一个是ioctl()接口。参数是基本物理地址和存储区域的长度。从ACPI中的SRAT获取CXL HDM的物理内存区域,使用ioctl将该内存区域设置为不可缓存。
-
Intel ISA提供了特定的指令,如clflush、clwb或ntstore,用于将数据刷新或直接写入CXL HDM。在HydraRPC中,客户端和服务器端都使用了非临时内存操作,使用clflush/refetch绕过本地缓存。使用内存存储/加载围栏(sfence/lfence),用于同步非临时访问。
-
这两种绕过缓存机制的延迟接近。
-
-
为了实现低CPU利用率和提高性能,提出两种方法。
-
基于轮询的优化。利用CXL HDM上的轮询来检测传入的请求/响应[23,47]。CPU读取请求/响应条目的到达标志,并在到达标志有效时启动处理。为了缓解繁忙轮询期间在内存位置上旋转的问题,使用了两个内部函数(monitor和mwait),专门为具有第三代数据流单指令多数据扩展指令集(SSE3)的英特尔处理器设计,还具有用户模式等效项(ummonitor和umwait)。客户端/服务器以循环缓冲区的缓存行粒度发出监视指令,随后执行mwait指令以停止CPU并节约电源。当另一方修改监控数据时,CPU会被唤醒。这种方法有效地减少了CPU占用空间,提高了内存轮询的性能。
-
基于中断。PCIe MSI(消息信号中断)允许PCIe设备通过消息而不是物理中断线路向CPU发送中断信号[6],通过为每个设备提供多个可扩展的中断向量,提供了更高的性能。CXL的事务层基于PCIe,可以在内核的MSI表中定义一个新的中断类型。当新的内存写入即将到来时,它会启动一个指向主机软件的内存写入事务层包(TLP),此TLP数据包是使用MSI表中相应条目的地址和数据生成的。随后,主机的中断服务例程将TLP识别为中断,并相应地对其进行寻址,RPC处理被唤醒。【目前平台中的无法启用注册以发出MSI信号,没有实现】
-
-
支持滑动窗口协议,以防止访问拥塞。
在真实的CXL硬件上对HydraRPC进行了评估,HydraRPC每个RPC连接可以实现620KOPS的吞吐量,比mRPC[17]和基于RDMA的RPC高1.6/3.1倍,最低RPC延迟为1.47μs。HydraRPC具有良好的可扩展性,每台服务器可以扩展到96个以上的RPC连接,性能仅下降19%。
实验
实验环境:
-
硬件架构:基于Intel Agilex I系列FPGA[26]和配备Sapphire Rapids CPU的Archer City平台。服务器有96个超线程和64GB DIMM,带有16GB CXL HDM的CXL FPGA插入一个节点的PCIe插槽,并用两根8x MCIO电缆连接到另一个节点。FPGA中的硬CXL IP严格遵守CXL规范要求,并配置为支持内存池和共享。硬件架构存在几个限制:
-
必须对CXL链接访问的内存部分和访问类型(读取或读写)进行对齐。HydraRPC应管理该内存(例如使用memmap内核选项),以防止不受控制的访问。
-
为了确保从devkit内存而不是本地缓存读取数据,需要对地址进行缓存失效。
-
为了确保数据被写入devkit内存,而不仅仅是写入本地缓存,需要在写入后刷新缓存行(例如clflush/refetch)。
-
-
软件配置:使用CXL 1.1+驱动程序,支持CXL HDM的服务器内共享。使用daxctl工具在devdax(设备直接访问)模式下初始化CXL HDM,允许load/store指令通过mmap映射dax设备来访问CXL HDM。
实验对比:延迟、吞吐量、CPU利用率
实验参数:请求大小、滑动窗口大小、客户端数量
总结
本文提出基于CXL优化RPC,现有基于消息传递的RPC面临:网络开销高,数据复制开销,可扩展性差。本文提出利用CXL HDM(主机管理设备内存)进行数据传输的HydraRPC。包括4个技术:(1)利用多机间共享的CXL HDM来避免昂贵的网络开销、内存复制和(反)序列化。(2)采用不可缓存的共享来绕过CPU缓存,而不是通用的load/store内存访问指令。(3)基于轮询的优化,使用SSE3的功率降低指令,降低CPU利用率。(4)滑动窗口协议,防止访问拥塞。
相关文章:
HydraRPC: RPC in the CXL Era——论文阅读
ATC 2024 Paper CXL论文阅读笔记整理 问题 远程过程调用(RPC)是分布式系统中的一项基本技术,它允许函数在远程服务器上通过本地调用执行来促进网络通信,隐藏底层通信过程的复杂性简化了客户端/服务器交互[15]。RPC已成为数据中心…...
pve笔记
配置显卡直通参考 https://blog.csdn.net/m0_59148723/article/details/130923893 https://foxi.buduanwang.vip/virtualization/pve/561.html/ https://www.cnblogs.com/MAENESA/p/18005241 https://www.wangsansan.com/archives/181/ pve配置显卡直通到虚拟机后,…...
typecho仿某度响应式主题Xaink
新闻类型博客主题,简洁好看,适合资讯类、快讯类、新闻类博客建站,响应式设计,支持明亮和黑暗模式 直接下载 zip 源码->解压后移动到 Typecho 主题目录->改名为xaink->启用。 演示图: 下载链接: t…...
springcloud RocketMQ 客户端是怎么走到消费业务逻辑的 - debug step by step
springcloud RocketMQ ,一个mq消息发送后,客户端是怎么一步步拿到消息去消费的?我们要从代码层面探究这个问题。 找的流程图,有待考究。 以下我们开始debug: 拉取数据的线程: PullMessageService.java 本…...
GPT-4o mini小型模型具备卓越的文本智能和多模态推理能力
GPT-4o mini 是首个应用OpenAI 指令层次结构方法的模型,这有助于增强模型抵抗越狱、提示注入和系统提示提取的能力。这使得模型的响应更加可靠,并有助于在大规模应用中更安全地使用。 GPT-4o mini 在学术基准测试中,无论是在文本智能还是多模…...
Milvus 向量数据库进阶系列丨部署形态选型
本系列文章介绍 在和社区小伙伴们交流的过程中,我们发现大家最关心的问题从来不是某个具体的功能如何使用,而是面对一个具体的实战场景时,如何选择合适的向量数据库解决方案或最优的功能组合。在 “Milvus 向量数据库进阶” 这个系列文章中&…...
【React】详解受控表单绑定
文章目录 一、受控组件的基本概念1. 什么是受控组件?2. 受控组件的优势3. 基本示例导入和初始化定义函数组件处理输入变化处理表单提交渲染表单导出组件 二、受控组件的进阶用法1. 多个输入框的处理使用多个状态变量使用一个对象管理状态 2. 处理选择框(…...
使用puma部署ruby on rails的记录
之前写过一篇《记录一下我的Ruby On Rails的systemd服务脚本》的记录,现在补上一个比较政治正确的Ruby On Rails的生产环境部署记录。使用Puma部署项目。 创建文件 /usr/lib/systemd/system/puma.service [Unit] DescriptionPuma HTTP Server DocumentationRuby O…...
如何在Linux上使用Ansible自动化部署
Ansible是一个开源的自动化工具,可以帮助开发人员和系统管理员对大规模的服务器进行自动化部署和管理。它使用SSH协议来在远程服务器上执行任务,并通过模块化的方式提供了丰富的功能,可以轻松地管理服务器配置、软件部署和应用程序运行。 在…...
scrapy爬取城市天气数据
scrapy爬取城市天气数据 一、创建scrapy项目二、修改settings,设置UA,开启管道三、编写爬虫文件四、编写items.py五、在weather.py中导入WeatherSpiderItem类六、管道中存入数据,保存至csv文件七、完整代码一、创建scrapy项目 先来看一下爬取的字段情况: 本次爬取城市天…...
一天搞定React(5)——ReactRouter(下)【已完结】
Hello!大家好,今天带来的是React前端JS库的学习,课程来自黑马的往期课程,具体连接地址我也没有找到,大家可以广搜巡查一下,但是总体来说,这套课程教学质量非常高,每个知识点都有一个…...
微信小程序之计算器
在日常生活中,计算器是人们广泛使用的工具,可以帮助我们快速且方便地计算金额、成本、利润等。下面将会讲解如何开发一个“计算器”微信小程序。 一、开发思路 1、界面和功能 “计算器”微信小程序的页面效果如图所示 在计算器中可以进行整数和小数的…...
【logstash】logstash使用多个子配置文件
这里有个误区在pipelines.yml中写conf.d/*,实测会有问题,不同的filter处理逻辑会复用。 现在有两个从kafka采集日志的配置文件:from_kafka1.conf,from_kafka2.conf 修改pipelines.yml配置文件 config/pipelines.yml- pipeline.i…...
暴风骑士S9电摩上市,定义青少年骑行安全新标准
暴风骑士,作为全球高端儿童电动车的开创品牌,以其卓越的技术实力和创新精神,不断推动行业发展。如今,暴风骑士再次突破自我,推出了全新力作——S9青少年电摩。这款全新上市的青少年专属电摩,以其领先的安全…...
spring security如何适配盐存在数据库中的密码
19.token认证过滤器代码实现_哔哩哔哩_bilibili19.token认证过滤器代码实现是SpringSecurity框架教程-Spring SecurityJWT实现项目级前端分离认证授权-挑战黑马&尚硅谷的第20集视频,该合集共计41集,视频收藏或关注UP主,及时了解更多相关视…...
Go语言编程 学习笔记整理 第2章 顺序编程 后半部分
1.流程控制 1.1 条件语句 if a < 5 { return 0 } else { return 1 } 注意:在有返回值的函数中,不允许将“最终的”return语句包含在if...else...结构中, 否则会编译失败!!! func example(x int) i…...
美团后端二面
美团后端二面 ……………………………… 两道场景 一道 数字转中文读法(1000-》一千) 0八股0自我介绍 反问 “您觉得我能过吗?” “这个需要横行对比之后才能有结果” ……………………………… 什么时候到岗 场景题 1 假设我有一个…...
学懂C语言(十六):对C语言作用域规则 局部变量、全局变量的认识
一、C 作用域规则 任何一种编程中,作用域是程序中定义的变量所存在的区域,超过该区域变量就不能被访问。C 语言中有三个地方可以声明变量: 局部变量:在函数或块内部全局变量:在所有函数外部形式参数:在函数…...
关于TS(typescript)的理论知识
关于TS(typescript)的理论知识 TypeScript 是一种由微软开发的开源编程语言,它是 JavaScript 的一个超集,添加了可选的静态类型和基于类的面向对象编程。TypeScript 最终会被编译成纯 JavaScript 代码,以便在任何支持 …...
【OpenCV C++20 学习笔记】基本图像容器——Mat
【OpenCV C20 学习笔记】基本图像容器——Mat 概述Mat内部结构引用计数机制颜色数据格式 显式创建Mat对象使用cv::Mat::Mat构造函数矩阵的数据项 使用数组进行初始化的构造函数cv::Mat::create函数MATLAB风格的初始化小型矩阵通过复制创建Mat对象 Mat对象的输出其他普通数据项的…...
枚举单例是怎么保证线程安全和防止反射的
枚举单例在Java中具有天然的线程安全性和防止反射攻击的特性,这是由于Java对枚举类型的特殊处理方式。以下是详细解释: 1. 线程安全性 Java 枚举类的特性 类加载机制:枚举类型在Java中是特殊的类,由JVM保证其线程安全性。枚举类…...
传知代码-智慧医疗:纹理特征VS卷积特征(论文复现)
代码以及视频讲解 本文所涉及所有资源均在传知代码平台可获取 论文链接:https://www.sciencedirect.com/science/article/abs/pii/S1076633223003537?__cf_chl_rt_tkJ9Aipfxyk5d.leu48P20ePFNd4B2aunaSmzVpXCg.7g-1721292386-0.0.1.1-6249 论文概述 今天我们把视线…...
数据结构中的八大金刚--------八大排序算法
目录 引言 一:InsertSort(直接插入排序) 二:ShellSort(希尔排序) 三:BubbleSort(冒泡排序) 四: HeapSort(堆排序) 五:SelectSort(直接选择排序) 六:QuickSort(快速排序) 1.Hoare版本 2.前后指针版本 …...
ACC2.【C语言】经验积累 栈区简单剖析
int main() {int i0;int arr[10]{1,2,3,4,5,6,7,8,9,10};for (i0;i<12;i){arr[i]0;printf("A");}return 0; } 执行后无限打印A 在VS2022,X86,Debug环境下,用监视后,原因是arr[12]的地址与i的地址重合(数组越界&…...
c# 索引器
索引器(Indexer)允许你像访问数组一样,通过索引访问对象的属性或数据。索引器的主要用途是在对象内部封装复杂的数据结构,使得数据访问更加直观。下面是关于 C# 索引器的详细解释及示例: 基本语法 索引器的语法类似于…...
低代码如何加速数字化转型
数字化转型,正日益决定企业成功的关键。这里的一个关键因素是它可以以更快的速度和质量来实施技术计划。在当今瞬息万变的商业环境中,战略性地采用低代码平台对于旨在加快上市时间、增强业务敏捷性和促进跨团队无缝协作的首席技术官来说至关重要。日益增…...
Pytest进阶之fixture的使用(超详细)
目录 Fixture定义 Fixture使用方式 作为参数使用 Fixture间相互调用(作为参数调用) 作为conftest.py文件传入 Fixture作用范围Scope function class module session Fixture中params和ids Fixture中autouse Fixture中Name 总结 pytest fixture 是一种用来管理测试…...
GitHub 详解教程
1. 引言 GitHub 是一个用于版本控制和协作的代码托管平台,基于 Git 构建。它提供了强大的功能,使开发者可以轻松管理代码、追踪问题、进行代码审查和协作开发。 2. Git 与 GitHub 的区别 Git 是一个分布式版本控制系统,用于跟踪文件的更改…...
边界网关IPSEC VPN实验
拓扑: 实验要求:通过IPSEC VPN能够使PC2通过网络访问PC3 将整个路线分为三段 IPSEC配置在FW1和FW2上,在FW1与FW2之间建立隧道,能够传递IKE(UDP500)和ESP数据包,然后在FW1与PC2之间能够流通数据…...
力扣高频SQL 50题(基础版)第六题
文章目录 1378. 使用唯一标识码替换员工ID题目说明思路分析实现过程结果截图总结 1378. 使用唯一标识码替换员工ID 题目说明 Employees 表: ---------------------- | Column Name | Type | ---------------------- | id | int | | name | varchar | ------…...
在一个事物方法中开启新事物,完成对数据库的修改
在Java中,使用Transactional注解来管理事务非常常见。但是,在一个已经标记为Transactional的方法内部调用另一个也标记了Transactional的方法时,如果不正确处理,可能会导致一些意料之外的行为。这是因为默认情况下,Spr…...
ffmpeg的vignetting filter
vignetting filter是暗角过滤器 vignetting filter在官网是vignette。但是我查了一下,vignetting应该是正确的表达,vignette是什么鬼? 官网参数 官书参数 参数解释 angle,x0,y0可以使用表达式。 angle:不知道什么意思…...
商场导航系统:从电子地图到AR导航,提升顾客体验与运营效率的智能解决方案
商场是集娱乐、休闲、社交于一体的综合性消费空间,随着商场规模的不断扩大和布局的日益复杂,顾客在享受丰富选择的同时,也面临着寻路难、店铺曝光率低以及商场管理效率低下等挑战。商场导航系统作为提升购物体验的关键因素,其重要…...
vue3中父子组件的双向绑定defineModel详细使用方法
文章目录 一、defineProps() 和 defineEmits()二、defineModel() 的双向绑定2.1、基础示例2.2、定义类型2.3、声明prop名称2.4、其他声明2.5、绑定多个值2.6、修饰符和转换器2.7、修饰符串联 一、defineProps() 和 defineEmits() 组件之间通讯,通过 props 和 emits…...
耳机、音响UWB传输数据模组,飞睿智能低延迟、高速率超宽带uwb模块技术音频应用
在数字化浪潮席卷全球的今天,无线通信技术日新月异,其中超宽带(Ultra-Wideband,简称UWB)技术以其独特的优势,正逐步成为无线传输领域的新星。本文将深入探讨飞睿智能UWB传输数据模组在音频应用中的创新应用…...
webpack配置报错:Invalid options object.
前言: 今天在使用webpack进行项目配置的时候,运行之后终端报错:Invalid options object. Dev Server has been initialized using an options object that does not match the API schema. - options has an unknown property inline. Thes…...
Java 并发编程:一文了解 Java 内存模型(处理器优化、指令重排序与内存屏障的深层解析)
大家好,我是栗筝i,这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 022 篇文章,在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验,并希望进…...
谷粒商城实战笔记-64-商品服务-API-品牌管理-OSS前后联调测试上传
文章目录 1,拷贝文件到前端工程2,局部修改3,在品牌编辑界面使用上传组件4,OSS配置允许跨域5,测试multiUpload.vue完整代码singleUpload.vue完整代码policy.js代码 在Web应用开发中,文件上传是一项非常常见的…...
Springboot 开发之 RestTemplate 简介
一、什么是RestTemplate RestTemplate 是Spring框架提供的一个用于应用中调用REST服务的类。它简化了与HTTP服务的通信,统一了RESTFul的标准,并封装了HTTP连接,我们只需要传入URL及其返回值类型即可。RestTemplate的设计原则与许多其他Sprin…...
Django transaction.atomic()事务处理
在Django中,transaction.atomic()是一个上下文管理器,它会自动开始一个事务,并在代码块执行完毕后提交事务。如果在代码块中抛出异常,事务将被自动回滚,确保数据库的一致性和完整性。 在实际应用中,你可能需…...
2024.07-电视版免费影视App推荐和猫影视catvod、TVBox源(最新接口地址)
文章目录 电视版免费影视App推荐精选列表(2024.07可用筛选列表):2024.07可用筛选列表,盲盒资源打包合集下载安装说明真的是盲盒? 猫影视catvod、TVBoxTVBox源推荐可用列表目前不可用列表(前缀为错误状态码&…...
【Python】 基于Q-learning 强化学习的贪吃蛇游戏(源码+论文)【独一无二】
👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉公众号👈:测试开发自动化【获取源码商业合作】 👉荣__誉👈:阿里云博客专家博主、5…...
谷粒商城实战笔记-44-前端基础-Vue-整合ElementUI快速开发/设置模板代码
文章目录 一,安装导入ElementUI1,安装 element-ui2,导入 element-ui 二,ElementUI 实战1,将 App.vue 改为 element-ui 中的后台布局2,开发导航栏2.1 开发MyTable组件2.2 注册路由2.3 改造App.vue2.4 新增左…...
Android adb shell ps进程查找以及kill
Android adb shell ps进程查找以及kill 列出当前Android手机上运行的所有进程信息如PID等: adb shell ps 但是这样会列出一大堆进程信息,不便于定向查阅,可以使用关键词查找: adb shell "ps | grep 关键词" 关键词查…...
[OJ]水位线问题,1.采用回溯法(深度优先遍历求解)2.采用广度优先遍历求解
1.深度优先遍历 使用回溯法,深度优先遍历利用栈先进后出的特点,在加水控制水量失败时, 回到最近一次可对水进行加水与否的位置1.对于给定水量k,是否在[l,r]之间, 是:是否加水(加水y,用掉x,是否在[l,r]之间)(不加水y,用掉x,是否在[l,r]之间)先尝试加水,如…...
《华为数据之道》读书笔记六---面向自助消费的数据服务建设
七、从结果管理到过程管理, 从能“看”到能“管” 1、数据赋能业务运营 数字化运营旨在利用数字化技术获取、管理和分析数据,从而为企业的战略决策与业务运营提供可量化的、科学的支撑。 数字化运营归根结底是运营,旨在推动运营效率与能力的…...
go语言day18 reflect反射
Golang-100-Days/Day16-20(Go语言基础进阶)/day19_Go语言反射.md at master rubyhan1314/Golang-100-Days (github.com) 7-19 接口:底层实现_哔哩哔哩_bilibili 一、interface接口 接口类型内部存储了一对pair(value,Type) type interface { type *Type // 类型信…...
理解 Objective-C 中 `+load` 方法的执行顺序
理解 Objective-C 中 load 方法的执行顺序 在 Objective-C 中,load 方法是在类或分类被加载到内存时调用的。它在程序启动过程中非常早的阶段执行,用于在类或分类被加载时进行一些初始化工作。理解 load 方法的执行顺序对于编写可靠的 Objective-C 代码…...
C++:类和对象2
1.类的默认成员函数 默认成员函数就是用户没有显示实现编译器会自动生成的成员函数称为默认成员函数。一个类,我们在不写的情况下编译器会默认生成6个默认成员函数,分别是构造函数,析构函数,拷贝构造函数,拷贝赋值运算…...
Docker安装kkFileView实现在线文件预览
kkFileView为文件文档在线预览解决方案,该项目使用流行的spring boot搭建,易上手和部署,基本支持主流办公文档的在线预览,如doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,rar,图片,视频,音频等等 官方文档地址:https://kkview.cn/zh-cn/docs/production.html 一、拉取镜像 do…...