608 lines
533 KiB
HTML
608 lines
533 KiB
HTML
|
<!DOCTYPE html>
|
|||
|
<html><head><title>6. KVM 性能优化</title><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><meta property="og:title" content="6. KVM 性能优化"/><meta property="og:description" content="本文详细讨论了KVM虚拟化环境中的性能优化策略,包括资源监控、CPU与内存优化、存储和网络性能提升,以及快照和备份的性能影响。强调了合理分配资源、使用高效技术和工具、以及日志分析在故障排查中的重要性。."/><meta property="og:image" content="https://wiki.7wate.com/static/og-image.png"/><meta property="og:width" content="1200"/><meta property="og:height" content="675"/><link rel="icon" href="../../../../static/icon.png"/><meta name="description" content="本文详细讨论了KVM虚拟化环境中的性能优化策略,包括资源监控、CPU与内存优化、存储和网络性能提升,以及快照和备份的性能影响。强调了合理分配资源、使用高效技术和工具、以及日志分析在故障排查中的重要性。."/><meta name="generator" content="Quartz"/><link rel="preconnect" href="https://fonts.googleapis.com"/><link rel="preconnect" href="https://fonts.gstatic.com"/><script async src="https://umami.7wate.com/script.js" data-website-id="c061efdc-95dd-4d21-9d04-a1ffda0a85b9"></script><script>
|
|||
|
var _hmt = _hmt || [];
|
|||
|
(function() {
|
|||
|
var hm = document.createElement("script");
|
|||
|
hm.src = "https://hm.baidu.com/hm.js?94d8ccb156eb7c65abf317e6e01cdba9";
|
|||
|
var s = document.getElementsByTagName("script")[0];
|
|||
|
s.parentNode.insertBefore(hm, s);
|
|||
|
})();
|
|||
|
</script><script async src="https://www.googletagmanager.com/gtag/js?id=G-MHMEL0F832"></script><script>
|
|||
|
(function() {
|
|||
|
window.dataLayer = window.dataLayer || [];
|
|||
|
function gtag() {
|
|||
|
window.dataLayer.push(arguments);
|
|||
|
}
|
|||
|
gtag('js', new Date());
|
|||
|
gtag('config', 'G-MHMEL0F832');
|
|||
|
})();
|
|||
|
</script><link href="../../../../index.css" rel="stylesheet" type="text/css" spa-preserve/><link href="https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/katex.min.css" rel="stylesheet" type="text/css" spa-preserve/><link href="https://fonts.googleapis.com/css2?family=IBM Plex Mono&family=Schibsted Grotesk:wght@400;700&family=Source Sans Pro:ital,wght@0,400;0,600;1,400;1,600&display=swap" rel="stylesheet" type="text/css" spa-preserve/><script src="../../../../prescript.js" type="application/javascript" spa-preserve></script><script type="application/javascript" spa-preserve>const fetchData = fetch(`../../../../static/contentIndex.json`).then(data => data.json())</script></head><body data-slug="Technology/OperatingSystem/Virtualization/2.KVM虚拟化/6.-KVM-性能优化"><div id="quartz-root" class="page"><div id="quartz-body"><div class="left sidebar"><h1 class="page-title "><a href="../../../..">📚 X·Eden</a></h1><div class="spacer mobile-only"></div><div class="search "><div id="search-icon"><p>Search</p><div></div><svg tabIndex="0" aria-labelledby="title desc" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19.9 19.7"><title id="title">Search</title><desc id="desc">Search</desc><g class="search-path" fill="none"><path stroke-linecap="square" d="M18.5 18.3l-5.4-5.4"></path><circle cx="8" cy="8" r="7"></circle></g></svg></div><div id="search-container"><div id="search-space"><input autocomplete="off" id="search-bar" name="search" type="text" aria-label="Search for something" placeholder="Search for something"/><div id="results-container"></div></div></div></div><div class="darkmode "><input class="toggle" id="darkmode-toggle" type="checkbox" tabIndex="-1"/><label id="toggle-label-light" for="darkmode-toggle" tabIndex="-1"><svg xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" version="1.1" id="dayIcon" x="0px" y="0px" viewBox="0 0 35 35" style="enable-background:new 0 0 35 35;" xmlSpace="preserve"><title>Light mode</title><path d="M6,17.5C6,16.672,5.328,16,4.5,16h-3C0.672,16,0,16.672,0,17.5 S0.672,19,1.5,19h3C5.328,19,6,18.328,6,17.5z M7.5,26c-0.414,0-0.789,0.168-1.061,0.439l-2,2C4.168,28.711,4,29.086,4,29.5 C4,30.328,4.671,31,5.5,31c0.414,0,0.789-0.168,1.06-0.44l2-2C8.832,28.289,9,27.914,9,27.5C9,26.672,8.329,26,7.5,26z M17.5,6 C18.329,6,19,5.328,19,4.5v-3C19,0.672,18.329,0,17.5,0S16,0.672,16,1.5v3C16,5.328,16.671,6,17.5,6z M27.5,9 c0.414,0,0.789-0.168,1.06-0.439l2-2C30.832,6.289,31,5.914,31,5.5C31,4.672,30.329,4,29.5,4c-0.414,0-0.789,0.168-1.061,0.44 l-2,2C26.168,6.711,26,7.086,26,7.5C26,8.328,26.671,9,27.5,9z M6.439,8.561C6.711,8.832,7.086,9,7.5,9C8.328,9,9,8.328,9,7.5 c0-0.414-0.168-0.789-0.439-1.061l-2-2C6.289,4.168,5.914,4,5.5,4C4.672,4,4,4.672,4,5.5c0,0.414,0.168,0.789,0.439,1.06 L6.439,8.561z M33.5,16h-3c-0.828,0-1.5,0.672-1.5,1.5s0.672,1.5,1.5,1.5h3c0.828,0,1.5-0.672,1.5-1.5S34.328,16,33.5,16z M28.561,26.439C28.289,26.168,27.914,26,27.5,26c-0.828,0-1.5,0.672-1.5,1.5c0,0.414,0.168,0.789,0.439,1.06l2,2 C28.711,30.832,29.086,31,29.5,31c0.828,0,1.5-0.672,1.5-1.5c0-0.414-0.168-0.789-0.439-1.061L28.561,26.439z M17.5,29 c-0.829,0-1.5,0.672-1.5,1.5v3c0,0.828,0.671,1.5,1.5,1.5s1.5-0.672,1.5-1.5v-3C19,29.672,18.329,29,17.5,29z M17.5,7 C11.71,7,7,11.71,7,17.5S11.71,28,17.5,28S28,23.29,28,17.5S23.29,7,17.5,7z M17.5,25c-4.136,0-7.5-3.364-7.5-7.5 c0-4.136,3.364-7.5,7.5-7.5c4.136,0,7.5,3.364,7.5,7.5C25,21.636,21.636,25,17.5,25z"></path></svg></label><label id="toggle-label-dark" for="darkmode-toggle" tabIndex="-1"><svg xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" version="1.1" id="nightIcon" x="0px" y="0px" viewBox="0 0 100 100" style="enable-background='new 0 0 100 100'" xmlSpace="preserve"><title>Dark mode</title><path d="M96.76,66.458c-0.853-0.852-2.15-1.064-3.23-0.534c-6.063,2.991-12.858,4.571-19.655,4.571 C62.022,70.495,50.88,65.88,42.5,57.5C29.043,44.043,25.658,23.536,34.076,6.47c0.532-1.08,0.318-2.379-0.534-3.23 c-0.851-0.852-2.15-1.064-3.23-0.534c-4.918,2.427-9.375,5.619-13.246,9.491c-9.447,
|
|||
|
<h3 id="为什么需要性能优化">为什么需要性能优化?<a aria-hidden="true" tabindex="-1" href="#为什么需要性能优化" class="internal"> §</a></h3>
|
|||
|
<p>性能优化在虚拟化环境中至关重要,原因如下:</p>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
<p><strong>提高资源利用率:</strong> 通过性能优化,可以更有效地利用计算资源(CPU、内存、存储和网络),从而支持更多的虚拟机运行在同一硬件上。</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p><strong>增强用户体验:</strong> 优化虚拟机性能可以降低延迟、提高响应速度,为最终用户提供更好的体验。</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p><strong>降低运营成本:</strong> 更高的资源利用率意味着可以在相同的硬件投资上运行更多的虚拟机,从而降低数据中心的运营成本。</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p><strong>延长硬件寿命:</strong> 通过优化,避免资源的过度使用和硬件的过度磨损,从而延长硬件的使用寿命。</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p><strong>提高系统稳定性和可靠性:</strong> 优化虚拟化环境中的性能可以减少瓶颈和故障,从而提高系统的稳定性和可靠性。</p>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
<h3 id="性能优化的基本原则">性能优化的基本原则<a aria-hidden="true" tabindex="-1" href="#性能优化的基本原则" class="internal"> §</a></h3>
|
|||
|
<ul>
|
|||
|
<li><strong>监控和分析</strong>:持续监控虚拟机和宿主机的性能指标,分析性能瓶颈。使用工具如 <code>top</code>、<code>htop</code>、<code>vmstat</code>、<code>iostat</code> 和 <code>sar</code>。</li>
|
|||
|
<li><strong>资源隔离和分配</strong>:合理配置虚拟机的资源分配,使用 CPU 和内存配额、限制和保留来避免资源争用。</li>
|
|||
|
<li><strong>调整虚拟机配置</strong>:根据负载情况调整虚拟机的 CPU、内存、存储和网络配置,确保满足应用需求。</li>
|
|||
|
<li><strong>优化存储性能</strong>:使用合适的存储格式(如 <code>qcow2</code> 和 <code>raw</code>)、启用缓存和 I/O 调度策略,优化磁盘 I/O 性能。</li>
|
|||
|
<li><strong>优化网络性能</strong>:使用 Virtio 网络驱动、启用多队列支持、调整网络缓冲区大小和使用网络分段来提高网络性能。</li>
|
|||
|
<li><strong>保持系统和软件更新</strong>:定期更新操作系统和虚拟化软件,获取最新的性能优化和安全补丁。</li>
|
|||
|
</ul>
|
|||
|
<h3 id="性能优化的常见挑战">性能优化的常见挑战<a aria-hidden="true" tabindex="-1" href="#性能优化的常见挑战" class="internal"> §</a></h3>
|
|||
|
<ul>
|
|||
|
<li><strong>资源争用</strong>:当多个虚拟机共享相同的物理资源时,可能会导致资源争用,影响整体性能。需要合理配置资源隔离和分配策略。</li>
|
|||
|
<li><strong>I/O 瓶颈</strong>:磁盘 I/O 和网络 I/O 是虚拟化环境中常见的瓶颈。需要优化存储和网络配置以提高 I/O 性能。</li>
|
|||
|
<li><strong>CPU 和内存过载</strong>:虚拟机可能会导致宿主机的 CPU 和内存过载,从而影响系统性能。需要监控和调整虚拟机的 CPU 和内存使用。</li>
|
|||
|
<li><strong>网络延迟和吞吐量</strong>:虚拟化环境中的网络性能可能受到延迟和吞吐量的限制,需要优化网络配置和使用高效的网络驱动。</li>
|
|||
|
<li><strong>存储性能下降</strong>:存储设备性能下降可能会影响虚拟机的响应时间。需要选择合适的存储设备和优化存储配置。</li>
|
|||
|
<li><strong>软件和硬件兼容性</strong>:某些软件和硬件可能无法充分利用虚拟化环境中的优化功能,需要确保兼容性和最佳实践。</li>
|
|||
|
</ul>
|
|||
|
<h2 id="cpu-性能优化">CPU 性能优化<a aria-hidden="true" tabindex="-1" href="#cpu-性能优化" class="internal"> §</a></h2>
|
|||
|
<p>在 KVM(Kernel-based Virtual Machine)虚拟化环境中,CPU 性能优化对于提升虚拟机(VM)的运行效率和整体系统性能至关重要。本文将深入探讨 CPU 性能优化的几个关键方面,包括 CPU 分配和超线程、CPU 亲和性设置、以及优化 CPU 调度策略。</p>
|
|||
|
<h3 id="cpu-分配和超线程">CPU 分配和超线程<a aria-hidden="true" tabindex="-1" href="#cpu-分配和超线程" class="internal"> §</a></h3>
|
|||
|
<h4 id="分配虚拟-cpu-vcpu">分配虚拟 CPU (vCPU)<a aria-hidden="true" tabindex="-1" href="#分配虚拟-cpu-vcpu" class="internal"> §</a></h4>
|
|||
|
<p>虚拟机的 CPU 分配直接影响其性能。为虚拟机分配适当数量的 vCPU 可以确保其在执行任务时拥有足够的计算资源。以下是几个关键点:</p>
|
|||
|
<ol>
|
|||
|
<li><strong>评估工作负载</strong>:根据虚拟机所需运行的应用程序或服务的特定需求来分配 vCPU 数量。一般来说,轻量级应用程序需要较少的 vCPU,而计算密集型应用程序则需要更多的 vCPU。</li>
|
|||
|
<li><strong>避免过度分配</strong>:避免为虚拟机分配过多的 vCPU,这样可能会导致宿主机资源紧张,影响整体性能。</li>
|
|||
|
<li><strong>动态调整</strong>:利用 KVM 的热插拔功能,可以在虚拟机运行时动态调整 vCPU 数量,以适应变化的工作负载。</li>
|
|||
|
</ol>
|
|||
|
<h4 id="启用和配置超线程">启用和配置超线程<a aria-hidden="true" tabindex="-1" href="#启用和配置超线程" class="internal"> §</a></h4>
|
|||
|
<p>超线程技术(Hyper-Threading)允许每个物理 CPU 核心同时处理多个线程,从而提高 CPU 的并行处理能力。启用和配置超线程可以显著提升虚拟机的性能:</p>
|
|||
|
<ol>
|
|||
|
<li><strong>启用超线程</strong>:在 BIOS 或 UEFI 中启用超线程功能,以便操作系统和 KVM 可以利用这一技术。</li>
|
|||
|
<li><strong>合理配置</strong>:在分配 vCPU 时,考虑超线程的影响。例如,如果物理 CPU 核心启用了超线程,理论上每个核心可以运行两个 vCPU。根据实际性能测试结果,调整 vCPU 分配策略。</li>
|
|||
|
</ol>
|
|||
|
<h3 id="cpu-亲和性设置">CPU 亲和性设置<a aria-hidden="true" tabindex="-1" href="#cpu-亲和性设置" class="internal"> §</a></h3>
|
|||
|
<h4 id="配置-cpu-亲和性">配置 CPU 亲和性<a aria-hidden="true" tabindex="-1" href="#配置-cpu-亲和性" class="internal"> §</a></h4>
|
|||
|
<p>CPU 亲和性(CPU Affinity)指将特定的 vCPU 绑定到物理 CPU 核心上,从而减少 CPU 切换带来的性能开销,提高缓存命中率。配置 CPU 亲和性的方法包括:</p>
|
|||
|
<ol>
|
|||
|
<li><strong>手动配置</strong>:在创建虚拟机时,通过指定 vCPU 与物理 CPU 核心的绑定关系来配置 CPU 亲和性。</li>
|
|||
|
<li><strong>自动化工具</strong>:使用自动化工具(如 libvirt)进行配置,简化管理过程。</li>
|
|||
|
</ol>
|
|||
|
<h4 id="使用-virsh-设置-vcpu-亲和性">使用 <code>virsh</code> 设置 vCPU 亲和性<a aria-hidden="true" tabindex="-1" href="#使用-virsh-设置-vcpu-亲和性" class="internal"> §</a></h4>
|
|||
|
<p><code>virsh</code> 是一个用于管理 KVM 虚拟机的命令行工具,通过它可以方便地设置和调整 vCPU 亲和性:</p>
|
|||
|
<ol>
|
|||
|
<li><strong>查看当前配置</strong>:使用 <code>virsh vcpuinfo <VM名></code> 查看虚拟机当前的 vCPU 配置和绑定关系。</li>
|
|||
|
<li><strong>设置亲和性</strong>:使用 <code>virsh vcpupin <VM名> <vCPU编号> <物理CPU编号></code> 命令,将指定的 vCPU 绑定到物理 CPU 核心。例如,<code>virsh vcpupin myvm 0 2</code> 将虚拟机 myvm 的第一个 vCPU 绑定到物理 CPU 的第二个核心。</li>
|
|||
|
<li><strong>保存配置</strong>:确保更改的配置在虚拟机重启后仍然有效,可以将配置写入虚拟机的 XML 配置文件中。</li>
|
|||
|
</ol>
|
|||
|
<h3 id="优化-cpu-调度策略">优化 CPU 调度策略<a aria-hidden="true" tabindex="-1" href="#优化-cpu-调度策略" class="internal"> §</a></h3>
|
|||
|
<h4 id="使用-cgroups-控制-cpu-使用">使用 Cgroups 控制 CPU 使用<a aria-hidden="true" tabindex="-1" href="#使用-cgroups-控制-cpu-使用" class="internal"> §</a></h4>
|
|||
|
<p>控制组(cgroups)是一种 Linux 内核功能,允许用户对进程进行资源限制和监控。利用 cgroups 可以更精细地控制虚拟机的 CPU 资源使用:</p>
|
|||
|
<ol>
|
|||
|
<li><strong>创建 cgroup</strong>:使用 <code>cgcreate</code> 命令创建一个新的 cgroup。例如,<code>cgcreate -g cpu:/mygroup</code> 创建一个名为 mygroup 的 cgroup。</li>
|
|||
|
<li><strong>设置 CPU 限额</strong>:使用 <code>cgset</code> 命令设置 cgroup 的 CPU 使用限制。例如,<code>cgset -r cpu.shares=512 mygroup</code> 将 mygroup 的 CPU 使用份额设置为 512。</li>
|
|||
|
<li><strong>将虚拟机进程加入 cgroup</strong>:通过 <code>cgclassify</code> 或 <code>echo <PID> > /sys/fs/cgroup/cpu/mygroup/tasks</code> 命令将虚拟机进程加入 cgroup 中,以应用资源限制。</li>
|
|||
|
</ol>
|
|||
|
<h4 id="调整调度策略">调整调度策略<a aria-hidden="true" tabindex="-1" href="#调整调度策略" class="internal"> §</a></h4>
|
|||
|
<p>KVM 虚拟化环境中,合理的 CPU 调度策略可以显著提升虚拟机的性能和响应速度。常见的调度策略包括:</p>
|
|||
|
<ol>
|
|||
|
<li><strong>完全公平调度器(CFS)</strong>:Linux 默认的调度策略,适用于大多数场景。通过调整 CFS 参数,可以优化虚拟机的 CPU 性能。</li>
|
|||
|
<li><strong>实时调度器(RT)</strong>:适用于对延迟敏感的应用,如音视频处理或实时计算任务。可以通过设置实时优先级和资源预留来优化性能。</li>
|
|||
|
<li><strong>自动化调度工具</strong>:使用如 libvirt 的调度策略配置功能,自动优化虚拟机的调度策略。</li>
|
|||
|
</ol>
|
|||
|
<p>通过以上方法和工具,可以系统地优化 KVM 环境下虚拟机的 CPU 性能,从而提高整体系统的效率和稳定性。在实际应用中,应根据具体需求和工作负载特征,选择合适的优化策略和参数设置,以达到最佳性能表现。</p>
|
|||
|
<h2 id="内存性能优化">内存性能优化<a aria-hidden="true" tabindex="-1" href="#内存性能优化" class="internal"> §</a></h2>
|
|||
|
<p>内存性能是虚拟化环境中影响虚拟机(VM)运行效率的关键因素之一。KVM(Kernel-based Virtual Machine)提供了多种内存优化技术,本文将详细探讨内存分配和大页支持、内存过量使用和气球驱动、以及 NUMA 配置优化等方面的内容。</p>
|
|||
|
<h3 id="内存分配和大页支持">内存分配和大页支持<a aria-hidden="true" tabindex="-1" href="#内存分配和大页支持" class="internal"> §</a></h3>
|
|||
|
<h4 id="分配合适的内存大小">分配合适的内存大小<a aria-hidden="true" tabindex="-1" href="#分配合适的内存大小" class="internal"> §</a></h4>
|
|||
|
<p>为虚拟机分配合适的内存大小是确保其性能的基本步骤:</p>
|
|||
|
<ol>
|
|||
|
<li><strong>评估工作负载需求</strong>:根据虚拟机上运行的应用程序和服务的需求,确定所需的内存大小。轻量级应用程序需要较少的内存,而数据密集型或计算密集型应用程序则需要更多的内存。</li>
|
|||
|
<li><strong>避免过度分配</strong>:过度分配内存会导致宿主机的内存资源紧张,影响整体系统性能。因此,需要合理分配内存,确保宿主机和所有虚拟机的内存需求都能得到满足。</li>
|
|||
|
<li><strong>动态调整内存</strong>:利用 KVM 的热插拔内存功能,可以在虚拟机运行时动态调整内存大小,以应对变化的工作负载需求。</li>
|
|||
|
</ol>
|
|||
|
<h4 id="启用和配置大页hugepages">启用和配置大页(HugePages)<a aria-hidden="true" tabindex="-1" href="#启用和配置大页hugepages" class="internal"> §</a></h4>
|
|||
|
<p>大页(HugePages)是指较大的内存页,用于减少内存分页和 TLB(Translation Lookaside Buffer)失效的开销,从而提高内存访问效率。启用和配置大页可以显著提升虚拟机的性能:</p>
|
|||
|
<ol>
|
|||
|
<li><strong>启用大页支持</strong>:在宿主机上启用大页支持,可以通过修改内核参数或使用命令来实现。例如,可以在 <code>/etc/sysctl.conf</code> 文件中添加 <code>vm.nr_hugepages=512</code>,然后运行 <code>sysctl -p</code> 应用配置。</li>
|
|||
|
<li><strong>配置大页使用</strong>:在创建或配置虚拟机时,指定其使用大页内存。例如,通过 libvirt 的 XML 配置文件,可以在 <code><memoryBacking></code> 节点中添加 <code><hugepages/></code> 元素。</li>
|
|||
|
<li><strong>监控大页使用</strong>:使用 <code>cat /proc/meminfo | grep HugePages</code> 查看当前系统的大页使用情况,确保配置的生效和合理性。</li>
|
|||
|
</ol>
|
|||
|
<h3 id="内存过量使用和气球驱动">内存过量使用和气球驱动<a aria-hidden="true" tabindex="-1" href="#内存过量使用和气球驱动" class="internal"> §</a></h3>
|
|||
|
<h4 id="启用内存过量使用">启用内存过量使用<a aria-hidden="true" tabindex="-1" href="#启用内存过量使用" class="internal"> §</a></h4>
|
|||
|
<p>内存过量使用(Memory Overcommitment)允许为虚拟机分配的内存总量超过宿主机的物理内存量,从而提高资源利用率:</p>
|
|||
|
<ol>
|
|||
|
<li><strong>评估风险</strong>:内存过量使用虽然可以提高资源利用率,但也带来了一定的风险,如宿主机内存不足导致的性能下降或崩溃。因此,需要谨慎评估和控制过量使用的程度。</li>
|
|||
|
<li><strong>启用内存过量使用</strong>:在 KVM 环境中,可以通过调整宿主机的内存管理策略和参数来实现内存过量使用。例如,调整 <code>vm.overcommit_memory</code> 参数为 <code>1</code>,表示允许过量分配内存。</li>
|
|||
|
</ol>
|
|||
|
<h4 id="使用气球驱动动态调整内存">使用气球驱动动态调整内存<a aria-hidden="true" tabindex="-1" href="#使用气球驱动动态调整内存" class="internal"> §</a></h4>
|
|||
|
<p>气球驱动(Ballooning)是一种动态调整虚拟机内存分配的技术,通过调整虚通过以上常见性能问题及其解决方法的介绍,以及日志分析方法的讲解,可以帮助管理员有效地排查和解决 KVM 虚拟化环境中的性能问题,确保虚拟机的稳定运行和高效性能。在实际应用中,应结合具体问题和环境特点,灵活应用这些故障排查方法。拟机的内存使用,优化宿主机的内存资源分配:</p>
|
|||
|
<ol>
|
|||
|
<li><strong>安装气球驱动</strong>:确保虚拟机中安装了气球驱动,通常 KVM 虚拟机中默认包含该驱动。如果没有,可以通过安装相应的虚拟化工具包来获取。</li>
|
|||
|
<li><strong>启用气球驱动</strong>:在虚拟机的配置文件中启用气球驱动,例如在 libvirt 的 XML 配置文件中,添加 <code><memballoon model='virtio'/></code> 元素。</li>
|
|||
|
<li><strong>动态调整内存</strong>:使用 <code>virsh</code> 命令行工具,通过 <code>virsh setmem <VM名> <内存大小></code> 命令动态调整虚拟机的内存大小。例如,<code>virsh setmem myvm 2G</code> 将虚拟机 myvm 的内存调整为 2GB。</li>
|
|||
|
</ol>
|
|||
|
<h3 id="numa-配置优化">NUMA 配置优化<a aria-hidden="true" tabindex="-1" href="#numa-配置优化" class="internal"> §</a></h3>
|
|||
|
<h4 id="什么是-numa">什么是 NUMA?<a aria-hidden="true" tabindex="-1" href="#什么是-numa" class="internal"> §</a></h4>
|
|||
|
<p>非一致性内存访问(NUMA,Non-Uniform Memory Access)是一种内存架构,在多处理器系统中,每个处理器拥有自己的本地内存,访问本地内存的速度比访问其他处理器的内存更快。合理配置 NUMA 可以显著提升多处理器系统中虚拟机的性能。</p>
|
|||
|
<h4 id="配置虚拟机的-numa-节点">配置虚拟机的 NUMA 节点<a aria-hidden="true" tabindex="-1" href="#配置虚拟机的-numa-节点" class="internal"> §</a></h4>
|
|||
|
<p>在 KVM 虚拟化环境中,可以配置虚拟机的 NUMA 节点,以优化内存访问性能:</p>
|
|||
|
<ol>
|
|||
|
<li>
|
|||
|
<p><strong>查看宿主机的 NUMA 配置</strong>:使用 <code>numactl --hardware</code> 或 <code>lscpu</code> 命令查看宿主机的 NUMA 节点和 CPU、内存分布情况。</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>配置虚拟机的 NUMA 节点:在 libvirt 的 XML 配置文件中,指定虚拟机的 NUMA 节点。例如:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="xml" data-theme="default"><code data-language="xml" data-theme="default"><span data-line> </span>
|
|||
|
<span data-line> </span>
|
|||
|
<span data-line> </span>
|
|||
|
<span data-line> </span>
|
|||
|
<span data-line> </span>
|
|||
|
<span data-line> </span>
|
|||
|
<span data-line> </span>
|
|||
|
<span data-line> </span></code></pre></div>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
<numatune>
|
|||
|
<memory mode="strict" nodeset="0-1">
|
|||
|
</memory></numatune>
|
|||
|
<cputune>
|
|||
|
<vcpupin vcpu="0" cpuset="0-3">
|
|||
|
<vcpupin vcpu="1" cpuset="4-7">
|
|||
|
</vcpupin></vcpupin></cputune>
|
|||
|
<memorybacking>
|
|||
|
<nodeset>0-1</nodeset>
|
|||
|
</memorybacking>
|
|||
|
```
|
|||
|
<p>以上配置将虚拟机的内存和 vCPU 绑定到宿主机的 0 和 1 号 NUMA 节点,确保虚拟机内存访问的性能。</p>
|
|||
|
<ol start="3">
|
|||
|
<li><strong>测试和调整</strong>:在实际应用中,通过性能测试和监控工具,评估 NUMA 配置的效果,根据需要进行调整和优化。</li>
|
|||
|
</ol>
|
|||
|
<h2 id="存储性能优化">存储性能优化<a aria-hidden="true" tabindex="-1" href="#存储性能优化" class="internal"> §</a></h2>
|
|||
|
<p>在 KVM(Kernel-based Virtual Machine)虚拟化环境中,磁盘 I/O 性能是影响虚拟机(VM)整体性能的关键因素之一。本文将详细探讨使用 Virtio 驱动提升性能、优化磁盘 I/O 调度策略、以及使用缓存策略等方面的内容。</p>
|
|||
|
<h3 id="使用-virtio-驱动提升性能">使用 Virtio 驱动提升性能<a aria-hidden="true" tabindex="-1" href="#使用-virtio-驱动提升性能" class="internal"> §</a></h3>
|
|||
|
<h4 id="virtio-驱动的优势">Virtio 驱动的优势<a aria-hidden="true" tabindex="-1" href="#virtio-驱动的优势" class="internal"> §</a></h4>
|
|||
|
<p>Virtio 是 KVM 环境中用于提高虚拟机 I/O 性能的一组标准驱动程序。Virtio 驱动通过简化虚拟化 I/O 路径和减少开销,提供了显著的性能提升:</p>
|
|||
|
<ol>
|
|||
|
<li><strong>高效的 I/O 处理</strong>:Virtio 驱动直接与 KVM hypervisor 通信,减少了传统设备模拟带来的开销,提高了 I/O 操作的效率。</li>
|
|||
|
<li><strong>更低的延迟</strong>:通过简化 I/O 路径和优化数据传输,Virtio 驱动显著降低了 I/O 操作的延迟,提升了虚拟机的响应速度。</li>
|
|||
|
<li><strong>广泛的兼容性</strong>:Virtio 驱动被广泛支持,适用于大多数 Linux 发行版和现代 Windows 操作系统,确保了虚拟机的兼容性和稳定性。</li>
|
|||
|
</ol>
|
|||
|
<h4 id="安装和配置-virtio-驱动">安装和配置 Virtio 驱动<a aria-hidden="true" tabindex="-1" href="#安装和配置-virtio-驱动" class="internal"> §</a></h4>
|
|||
|
<p>安装和配置 Virtio 驱动以充分利用其性能优势:</p>
|
|||
|
<ol>
|
|||
|
<li>
|
|||
|
<p><strong>Linux 虚拟机</strong>:在大多数现代 Linux 发行版中,Virtio 驱动通常已经内置。如果需要手动安装,可以使用包管理器安装相应的 Virtio 驱动包。</p>
|
|||
|
<p>配置虚拟机使用 Virtio 驱动,在 libvirt 的 XML 配置文件中,将磁盘设备类型设置为 <code>virtio</code>:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="xml" data-theme="default"><code data-language="xml" data-theme="default"><span data-line><span style="color:var(--shiki-color-text);"><</span><span style="color:var(--shiki-token-string-expression);">disk</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">type</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'file'</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">device</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'disk'</span><span style="color:var(--shiki-color-text);">></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">driver</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">name</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'qemu'</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">type</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'qcow2'</span><span style="color:var(--shiki-color-text);">/></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">source</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">file</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'/var/lib/libvirt/images/myvm.qcow2'</span><span style="color:var(--shiki-color-text);">/></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">target</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">dev</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'vda'</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">bus</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'virtio'</span><span style="color:var(--shiki-color-text);">/></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"></</span><span style="color:var(--shiki-token-string-expression);">disk</span><span style="color:var(--shiki-color-text);">></span></span></code></pre></div>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p><strong>Windows 虚拟机</strong>:</p>
|
|||
|
<ul>
|
|||
|
<li>下载并安装 Virtio 驱动程序,通常可以从 Red Hat 提供的 Virtio 驱动包中获取。</li>
|
|||
|
<li>在虚拟机创建过程中,通过虚拟光驱加载 Virtio 驱动 ISO 文件,并在 Windows 安装过程中手动加载驱动程序。</li>
|
|||
|
<li>配置完成后,在设备管理器中确认 Virtio 驱动已正确安装并应用于相应的设备。</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
<h3 id="磁盘-io-调度策略">磁盘 I/O 调度策略<a aria-hidden="true" tabindex="-1" href="#磁盘-io-调度策略" class="internal"> §</a></h3>
|
|||
|
<h4 id="选择合适的-io-调度器">选择合适的 I/O 调度器<a aria-hidden="true" tabindex="-1" href="#选择合适的-io-调度器" class="internal"> §</a></h4>
|
|||
|
<p>I/O 调度器负责管理磁盘 I/O 请求的调度,选择合适的 I/O 调度器可以显著提升磁盘 I/O 性能。常见的 I/O 调度器包括:</p>
|
|||
|
<ol>
|
|||
|
<li><strong>CFQ(Completely Fair Queuing)</strong>:适用于大多数通用场景,通过公平分配 I/O 带宽,提供较好的性能和响应时间。</li>
|
|||
|
<li><strong>Deadline</strong>:适用于对延迟敏感的应用,通过设置请求的截止时间,确保 I/O 请求在规定时间内完成,减少延迟。</li>
|
|||
|
<li><strong>NOOP</strong>:适用于 SSD 等固态存储设备,采用简单的 FIFO 队列,减少 I/O 调度开销。</li>
|
|||
|
</ol>
|
|||
|
<p>在宿主机上,可以通过修改 <code>/sys/block/<设备名>/queue/scheduler</code> 文件来设置 I/O 调度器,例如:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line><span style="color:var(--shiki-token-function);">echo</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">deadline</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-keyword);">></span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">/sys/block/sda/queue/scheduler</span></span></code></pre></div>
|
|||
|
<h4 id="使用-ionice-控制-io-优先级">使用 <code>ionice</code> 控制 I/O 优先级<a aria-hidden="true" tabindex="-1" href="#使用-ionice-控制-io-优先级" class="internal"> §</a></h4>
|
|||
|
<p><code>ionice</code> 命令可以设置进程的 I/O 优先级,从而控制其 I/O 操作的优先级顺序:</p>
|
|||
|
<ol>
|
|||
|
<li>
|
|||
|
<p><strong>命令语法</strong>:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line><span style="color:var(--shiki-token-function);">ionice</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">-c</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-keyword);"><</span><span style="color:var(--shiki-token-string);">clas</span><span style="color:var(--shiki-color-text);">s</span><span style="color:var(--shiki-token-keyword);">></span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">-n</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-keyword);"><</span><span style="color:var(--shiki-token-string);">priorit</span><span style="color:var(--shiki-color-text);">y</span><span style="color:var(--shiki-token-keyword);">></span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-keyword);"><</span><span style="color:var(--shiki-token-string);">comman</span><span style="color:var(--shiki-color-text);">d</span><span style="color:var(--shiki-token-keyword);">></span></span></code></pre></div>
|
|||
|
<ul>
|
|||
|
<li><code><class></code>:I/O 优先级类别,0(实时)、1(最佳努力)、2(空闲)。</li>
|
|||
|
<li><code><priority></code>:优先级级别,范围为 0 到 7,数值越小优先级越高。</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p><strong>示例</strong>:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line><span style="color:var(--shiki-token-function);">ionice</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">-c</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-constant);">1</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">-n</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-constant);">3</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">dd</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">if=/dev/zero</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">of=/var/lib/libvirt/images/test.img</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">bs=</span><span style="color:var(--shiki-token-constant);">1</span><span style="color:var(--shiki-token-string);">M</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">count=</span><span style="color:var(--shiki-token-constant);">1024</span></span></code></pre></div>
|
|||
|
<p>以上命令将 <code>dd</code> 命令的 I/O 优先级设置为最佳努力类别,优先级为 3。</p>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
<h3 id="使用缓存策略">使用缓存策略<a aria-hidden="true" tabindex="-1" href="#使用缓存策略" class="internal"> §</a></h3>
|
|||
|
<h4 id="配置缓存模式">配置缓存模式<a aria-hidden="true" tabindex="-1" href="#配置缓存模式" class="internal"> §</a></h4>
|
|||
|
<p>KVM 虚拟机的磁盘设备支持多种缓存模式,不同缓存模式对性能有不同影响:</p>
|
|||
|
<ol>
|
|||
|
<li><strong>none</strong>:直接 I/O 模式,虚拟机的 I/O 请求直接传递到宿主机,不经过宿主机的页缓存。适用于需要确保数据一致性的场景,如数据库应用。</li>
|
|||
|
<li><strong>writeback</strong>:写回缓存模式,I/O 请求先写入缓存,再异步写入磁盘。提供较好的写入性能,但在宿主机崩溃时可能导致数据丢失。</li>
|
|||
|
<li><strong>writethrough</strong>:直写缓存模式,写请求直接写入磁盘,同时更新缓存。确保数据的一致性,但写入性能相对较低。</li>
|
|||
|
</ol>
|
|||
|
<p>在 libvirt 的 XML 配置文件中,可以通过 <code><driver></code> 元素配置缓存模式,例如:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="xml" data-theme="default"><code data-language="xml" data-theme="default"><span data-line><span style="color:var(--shiki-color-text);"><</span><span style="color:var(--shiki-token-string-expression);">disk</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">type</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'file'</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">device</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'disk'</span><span style="color:var(--shiki-color-text);">></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">driver</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">name</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'qemu'</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">type</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'qcow2'</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">cache</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'none'</span><span style="color:var(--shiki-color-text);">/></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">source</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">file</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'/var/lib/libvirt/images/myvm.qcow2'</span><span style="color:var(--shiki-color-text);">/></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">target</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">dev</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'vda'</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">bus</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'virtio'</span><span style="color:var(--shiki-color-text);">/></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"></</span><span style="color:var(--shiki-token-string-expression);">disk</span><span style="color:var(--shiki-color-text);">></span></span></code></pre></div>
|
|||
|
<h4 id="使用-directsync-和-none-模式">使用 Directsync 和 None 模式<a aria-hidden="true" tabindex="-1" href="#使用-directsync-和-none-模式" class="internal"> §</a></h4>
|
|||
|
<p><code>directsync</code> 和 <code>none</code> 模式在确保数据一致性的同时提供不同的性能优势:</p>
|
|||
|
<ol>
|
|||
|
<li><strong>directsync</strong>:同步 I/O 模式,I/O 请求直接传递到宿主机,并在请求完成后返回,确保数据一致性。适用于需要严格数据一致性的应用。</li>
|
|||
|
<li><strong>none</strong>:直接 I/O 模式,无缓存。适用于需要高性能的读写操作,且能够容忍一定程度数据丢失的场景。</li>
|
|||
|
</ol>
|
|||
|
<p>通过合理选择和配置缓存模式,可以在性能和数据一致性之间取得平衡,优化虚拟机的磁盘 I/O 性能。</p>
|
|||
|
<p>综上所述,通过使用 Virtio 驱动、优化 I/O 调度策略和缓存策略,可以显著提升 KVM 虚拟化环境中虚拟机的磁盘 I/O 性能。在实际应用中,应根据具体需求和工作负载特征,选择合适的优化策略和参数设置,以达到最佳性能表现。</p>
|
|||
|
<h2 id="网络性能优化">网络性能优化<a aria-hidden="true" tabindex="-1" href="#网络性能优化" class="internal"> §</a></h2>
|
|||
|
<h3 id="使用-virtio-网卡">使用 Virtio 网卡<a aria-hidden="true" tabindex="-1" href="#使用-virtio-网卡" class="internal"> §</a></h3>
|
|||
|
<h4 id="virtio-网卡的优势">Virtio 网卡的优势<a aria-hidden="true" tabindex="-1" href="#virtio-网卡的优势" class="internal"> §</a></h4>
|
|||
|
<p>Virtio 网卡是 KVM 虚拟化环境中用于提高网络性能的一种标准化虚拟网络接口。使用 Virtio 网卡具有以下优势:</p>
|
|||
|
<ol>
|
|||
|
<li><strong>高效的 I/O 处理</strong>:Virtio 网卡通过简化 I/O 路径,减少传统网络设备模拟带来的开销,提高网络吞吐量和数据传输效率。</li>
|
|||
|
<li><strong>低延迟</strong>:Virtio 网卡通过优化数据传输路径,显著降低了网络延迟,提高了虚拟机的网络响应速度。</li>
|
|||
|
<li><strong>广泛的兼容性</strong>:Virtio 网卡被广泛支持,适用于大多数 Linux 发行版和现代 Windows 操作系统,确保虚拟机的兼容性和稳定性。</li>
|
|||
|
</ol>
|
|||
|
<h4 id="配置-virtio-网卡">配置 Virtio 网卡<a aria-hidden="true" tabindex="-1" href="#配置-virtio-网卡" class="internal"> §</a></h4>
|
|||
|
<p>配置 Virtio 网卡以充分利用其性能优势:</p>
|
|||
|
<ol>
|
|||
|
<li>
|
|||
|
<p><strong>在 Linux 虚拟机中配置 Virtio 网卡</strong>:</p>
|
|||
|
<p>确保虚拟机的网络接口类型设置为 <code>virtio</code>,在 libvirt 的 XML 配置文件中,可以这样配置:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="xml" data-theme="default"><code data-language="xml" data-theme="default"><span data-line><span style="color:var(--shiki-color-text);"><</span><span style="color:var(--shiki-token-string-expression);">interface</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">type</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'network'</span><span style="color:var(--shiki-color-text);">></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">mac</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">address</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'52:54:00:6b:3c:58'</span><span style="color:var(--shiki-color-text);">/></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">source</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">network</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'default'</span><span style="color:var(--shiki-color-text);">/></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">model</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">type</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'virtio'</span><span style="color:var(--shiki-color-text);">/></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">address</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">type</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'pci'</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">domain</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'0x0000'</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">bus</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'0x00'</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">slot</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'0x03'</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">function</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'0x0'</span><span style="color:var(--shiki-color-text);">/></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"></</span><span style="color:var(--shiki-token-string-expression);">interface</span><span style="color:var(--shiki-color-text);">></span></span></code></pre></div>
|
|||
|
<p>在虚拟机操作系统中确认 Virtio 驱动已正确加载,通常在现代 Linux 发行版中默认支持。</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p><strong>在 Windows 虚拟机中配置 Virtio 网卡</strong>:</p>
|
|||
|
<ol>
|
|||
|
<li>下载并安装 Virtio 网络驱动程序,通常可以从 Red Hat 提供的 Virtio 驱动包中获取。</li>
|
|||
|
<li>在虚拟机创建过程中,通过虚拟光驱加载 Virtio 驱动 ISO 文件,并在 Windows 设备管理器中手动安装驱动程序。</li>
|
|||
|
<li>确认 Virtio 网卡在设备管理器中正确识别并工作。</li>
|
|||
|
</ol>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
<h3 id="网络带宽限制和优先级">网络带宽限制和优先级<a aria-hidden="true" tabindex="-1" href="#网络带宽限制和优先级" class="internal"> §</a></h3>
|
|||
|
<h4 id="配置网络带宽限制">配置网络带宽限制<a aria-hidden="true" tabindex="-1" href="#配置网络带宽限制" class="internal"> §</a></h4>
|
|||
|
<p>通过配置网络带宽限制,可以有效管理虚拟机的网络流量,防止个别虚拟机占用过多带宽,从而影响其他虚拟机的网络性能:</p>
|
|||
|
<p>使用 libvirt 的 XML 配置文件,可以为虚拟机的网络接口设置带宽限制。例如:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="xml" data-theme="default"><code data-language="xml" data-theme="default"><span data-line><span style="color:var(--shiki-color-text);"><</span><span style="color:var(--shiki-token-string-expression);">interface</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">type</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'network'</span><span style="color:var(--shiki-color-text);">></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">mac</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">address</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'52:54:00:6b:3c:58'</span><span style="color:var(--shiki-color-text);">/></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">source</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">network</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'default'</span><span style="color:var(--shiki-color-text);">/></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">model</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">type</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'virtio'</span><span style="color:var(--shiki-color-text);">/></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">bandwidth</span><span style="color:var(--shiki-color-text);">></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">inbound</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">average</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'1000'</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">peak</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'1200'</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">burst</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'256'</span><span style="color:var(--shiki-color-text);">/></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">outbound</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">average</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'1000'</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">peak</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'1200'</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">burst</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'256'</span><span style="color:var(--shiki-color-text);">/></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> </</span><span style="color:var(--shiki-token-string-expression);">bandwidth</span><span style="color:var(--shiki-color-text);">></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"></</span><span style="color:var(--shiki-token-string-expression);">interface</span><span style="color:var(--shiki-color-text);">></span></span></code></pre></div>
|
|||
|
<p>以上配置将虚拟机的入站和出站流量限制为平均 1000kbps,峰值 1200kbps,突发流量 256kb。</p>
|
|||
|
<h4 id="使用-tc-命令设置优先级">使用 <code>tc</code> 命令设置优先级<a aria-hidden="true" tabindex="-1" href="#使用-tc-命令设置优先级" class="internal"> §</a></h4>
|
|||
|
<p><code>tc</code>(Traffic Control)命令是 Linux 中用于网络流量控制的强大工具,可以设置流量优先级,确保关键应用的网络性能:</p>
|
|||
|
<ol>
|
|||
|
<li>
|
|||
|
<p><strong>安装 <code>tc</code> 工具</strong>:大多数 Linux 发行版默认包含 <code>tc</code> 工具,如果没有安装,可以通过包管理器安装(如 <code>apt-get install iproute2</code>)。</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>配置流量优先级:</p>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
<p>创建根队列:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line> </span></code></pre></div>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
<p>tc qdisc add dev eth0 root handle 1: htb default 12</p>
|
|||
|
<pre><code> ```
|
|||
|
|
|||
|
|
|||
|
</code></pre>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
<p>创建类并分配带宽:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line> </span></code></pre></div>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
<p>tc class add dev eth0 parent 1: classid 1:1 htb rate 100mbit</p>
|
|||
|
<pre><code> tc class add dev eth0 parent 1:1 classid 1:11 htb rate 30mbit
|
|||
|
</code></pre>
|
|||
|
<p>tc class add dev eth0 parent 1:1 classid 1:12 htb rate 70mbit</p>
|
|||
|
<pre><code> ```
|
|||
|
</code></pre>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
<p>配置流量过滤规则:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line> </span></code></pre></div>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
<p>tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip src 192.168.1.100/32 flowid 1:11</p>
|
|||
|
<pre><code> tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dst 192.168.1.100/32 flowid 1:11
|
|||
|
</code></pre>
|
|||
|
<pre><code>
|
|||
|
### 调整网络缓冲区和队列
|
|||
|
|
|||
|
#### 优化网络缓冲区大小
|
|||
|
|
|||
|
优化网络缓冲区大小可以提高网络吞吐量,减少丢包率,从而提升网络性能:
|
|||
|
|
|||
|
1. **调整接收(RX)和发送(TX)缓冲区**:使用 `ethtool`命令查看和设置网卡的缓冲区大小。例如:
|
|||
|
|
|||
|
```shell
|
|||
|
ethtool -g eth0
|
|||
|
ethtool -G eth0 rx 4096 tx 4096
|
|||
|
</code></pre>
|
|||
|
<p>以上命令将 eth0 网卡的接收和发送缓冲区大小设置为 4096。</p>
|
|||
|
<ol>
|
|||
|
<li>
|
|||
|
<p><strong>调整内核参数</strong>:修改 <code>/etc/sysctl.conf</code> 文件,增加以下参数:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line><span style="color:var(--shiki-token-function);">net.core.rmem_max</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">=</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-constant);">16777216</span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-token-function);">net.core.wmem_max</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">=</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-constant);">16777216</span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-token-function);">net.core.rmem_default</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">=</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-constant);">8388608</span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-token-function);">net.core.wmem_default</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">=</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-constant);">8388608</span></span></code></pre></div>
|
|||
|
<p>应用配置:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line><span style="color:var(--shiki-token-function);">sysctl</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">-p</span></span></code></pre></div>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
<h4 id="配置多队列支持">配置多队列支持<a aria-hidden="true" tabindex="-1" href="#配置多队列支持" class="internal"> §</a></h4>
|
|||
|
<p>启用和配置多队列(Multiqueue)支持,可以提高网络 I/O 并行处理能力,提升网络性能:</p>
|
|||
|
<ol>
|
|||
|
<li>
|
|||
|
<p><strong>启用多队列</strong>:</p>
|
|||
|
<p>在 libvirt 的 XML 配置文件中,为 Virtio 网卡启用多队列支持:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="xml" data-theme="default"><code data-language="xml" data-theme="default"><span data-line><span style="color:var(--shiki-color-text);"><</span><span style="color:var(--shiki-token-string-expression);">interface</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">type</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'network'</span><span style="color:var(--shiki-color-text);">></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">mac</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">address</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'52:54:00:6b:3c:58'</span><span style="color:var(--shiki-color-text);">/></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">source</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">network</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'default'</span><span style="color:var(--shiki-color-text);">/></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">model</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">type</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'virtio'</span><span style="color:var(--shiki-color-text);">/></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"> <</span><span style="color:var(--shiki-token-string-expression);">driver</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">name</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'vhost'</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">queues</span><span style="color:var(--shiki-color-text);">=</span><span style="color:var(--shiki-token-string-expression);">'4'</span><span style="color:var(--shiki-color-text);">/></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-color-text);"></</span><span style="color:var(--shiki-token-string-expression);">interface</span><span style="color:var(--shiki-color-text);">></span></span></code></pre></div>
|
|||
|
<p>以上配置将 Virtio 网卡的队列数设置为 4。</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p><strong>调整虚拟机内核参数</strong>:</p>
|
|||
|
<p>修改虚拟机操作系统内核参数,以支持多队列。例如,在 Linux 虚拟机中,可以使用</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line><span style="color:var(--shiki-token-function);">ethtool</span></span></code></pre></div>
|
|||
|
<p>命令启用多队列:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line><span style="color:var(--shiki-token-function);">ethtool</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">-L</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">eth0</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">combined</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-constant);">4</span></span></code></pre></div>
|
|||
|
<p>以上命令将 eth0 网卡的队列数设置为 4。</p>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
<h2 id="虚拟机快照和备份的性能优化">虚拟机快照和备份的性能优化<a aria-hidden="true" tabindex="-1" href="#虚拟机快照和备份的性能优化" class="internal"> §</a></h2>
|
|||
|
<p>在 KVM(Kernel-based Virtual Machine)虚拟化环境中,快照和备份功能是保障数据安全和系统可靠性的重要手段。然而,这些操作也会对系统性能产生影响。本文将详细探讨快照性能影响及其优化策略、以及优化备份策略以减少对系统性能的影响。</p>
|
|||
|
<h3 id="快照性能影响">快照性能影响<a aria-hidden="true" tabindex="-1" href="#快照性能影响" class="internal"> §</a></h3>
|
|||
|
<h4 id="快照的创建和管理">快照的创建和管理<a aria-hidden="true" tabindex="-1" href="#快照的创建和管理" class="internal"> §</a></h4>
|
|||
|
<p>快照是虚拟机在某一时刻的状态,包括内存、磁盘和设备状态的完整备份。快照可以用于快速恢复到某一特定状态,但频繁的快照操作会影响系统性能:</p>
|
|||
|
<ol>
|
|||
|
<li>
|
|||
|
<p><strong>快照的创建</strong>:</p>
|
|||
|
<p>快照创建过程中,KVM 会冻结虚拟机的运行状态并复制当前的内存和磁盘数据。这会占用大量 I/O 资源,导致虚拟机短暂的性能下降。使用 <code>virsh</code> 命令创建快照,例如:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line><span style="color:var(--shiki-token-function);">virsh</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">snapshot-create-as</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">--domain</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-keyword);"><</span><span style="color:var(--shiki-token-string);">VM</span><span style="color:var(--shiki-color-text);">名</span><span style="color:var(--shiki-token-keyword);">></span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">--name</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-keyword);"><</span><span style="color:var(--shiki-token-string);">快照</span><span style="color:var(--shiki-color-text);">名</span><span style="color:var(--shiki-token-keyword);">></span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">--description</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string-expression);">"<描述>"</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">--disk-only</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">--atomic</span></span></code></pre></div>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p><strong>快照的管理</strong>:</p>
|
|||
|
<p>定期检查并管理快照,删除不再需要的快照以释放存储空间,减少性能影响。使用 <code>virsh</code> 命令查看和删除快照,例如:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line><span style="color:var(--shiki-token-function);">virsh</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">snapshot-list</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-keyword);"><</span><span style="color:var(--shiki-token-string);">VM</span><span style="color:var(--shiki-color-text);">名</span><span style="color:var(--shiki-token-keyword);">></span></span>
|
|||
|
<span data-line><span style="color:var(--shiki-token-function);">virsh</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">snapshot-delete</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-keyword);"><</span><span style="color:var(--shiki-token-string);">VM</span><span style="color:var(--shiki-color-text);">名</span><span style="color:var(--shiki-token-keyword);">></span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-keyword);"><</span><span style="color:var(--shiki-token-string);">快照</span><span style="color:var(--shiki-color-text);">名</span><span style="color:var(--shiki-token-keyword);">></span></span></code></pre></div>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
<h4 id="减少快照对性能的影响">减少快照对性能的影响<a aria-hidden="true" tabindex="-1" href="#减少快照对性能的影响" class="internal"> §</a></h4>
|
|||
|
<p>为了减少快照对虚拟机性能的影响,可以采取以下优化策略:</p>
|
|||
|
<ol>
|
|||
|
<li>
|
|||
|
<p><strong>优化快照存储位置</strong>:</p>
|
|||
|
<p>将快照存储在性能较高的存储设备上,例如 SSD,减少 I/O 瓶颈对虚拟机性能的影响。</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p><strong>限制快照数量</strong>:</p>
|
|||
|
<p>避免同时创建过多的快照,定期清理不需要的快照,保持系统存储的简洁性和高效性。</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p><strong>使用外部快照</strong>:</p>
|
|||
|
<p>使用外部快照(External Snapshot)将快照数据与原始磁盘数据分开存储,减少对原始磁盘 I/O 的影响。例如:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line><span style="color:var(--shiki-token-function);">virsh</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">snapshot-create-as</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">--domain</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-keyword);"><</span><span style="color:var(--shiki-token-string);">VM</span><span style="color:var(--shiki-color-text);">名</span><span style="color:var(--shiki-token-keyword);">></span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">--name</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-keyword);"><</span><span style="color:var(--shiki-token-string);">快照</span><span style="color:var(--shiki-color-text);">名</span><span style="color:var(--shiki-token-keyword);">></span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">--diskspec</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-keyword);"><</span><span style="color:var(--shiki-token-string);">dis</span><span style="color:var(--shiki-color-text);">k</span><span style="color:var(--shiki-token-keyword);">></span><span style="color:var(--shiki-token-string);">,snapshot=external</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">--disk-only</span></span></code></pre></div>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
<h3 id="备份策略">备份策略<a aria-hidden="true" tabindex="-1" href="#备份策略" class="internal"> §</a></h3>
|
|||
|
<h4 id="使用增量备份减少影响">使用增量备份减少影响<a aria-hidden="true" tabindex="-1" href="#使用增量备份减少影响" class="internal"> §</a></h4>
|
|||
|
<p>增量备份是指仅备份自上次备份以来发生变化的数据,相较于全量备份,增量备份占用的存储空间更少,备份速度更快,性能影响更低:</p>
|
|||
|
<ol>
|
|||
|
<li>
|
|||
|
<p><strong>配置增量备份</strong>:</p>
|
|||
|
<p>使用增量备份工具(如 rsync、Bacula、Duplicity)配置增量备份任务,定期备份虚拟机的数据。例如,使用 <code>rsync</code> 进行增量备份:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line><span style="color:var(--shiki-token-function);">rsync</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">-av</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">--progress</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">--delete</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">/path/to/source</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">/path/to/destination</span></span></code></pre></div>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p><strong>利用 KVM 内置增量备份功能</strong>:</p>
|
|||
|
<p>利用 KVM 和 QEMU 的增量备份功能,使用 QEMU 提供的块设备接口(如 qemu-img)进行增量备份。例如:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line><span style="color:var(--shiki-token-function);">qemu-img</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">create</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">-f</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">qcow2</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">-b</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-keyword);"><</span><span style="color:var(--shiki-token-string);">base-imag</span><span style="color:var(--shiki-color-text);">e</span><span style="color:var(--shiki-token-keyword);">></span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-keyword);"><</span><span style="color:var(--shiki-token-string);">incremental-imag</span><span style="color:var(--shiki-color-text);">e</span><span style="color:var(--shiki-token-keyword);">></span></span></code></pre></div>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
<h4 id="配置备份窗口和策略">配置备份窗口和策略<a aria-hidden="true" tabindex="-1" href="#配置备份窗口和策略" class="internal"> §</a></h4>
|
|||
|
<p>配置合理的备份窗口和策略,减少备份操作对系统性能的影响:</p>
|
|||
|
<ol>
|
|||
|
<li>
|
|||
|
<p><strong>选择备份窗口</strong>:</p>
|
|||
|
<p>选择系统负载较低的时间段进行备份操作,例如夜间或周末,避免影响业务高峰期的性能。</p>
|
|||
|
<p>使用任务调度工具(如 cron)配置备份任务的执行时间。例如,配置每日凌晨 3 点进行备份:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line><span style="color:var(--shiki-token-function);">0</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-constant);">3</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">*</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">*</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">*</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">/path/to/backup-script.sh</span></span></code></pre></div>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p><strong>配置备份策略</strong>:</p>
|
|||
|
<p>制定合理的备份策略,包括全量备份和增量备份的频率、保留周期等。例如,每周进行一次全量备份,每日进行增量备份,保留最近一个月的备份数据。</p>
|
|||
|
<p>使用备份管理工具(如 Bacula、Amanda)配置和管理备份策略,实现自动化和集中管理。</p>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
<h2 id="性能问题的故障排查">性能问题的故障排查<a aria-hidden="true" tabindex="-1" href="#性能问题的故障排查" class="internal"> §</a></h2>
|
|||
|
<p>在 KVM(Kernel-based Virtual Machine)虚拟化环境中,性能问题的故障排查是保障虚拟机(VM)稳定运行的重要工作。本文将详细探讨常见性能问题及其解决方法,以及如何通过日志分析进行性能排查。</p>
|
|||
|
<h3 id="常见性能问题及解决方法">常见性能问题及解决方法<a aria-hidden="true" tabindex="-1" href="#常见性能问题及解决方法" class="internal"> §</a></h3>
|
|||
|
<h4 id="虚拟机运行缓慢">虚拟机运行缓慢<a aria-hidden="true" tabindex="-1" href="#虚拟机运行缓慢" class="internal"> §</a></h4>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<table><thead><tr><th><strong>问题</strong></th><th><strong>原因</strong></th><th><strong>解决方法</strong></th></tr></thead><tbody><tr><td><strong>CPU 资源不足</strong></td><td>虚拟机分配的 vCPU 数量不足,或者宿主机的 CPU 资源紧张</td><td>增加虚拟机的 vCPU 数量。检查宿主机的 CPU 负载,优化其他虚拟机的 CPU 使用,必要时迁移部分虚拟机到其他宿主机。</td></tr><tr><td><strong>内存资源不足</strong></td><td>虚拟机分配的内存不足,或者宿主机的内存资源紧张</td><td>增加虚拟机的内存。检查宿主机的内存使用情况,优化其他虚拟机的内存使用,必要时使用内存气球驱动动态调整内存分配。</td></tr><tr><td><strong>磁盘 I/O 瓶颈</strong></td><td>虚拟机磁盘 I/O 负载过高,导致 I/O 操作延迟</td><td>优化虚拟机的磁盘 I/O 调度策略,使用合适的 I/O 调度器。将虚拟机的磁盘文件迁移到性能更好的存储设备(如 SSD)。启用并配置 Virtio 磁盘驱动,提高 I/O 性能。</td></tr><tr><td><strong>网络 I/O 瓶颈</strong></td><td>虚拟机网络负载过高,导致网络延迟和吞吐量下降</td><td>配置 Virtio 网卡,提高网络 I/O 性能。优化网络带宽限制和优先级配置,确保关键应用的网络带宽。检查宿主机和虚拟机的网络配置,确保网络连接正常。</td></tr></tbody></table>
|
|||
|
<h4 id="网络性能不佳">网络性能不佳<a aria-hidden="true" tabindex="-1" href="#网络性能不佳" class="internal"> §</a></h4>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<table><thead><tr><th><strong>问题</strong></th><th><strong>原因</strong></th><th><strong>解决方法</strong></th></tr></thead><tbody><tr><td><strong>网络配置问题</strong></td><td>虚拟机或宿主机的网络配置错误或不优化</td><td>检查虚拟机和宿主机的网络配置,确保网络接口和路由配置正确。优化虚拟机的网络缓冲区和队列配置,提高网络 I/O 性能。</td></tr><tr><td><strong>网络带宽瓶颈</strong></td><td>虚拟机网络流量过大,占用过多带宽</td><td>配置网络带宽限制,确保网络资源合理分配。使用 <code>tc</code> 命令配置网络流量优先级,确保关键应用的网络性能。</td></tr><tr><td><strong>网络延迟问题</strong></td><td>虚拟机或宿主机的网络延迟过高</td><td>优化虚拟机的网络路由配置,减少中间跳数和延迟。检查宿主机的网络硬件,确保网卡和交换机性能正常。</td></tr></tbody></table>
|
|||
|
<h3 id="性能日志分析">性能日志分析<a aria-hidden="true" tabindex="-1" href="#性能日志分析" class="internal"> §</a></h3>
|
|||
|
<p>日志分析是故障排查的重要手段,通过查看和分析 KVM 和系统日志,可以快速定位和解决性能问题。</p>
|
|||
|
<h4 id="查看和分析-kvm-日志">查看和分析 KVM 日志<a aria-hidden="true" tabindex="-1" href="#查看和分析-kvm-日志" class="internal"> §</a></h4>
|
|||
|
<p>KVM 和 libvirt 生成的日志文件可以提供虚拟机运行的详细信息,帮助排查性能问题:</p>
|
|||
|
<ol>
|
|||
|
<li>
|
|||
|
<p><strong>查看 libvirt 日志</strong>:libvirt 日志通常位于 <code>/var/log/libvirt</code> 目录下,可以通过 <code>virsh</code> 命令查看特定虚拟机的日志:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line><span style="color:var(--shiki-token-function);">virsh</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">log</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-keyword);"><</span><span style="color:var(--shiki-token-string);">VM</span><span style="color:var(--shiki-color-text);">名</span><span style="color:var(--shiki-token-keyword);">></span></span></code></pre></div>
|
|||
|
<p>直接查看日志文件:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line><span style="color:var(--shiki-token-function);">tail</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">-f</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">/var/log/libvirt/qemu/</span><span style="color:var(--shiki-token-keyword);"><</span><span style="color:var(--shiki-token-string);">VM</span><span style="color:var(--shiki-color-text);">名</span><span style="color:var(--shiki-token-keyword);">></span><span style="color:var(--shiki-token-string);">.log</span></span></code></pre></div>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p><strong>分析日志内容</strong>:</p>
|
|||
|
<ul>
|
|||
|
<li>检查日志中是否有错误信息、警告信息或性能相关的提示。</li>
|
|||
|
<li>根据日志中的时间戳和事件,定位性能问题发生的时间段和可能的原因。</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
<h4 id="使用系统日志进行排查">使用系统日志进行排查<a aria-hidden="true" tabindex="-1" href="#使用系统日志进行排查" class="internal"> §</a></h4>
|
|||
|
<p>系统日志(如 syslog、dmesg)记录了宿主机的各种事件,包括硬件信息、系统错误和性能警告,通过分析系统日志,可以排查性能问题:</p>
|
|||
|
<ol>
|
|||
|
<li>
|
|||
|
<p><strong>查看系统日志</strong>:使用 <code>dmesg</code> 命令查看内核日志:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line><span style="color:var(--shiki-token-function);">dmesg</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-keyword);">|</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-function);">less</span></span></code></pre></div>
|
|||
|
<p>查看 syslog 日志,通常位于 <code>/var/log</code> 目录下:</p>
|
|||
|
<div data-rehype-pretty-code-fragment><pre style="background-color:var(--shiki-color-background);" tabindex="0" data-language="shell" data-theme="default"><code data-language="shell" data-theme="default"><span data-line><span style="color:var(--shiki-token-function);">tail</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">-f</span><span style="color:var(--shiki-color-text);"> </span><span style="color:var(--shiki-token-string);">/var/log/syslog</span></span></code></pre></div>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p><strong>分析日志内容</strong>:</p>
|
|||
|
<ul>
|
|||
|
<li>检查是否有与虚拟机或宿主机相关的错误信息或警告信息。</li>
|
|||
|
<li>根据日志信息,确定是否有硬件故障、资源瓶颈或其他性能问题。</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ol></article></div><div class="right sidebar"><div class="graph "><h3>Graph View</h3><div class="graph-outer"><div id="graph-container" data-cfg="{"drag":true,"zoom":true,"depth":1,"scale":1.1,"repelForce":0.5,"centerForce":0.3,"linkDistance":30,"fontSize":0.6,"opacityScale":1,"showTags":true,"removeTags":[]}"></div><svg version="1.1" id="global-graph-icon" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 55 55" fill="currentColor" xmlSpace="preserve"><path d="M49,0c-3.309,0-6,2.691-6,6c0,1.035,0.263,2.009,0.726,2.86l-9.829,9.829C32.542,17.634,30.846,17,29,17
|
|||
|
s-3.542,0.634-4.898,1.688l-7.669-7.669C16.785,10.424,17,9.74,17,9c0-2.206-1.794-4-4-4S9,6.794,9,9s1.794,4,4,4
|
|||
|
c0.74,0,1.424-0.215,2.019-0.567l7.669,7.669C21.634,21.458,21,23.154,21,25s0.634,3.542,1.688,4.897L10.024,42.562
|
|||
|
C8.958,41.595,7.549,41,6,41c-3.309,0-6,2.691-6,6s2.691,6,6,6s6-2.691,6-6c0-1.035-0.263-2.009-0.726-2.86l12.829-12.829
|
|||
|
c1.106,0.86,2.44,1.436,3.898,1.619v10.16c-2.833,0.478-5,2.942-5,5.91c0,3.309,2.691,6,6,6s6-2.691,6-6c0-2.967-2.167-5.431-5-5.91
|
|||
|
v-10.16c1.458-0.183,2.792-0.759,3.898-1.619l7.669,7.669C41.215,39.576,41,40.26,41,41c0,2.206,1.794,4,4,4s4-1.794,4-4
|
|||
|
s-1.794-4-4-4c-0.74,0-1.424,0.215-2.019,0.567l-7.669-7.669C36.366,28.542,37,26.846,37,25s-0.634-3.542-1.688-4.897l9.665-9.665
|
|||
|
C46.042,11.405,47.451,12,49,12c3.309,0,6-2.691,6-6S52.309,0,49,0z M11,9c0-1.103,0.897-2,2-2s2,0.897,2,2s-0.897,2-2,2
|
|||
|
S11,10.103,11,9z M6,51c-2.206,0-4-1.794-4-4s1.794-4,4-4s4,1.794,4,4S8.206,51,6,51z M33,49c0,2.206-1.794,4-4,4s-4-1.794-4-4
|
|||
|
s1.794-4,4-4S33,46.794,33,49z M29,31c-3.309,0-6-2.691-6-6s2.691-6,6-6s6,2.691,6,6S32.309,31,29,31z M47,41c0,1.103-0.897,2-2,2
|
|||
|
s-2-0.897-2-2s0.897-2,2-2S47,39.897,47,41z M49,10c-2.206,0-4-1.794-4-4s1.794-4,4-4s4,1.794,4,4S51.206,10,49,10z"></path></svg></div><div id="global-graph-outer"><div id="global-graph-container" data-cfg="{"drag":true,"zoom":true,"depth":-1,"scale":0.9,"repelForce":0.5,"centerForce":0.3,"linkDistance":30,"fontSize":0.6,"opacityScale":1,"showTags":true,"removeTags":[]}"></div></div></div><div class="toc desktop-only"><button type="button" id="toc" class><h3>Table of Contents</h3><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="fold"><polyline points="6 9 12 15 18 9"></polyline></svg></button><div id="toc-content"><ul class="overflow"><li class="depth-0"><a href="#性能优化概述" data-for="性能优化概述">性能优化概述</a></li><li class="depth-1"><a href="#为什么需要性能优化" data-for="为什么需要性能优化">为什么需要性能优化?</a></li><li class="depth-1"><a href="#性能优化的基本原则" data-for="性能优化的基本原则">性能优化的基本原则</a></li><li class="depth-1"><a href="#性能优化的常见挑战" data-for="性能优化的常见挑战">性能优化的常见挑战</a></li><li class="depth-0"><a href="#cpu-性能优化" data-for="cpu-性能优化">CPU 性能优化</a></li><li class="depth-1"><a href="#cpu-分配和超线程" data-for="cpu-分配和超线程">CPU 分配和超线程</a></li><li class="depth-1"><a href="#cpu-亲和性设置" data-for="cpu-亲和性设置">CPU 亲和性设置</a></li><li class="depth-1"><a href="#优化-cpu-调度策略" data-for="优化-cpu-调度策略">优化 CPU 调度策略</a></li><li class="depth-0"><a href="#内存性能优化" data-for="内存性能优化">内存性能优化</a></li><li class="depth-1"><a href="#内存分配和大页支持" data-for="内存分配和大页支持">内存分配和大页支持</a></li><li class="depth-1"><a href="#内存过量使用和气球驱动" data-for="内存过量使用和气球驱动">内存过量使用和气球驱动</a></li><li class="depth-1"><a href="#numa-配置优化" data-for="numa-配置优化">NUMA 配置优化</a></li><li class="depth-0"><a href="#存储性能优化" data-for="存储性能优化">存储性能优化</a></li><li class="depth-1"><a href="#使用-virtio-驱动提升性能" data-for="使用-virtio-驱动提升性能">使用 Virtio 驱动提升性能</a></li><li class="depth-1"><a href="#磁盘-io-调度策略" data-for="磁盘-io-调度策略">磁盘 I/O 调度策略</a></li><li class="depth-1"><a href="#使用缓存策略" data-for="使用缓存策略">使用缓存策略</a></li><li class="depth-0"><a href="#网络性能优化" data-for="网络性能优化">网络性能优化</a></li><li class="depth-1"><a href="#使用-virtio-网卡" data-for="使用-virtio-网卡">使用 Virtio 网卡</a></li><li class="depth-1"><a href="#网络带宽限制和优先级" data-for="网络带宽限制和优先级">网络带宽限制和优先级</a></li><li class="depth-0"><a href="#虚拟机快照和备份的性能优化" data-for="虚拟机快照和备份的性能优化">虚拟机快照和备份的性能优化</a></li><li class="depth-1"><a href="#快照性能影响" data-for="快照性能影响">快照性能影响</a></li><li class="depth-1"><a href="#备份策略" data-for="备份策略">备份策略</a></li><li class="depth-0"><a href="#性能问题的故障排查" data-for="性能问题的故障排查">性能问题的故障排查</a></li><li class="depth-1"><a href="#常见性能问题及解决方法" data-for="常见性能问题及解决方法">常见性能问题及解决方法</a></li><li class="depth-1"><a href="#性能日志分析" data-for="性能日志分析">性能日志分析</a></li></ul></div></div><div class="backlinks "><h3>Backlinks</h3><ul class="overflow"><li>No backlinks found</li></ul></div><div class="explorer
|
|||
|
function toggleCallout() {
|
|||
|
const outerBlock = this.parentElement;
|
|||
|
outerBlock.classList.toggle(`is-collapsed`);
|
|||
|
const collapsed = outerBlock.classList.contains(`is-collapsed`);
|
|||
|
const height = collapsed ? this.scrollHeight : outerBlock.scrollHeight;
|
|||
|
outerBlock.style.maxHeight = height + `px`;
|
|||
|
let current = outerBlock;
|
|||
|
let parent = outerBlock.parentElement;
|
|||
|
while (parent) {
|
|||
|
if (!parent.classList.contains(`callout`)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
const collapsed2 = parent.classList.contains(`is-collapsed`);
|
|||
|
const height2 = collapsed2 ? parent.scrollHeight : parent.scrollHeight + current.scrollHeight;
|
|||
|
parent.style.maxHeight = height2 + `px`;
|
|||
|
current = parent;
|
|||
|
parent = parent.parentElement;
|
|||
|
}
|
|||
|
}
|
|||
|
function setupCallout() {
|
|||
|
const collapsible = document.getElementsByClassName(
|
|||
|
`callout is-collapsible`
|
|||
|
);
|
|||
|
for (const div of collapsible) {
|
|||
|
const title = div.firstElementChild;
|
|||
|
if (title) {
|
|||
|
title.removeEventListener(`click`, toggleCallout);
|
|||
|
title.addEventListener(`click`, toggleCallout);
|
|||
|
const collapsed = div.classList.contains(`is-collapsed`);
|
|||
|
const height = collapsed ? title.scrollHeight : div.scrollHeight;
|
|||
|
div.style.maxHeight = height + `px`;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
document.addEventListener(`nav`, setupCallout);
|
|||
|
window.addEventListener(`resize`, setupCallout);
|
|||
|
</script><script type="module">
|
|||
|
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs';
|
|||
|
const darkMode = document.documentElement.getAttribute('saved-theme') === 'dark'
|
|||
|
mermaid.initialize({
|
|||
|
startOnLoad: false,
|
|||
|
securityLevel: 'loose',
|
|||
|
theme: darkMode ? 'dark' : 'default'
|
|||
|
});
|
|||
|
document.addEventListener('nav', async () => {
|
|||
|
await mermaid.run({
|
|||
|
querySelector: '.mermaid'
|
|||
|
})
|
|||
|
});
|
|||
|
</script><script src="https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/contrib/copy-tex.min.js" type="application/javascript"></script><script src="../../../../postscript.js" type="module"></script></html>
|