0

0

Linux怎么限制服务的资源占用

P粉602998670

P粉602998670

发布时间:2025-09-17 10:29:01

|

238人浏览过

|

来源于php中文网

原创

答案:通过Systemd服务单元文件配置Cgroups资源限制是管理Linux服务资源占用的核心方法。具体可设置CPUQuota和MemoryLimit等参数实现对CPU和内存的硬性限制,结合BlockIOWeight和IOWriteBandwidthMax等控制I/O,同时启用Accounting以监控使用情况,并遵循监控先行、逐步调优的最佳实践,避免过度限制导致服务异常。

linux怎么限制服务的资源占用

Linux服务限制资源占用,核心机制在于Linux内核的Control Groups(Cgroups)功能。通过Cgroups,我们可以精细地为进程组分配和限制CPU、内存、I/O等系统资源。而Systemd作为现代Linux系统中的初始化系统和服务管理器,则提供了更高级、更便捷的接口来配置和管理这些Cgroups限制,极大地简化了操作。

解决方案

要限制Linux服务的资源占用,主要有两大途径:直接操作Cgroups文件系统,或通过Systemd服务单元文件进行配置。在我看来,后者是更推荐的方案,因为它与服务生命周期管理紧密结合,更具可维护性。

1. 通过Systemd配置资源限制

Systemd集成了Cgroups的功能,允许你在服务的

.service
单元文件中直接定义资源限制。这是最常见且推荐的做法。

  • CPU限制:

    • CPUShares=
      : 设置CPU份额。这是一个相对值,默认是1024。如果一个服务有2048,另一个有1024,那么第一个服务理论上可以获得两倍的CPU时间,当系统CPU资源紧张时尤其明显。
    • CPUQuota=
      : 设置CPU硬性配额。例如,
      CPUQuota=50%
      意味着该服务最多只能使用一个CPU核心的50%时间。
      CPUQuota=200%
      则意味着最多可以使用两个CPU核心。这比
      CPUShares
      更直接,尤其适合需要严格控制CPU上限的场景。
    • CPUAccounting=true
      : 启用CPU资源统计,这样你才能看到服务实际的CPU使用情况。
  • 内存限制:

    • MemoryLimit=
      : 设置内存的硬性上限。例如,
      MemoryLimit=512M
      。当服务尝试分配超过此限制的内存时,可能会触发OOM Killer(Out-Of-Memory Killer)终止该服务。
    • MemorySwapMax=
      : 限制交换空间的使用。
    • MemoryAccounting=true
      : 启用内存资源统计。
  • I/O限制:

    • BlockIOWeight=
      : 设置块设备I/O的权重,类似于
      CPUShares
      ,默认是1000。
    • IOReadBandwidthMax=
      : 限制从块设备读取的最大带宽,例如
      IOReadBandwidthMax=/dev/sda 10M
    • IOWriteBandwidthMax=
      : 限制写入块设备的最大带宽。
    • IOAccounting=true
      : 启用I/O资源统计。

操作步骤:

  1. 找到或创建一个服务的

    .service
    文件,通常位于
    /etc/systemd/system/
    /usr/lib/systemd/system/

  2. [Service]
    部分添加相应的资源限制参数。 例如,要限制一个名为
    my-app.service
    的服务最多使用一个核心的50% CPU和512MB内存:

    [Unit]
    Description=My Application Service
    
    [Service]
    ExecStart=/usr/bin/my-app-server
    CPUQuota=50%
    MemoryLimit=512M
    CPUAccounting=true
    MemoryAccounting=true
    BlockIOWeight=700 # 假设需要降低I/O优先级
    
    [Install]
    WantedBy=multi-user.target
  3. 保存文件后,运行

    sudo systemctl daemon-reload
    重新加载Systemd配置。

  4. 然后重启服务:

    sudo systemctl restart my-app.service

  5. 你可以使用

    systemctl status my-app.service
    systemd-cgtop
    来查看资源使用情况。

2. 直接操作Cgroups文件系统(不常用,但理解原理很重要)

这种方式更底层,通常用于Systemd无法满足的复杂场景,或者在没有Systemd的环境中。Cgroups文件系统通常挂载在

/sys/fs/cgroup/
下,每个子系统(如
cpu
memory
blkio
)都有自己的目录。

  • 创建Cgroup:

    sudo mkdir /sys/fs/cgroup/cpu/my_service_group
    sudo mkdir /sys/fs/cgroup/memory/my_service_group
    ...

  • 设置限制:

    sudo echo 50000 > /sys/fs/cgroup/cpu/my_service_group/cpu.cfs_quota_us
    (50% of one core)
    sudo echo 100000 > /sys/fs/cgroup/cpu/my_service_group/cpu.cfs_period_us
    sudo echo 536870912 > /sys/fs/cgroup/memory/my_service_group/memory.limit_in_bytes
    (512MB)

  • 将进程ID(PID)加入Cgroup:

    sudo echo  > /sys/fs/cgroup/cpu/my_service_group/tasks
    sudo echo  > /sys/fs/cgroup/memory/my_service_group/tasks

这种方式虽然灵活,但手动管理复杂且容易出错,所以Systemd的抽象层更受欢迎。

Linux怎么限制服务的资源占用

如何利用Cgroups精确控制Linux服务的CPU和内存使用?

要精确控制Linux服务的CPU和内存,Cgroups提供了非常细致的参数。我们得先明白,CPU的限制有两种主要模式:份额(shares)和配额(quota)。内存则主要是硬性限制。

行盟APP1.0 php版
行盟APP1.0 php版

行盟APP是结合了通信和互联网的优势,加之云计算所拥有的强大信息资源,借助广大的终端传递服务,潜在的拥有巨大商机。她到底是什么,又有什么作用?她是一款手机应用软件;她是一款专门为企业服务的手机应用软件;她是一款能够将企业各种信息放入其中并进行推广传播的手机应用软件!只要轻轻一点,企业的简介,产品信息以及其他优势就能最快最大限度的透过手机展现在客户的眼前,一部手机,一个APP,你面对的将是一个6亿&

下载

对于CPU,

cpu.shares
是一个相对权重。如果你有两个服务A和B,服务A的
cpu.shares
是2048,服务B是1024,那么当CPU资源紧张时,A会获得大约两倍于B的CPU时间。但如果CPU资源充足,它们都可以无限制地使用。这在多租户环境中很有用,可以保证重要服务在资源争抢时获得更多份额。

更直接的控制是

cpu.cfs_quota_us
cpu.cfs_period_us
cfs_period_us
定义了一个周期(通常是100ms即100000微秒),
cfs_quota_us
则定义了在这个周期内,该cgroup下的进程可以使用的CPU时间。比如,如果
period
是100000,
quota
是50000,那么这个cgroup在一个100ms的周期内最多只能使用50ms的CPU时间,这相当于限制它只能使用一个核心的50%。如果需要使用两个核心的全部时间,你可以设置
quota
为200000。这种方式提供了硬性的上限,确保服务不会“跑飞”。在我看来,对于那些CPU敏感且需要严格控制的服务,
CPUQuota
是更稳妥的选择。

至于内存,

memory.limit_in_bytes
是其核心。它设定了一个绝对的内存上限。一旦cgroup中的进程试图分配超过这个限制的内存,系统就会触发OOM Killer,通常会终止占用内存最多的进程。这可能会导致服务崩溃,所以设置时务必谨慎。除了硬限制,
memory.swappiness
(虽然不在cgroup本身,但影响内存管理)也值得关注,它决定了系统将内存页交换到磁盘的积极程度。一个较低的
swappiness
值(如0或10)会使系统更倾向于使用物理内存,减少交换。不过,如果内存限制很严格,即使
swappiness
很低,也可能导致频繁的OOM。一个常见的实践是,在设置
MemoryLimit
时,同时启用
MemoryAccounting=true
,这样才能通过
cat /sys/fs/cgroup/memory//memory.usage_in_bytes
等文件来监控实际的内存使用情况。

举个例子,假设我们有一个Web服务,它偶尔会有流量高峰,但我们不希望它占用超过一个核心的CPU资源,并且内存不能超过2GB。在Systemd中,我们会这样配置:

[Service]
ExecStart=/usr/bin/my-web-server
CPUQuota=100% # 限制最多使用一个核心
MemoryLimit=2G
CPUAccounting=true
MemoryAccounting=true

这样,即使Web服务在高峰期,它的CPU使用率也不会超过一个核心,同时内存也被限制在2GB以内。这种硬性限制对于维持系统稳定性至关重要,尤其是在资源有限的服务器上部署多个服务时。

Linux怎么限制服务的资源占用

Systemd如何与Cgroups协同,简化服务I/O和网络带宽的限制?

Systemd在处理I/O限制方面,同样提供了非常友好的抽象。虽然Cgroups本身对网络带宽的直接限制能力相对有限(通常需要结合

tc
工具),但对于块设备的I/O(磁盘读写),Systemd与Cgroups的协同工作非常出色。

Systemd通过

BlockIOWeight=
,
IOReadBandwidthMax=
,
IOWriteBandwidthMax=
这些参数来管理服务的磁盘I/O。

  • BlockIOWeight=
    : 这个参数设置的是一个相对权重,类似于CPU的
    CPUShares
    。它影响的是当多个服务争抢磁盘I/O时,各自能获得的I/O带宽比例。默认值是1000。如果你的数据库服务对I/O性能要求极高,而日志收集服务可以容忍较低的I/O,你可以将数据库服务的
    BlockIOWeight
    设为2000,而日志服务的设为500。这样,在磁盘繁忙时,数据库服务就能获得更多的I/O资源。这对于避免“I/O饥饿”问题非常有效。

  • IOReadBandwidthMax=
    IOWriteBandwidthMax=
    : 这两个参数提供的是硬性的I/O带宽限制。你可以指定具体的设备和最大带宽,例如
    IOReadBandwidthMax=/dev/sda 10M
    意味着从
    /dev/sda
    设备读取数据的最大速度是10MB/s。这对于防止某个服务因为大量读写操作而耗尽磁盘I/O带宽,影响其他关键服务至关重要。我个人觉得,对于那些已知会产生大量I/O的服务,设定一个明确的硬性带宽上限是很有必要的,尤其是在共享存储或SSD寿命管理方面。

关于网络带宽: 这是一个比较棘手的问题。Cgroups本身并没有直接提供像CPU或内存那样简单直接的网络带宽限制机制。通常,网络流量整形(traffic shaping)是通过Linux内核的

tc
(traffic control)工具来实现的。
tc
可以基于IP地址、端口、协议等多种规则来限制带宽。虽然Cgroups可以将进程分组,但这主要是为了方便
tc
规则的匹配,而不是Cgroups本身在限制带宽。也就是说,你可以在一个cgroup中运行你的服务,然后通过
tc
规则去匹配这个cgroup中的进程产生的网络流量,进而限制其带宽。这通常需要更复杂的配置,涉及到
iptables
tc
命令的组合。所以,如果你需要精细到网络带宽的限制,可能需要跳出Systemd和Cgroups的直接管理范畴,深入到网络层配置。

在Systemd单元文件中配置I/O限制的例子:

[Service]
ExecStart=/usr/bin/my-data-processor
BlockIOWeight=500 # 降低其I/O优先级
IOReadBandwidthMax=/dev/nvme0n1 20M # 限制从NVMe设备读取20MB/s
IOWriteBandwidthMax=/dev/nvme0n1 10M # 限制写入NVMe设备10MB/s
IOAccounting=true

通过这样的配置,我们可以确保数据处理服务不会因为其大量的磁盘I/O操作而拖垮整个系统,特别是在使用高性能存储设备时,避免某个进程“独占”带宽。

Linux怎么限制服务的资源占用

在实施Linux服务资源限制时,有哪些常见的陷阱和最佳实践?

实施Linux服务资源限制,虽然能有效提升系统稳定性,但过程中也容易踩坑。在我看来,理解这些陷阱并遵循最佳实践,是确保限制有效且不产生负面影响的关键。

常见的陷阱:

  1. 限制过低导致服务崩溃或性能下降: 这是最常见的错误。如果你对服务的资源需求预估不足,设置的CPU、内存或I/O限制过低,服务在高负载时就可能因为资源不足而变慢、报错,甚至被OOM Killer终止。我见过不少案例,因为内存限制太紧,服务在启动时就因为初始化需要更多内存而直接崩溃。
  2. 忽略依赖服务的影响: 一个服务可能依赖于其他服务(如数据库、缓存)。如果你只限制了主服务,而其依赖的服务没有得到相应的限制或优化,那么瓶颈可能会转移,导致整体性能不佳。
  3. I/O限制可能影响整个磁盘性能: 特别是当多个服务共享同一个物理磁盘时,对某个服务的I/O限制可能会在某种程度上影响到其他服务的I/O性能,尤其是在使用
    BlockIOWeight
    时,需要权衡。硬性带宽限制(
    IOReadBandwidthMax
    等)虽然直接,但如果设备路径不准确或限制过严,也可能导致意想不到的问题。
  4. OOM Killer的触发时机和后果: 当内存限制被突破时,OOM Killer会选择一个进程(不一定是你的服务进程)来终止,以释放内存。这可能导致关键服务被误杀,而不是你期望的那个“超限”服务。理解OOM Killer的启发式算法很重要。
  5. 监控不足,无法评估效果: 缺乏有效的监控,你根本不知道你的资源限制是否合理,服务是否真的在限制下稳定运行,或者是否存在潜在的资源瓶颈。盲目设置限制就像盲人摸象。
  6. 过度依赖默认值: Systemd和Cgroups有很多默认行为。不理解这些默认值,可能会导致限制不如预期,或者产生副作用。

最佳实践:

  1. 充分了解服务资源需求: 在设置任何限制之前,先通过一段时间的监控(
    top
    ,
    htop
    ,
    vmstat
    ,
    iostat
    ,
    promtool
    配合node_exporter等)来了解服务在正常负载和峰值负载下的CPU、内存、I/O使用情况。这是最基础也是最重要的一步。
  2. 从小范围开始,逐步调整: 不要一次性设置过于严格的限制。可以先设置一个相对宽松的限制,然后根据监控数据和实际运行情况,逐步收紧。这就像给一个水龙头拧螺丝,慢慢来才能找到最佳平衡点。
  3. 进行压力测试和回归测试: 在生产环境部署前,务必在测试环境中对设置了资源限制的服务进行压力测试,模拟峰值负载,观察其行为。同时,也要确保限制不会引入新的bug或性能问题。
  4. 结合监控工具: 部署专业的监控系统,实时收集Cgroups的各项指标(如
    /sys/fs/cgroup/.../cpu.usage_usec
    ,
    memory.usage_in_bytes
    等)。这能让你清晰地看到服务是否接近或触及限制,并及时做出调整。
    systemd-cgtop
    cgget
    也是很好的即时查看工具。
  5. 区分硬限制和软限制:
    CPUQuota
    是硬限制,
    CPUShares
    是软限制。根据服务的关键程度和对资源独占的需求,合理选择。关键服务可能需要硬限制,而后台批处理任务则更适合软限制,以充分利用空闲资源。
  6. 考虑容器化技术: 如果你的服务部署环境允许,Docker和Kubernetes等容器化平台已经将Cgroups的资源管理进行了高度封装和自动化。通过这些平台,你可以更声明式地定义服务的资源需求和限制,大大简化了管理复杂度。在我看来,这是现代微服务架构下管理资源最优雅的方式。
  7. 记录和文档化: 记录你为每个服务设置的资源限制及其背后的理由。这对于未来的维护、故障排查和团队协作都至关重要。

总而言之,资源限制不是一劳永逸的配置,它是一个需要持续监控、评估和调整的过程。通过细致的分析和实践,我们才能真正驾驭Cgroups和Systemd,让Linux系统更加健壮和高效。

相关专题

更多
硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1010

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

59

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

359

2025.12.29

k8s和docker区别
k8s和docker区别

k8s和docker区别有抽象层次不同、管理范围不同、功能不同、应用程序生命周期管理不同、缩放能力不同、高可用性等等区别。本专题为大家提供k8s和docker区别相关的各种文章、以及下载和课程。

249

2023.07.24

docker进入容器的方法有哪些
docker进入容器的方法有哪些

docker进入容器的方法:1. Docker exec;2. Docker attach;3. Docker run --interactive --tty;4. Docker ps -a;5. 使用 Docker Compose。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

494

2024.04.08

docker容器无法访问外部网络怎么办
docker容器无法访问外部网络怎么办

docker 容器无法访问外部网络的原因和解决方法:配置 nat 端口映射以将容器端口映射到主机端口。根据主机兼容性选择正确的网络驱动(如 host 或 overlay)。允许容器端口通过主机的防火墙。配置容器的正确 dns 服务器。选择正确的容器网络模式。排除主机网络问题,如防火墙或连接问题。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

398

2024.04.08

docker镜像有什么用
docker镜像有什么用

docker 镜像是预构建的软件组件,用途广泛,包括:应用程序部署:简化部署,提高移植性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

435

2024.04.08

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

397

2023.08.14

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

25

2026.01.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 6.9万人学习

Git 教程
Git 教程

共21课时 | 2.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号