news 2026/9/17 10:19:26

Headlamp 插件开发教程:用 registerRoute 与 registerSidebarEntry 构建自定义页面与侧边栏导航

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Headlamp 插件开发教程:用 registerRoute 与 registerSidebarEntry 构建自定义页面与侧边栏导航

Headlamp 插件开发教程:用 registerRoute 与 registerSidebarEntry 构建自定义页面与侧边栏导航

【免费下载链接】headlampA Kubernetes web UI that is fully-featured, user-friendly and extensible项目地址: https://gitcode.com/GitHub_Trending/he/headlamp

导读

本篇是 Headlamp 插件开发入门系列(Getting Started)的第三篇教程,聚焦于一个核心问题:如何在 Headlamp 中创建独立的自定义页面,并通过侧边栏导航让用户发现这些页面。你将掌握registerRoute()注册路由、registerSidebarEntry()添加侧边栏条目、父子级子条目组织、图标配置,以及 Home View 与 Cluster View 两种视图下导航的差异。学完本篇,你就能为自己的插件搭建出结构清晰、可导航、可扩展的多页面 UI。


前置准备:承接 Tutorial 2 的插件工程

本教程假设你已经完成了 Tutorial 2:创建你的第一个插件,手头有一个可运行的hello-headlamp插件,并且 Headlamp 正在本地运行。如果你还没有运行环境的搭建经验,可以参考 从源码运行。

在 Tutorial 2 中,我们通过registerAppBarAction()在 Headlamp 顶部的 App Bar 中放置了一个 "Say Hello" 按钮,点击后弹出 alert。本教程将在这个基础上:

  1. registerRoute()创建一个真正的自定义页面;
  2. 让 App Bar 按钮从"弹提示"进化为"跳转页面";
  3. registerSidebarEntry()把页面挂进左侧导航菜单。

最终目标效果如下:

Sidebar (Home View): ├── [Clusters list] ├── 🆕 My Plugin → expandable parent │ ├── Overview → /my-plugin │ └── Settings → /my-plugin/settings └── 📚 Plugin Docs → /plugin-docs

预计耗时:约 20 分钟。


核心概念:路由(Route)与侧边栏条目(SidebarEntry)

在动手写代码之前,先理解 Headlamp 插件扩展导航的两大 API。二者都从@kinvolk/headlamp-plugin/lib导出(见 插件 SDK 入口):

API职责
registerRoute(routeSpec)把某个 React 组件注册到指定 URL 路径上,形成可访问的页面
registerSidebarEntry(entryProps)在左侧导航菜单中注册一个条目,点击后跳转到指定 URL

从源码层面看,这两个函数最终都是向 Headlamp 的 Redux store 派发 action(见 frontend/src/plugin/registry.tsx 与 frontend/src/plugin/registry.tsx):

  • registerSidebarEntry({...})store.dispatch(setSidebarItem({ name, label, url, parent, useClusterURL, icon, sidebar, entryType, sx }))
  • registerRoute(routeSpec)store.dispatch(setRoute(routeSpec))

也就是说,路由决定"哪个 URL 显示什么组件",侧边栏条目决定"导航菜单里有什么、点了去哪",二者通过sidebar字段(路由侧)与name字段(条目侧)建立关联。

Route接口的完整字段定义可以查看 frontend/src/lib/router/Route.tsx:包含pathexactnameuseClusterURLnoCluster已废弃)、noAuthRequiredsidebarcomponenthideAppBardisabledisFullWidth等;SidebarEntry的完整字段定义见 frontend/src/components/Sidebar/sidebarSlice.ts,包括namelabelparenturluseClusterURLiconsidebarentryTypesx等。后面的章节会逐一解释这些字段的用法。


创建自定义页面:第一步registerRoute

在 Headlamp 中,一个"页面"本质上就是一个被渲染到特定 URL 上的 React 组件

Step 1:编写页面组件

打开hello-headlamp插件的src/index.tsx,用下面的内容替换:

import { registerRoute } from '@kinvolk/headlamp-plugin/lib'; import { SectionBox } from '@kinvolk/headlamp-plugin/lib/CommonComponents'; import { Typography } from '@mui/material'; function WelcomePage() { return ( <SectionBox title="Welcome to My Plugin"> <Typography variant="body1"> This is your first custom page! 🎉 </Typography> </SectionBox> ); } registerRoute({ path: '/my-plugin', sidebar: null, component: WelcomePage, useClusterURL: false, noAuthRequired: true, });

这段代码在做什么?

代码作用
registerRoute()告诉 Headlamp 在特定 URL 显示某个组件
path: '/my-plugin'页面可访问的 URL 路径
sidebar: null暂时不关联任何侧边栏条目(后面会补上)
component: WelcomePage要渲染的 React 组件
useClusterURL: false页面在/my-plugin访问,而非集群专属 URL
noAuthRequired: true页面无需认证即可访问

SectionBox来自@kinvolk/headlamp-plugin/lib/CommonComponents。这个模块提供与 Headlamp 风格一致、开箱即用的 UI 组件,后续教程还会用到NameValueTableResourceListView等。它的实现位于仓库的 frontend/src/components/common 目录下。

Step 2:手动访问页面

保存文件后,在浏览器中打开http://localhost:3000/my-plugin,你应该能看到 Welcome 页面:

手动导航的问题

页面能用了,但存在一个明显的体验缺陷:用户必须知道确切的 URL 才能访问。接下来我们逐步改进。


连接 App Bar 按钮:从 alert 到页面跳转

还记得 Tutorial 2 中的 "Say Hello" 按钮吗?现在让它直接导航到新页面,而不是弹出 alert。

更新src/index.tsx

import { registerAppBarAction, registerRoute } from '@kinvolk/headlamp-plugin/lib'; import { SectionBox } from '@kinvolk/headlamp-plugin/lib/CommonComponents'; import { Button, Typography } from '@mui/material'; function WelcomePage() { return ( <SectionBox title="Welcome to My Plugin"> <Typography variant="body1"> This is your first custom page! 🎉 </Typography> </SectionBox> ); } registerRoute({ path: '/my-plugin', sidebar: null, component: WelcomePage, useClusterURL: false, noAuthRequired: true, }); function HelloButton() { return ( <Button variant="outlined" size="small" href="/my-plugin" sx={{ color: 'inherit', borderColor: 'inherit', mx: 1 }} > My Plugin </Button> ); } registerAppBarAction(<HelloButton />);

与 Tutorial 2 的差异

之前(Tutorial 2)之后(Tutorial 3)
onClick={() => alert(...)}href="/my-plugin"
点击弹出 alert 提示点击跳转到自定义页面

保存后把鼠标悬停在 App Bar 的"My Plugin"按钮上,浏览器左下角会显示目标链接/my-plugin;点击即可进入 Welcome 页面。

不过你可能会注意到一个细节:这个页面没有侧边栏。原因是我们使用了useClusterURL: false,创建了一个脱离集群上下文的独立页面。下面进入本教程的重点——侧边栏导航。


为什么侧边栏导航如此重要

App Bar 按钮能用,但存在硬伤:App Bar 空间有限。如果插件有多个页面,不可能为每个页面都加一个按钮。

侧边栏——Headlamp 左侧的导航菜单——是标准解决方案,它具备:

  • 容纳多个条目的空间;
  • 父子层级组织(parent/child)能力;
  • 当前页面高亮(highlight)反馈,用户始终知道自己在哪;
  • 作为 Headlamp 标准导航模式的一致性体验。

添加侧边栏条目:registerSidebarEntry

把页面挂进侧边栏,需要两步:注册条目,并把路由的sidebar字段指向该条目。

Step 1:注册侧边栏条目并关联路由

更新src/index.tsx

import { registerAppBarAction, registerRoute, registerSidebarEntry } from '@kinvolk/headlamp-plugin/lib'; import { SectionBox } from '@kinvolk/headlamp-plugin/lib/CommonComponents'; import { Button, Typography } from '@mui/material'; function WelcomePage() { return ( <SectionBox title="Welcome to My Plugin"> <Typography variant="body1"> This is your first custom page! 🎉 </Typography> <Typography variant="body2" sx={{ mt: 2, color: 'text.secondary' }}> Now accessible from the sidebar! </Typography> </SectionBox> ); } // 注册页面——注意 sidebar 现在指向我们的条目 registerRoute({ path: '/my-plugin', sidebar: 'my-plugin', component: WelcomePage, useClusterURL: false, noAuthRequired: true, }); // 注册侧边栏条目 registerSidebarEntry({ name: 'my-plugin', label: 'My Plugin', url: '/my-plugin', useClusterURL: false, }); // 保留 App Bar 按钮(可选) function HelloButton() { return ( <Button variant="outlined" size="small" href="/my-plugin" sx={{ color: 'inherit', borderColor: 'inherit', mx: 1 }} > My Plugin </Button> ); } registerAppBarAction(<HelloButton />);

新增内容详解

registerSidebarEntry的选项:

属性作用
name条目的唯一标识(必须与路由中的sidebar匹配)
label侧边栏中显示的文本
url点击后跳转的 URL
useClusterURLfalse时 URL 保持/my-plugin;为true(默认)时 URL 变为/c/:cluster/my-plugin

registerRoute的变化:

属性之前之后
sidebarnull'my-plugin'——把路由与侧边栏条目关联起来

注意:registerRoute还接受可选的name属性(如name: 'My Plugin'),提供人类可读的名称,可用于浏览器标签页标题。这也与仓库中的约定一致——在 frontend/src/lib/router/Route.tsx 中name被注释为"Human readable name. Capitalized and short."(人类可读、首字母大写且简短)。

关键约定:registerRoute中的sidebar值必须与registerSidebarEntry中的name完全一致。这一关联带来三个效果:

  • 当你停留在该页面时,侧边栏条目被高亮;
  • Headlamp 据此决定显示哪个侧边栏;
  • 无论你是点击侧边栏条目、点击 App Bar 按钮,还是手动输入 URL,侧边栏条目都会被正确选中。

Step 2:查看效果

  1. 保存文件;
  2. 进入 Headlamp 首页(http://localhost:3000/);
  3. 左侧侧边栏会看到新的"My Plugin"条目;
  4. 点击它,进入 Welcome 页面。

连接是双向的:点击侧边栏条目 → 跳转到页面;停留在页面 → 侧边栏条目高亮。


添加图标:Iconify 图标字符串

没有图标的侧边栏条目看起来有些单调。Headlamp 使用Iconify作为图标体系,通过字符串标识符即可使用数千个图标(MDI 系列,Material Design Icons)。

registerSidebarEntry加上icon字段:

registerSidebarEntry({ name: 'my-plugin', label: 'My Plugin', url: '/my-plugin', icon: 'mdi:new-box', useClusterURL: false, });

保存后,侧边栏条目旁边会出现一个 "new"(新盒子)图标。图标字符串的格式为mdi:图标名,例如mdi:book-open-variant(书本)、mdi:comment-quote(评论)。在仓库的 Sidebar 示例插件 中可以看到icon: 'mdi:comment-quote'icon: 'mdi:hexagon'等更多用法。

从源码角度看,icon字段的类型是 Iconify 的IconProps['icon'](见 frontend/src/components/Sidebar/sidebarSlice.ts),支持字符串标识或图标对象两种形式。


创建子条目:用parent组织层级

随着插件功能增长,你会希望把相关页面归组到父级条目之下。下面把插件扩展为"父级 + 两个子条目"的结构。

Step 1:更新插件代码

用下面的完整版本替换src/index.tsx

import { registerRoute, registerSidebarEntry } from '@kinvolk/headlamp-plugin/lib'; import { SectionBox } from '@kinvolk/headlamp-plugin/lib/CommonComponents'; import { Typography } from '@mui/material'; // 页面组件 function OverviewPage() { return ( <SectionBox title="Overview"> <Typography>Welcome to the plugin overview!</Typography> </SectionBox> ); } function SettingsPage() { return ( <SectionBox title="Plugin Settings"> <Typography>Configure your plugin settings here.</Typography> </SectionBox> ); } // 注册路由 registerRoute({ path: '/my-plugin', exact: true, name: 'Plugin Overview', sidebar: 'my-plugin-overview', component: OverviewPage, }); registerRoute({ path: '/my-plugin/settings', name: 'Plugin Settings', exact: true, sidebar: 'my-plugin-settings', component: SettingsPage, }); // 注册父级侧边栏条目 registerSidebarEntry({ name: 'my-plugin', label: 'My Plugin', icon: 'mdi:new-box', url: '/my-plugin', }); // 注册子级侧边栏条目 registerSidebarEntry({ parent: 'my-plugin', name: 'my-plugin-overview', label: 'Overview', url: '/my-plugin', }); registerSidebarEntry({ parent: 'my-plugin', name: 'my-plugin-settings', label: 'Settings', url: '/my-plugin/settings', });

新增内容详解

代码作用
exact: true路由只做精确匹配,而不是"以该路径开头"就匹配
parent: 'my-plugin'让 Overview 和 Settings 成为my-plugin的子条目
父条目带url父条目本身可点击,跳转到 Overview 页面
子条目Overview 与 Settings 作为子菜单显示在 My Plugin 之下

parent字段在SidebarEntry接口中的类型为parent?: string | null(见 frontend/src/components/Sidebar/sidebarSlice.ts)。当不指定parent(或为null)时,条目出现在顶层。

Step 2:查看层级效果

保存后侧边栏会呈现:

My Plugin (🆕) → 可展开的父级 ├── Overview → 点击跳转 /my-plugin └── Settings → 点击跳转 /my-plugin/settings

点击 "My Plugin" 或 "Overview" 进入 Overview 页面;点击 "Settings" 进入 Settings 页面。当停留在任一子页面时,父条目会自动展开并高亮当前子条目:


Home View 与 Cluster View:两种导航上下文

Headlamp 存在两个主要上下文:

  1. Home View(首页视图)——未选择集群时显示(例如集群选择界面);
  2. Cluster View(集群视图)——正在使用某个具体集群时显示。

默认情况下,侧边栏条目只会出现在 Cluster View 中。如果你希望某些导航在未连接集群时也可见,需要显式指定sidebar: 'HOME'

从源码看,Headlamp 用DefaultSidebars枚举定义这两个内建侧边栏(见 frontend/src/components/Sidebar/sidebarSlice.ts):

export enum DefaultSidebars { HOME = 'HOME', IN_CLUSTER = 'IN-CLUSTER', }

sidebar字段的类型是DefaultSidebars | string,这意味着你既可以指向内建的HOME/集群侧边栏,也可以创建一个全新的命名侧边栏(仓库的 Sidebar 示例插件 就演示了通过sidebar: 'myplugin'创建全新侧边栏并往其中添加条目的玩法)。

添加 Home View 条目

下面注册一个无需集群即可访问的文档页面:

import { registerRoute, registerSidebarEntry } from '@kinvolk/headlamp-plugin/lib'; import { SectionBox } from '@kinvolk/headlamp-plugin/lib/CommonComponents'; import { Typography, Link } from '@mui/material'; // 文档页面(无需集群即可访问) function DocsPage() { return ( <SectionBox title="Plugin Documentation"> <Typography paragraph> Welcome to the plugin documentation! </Typography> <Typography paragraph> This page is accessible even when no cluster is selected. </Typography> <Link href="/">← Back to Clusters</Link> </SectionBox> ); } // 注册路由(注意 useClusterURL: false) registerRoute({ path: '/plugin-docs', name: 'Plugin Docs', sidebar: { item: 'plugin-docs', sidebar: 'HOME', }, component: DocsPage, useClusterURL: false, noAuthRequired: true, }); // 在 HOME 侧边栏中注册条目 registerSidebarEntry({ name: 'plugin-docs', label: 'Plugin Docs', url: '/plugin-docs', icon: 'mdi:book-open-variant', sidebar: 'HOME', useClusterURL: false, });

关键差异

属性作用
sidebar: { item, sidebar }registerRoute中,指定要高亮的侧边栏条目以及它属于哪个侧边栏
sidebar: 'HOME'registerSidebarEntry中,把条目放入首页侧边栏
useClusterURL: falseURL 不含/c/:cluster/前缀
noAuthRequired: true页面无需认证即可访问

Route.sidebar字段支持三种形态:string | null | { item, sidebar }(见 frontend/src/lib/router/Route.tsx),其中对象形态允许你同时指定要激活的条目名与所属侧边栏。

验证

  1. 保存文件;
  2. 回到首页(点击 Headlamp Logo 或访问http://localhost:3000/);
  3. 在侧边栏中找到 "Plugin Docs"(带书本图标);
  4. 点击进入文档页面:

完整示例:Cluster View + Home View 组合

下面是一份完整的src/index.tsx,同时演示集群视图与首页视图导航:

import { registerRoute, registerSidebarEntry } from '@kinvolk/headlamp-plugin/lib'; import { SectionBox } from '@kinvolk/headlamp-plugin/lib/CommonComponents'; import { Typography, Link } from '@mui/material'; // ========== Cluster View Pages ========== function OverviewPage() { return ( <SectionBox title="Plugin Overview"> <Typography>Welcome to My Plugin! This page is cluster-specific.</Typography> </SectionBox> ); } function SettingsPage() { return ( <SectionBox title="Plugin Settings"> <Typography>Configure your plugin settings here.</Typography> </SectionBox> ); } // ========== Home View Pages ========== function DocsPage() { return ( <SectionBox title="Plugin Documentation"> <Typography paragraph> This page is accessible without selecting a cluster. </Typography> <Link href="/">← Back to Clusters</Link> </SectionBox> ); } // ========== Cluster View Routes & Sidebar ========== registerRoute({ path: '/my-plugin', sidebar: 'my-plugin-overview', component: OverviewPage, exact: true, }); registerRoute({ path: '/my-plugin/settings', sidebar: 'my-plugin-settings', component: SettingsPage, exact: true, }); registerSidebarEntry({ name: 'my-plugin', label: 'My Plugin', icon: 'mdi:new-box', url: '/my-plugin', }); registerSidebarEntry({ parent: 'my-plugin', name: 'my-plugin-overview', label: 'Overview', url: '/my-plugin', }); registerSidebarEntry({ parent: 'my-plugin', name: 'my-plugin-settings', label: 'Settings', url: '/my-plugin/settings', }); // ========== Home View Routes & Sidebar ========== registerRoute({ path: '/plugin-docs', component: DocsPage, useClusterURL: false, noAuthRequired: true, sidebar: { item: 'plugin-docs', sidebar: 'HOME', }, }); registerSidebarEntry({ name: 'plugin-docs', label: 'Plugin Docs', url: '/plugin-docs', icon: 'mdi:book-open-variant', sidebar: 'HOME', useClusterURL: false, });

更进阶的能力:从示例插件中挖掘

仓库中的 Sidebar 示例插件 是官方提供的完整参考实现,它展示了本教程之外的多种进阶玩法,值得通读:

  • entryType: 'subheader':注册不可点击的分组标题条目(配合sx自定义样式),用于在侧边栏中给条目分组(见 示例插件第 84-93 行);
  • registerSidebarEntryFilter/registerRouteFilter:动态移除或修改侧边栏条目与路由,例如在进入某个页面时用useEffect隐藏特定条目(见 示例插件第 216-228 行);
  • registerHomeSidebarEntryFilter:过滤 HOME 侧边栏条目(见 示例插件第 295 行);
  • useClusterURL: false+hideAppBar: true:创建完全脱离集群前缀、甚至隐藏顶部 App Bar 的独立页面(见 示例插件第 257-282 行)。

这些能力对应的底层实现同样位于 frontend/src/plugin/registry.tsx:registerSidebarEntryFilter派发setSidebarItemFilterregisterRouteFilter派发setRouteFilter,返回null即删除条目/路由,返回(可修改的)条目/路由则保留。


Troubleshooting:常见问题排查

侧边栏条目不出现

检查集群上下文:

  • 未指定sidebar: 'HOME'的条目只会在选中集群后出现;
  • 确保已选择集群,才能看到集群视图条目。

检查拼写:

  • registerSidebarEntry中的name必须与registerRoute中的sidebar完全一致。

确认插件已加载:

  • 进入 Settings → Plugins;
  • 确认你的插件已列出且已启用。

页面 404 或空白

检查 URL 模式:

  • 集群视图 URL 格式:/c/:cluster/你的路径
  • 首页视图 URL 格式:/你的路径

检查useClusterURL

  • 路由中为useClusterURL: false时,不带集群前缀访问;
  • useClusterURL: true(默认)时,URL 需要包含集群前缀。

侧边栏条目不高亮

确保sidebarname匹配:

// 这两处必须一致! registerRoute({ path: '/my-plugin', sidebar: 'my-plugin', // ← 这个... component: MyPage, }); registerSidebarEntry({ name: 'my-plugin', // ← ...必须与这个一致 label: 'My Plugin', url: '/my-plugin', });

子条目不显示

检查parent引用:

registerSidebarEntry({ name: 'my-plugin', // ← 父条目 name label: 'My Plugin', }); registerSidebarEntry({ parent: 'my-plugin', // ← 必须与父条目 name 一致 name: 'my-plugin-child', label: 'Child Entry', url: '/my-plugin/child', });

parent的值必须与父条目的name精确一致,否则层级关系无法建立。


下一步

通过本教程,你已经掌握了 Headlamp 插件导航的完整基础:

  • ✅ 用registerRoute()创建自定义页面
  • ✅ 用registerSidebarEntry()添加侧边栏条目
  • ✅ 用 Iconify 图标提升视觉效果
  • ✅ 用parent组织父子层级
  • ✅ 区分 Home View 与 Cluster View 两种导航上下文

目前页面还是静态的。接下来的教程将让页面"活"起来:

  • Tutorial 4:使用 Kubernetes 数据——用内置资源类和 ApiProxy 获取集群信息、命名空间等数据(见 working-with-kubernetes-data);
  • Tutorial 5:进阶 Kubernetes 交互——创建自定义资源类、通过 API 修改资源(见 working-with-kubernetes-data-advanced)。

Quick Reference:快速参考

registerRoute 选项

registerRoute({ path: '/my-path', // URL 路径(必填) sidebar: 'sidebar-name', // 要高亮的侧边栏条目(必填) component: MyComponent, // React 组件(必填) useClusterURL: true, // 是否包含 /c/:cluster/ 前缀(默认: true) noAuthRequired: false, // 是否允许未认证访问(默认: false) exact: true, // 精确路径匹配(默认: true) name: 'route-name', // 可选的路由标识 });

registerSidebarEntry 选项

registerSidebarEntry({ name: 'unique-name', // 唯一标识(必填) label: 'Display Label', // 侧边栏显示的文本(必填) url: '/my-path', // 点击跳转的 URL icon: 'mdi:icon-name', // Iconify 图标字符串 parent: 'parent-name', // 父条目 name(用于子条目) sidebar: 'HOME', // 'HOME' 表示首页视图,省略则为集群视图 useClusterURL: true, // 是否包含 /c/:cluster/ 前缀(默认: true) });

URL 模式速查

上下文模式示例
集群视图/c/:cluster/你的路径/c/minikube/my-plugin
首页视图/你的路径/plugin-docs

【免费下载链接】headlampA Kubernetes web UI that is fully-featured, user-friendly and extensible项目地址: https://gitcode.com/GitHub_Trending/he/headlamp

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 10:14:27

MySQL WHERE条件查询全解析:从执行逻辑到索引优化实战

写WHERE语句这么多年&#xff0c;我发现很多做开发的朋友对它的理解其实停留在“会用”层面。能把数据查出来是一回事&#xff0c;能查得对、查得快、还能把背后的逻辑讲清楚&#xff0c;是另一回事。MySQL里的WHERE条件查询是整个SQL体系中接触最频繁、也最容易埋坑的环节&…

作者头像 李华
网站建设 2026/9/17 10:11:05

嵌入式学习路线:从C语言到ARM/Linux项目实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 10:07:25

如何把 PDF 快速变成可编辑的 PPT:PPT Master 实战指南

如何把 PDF 快速变成可编辑的 PPT&#xff1a;PPT Master 实战指南 【免费下载链接】ppt-master AI turns documents or topics into real, native PowerPoint decks—with native shapes, transitions and animations, data-backed charts and tables on demand, audio narrat…

作者头像 李华
网站建设 2026/9/17 10:03:27

Linux下程序只用一个核?从top到perf的完整排查指南

大家应该都见过这道经典场景&#xff1a;新买的云服务器&#xff0c;16核配置拉满&#xff0c;高高兴兴把程序部署上去&#xff0c;top一敲&#xff0c;愣住了——进程列表里明晃晃挂着接近100%的占用&#xff0c;再按个1看每个核心&#xff0c;只有0号核在拼命工作&#xff0c…

作者头像 李华