Docker build error

Error Message is :

`Docker build :@Err:2 http://deb.debian.org/debian-security bullseye-security InRelease Temporary failure resolving 'deb.debian.org'

这个错误通常是由于 Docker 容器在构建过程中无法解析域名,可能的原因包括 Docker 容器的网络配置问题或主机的 DNS 设置问题。以下是几种解决方法:

方法 1:检查主机网络连接

1. 确保主机能够访问 http://deb.debian.org

ping deb.debian.org

2.如果主机可以正常访问,但容器不能访问,继续以下步骤。

方法 2:配置 Docker 的 DNS

默认情况下,Docker 使用主机的 DNS 配置。如果主机的 DNS 设置有问题或被防火墙阻止,可以手动为 Docker 配置 DNS。

方法 2.1:在 docker build 中指定 DNS

docker build --network=host -t my-image .

–network=host 选项让构建过程直接使用主机的网络。

方法 2.2:通过 –dns 手动指定 DNS

在构建镜像时明确指定 DNS:

docker build --dns=8.8.8.8 --dns=8.8.4.4 -t my-image .

方法 3:更新 Docker 的全局 DNS 设置

1.编辑 Docker 的配置文件(通常在 /etc/docker/daemon.json 中):

sudo nano /etc/docker/daemon.json

2.添加或修改以下内容:

{

  "dns": ["8.8.8.8", "8.8.4.4"]

}

3.重启 Docker 服务:

sudo systemctl restart docker

方法 4:更新 Dockerfile

Dockerfile 中添加以下内容,确保在构建过程中可以使用不同的网络解析器:

RUN echo "nameserver 8.8.8.8" > /etc/resolv.conf && echo "nameserver 8.8.4.4" >> /etc/resolv.conf

方法 5:确保主机的 DNS 设置正确

1.检查主机的 DNS 配置文件 /etc/resolv.conf,内容应该类似:

nameserver 8.8.8.8

nameserver 8.8.4.4

2.如果文件为空或 DNS 服务器不可用,更新内容后保存。

方法 6:切换到其他网络模式

如果构建时网络配置出错,可以尝试使用 --network=host

docker build --network=host -t my-image .

通过上述方法,可以解决 Docker 在构建过程中因网络问题无法解析域名的问题。如果问题依然存在,请提供更多环境信息,以便进一步排查。

方法7 : 重启Docker服务

service docker status

service docker restart

 

close the function :ufw block print log.

要关闭 UFW 阻止日志的打印,可以通过以下步骤调整设置:

方法 1:修改 UFW 配置

1.打开 UFW 的主配置文件:

sudo nano /etc/ufw/ufw.conf

2.找到以下行并修改:

LOGLEVEL=low

改为:

LOGLEVEL=off

3.保存并退出,然后重启 UFW:

sudo ufw reload

方法 2:调整 rsyslog 配置

如果仍然出现日志,可以通过调整 rsyslog 配置来过滤掉这些日志:

1.编辑 rsyslog 配置文件:

sudo nano /etc/rsyslog.d/20-ufw.conf

2.添加以下行以过滤掉 UFW 阻止日志:

:msg, contains, "[UFW BLOCK]" ~

3.保存并重启 rsyslog 服务:

sudo systemctl restart rsyslog

方法 3:通过内核日志禁用

如果日志是由内核通过 dmesg 打印的,可以调整 sysctl 参数:

1. 添加以下行到 /etc/sysctl.conf

net.ipv4.conf.all.log_martians = 0

net.ipv4.conf.default.log_martians = 0

2.应用设置:

sudo sysctl -p

检查日志是否停止

完成上述步骤后,检查 /var/log/syslog 或其他日志文件是否仍然有相关记录。如果还有问题,可以针对具体环境进一步调整。

这样应该可以成功关闭这些日志的打印。

X86/64,x86/Geode,x86/legacy 的区别

在 ImmortalWrt 或类似的固件选项中,Generic x86/64Generic x86/GeodeGeneric x86/legacy 的区别主要涉及处理器架构和兼容性。以下是详细解释:

1. Generic x86/64

适用范围: 针对 64 位架构 的 x86 处理器(常见于现代桌面、服务器和嵌入式设备)。

特点:

•支持更大的内存地址(4GB 以上)。

•提供更高的性能优化,适用于现代 x86/64 架构(如 Intel Core 系列、AMD Ryzen 等)。

推荐使用: 如果你的设备是现代 64 位处理器,请选择此选项。

2. Generic x86/Geode

适用范围: 针对 AMD 的 Geode 系列处理器(如 Geode GX/LX 等)。

特点:

•Geode 是一类低功耗、嵌入式 x86 处理器,常用于旧式嵌入式设备或轻量化服务器。

•优化代码以适配 Geode 的特性(如有限的指令集支持)。

推荐使用: 如果你的设备是较老的嵌入式系统,并且明确使用的是 Geode 处理器,选择此选项。

3. Generic x86/legacy

适用范围: 针对旧版的 x86 处理器,通常为 32 位架构(如早期的 Intel Pentium、Celeron 或其他早期 x86 CPU)。

特点:

•没有使用 64 位特性,适合旧设备。

•优化用于处理器性能较低、内存较小的系统。

推荐使用: 如果你的设备不支持 64 位(如老式路由器、旧电脑),选择此选项。

如何选择?

1.现代设备(大多数支持 64 位): 选择 Generic x86/64

2.嵌入式或低功耗设备(明确使用 Geode 处理器): 选择 Generic x86/Geode

3. 老旧设备(32 位处理器): 选择 Generic x86/legacy

建议: 根据你的硬件特性和使用目标选择合适版本,以确保系统性能和兼容性达到最佳。

Linux TCP/UDP connection nums.

在 Linux 系统中,可以通过以下方法查看 TCP/UDP 网络连接数,并统计不同网卡的总连接数:

1. 使用 ss 命令

ss 是现代 Linux 系统中用于查看套接字统计信息的工具。

# 查看所有 TCP 连接

ss -t | wc -l

# 查看所有 UDP 连接

ss -u | wc -l

说明:

-t:显示 TCP 连接。

-u:显示 UDP 连接。

wc -l:统计行数,表示连接数。

2. 使用 netstat 命令

虽然 netstat 已被弃用,但仍然可以用来统计连接数。

# 查看所有 TCP 连接数

netstat -ant | wc -l

# 查看所有 UDP 连接数

netstat -anu | wc -l

说明:

-a:显示所有连接。

-n:数字格式显示地址和端口。

-t:显示 TCP 连接。

-u:显示 UDP 连接。

3. 按网卡统计连接数

如果需要统计每个网卡的连接数,可以结合 ss 命令和 awk 或其他工具进行筛选。例如:

# 按网卡统计 TCP 连接数

ss -t -i | grep -E "eth0|wlan0" | wc -l

# 替换网卡名称为实际名称 (如 `eth0`, `wlan0`)

4. 使用 /proc 文件系统

/proc/net/tcp /proc/net/udp 文件提供了当前 TCP 和 UDP 连接的详细信息。

# 查看 TCP 连接数

cat /proc/net/tcp | wc -l

# 查看 UDP 连接数

cat /proc/net/udp | wc -l

说明:

•减去标题行可以获得实际连接数(通常为第一行)。

5. 结合网卡信息统计

可以使用 iftopnload 等工具实时监控特定网卡的网络流量和连接数,或者结合以下命令筛选。

# 结合 IP 信息筛选网卡数据 (以 eth0 为例)

ss -t -n | grep -E "eth0" | wc -l

6. 使用 lsof 命令

lsof 也可以列出与网卡相关的连接。

# 查看 TCP 连接

lsof -iTCP | wc -l

# 查看 UDP 连接

lsof -iUDP | wc -l

如果有更复杂的需求,比如持续监控或按状态分类统计,可以使用脚本或监控工具(如 Prometheus + Grafana)实现。需要进一步深入分析吗?

What’s The MCP (Model Context Protocol) ? 什么是Model Context Protocol(MCP)?

The Model Context Protocol (MCP) is an open protocol that enables seamless integration between LLM applications and external data sources and tools. Whether you’re building an AI-powered IDE, enhancing a chat interface, or creating custom AI workflows, MCP provides a standardized way to connect LLMs with the context they need.

模型上下文协议(MCP)是一个开放协议,旨在实现LLM应用与外部数据源和工具之间的无缝集成。无论您是在构建AI驱动的集成开发环境(IDE)、增强聊天界面,还是创建自定义的AI工作流,MCP都提供了一种标准化的方式,将LLM与所需的上下文连接起来。

As AI assistants gain mainstream adoption, the industry has invested heavily in model capabilities, achieving rapid advances in reasoning and quality. Yet even the most sophisticated models are constrained by their isolation from data—trapped behind information silos and legacy systems. Every new data source requires its own custom implementation, making truly connected systems difficult to scale.

随着AI助手的广泛采用,业界在模型能力上进行了大量投资,取得了快速的推理和质量进展。然而,即便是最复杂的模型也受到与数据隔离的限制——被困在信息孤岛和遗留系统中。每个新的数据源都需要定制的实现,使得真正连接的系统难以扩展。

MCP addresses this challenge. It provides a universal, open standard for connecting AI systems with data sources, replacing fragmented integrations with a single protocol. The result is a simpler, more reliable way to give AI systems access to the data they need.

MCP解决了这一挑战。它提供了一种通用的开放标准,用于将AI系统与数据源连接,通过一个单一协议取代了碎片化的集成。结果是为AI系统提供所需数据的更简单、更可靠的方式。

Model Context Protocol

The Model Context Protocol is an open standard that enables developers to build secure, two-way connections between their data sources and AI-powered tools. The architecture is straightforward: developers can either expose their data through MCP servers or build AI applications (MCP clients) that connect to these servers.

模型上下文协议是一个开放标准,使开发者能够在其数据源和AI驱动的工具之间建立安全的双向连接。其架构非常简单:开发者可以通过MCP服务器暴露其数据,或构建连接到这些服务器的AI应用(MCP客户端)。

Today, we’re introducing three major components of the Model Context Protocol for developers:

Claude 3.5 Sonnet is adept at quickly building MCP server implementations, making it easy for organizations and individuals to rapidly connect their most important datasets with a range of AI-powered tools. To help developers start exploring, we’re sharing pre-built MCP servers for popular enterprise systems like Google Drive, Slack, GitHub, Git, Postgres, and Puppeteer.

Claude 3.5 Sonnet擅长快速构建MCP服务器实现,使组织和个人能够迅速将其最重要的数据集与各种AI驱动的工具连接起来。为了帮助开发者快速入门,我们提供了适用于Google Drive、Slack、GitHub、Git、Postgres和Puppeteer等流行企业系统的预构建MCP服务器。

Early adopters like Block and Apollo have integrated MCP into their systems, while development tools companies including Zed, Replit, Codeium, and Sourcegraph are working with MCP to enhance their platforms—enabling AI agents to better retrieve relevant information to further understand the context around a coding task and produce more nuanced and functional code with fewer attempts.

像Block和Apollo这样的早期采用者已将MCP集成到其系统中,而开发工具公司如Zed、Replit、Codeium和Sourcegraph也正在与MCP合作,增强他们的平台——使AI代理能够更好地检索相关信息,更好地理解编程任务的上下文,并生成更细致、功能更强大的代码,减少尝试次数。

“At Block, open source is more than a development model—it’s the foundation of our work and a commitment to creating technology that drives meaningful change and serves as a public good for all,” said Dhanji R. Prasanna, Chief Technology Officer at Block. “Open technologies like the Model Context Protocol are the bridges that connect AI to real-world applications, ensuring innovation is accessible, transparent, and rooted in collaboration. We are excited to partner on a protocol and use it to build agentic systems, which remove the burden of the mechanical so people can focus on the creative.”

Block的首席技术官Dhanji R. Prasanna表示:“在Block,开源不仅仅是开发模型——它是我们工作的基础,是创建推动有意义变化的技术、服务公共利益的承诺。像模型上下文协议这样的开源技术,是将AI与现实世界应用连接起来的桥梁,确保创新能够得到访问、透明,并且根植于合作。我们很高兴能合作制定这个协议,并用它构建代理系统,去除机械的负担,让人们专注于创意。”

Instead of maintaining separate connectors for each data source, developers can now build against a standard protocol. As the ecosystem matures, AI systems will maintain context as they move between different tools and datasets, replacing today’s fragmented integrations with a more sustainable architecture.

开发者现在可以在标准协议的基础上进行开发,而不必为每个数据源维护单独的连接器。随着生态系统的成熟,AI系统将能够在不同工具和数据集之间保持上下文,取代当前的碎片化集成,形成一种更可持续的架构。

Getting started

Developers can start building and testing MCP connectors today. Existing Claude for Work customers can begin testing MCP servers locally, connecting Claude to internal systems and datasets. We’ll soon provide developer toolkits for deploying remote production MCP servers that can serve your entire Claude for Work organization.

开发者可以立即开始构建和测试MCP连接器。现有的Claude for Work客户可以开始本地测试MCP服务器,将Claude连接到内部系统和数据集。我们很快将提供开发工具包,用于部署远程生产MCP服务器,服务整个Claude for Work组织。

To start building:

An open community

We’re committed to building MCP as a collaborative, open-source project and ecosystem, and we’re eager to hear your feedback. Whether you’re an AI tool developer, an enterprise looking to leverage existing data, or an early adopter exploring the frontier, we invite you to build the future of context-aware AI together.

我们致力于将MCP构建为一个协作的开源项目和生态系统,并期待听取您的反馈。无论您是AI工具开发者、希望利用现有数据的企业,还是正在探索前沿的早期采用者,我们邀请您一起构建上下文感知AI的未来。

Giving somebody advice 提出建議

There are a number of tactful ways of telling people what you think they should do .

給別人提建議時有一些較為得體的表達方式。

give .

✅ give是动词,意思是“给予”;

✅somebody 是give的被动方。

✅advice 名词,表示“建议”或者“忠告”,是一个不可数名词。 所以不可以说” an advice ” 或者“many advices” ,需要表达几条建议,可以使用: some advice ; a piece of advice ; two pieces of advice.

✅:give advice 正确;

❌: give an advice 错误。 advice是不可数名词。

✅:常用的搭配和例句

  1. Can you give me some advice ?
    • 你能給我一些建議嗎?
  2. She gave him excellent advice on how to prepare for the interview .
    • 她就如何準備面試給了他很好的建議。
  3. If you don’t mind, I’d like to give you a piece of advice.
    • 如果你不介意,我想給妳一條建議。

✅更得體的提建議的表達方式:

  1. If I were you , i’d wait . 如果我是你,我會等等看的。
  2. I think you should / ought to see a doctor .我覺得你該去看看醫生。
  3. Why don’t you /Why not /Could you maybe ask Tome to help ? 你為什麼不/你或許可以找Tom幫忙。
  4. If you want my advice / If you want to know what I think, I’d say it’s better to tell him. 如果你想听我的建议/如果你想知道我的想法,我认为最好还是高速他。
  5. I’d advise you to sell it now . 我劝你现在就卖掉它。

如何在 WordPress 中添加 Cloudflare Turnstile 验证码

背景

新建博客系統的時候,默認的配置往往沒有開啟spam信息過濾的,導致一些爬蟲網站會頻繁的在你的文章下面進行機器人流言,在後台產生一大堆的辣雞信息,雖然不能直接展示出來,但是在後台展示的提示信息,對於有點強迫症的我來說,多少有點不可接受,以前使用過Google CAPCHA和reCAPTCHA 用於阻止非用戶的惡意支付行為,現在用在博客系統中,想使用Cloudflare 的Turnstile試試,像比較google 一些CAPCHA的地獄級的圖片識別,Cloudflare Turnstile 的用戶體驗比前者舒服很多。

Cloudflare Turnstile 使用了一系列非侵入性技術,這種技術通常在瀏覽器中不可見地運行,這使您可以在不要求訪問完成複雜的謎題的情況下保護您的網站。 Cloudflare 為了保護訪問者的私密性,使用了Apple 的Private Access Tokens 來測試訪問者是否是真人,而無需搜集額外數據,同時支持表單生成器或者WooCommece的集成,可以根據你的需求在不同的地方添加Cloudflare Turnstile。

在本文中,將向您展示如何將Cloudflare Turnstile 添加到Wordpress 網站中。

安裝Wordpress Cloudflare turnstile 插件

在wordpres的後台的插件市場,搜索關鍵詞 cloudflare Turnstile ,就會看到該插件,該插件允許您免費接入到Cloudflare Turnstile 服務。

安裝並激活插件,跳轉到設置-> Cloudflare Turnstile.

該插件需要您提供API keys(密鑰和密碼)。 在後台提示中的Link 點擊訪問:


You can get your site key and secret key from here: https://dash.cloudflare.com/?to=/:account/turnstile

獲取Cloudflare Turnstile的密鑰和密碼

註冊Cloudflare 平台的帳號,該平台的帳號註冊免費,登陸您的帳號然後訪問上述連結,會進入如下界面。

然後點擊【添加小組件】,自定義自己的組件名字,比如:wp-name. 和自定義主機名,也就是你的網站主域名(ethanwong.online就是主域名)。

點擊【添加】 ,其他配置不變,然後再【創建】 ,會看到你的密鑰和密碼,複製保存。

將密鑰和密碼保存到你的wordpress 的 cloudflare turnstile 配置中,勾選需要添加Cloudflare Turnstile的界面,點擊wordpress 後台 cloudflare Turnstile 的【保存】按鈕。

再看你的文章界面的評論,就可以看到了。

Docker compose up

sudo apt install -y docker-compose-v2

docker error:

ubuntu@iZj6ce8708hro5jg9q9wgaZ:~/typesense$ sudo docker-compose up
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/docker/api/client.py", line 214, in _retrieve_server_version
    return self.version(api_version=False)["ApiVersion"]
  File "/usr/lib/python3/dist-packages/docker/api/daemon.py", line 181, in version
    return self._result(self._get(url), json=True)
  File "/usr/lib/python3/dist-packages/docker/utils/decorators.py", line 46, in inner
    return f(self, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/docker/api/client.py", line 237, in _get
    return self.get(url, **self._set_request_timeout(kwargs))
  File "/usr/local/lib/python3.10/dist-packages/requests/sessions.py", line 602, in get
    return self.request("GET", url, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/requests/sessions.py", line 589, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python3.10/dist-packages/requests/sessions.py", line 703, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/requests/adapters.py", line 486, in send
    resp = conn.urlopen(
  File "/usr/local/lib/python3.10/dist-packages/urllib3/connectionpool.py", line 790, in urlopen
    response = self._make_request(
  File "/usr/local/lib/python3.10/dist-packages/urllib3/connectionpool.py", line 496, in _make_request
    conn.request(
TypeError: HTTPConnection.request() got an unexpected keyword argument 'chunked'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/bin/docker-compose", line 33, in <module>
    sys.exit(load_entry_point('docker-compose==1.29.2', 'console_scripts', 'docker-compose')())
  File "/usr/lib/python3/dist-packages/compose/cli/main.py", line 81, in main
    command_func()
  File "/usr/lib/python3/dist-packages/compose/cli/main.py", line 200, in perform_command
    project = project_from_options('.', options)
  File "/usr/lib/python3/dist-packages/compose/cli/command.py", line 60, in project_from_options
    return get_project(
  File "/usr/lib/python3/dist-packages/compose/cli/command.py", line 152, in get_project
    client = get_client(
  File "/usr/lib/python3/dist-packages/compose/cli/docker_client.py", line 41, in get_client
    client = docker_client(
  File "/usr/lib/python3/dist-packages/compose/cli/docker_client.py", line 170, in docker_client
    client = APIClient(use_ssh_client=not use_paramiko_ssh, **kwargs)
  File "/usr/lib/python3/dist-packages/docker/api/client.py", line 197, in __init__
    self._version = self._retrieve_server_version()
  File "/usr/lib/python3/dist-packages/docker/api/client.py", line 221, in _retrieve_server_version
    raise DockerException(
docker.errors.DockerException: Error while fetching server API version: HTTPConnection.request() got an unexpected keyword argument 'chunked'

Docker 版本:

Docker version 24.0.5, build 24.0.5-0ubuntu1~22.04.1

How to fix it ?

sudo apt install -y docker-compose-v2

Then you will use the docker compose replace the old command docker-compose

Run it use new command

sudo docker compose 

From July 2023 Compose V1 stopped receiving updates. It’s also no longer available in new releases of Decker Desktop.

Compose V2 which was first released in 2020. is included with all currently supported versions of Docker Desktop.

It offers an improved CLI experience , improved build performance with BuildKit , and continued new-feature development.

unlike Compose V1,Compose V2 integrates into the Docker CLI platform and recommended command-line syntax is docker compose

The Docker CLI platform provides a consistent and predictable set of options and flags, such as the DOCKER_HOST environment variable or the --context command-line flag.

This change lets you use all of the shared flags on the root docker command. For example, docker --log-level=debug --tls compose up enables debug logging from the Docker Engine as well as ensuring that TLS is used for the connection.

Update scripts to use Compose V2 by replacing the hyphen(-) with a space , using docker compose instead of doker-compose

Related Article .

  1. https://github.com/itzg/docker-minecraft-server/issues/2578

/sbin/multipathd 的功能、实现原理及内存占用分析

I. 引言

在现代数据中心和企业IT环境中,存储区域网络 (SAN) 的可靠性和性能至关重要。/sbin/multipathd 守护进程是 Linux 系统中设备映射器多路径 (Device Mapper Multipath, DM-Multipath) 功能的核心组件,它通过管理服务器与存储阵列之间的多条物理路径,提供了关键的 I/O 故障切换和负载均衡能力,从而确保了存储访问的高可用性和性能优化 1。理解 multipathd 的功能、其底层的实现机制,以及分析其可能导致高内存占用的原因,对于系统管理员和性能分析师来说至关重要。本报告旨在深入探讨 /sbin/multipathd 的这些方面,并提供诊断和优化的策略,以帮助维护一个稳定且高效的多路径环境。multipathd 不仅仅是一个简单的路径监控器,它在用户空间与内核的 dm-multipath 模块紧密协作,共同构成了 Linux 多路径解决方案的控制平面和管理核心。

II. /sbin/multipathd 的功能与实现原理

/sbin/multipathd 的设计目标是为块设备提供持续的可用性和更高的带宽连接,尤其是在 Fibre Channel (FC) 和 iSCSI SAN 环境中 1

A. 核心功能

multipathd 的核心功能主要围绕着确保数据路径的冗余和效率。

  1. 路径管理与故障切换 (Path Management and Failover)multipathd 负责监控服务器到存储设备的每条物理路径的状态。当检测到活动路径发生故障(例如线缆断开、交换机端口故障或存储控制器端口故障)时,它会自动将 I/O 请求重新路由到另一条可用的备用路径上 1。这个过程称为故障切换 (Failover),其目的是最大限度地减少因单点故障导致的服务中断,确保数据的持续可访问性 5。
  2. 负载均衡 (Load Balancing)在某些配置下(例如 Active/Active 模式),multipathd 能够将 I/O 负载分散到多条可用的活动路径上 1。这有助于避免单一路径成为瓶颈,从而提高整体的 I/O 吞吐量并优化存储资源的利用率。不同的负载均衡策略(如轮询 round-robin、队列长度 queue-length 等)可以根据具体的工作负载特性进行配置 6。
  3. 设备映射与统一视图 (Device Mapping and Unified View)multipathd 利用内核的 Device Mapper 框架,将指向同一存储 LUN (Logical Unit Number) 的多个物理路径聚合成一个单一的虚拟块设备(通常称为多路径设备或 mpath 设备)1。应用程序和文件系统通过这个虚拟设备与存储进行交互,而无需关心底层的物理路径复杂性。这个虚拟设备拥有一个全局唯一的 WWID (World Wide Identifier),确保了设备标识的一致性 7。

下表总结了 multipathd 及其相关组件的核心功能:

表 2: multipathd 组件及其核心功能

组件/功能描述相关资料
路径管理监控物理路径的状态,检测路径故障和恢复。1
故障切换在路径失败时,自动将 I/O 重定向到健康的备用路径,保证业务连续性。1
负载均衡在多条活动路径间分配 I/O 请求,以提高性能和吞吐量。1
设备映射将多个指向同一 LUN 的物理路径聚合成一个单一的虚拟设备,简化上层应用对存储的访问。1
路径恢复 (Failback)当故障路径恢复正常后,根据配置策略决定是否将 I/O 切回原路径。1
配置管理通过 /etc/multipath.conf 文件进行用户自定义配置,如黑名单、设备特定参数、默认行为等。1
事件处理响应内核或 udev 产生的设备事件(如设备添加、移除、状态变更),并执行相应的路径配置或重配置操作。3
持久化预留 (SCSI-3)mpathpersist 工具配合,管理 SCSI-3 持久化预留,确保在集群环境中对共享存储的独占访问。5

B. 关键组件

DM-Multipath 的实现依赖于内核模块和用户空间工具的协同工作 1

  1. dm-multipath 内核模块这是 Device Mapper 的一个目标驱动 (target driver),运行在内核空间。它负责实际的 I/O 重路由、路径分组管理以及实现故障切换和负载均衡逻辑 1。multipathd 通过与该模块交互来更新路径状态和配置。
  2. multipath-tools 用户空间工具集这是一套用于管理和配置多路径设备的用户空间程序 1。
    • multipathd 守护进程: 这是核心的后台服务,负责监控路径状态,响应 udev 事件,执行路径检查器,并在路径状态变化时更新 dm-multipath 内核模块的映射表 1。它还处理 /etc/multipath.conf 中的配置。
    • multipath 命令: 一个命令行工具,用于扫描系统中的多路径设备、手动创建或刷新多路径映射、显示当前多路径拓扑和状态 1udev 规则通常在块设备添加时调用此命令来判断设备是否应成为多路径设备的一部分 5
    • kpartx 命令: 用于从设备或多路径映射创建分区设备映射。当多路径设备包含分区表时,kpartx 会为每个分区创建对应的 /dev/dm-X 设备 1
    • /etc/multipath.conf 配置文件: 这是 multipathdmultipath 命令的主要配置文件。用户可以通过编辑此文件来覆盖内置的默认配置,定义设备黑名单、特定存储阵列的参数、路径分组策略、路径检查方式等 1。配置文件的正确性对多路径功能的稳定运行至关重要。

C. 工作流程

multipathd 的工作流程涉及路径的发现、监控和故障处理。

  1. 路径发现与设备聚合 (Path Discovery and Device Aggregation)当系统启动或新的存储路径被添加到系统时(例如通过 HBA 卡扫描或 iSCSI 登录),udev 会为每个物理路径创建一个设备节点(如 /dev/sda, /dev/sdb 等)。udev 规则会触发 multipath 命令 5。multipath 命令根据 /etc/multipath.conf 中的配置(特别是黑名单 blacklist 和黑名单例外 blacklist_exceptions 2)以及设备的 WWID 来识别所有指向同一 LUN 的路径。如果满足条件(例如,根据 find_multipaths 设置,发现至少两条路径指向同一 WWID 12),multipath 会指示 dm-multipath 内核模块将这些路径聚合成一个新的多路径设备(如 /dev/mapper/mpatha 或 /dev/mapper/<WWID>) 7。
  2. 路径监控与状态检测 (Path Monitoring and State Detection)multipathd 守护进程持续监控所有已配置多路径设备的各个路径的健康状况 1。
    • 路径检查器 (Path Checkers): multipathd 使用路径检查器来确定路径的可用性。常见的检查器包括:
      • tur (Test Unit Ready): 发送 SCSI TEST UNIT READY 命令。这是许多存储设备推荐的检查器 6
      • directio: 通过直接读取路径设备上的一个扇区来检查路径状态。这对于不支持 TUR 命令的设备可能有用,但开销相对较大 6
      • emc_clariion: 专门为 EMC Clariion/VNX 存储设计的检查器 6
      • 其他特定硬件的检查器,如 rdac, hp_sw6。 选择正确的路径检查器对及时准确地检测路径故障至关重要。错误的检查器可能导致路径状态误判或检测延迟。
    • 轮询间隔 (polling_interval): multipathd 按照在 /etc/multipath.conf 中定义的 polling_interval(默认为5秒 6)定期调用路径检查器。对于健康的路径,检查间隔可能会逐渐增加到 max_polling_interval 6
  3. 故障处理与恢复机制 (Failure Handling and Recovery Mechanisms)
    • 故障切换逻辑 (Failover Logic): 当路径检查器报告某条活动路径失败时,multipathd 会通知 dm-multipath 内核模块。内核模块随后将 I/O 从故障路径切换到同一路径组 (path group) 中的下一条可用路径,或者切换到优先级更高的路径组中的路径,具体取决于 path_grouping_policypath_selector 的配置 1。路径状态可能变为 failedfaulty 1
    • 恢复逻辑 (Failback Logic): 当一条之前发生故障的路径恢复正常并通过路径检查器的验证后,multipathd 会根据 /etc/multipath.conf 中配置的 failback 策略来处理 1
      • immediate: 立即将 I/O 切回恢复的路径(如果其优先级更高)。
      • manual: 路径恢复后保持在备用状态,需要管理员手动干预才能切回。这是许多配置中的默认值 6
      • followover: 将此路径组的故障切换行为委托给集群资源管理器。
      • <N> (数值): 等待 N 秒后,如果路径仍然健康,则切回。 multipathd 还处理 queue_if_no_pathno_path_retry 6 这类特性,允许在所有路径都不可用时对 I/O 请求进行排队,而不是立即失败,这为路径恢复提供了缓冲时间。

III. /sbin/multipathd 占用内存高的潜在原因

multipathd 守护进程在某些情况下可能会消耗较高的内存,这可能由多种因素共同导致,包括其自身的设计、配置选项以及与系统其他部分的交互。

A. 内部因素:multipathd 自身机制与设计

  1. 每路径内存开销 (Per-Path Memory Overhead)multipathd 为其监控的每条路径维护状态信息、统计数据和相关句柄。
    • pthreads 的影响: 根据一些分析,multipathd 为每条路径创建的线程(或线程相关资源,如早期版本中为每个设备创建独立线程进行事件等待 3 或路径检查)是内存占用的一个重要部分。即使线程本身不做太多工作,pthreads 库调用和线程上下文本身也会消耗一定的内存 17。一份报告指出,multipathd 每条路径大约消耗 84KB 到 160KB 内存,并且在服务重载后这个值可能会增加 17。尽管 Valgrind 等工具可能未检测到明显的内存泄漏,但 pthreads 库的内存分配行为本身构成了基础开销。
    • 路径状态和统计信息: 存储每条路径的详细状态(如 active, failed, ready, ghost 16)、性能计数器、错误统计等都需要内存。路径数量越多,这部分累积的内存就越多。
  2. 路径检查器 (path_checker) 的选择与开销不同的路径检查器具有不同的资源消耗特性 6。
    • 例如,directio 检查器通过实际读写操作来验证路径,这比仅发送 SCSI 命令(如 tur)的检查器可能需要更多的 CPU 时间和临时内存缓冲区。
    • 如果配置了资源密集型的检查器,并且路径数量很多或 polling_interval 很短,那么检查器操作本身可能导致 multipathd 的工作集增大或更频繁的内存分配/释放周期。同步检查器(turdirectio 除外)在执行时会暂停 multipathd 的其他活动,这可能间接影响其行为模式 6
  3. 大量路径管理 (Management of a Large Number of Paths)直接地,系统中的路径数量是影响 multipathd 内存占用的最主要因素之一。每个被监控的路径都需要 multipathd 分配资源来跟踪其状态、执行检查、处理事件等。在一个拥有数百甚至数千条路径的大型 SAN 环境中,即使每条路径的开销很小,累积起来的内存占用也会相当可观 17。例如,如果每路径平均消耗 100KB,1000 条路径就意味着大约 100MB 的基础内存占用,这还不包括其他全局数据结构和缓存。

B. 外部与配置因素

  1. 已知的内存泄漏与软件版本特定版本的 multipath-tools 或相关的内核组件可能存在已知的内存泄漏。
    • multipath-tools 特定版本问题:
      • SUSE 的一个更新通告提到修复了 multipath-tools 0.9.8 版本中 nvme foreign library 的一个内存泄漏问题 (bsc#1229898) 20
      • multipath-tools 的 NEWS 文件提到了在 0.9.3 版本中修复了一个内存泄漏,但未提供详细信息 21
      • 一个 Red Hat 的问题报告指出,当 nvme_core.multipath (内核原生 NVMe 多路径) 和 multipathd 同时启用时,可能会暴露 multipathd 的内存泄漏 22
    • 内核与 nvme_core.multipath 交互问题: 如上所述,与 NVMe 原生多路径的交互可能是一个潜在的泄漏源 22
    • libvirtd 的交互: 有报告指出,在特定场景下,multipathudev 规则(特别是处理 change 事件的规则)可能与 libvirtd 交互导致 libvirtd 发生内存泄漏 19。虽然这不是 multipathd 本身的泄漏,但它表明了多路径子系统事件处理可能对其他系统组件产生非预期的影响。 定期更新 multipath-tools 和内核至关重要,因为新版本通常会修复已知的错误和内存问题 20
  2. 配置不当引发的内存压力/etc/multipath.conf 中的某些设置如果配置不当,可能会导致 multipathd 消耗更多内存或表现出类似内存泄漏的行为。
    • polling_interval, max_polling_interval, 和 checker_timeout:
      • 非常短的 polling_interval(例如,远小于默认的 5 秒)会导致路径检查器更频繁地运行。如果路径检查器本身开销较大,或者系统中路径数量众多,这会增加 multipathd 的持续工作负载,可能导致其工作集(working set)增大 6
      • 过长的 checker_timeout 可能导致路径检查线程或资源在等待超时期间被长时间占用,如果同时有多个路径检查超时,可能会累积资源消耗。
    • max_fds (Maximum File Descriptors):
      • 此参数设置 multipathd 进程可以打开的最大文件描述符数量。默认值可能是 max(系统限制)或 1024 6。如果实际需要的 FD 数量(约等于路径数 + 一些额外开销)超过此限制且未设置为 max,可能会导致操作失败或行为异常。虽然这不直接导致持久性内存增加,但反复的失败和重试操作可能会对内存管理造成压力。
    • find_multipaths (Modes: greedy, smart, strict, yes/on):
      • greedy 模式(或在 find_multipaths 参数出现之前的默认行为,有时也称为 yeson)会导致 multipathd 尝试为每个未被列入黑名单的路径创建多路径设备 6。在拥有大量路径(其中许多可能不是真正的多路径候选者)的系统中,这种模式会在发现阶段进行更多的评估和尝试,可能消耗更多内存来处理这些临时的候选设备状态。
      • strict 模式(或 off)最为保守,仅当设备的 WWID 已知(例如,存在于 wwids 文件中)或由用户手动强制创建时,才会创建多路径设备。这种模式在发现阶段的内存开销最小。
      • smart 模式会在创建映射前等待 find_multipaths_timeout 定义的时间,以收集更多路径信息。这需要在发现阶段为待处理设备维护一些状态,内存消耗介于 strictgreedy 之间。
      • SUSE 的文档指出,当 find_multipaths yes 时,multipathd 可能会以 -n(忽略新设备)模式启动,除非 WWID 已在 wwids 文件中,这可能需要初始手动运行 multipath 命令 26。这种机制意味着系统需要维护一个已知 WWID 的列表,这本身会消耗少量内存。
    • user_friendly_names 与绑定文件缓存 (and Bindings File Caching):
      • user_friendly_names 设置为 yes 时,multipathd 会使用一个绑定文件(例如 /etc/multipath/bindings/var/lib/multipath/bindings)将 WWID 映射到持久的、人类可读的别名(如 mpatha3
      • 较新版本的 multipath-tools(例如 0.9.x 系列)会将这个绑定表缓存到内存中,并通过 inotify 监控文件的变化,仅在必要时回写文件 21。如果绑定文件非常庞大(例如,包含数千个条目),这个内存缓存本身就可能占用可观的内存空间。
  3. 与 udev 在高设备负载下的交互 (Interaction with udev under Heavy Device Load)当大量新的存储设备或路径同时出现在系统中时(例如,一次性划分许多 LUN),udev 会处理大量的设备事件。每个事件都可能触发 udev 规则,包括那些调用 multipath 命令来评估新路径的规则。这可能导致:
    • 短时间内运行多个 multipath 命令实例。
    • 产生大量 udevd 工作进程,每个进程都会消耗内存。一份报告提到,在快速创建大量设备时,观察到多达 240 个 udevd 进程,平均每个消耗约 100KB 内存 17
    • multipathd 接收到大量通知,并尝试同时配置许多设备。 这种“事件风暴”会导致系统整体内存使用量激增。multipathd 在努力跟上设备创建和状态更新的过程中,其内存占用也可能相应增加。此时,问题可能并非 multipathd 本身的内存泄漏,而是整个系统在设备发现和配置的巨大压力下挣扎,其中 udev 是一个主要的资源消耗者 17
  4. 高 I/O 流量与事件风暴的压力诱导增长 (Stress-Induced Growth from High I/O Traffic and Event Storms)虽然 multipathd 通常不直接处理 I/O 数据路径(这是内核模块 dm-multipath 的职责),但高 I/O 流量可能导致路径在负载下变得不稳定或处于边缘状态 (marginal),从而引发更频繁的路径状态变化。这意味着 multipathd 需要处理更多的事件,如路径故障、恢复、状态更新等 9。每个事件都可能涉及日志记录、内部状态更新以及与内核模块的通信,这些都会消耗一定的 CPU 和内存资源。如果发生“事件风暴”(例如,由于 HBA 或交换机端口不稳定导致路径频繁地上下线),multipathd 的工作负载会急剧增加,可能导致其临时内存消耗升高,或者在极端情况下暴露潜在的软件缺陷。例如,不稳定的网络环境可能导致 iSCSI 路径频繁断开和重连,从而给 multipathd 带来持续的处理压力。

综合来看,multipathd 的高内存占用往往不是由单一原因造成的,而可能是多个因素的叠加效应:每条路径固有的 pthreads 开销、稍显频繁的轮询配置、大型绑定文件的内存缓存、udev 在设备发现高峰期的交互压力,以及事件处理中的一些低效环节。这些因素中的任何一个单独存在时可能并不严重,但在一个繁忙的、拥有大量路径的系统上,它们的共同作用就可能导致可观的内存占用。

IV. 诊断 multipathd 内存占用的工具与技术

诊断 multipathd 的高内存占用需要结合使用标准的 Linux 系统监控工具和 multipathd 自身的诊断功能。

A. 利用标准 Linux 工具 (top, htop, vmstat, /proc/meminfo, pmap, /proc/[pid]/smaps)

这些通用工具可以帮助了解 multipathd 进程的内存使用情况及其在整个系统内存环境中的状况。

  • top / htop: 这两个交互式工具可以实时显示系统中进程的资源使用情况。通过它们可以快速识别 multipathd 进程的 PID、CPU 使用率、以及内存占用(RES – Resident Memory Size,VIRT – Virtual Memory Size)28。在 top 中按 Shift+M 可以按内存使用排序,方便定位高内存消耗进程。
  • vmstat: 该命令报告虚拟内存统计信息,包括活动内存、空闲内存、缓冲区、缓存、交换区使用情况、I/O 等 29。通过定期运行 vmstat (例如 vmstat 1 10) 可以观察系统整体内存压力的变化趋势。
  • /proc/meminfo: 这个虚拟文件提供了内核内存管理的详细信息,包括 MemTotal, MemFree, MemAvailable, Buffers, Cached, Slab (内核数据结构缓存) 等 29。分析此文件可以判断系统是否真的内存不足,或者内存主要被用作缓存。
  • pmap -x <pid>pmap <pid>: pmap 命令报告一个进程的内存映射。使用 multipathd 的 PID (Process ID) 作为参数 (例如 pmap -x $(pidof multipathd)),可以列出该进程所有映射的内存段,包括它们的起始地址、大小 (Kbytes)、驻留集大小 (RSS)、权限、以及关联的文件(如可执行文件、共享库)或标记(如 [anon] 表示匿名映射,[stack] 表示栈)32。大的匿名映射段可能指示内存泄漏或大型动态数据结构。
  • cat /proc/<pid>/smapscat /proc/<pid>/smaps_rollup: /proc/<pid>/smaps 文件为每个内存映射区域提供了比 pmap 更详细的信息,包括 Pss (Proportional Set Size,按共享比例计算的内存大小,更能反映进程实际独占内存)、Shared_Clean/Shared_Dirty (共享且干净/脏的页)、Private_Clean/Private_Dirty (私有且干净/脏的页) 等 34/proc/<pid>/smaps_rollup (较新内核提供) 提供了整个进程的这些值的总和。Pss 对于理解共享库的实际内存成本尤其有用。

B. multipathd 特定诊断方法 (multipathd -k 交互命令, 详细日志)

multipath-tools 包自身提供了一些用于诊断和调试的工具和选项。

  • multipathd -k (交互模式): 这个命令允许用户连接到正在运行的 multipathd 守护进程,并执行一系列交互式命令来查询状态和配置 3。常用命令包括:
    • show pathslist paths [format $format]: 显示 multipathd 正在监控的所有路径及其状态 (如 devnode, major:minor, dm_status, path_status, online_status) 3
    • show mapslist maps [format $format]: 显示 multipathd 监控的所有多路径设备 (map) 及其状态 3
    • show status: 显示路径检查器的数量、各种状态下的路径数量、监控的路径总数,以及 multipathd 当前是否正在处理 uevent 3
    • show config: 显示当前加载的 multipath 配置,这对于验证 /etc/multipath.conf 中的更改是否已生效非常有用 6
    • show daemon: 显示 multipathd 守护进程的当前内部状态 3
    • show blacklist: 显示当前生效的黑名单规则 3
    • show devices: 列出所有可用的块设备及其是否被列入黑名单的信息 3
    • show wildcards: 显示可用于 list paths/maps format 命令的格式化通配符 36
  • 详细日志 (-v 级别或 multipath.conf 中的 verbosity): 增加 multipathd 的日志详细级别可以在系统日志(通常是 /var/log/messages 或通过 journalctl 查看)中记录更多关于其内部操作和决策过程的信息。可以在启动 multipathd 时使用 -v <level> 选项(例如 -v 33,或者在 /etc/multipath.confdefaults 部分设置 verbosity 参数 6。级别越高,信息越详细,有助于追踪其行为和潜在的资源使用模式。
  • multipath -ll / multipath -l: 这两个命令用于显示当前多路径拓扑的详细信息。-l 显示从 sysfs 和 Device Mapper 获取的多路径拓扑信息,而 -ll 则显示更全面的信息,包括系统中所有其他可用组件 5。输出内容包括每个多路径设备的 WWID、别名、dm 设备名、厂商/产品信息、大小、特性、硬件处理器、路径组策略、路径优先级、路径状态等。

C. 综合诊断策略

有效的诊断通常需要结合上述工具。例如,可以通过 multipathd -k 'show status' 或解析 multipathd -k 'show paths' 的输出来获取当前监控的路径数量。然后,使用 pmap 或分析 /proc/$(pidof multipathd)/smaps 来查看 multipathd 的总内存占用。将总 RSS 除以路径数量,可以得到一个平均每路径内存消耗值。如果这个值显著高于预期的范围(例如,远超之前提到的 160KB 17),或者 pmap 显示存在非常大的匿名内存段,这可能指向内存泄漏或特定配置导致的大量内存占用。

下表总结了用于 multipathd 内存分析的关键诊断工具:

表 3: multipathd 内存分析诊断工具

工具multipathd 分析目的提供的关键信息示例用法 (假设 multipathd PID 已知或通过 pidof multipathd 获取)
top / htop监控 multipathd 进程的总体资源使用情况。%CPU, VIRT (虚拟内存), RES (驻留内存)。top -p $(pidof multipathd)
vmstat评估系统整体内存压力。空闲内存, swap 使用, I/O 等待。vmstat 1 5
cat /proc/meminfo获取系统内存详细分类使用情况。MemTotal, MemFree, MemAvailable, Slab 等。cat /proc/meminfo
pmap -x $(pidof multipathd)查看 multipathd 进程的详细内存映射。各内存段的地址、大小 (Kbytes)、RSS、权限、映射文件或类型 ([anon], [stack])。sudo pmap -x $(pidof multipathd)
cat /proc/$(pidof multipathd)/smaps获取每个内存映射区域更详细的统计,如 PSS。Size, Rss, Pss, Shared_Clean/Dirty, Private_Clean/Dirty 等。cat /proc/$(pidof multipathd)/smaps
cat /proc/$(pidof multipathd)/smaps_rollup获取 multipathd 进程聚合的 smaps 统计信息。整个进程的 Rss, Pss, Shared_Clean/Dirty 总和等。cat /proc/$(pidof multipathd)/smaps_rollup
multipathd -k 'show status'获取 multipathd 监控的路径数量等概览信息。路径检查器数量, 监控路径总数, uevent 处理状态。`echo ‘show status’ \
multipathd -k 'show paths'列出所有被监控路径的详细状态。路径设备名, major:minor, dm 状态, 路径状态, online 状态。`echo ‘show paths’ \
multipathd -k 'show config'查看 multipathd 当前加载的有效配置。所有生效的配置参数及其值。`echo ‘show config’ \
multipath -ll显示详细的当前多路径拓扑和所有路径信息。WWID, 别名, 路径组, 路径状态, 设备特性。sudo multipath -ll
Journal (journalctl) / System Logs配合提高的 verbosity 级别,审查 multipathd 的详细活动日志。错误信息, 路径状态变化事件, 内部操作步骤。journalctl -u multipathd.service -f (需配置高 verbosity)

通过综合运用这些工具,可以从不同层面分析 multipathd 的内存使用行为,从而更准确地定位高内存消耗的根本原因。

V. 优化 multipathd 内存使用和性能的策略

优化 multipathd 的内存使用和性能通常涉及对其配置文件 /etc/multipath.conf 的细致调整、保持软件更新、以及在某些情况下的系统级调整。

A. multipath.conf 调优以提升内存效率的最佳实践

/etc/multipath.conf 文件是控制 multipathd 行为的主要手段。合理的配置可以显著减少不必要的资源消耗 12

  • 黑名单 (Blacklisting):应积极地将本地磁盘(如系统盘)和任何不打算用于多路径的设备(例如 ram, loop, fd, sr 设备,或具有特定 WWID 的非 SAN 磁盘)加入黑名单 2。这可以通过 devnode 或 wwid 正则表达式来实现。例如,devnode “^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*” 可以排除许多非多路径候选设备。精确的黑名单减少了 multipathd 需要考虑和监控的设备数量,从而降低了开销。
  • find_multipaths:此参数控制 multipathd 如何发现和创建多路径设备。
    • greedy(或早期版本中的 yes/on):尝试为每个未被列入黑名单的路径创建多路径设备。在有大量非多路径 SAN 设备的环境中,这可能导致发现阶段开销较大 6
    • strictoff:仅当设备 WWID 已知(例如,在 wwids 文件中)或手动强制时才创建。这是发现阶段内存开销最小的模式。
    • smart:在创建映射前等待 find_multipaths_timeout(可调,默认为 -10 秒,表示对已知设备等待10秒,未知设备等待1秒 6)以收集更多路径。 如果初始发现开销是个问题,应考虑使用 strictsmart 模式代替 greedy 6
  • polling_interval:路径检查的轮询间隔。默认值通常为 5 秒 6。除非确实需要极快的故障检测,否则应避免设置过短的间隔,以减少路径检查器带来的 CPU 和潜在的少量内存开销,特别是当路径检查器本身比较耗费资源时 25。
  • max_fds:multipathd 进程可以打开的最大文件描述符数。如果管理大量路径,确保此值设置为 max 或一个足够大的数值(例如,路径数 + 32,如果大于默认的 1024)6。通常,max 是一个安全的选择。
  • user_friendly_names:设置为 yes 时,multipathd 会使用绑定文件将 WWID 映射到 mpathN 形式的别名,并可能缓存此文件 3。如果别名不是必需的,且绑定文件非常大导致内存占用可观,可以考虑设置为 no。然而,别名带来的便利性通常超过其微小的内存成本。
  • 路径检查器 (path_checker):选择满足可靠性需求且资源消耗最小的检查器。例如,如果存储支持且工作良好,tur 通常比 directio 开销更小 6。
  • verbosity:在正常操作中,将日志详细级别保持在一个合理的水平(例如,默认的 2),以减少日志记录操作的开销,这间接使用 CPU 和磁盘 I/O,并可能影响内存中的日志缓冲区 3。
  • max_sectors_kb:此参数限制最大 I/O 大小 2。虽然主要影响 I/O 性能,但为存储阵列设置一个合适的值(例如,Pure Storage 建议不超过 4096KB 38)可以避免因 I/O 大小不匹配导致的问题,这些问题可能间接增加 multipathd 的错误处理工作量。

下表总结了 /etc/multipath.conf 中影响内存和性能的关键参数:

表 1: 影响内存和性能的关键 multipath.conf 参数

参数名称所属节参考默认值 (可能因发行版而异)描述对内存/性能的潜在影响优化建议考量
polling_intervaldefaults, devices5s路径检查之间的间隔(秒)。过低的值会增加CPU/IO(如果检查器较重),可能轻微增加检查状态的内存。如果5秒过于频繁,可适当增加。
max_polling_intervaldefaults4×polling_interval路径检查的最大间隔(秒)。影响健康路径的检查频率上限。通常保持与 polling_interval 的倍数关系。
find_multipathsdefaultsgreedy (SUSE), smart (RHEL 8+), yes (older RHEL)控制如何积极地发现和创建新的多路径设备。greedy 在设备众多时可能在发现阶段消耗更多内存/CPU。smart 模式有 find_multipaths_timeout如果发现开销大,考虑 smartstrict
user_friendly_namesdefaultsno (上游), yes (某些发行版)是否启用 mpathN 形式的别名。yes 时会加载并可能缓存绑定文件;大文件意味着更多内存。如果别名非必需且内存紧张,可禁用。
max_fdsdefaultsmax 或 1024multipathd 进程可打开的最大文件描述符数。过低可能导致操作失败。通常 max 或根据路径数量(路径数+32)设置是安全的。
path_checkerdefaults, devicestur用于确定路径状态的方法。不同的检查器资源消耗不同,directio 通常比 tur 开销大。选择满足需求且开销最小的检查器。
verbositydefaults2日志详细级别 (0-6)。过高的级别会增加日志量,间接消耗资源。生产环境保持较低级别 (如2),调试时按需提高。
bindings_filedefaults/etc/multipath/bindings (新) 或 /var/lib/multipath/bindings (旧)指定绑定文件的路径。文件位置影响 initrd 和早期启动。缓存此文件会占用内存。确保在 initrd 中可用,或在不需要 user_friendly_names 时避免使用。
no_path_retrydefaults, devices, multipathsfail当所有路径都失败时的行为(重试次数、failqueue)。queue 模式下,如果守护进程停止,queue_without_daemon 控制是否继续排队。排队会持有I/O。根据业务容忍度和恢复策略选择。
retain_attached_hw_handlerdefaultsyes (4.3+内核实际行为)(对 >= 4.3 内核已过时) 是否保留内核已附加的硬件处理器。对新内核无影响。无。
config_dirdefaults/etc/multipath/conf.d(已弃用,硬编码) 额外的配置文件目录。无,已硬编码。无。

B. 主动措施:升级 multipath-tools、内核考量

  • multipath-tools 更新:定期将 multipath-tools 软件包更新到您的发行版所支持的最新稳定版本。新版本通常包含重要的错误修复(包括内存泄漏修复,如之前提到的 NVMe foreign library 泄漏 20 或 0.9.3 版本中的通用泄漏修复 21)、性能改进以及对新硬件和内核特性的更好支持 20。
  • 内核版本:内核中的 dm-multipath 模块与用户空间的 multipathd 同样关键。较新的内核版本可能提供改进的性能、更优化的 ALUA (Asymmetric Logical Unit Access) 处理能力,或更高效的事件通知机制(例如,内核 4.14 及更高版本中引入的新的设备映射器事件轮询接口 3)。然而,内核更新也可能引入新的回归问题或交互行为,因此在生产环境中部署前进行充分测试至关重要。某些内存泄漏问题可能源于内核层面,而非 multipath-tools 本身 23。

multipathd(用户空间)和 dm-multipath(内核模块)是紧密耦合的。最佳性能和稳定性通常依赖于一个兼容且经过良好测试的组合。在一个非常旧的内核上运行一个非常新的 multipath-tools 版本,或者反之,都可能暴露缺陷或无法利用最新的功能。遵循操作系统供应商(如 Red Hat, SUSE)提供的经过验证的软件包组合通常是更安全的选择 22

C. 高级配置:管理路径状态与事件处理

虽然这些配置不直接减少静态内存占用,但通过优化 multipathd 处理不稳定或“抖动” (shaky/marginal) 路径的方式,可以减少不必要的路径状态变化和事件处理,从而降低动态资源消耗和CPU负载,间接有利于整体系统的内存表现。

  • 诸如 delay_watch_checksdelay_wait_checks(在较新版本中这些参数可能被映射到 san_path_err_* 系列参数,如 san_path_err_threshold, san_path_err_forget_rate, san_path_err_recovery_time 6)和 marginal_pathgroups 等参数,可以被配置用来调整 multipathd 对瞬时路径问题的敏感度。
  • 适当设置 SCSI 层的 dev_loss_tmofast_io_fail_tmo(这些值可以通过 multipath.conf 中的同名参数影响 6)也会影响系统对更持久路径丢失的反应速度,进而影响 multipathd 的后续操作。

在存在偶发性瞬时网络问题的环境中,过于敏感的路径检查和恢复机制可能导致 multipathd 持续处理大量事件(即“噪声”)。通过调整边缘路径的阈值或稍微延迟故障恢复,可以在保证数据安全的前提下减少守护进程的工作量,这可能对其资源占用产生轻微的积极影响,并显著改善系统稳定性和减少日志冗余。

D. 系统级调整:相关内核参数

虽然 /etc/multipath.conf 是主要的调优手段,但某些内核参数也可能间接影响 multipathd 的运行环境和整体内存使用。

  • vm.overcommit_memory / vm.overcommit_ratio: 这些是 Linux 通用的内存管理参数 28。虽然不直接针对 multipathd,但确保系统具有合理的内存过量使用策略,可以防止在系统内存紧张时 OOM (Out Of Memory) Killer 错误地终止 multipathd 或相关进程。
  • 巨页 (Huge Pages): 不正确的巨页配置可能导致常规内存饥饿,影响所有进程的运行 40。应确保系统没有此类配置错误。
  • 内核模块黑名单或 udev 规则: 可以通过内核的 module_blacklist 功能或自定义 udev 规则来阻止加载有问题的驱动程序,或阻止 udev 处理特定的设备,从而间接影响 multipathd “看到”的设备范围。
  • 其他: 文档 41 列出了许多内核参数,但大多数都非常特定于子系统(如网络、连接跟踪、密钥管理),不太可能直接用于调整 multipathd 本身的内存分配,主要还是通过确保整体系统健康来间接获益。文档 42 讨论了如何向内核模块传递参数。

直接用于调整 multipathd 特定内存分配策略的内核参数非常罕见。内核的影响更多是间接的:确保内核的整体内存管理、I/O 调度和设备事件处理机制健康运行,为 multipathd 提供一个稳定的操作环境。其他地方的问题(例如,驱动程序缺陷、影响 iSCSI 的网络风暴)可能会给 multipathd 带来压力,从而可能表现为更高的内存使用或不稳定,但这通常是次级效应。

E. 持续改进:监控与告警 multipathd 资源消耗

实施对 multipathd 内存(RSS, VIRT, PSS)和 CPU 使用情况的持续监控至关重要。可以使用如 Prometheus/Grafana、Nagios、Zabbix 等监控系统。

  • 设定基线:根据特定环境(路径数量、配置等)为 multipathd 的资源消耗建立一个正常的基线。
  • 设置告警:当内存使用量超过既定基线或出现持续增长趋势时触发告警,这可能预示着新的内存泄漏或配置问题 28

“高”内存使用是相对的。一个拥有 16 条路径的系统上 multipathd 的“高”内存占用,对于一个拥有 1024 条路径的系统来说可能完全正常 17。因此,基线需要针对每个环境甚至每台主机进行定制,并考虑其特定角色和配置。在发生重大的存储变更或软件升级后,可能还需要重新评估这些基线。监控应侧重于趋势变化和相对于自身基线的偏离,而不是固定的绝对阈值。

VI. 结论与战略建议

A. 关于功能、实现及内存使用的关键发现总结

/sbin/multipathd 作为 Linux Device Mapper Multipath 架构的核心用户空间组件,对于保障 SAN 环境下存储访问的连续性和性能至关重要。它通过与内核 dm-multipath 模块的紧密协作,实现了路径的自动发现、监控、故障切换和负载均衡。其实现原理依赖于路径检查器对路径状态的周期性探测、udev 事件驱动的设备管理,以及 /etc/multipath.conf 文件提供的灵活配置能力。

然而,multipathd 的高内存占用问题可能由多种因素导致:

  1. 固有的每路径开销pthreads 库的使用以及为每条路径维护状态信息都会带来基础内存消耗,路径数量越多,累积内存越大。
  2. 配置选项:如过于频繁的 polling_interval、资源密集型的 path_checkerfind_multipathsgreedy 模式、以及大型 user_friendly_names 绑定文件的内存缓存,都可能增加内存占用。
  3. 软件版本与已知泄漏:特定版本的 multipath-tools 或内核可能存在内存泄漏,尤其是在与 NVMe 原生多路径等新技术交互时。
  4. 系统交互压力:在高设备负载(如大量 LUN 同时上线)下,与 udev 的密集交互可能导致系统整体及 multipathd 的内存使用激增。高 I/O 流量或网络不稳定引发的“事件风暴”也会增加 multipathd 的工作负荷。

B. 维护稳定高效多路径环境的可行建议

为确保 multipathd 在提供关键功能的同时保持高效和稳定,建议采取以下战略措施:

  1. 软件版本管理
    • 优先考虑将 multipath-tools 软件包和 Linux 内核更新至操作系统供应商推荐和支持的最新稳定版本。这有助于获取最新的错误修复(包括已知的内存泄漏修复)和性能改进。
    • 在升级前,务必在测试环境中验证新版本与现有存储硬件和配置的兼容性。
  2. 精细化配置 /etc/multipath.conf
    • 严格黑名单策略:明确将所有非多路径设备(如本地磁盘、虚拟设备)加入黑名单,以减少 multipathd 的扫描和监控范围。
    • 审慎选择 find_multipaths 模式:对于大型或复杂的 SAN 环境,优先使用 smartstrict 模式,避免 greedy 模式可能带来的发现阶段开销。
    • 合理的轮询与超时设置:根据存储厂商的建议和实际业务需求,设置适当的 polling_intervalmax_polling_intervalchecker_timeout,在故障检测速度和系统开销之间取得平衡。
    • 选择合适的路径检查器:选用对存储设备兼容性好且资源消耗低的路径检查器(通常 tur 是一个不错的起点)。
    • 管理 user_friendly_names:如果启用了 user_friendly_names,需关注绑定文件的大小。若非绝对必要且内存极其敏感,可考虑禁用。
    • 控制日志级别 (verbosity):生产环境中保持默认或较低的日志级别,仅在调试时提高。
  3. 系统级监控与基线设定
    • 实施对 multipathd 进程(以及相关的 udevd 进程)的CPU和内存(RSS, PSS)使用情况的持续监控。
    • 为每个关键系统或集群建立个性化的资源消耗基线,考虑到其路径数量和配置的独特性。
    • 设置告警机制,以便在资源使用显著偏离基线或出现持续增长趋势时及时介入调查。
  4. 管理存储变更流程
    • 在向系统添加大量新的 LUN 或路径时,如果可行,应分批次进行,以避免瞬间产生大量 udev 事件,从而减轻对 udevdmultipathd 的冲击。
  5. 故障排除与诊断能力建设
    • 熟悉并掌握使用 pmap/proc/[pid]/smapsmultipathd -k 交互命令以及详细日志等工具进行问题诊断的方法。
    • 在遇到不明原因的高内存占用时,系统地运用这些工具,结合对配置和近期变更的回顾,以定位根本原因。

通过上述策略的综合运用,可以有效地管理和优化 /sbin/multipathd 的资源消耗,确保其在提供关键多路径功能的同时,不会成为系统性能瓶颈或不稳定的因素。