

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 限制 AL2023 中的程序資源使用量 systemd
<a name="resource-limiting-systemd"></a>

 在 Amazon Linux 2023 (AL2023) 上，建議使用 `systemd` 來控制程序或程序群組可以使用哪些資源。使用 `systemd` 是功能強大且易於使用的替代，可用於`cgroups`手動操作或使用 等公用程式[`cpulimit`](epel.md#cpulimit)，先前僅適用於第三方[EPEL](epel.md)儲存庫中的 Amazon Linux。

 如需完整資訊，請參閱 systemd.resource-control 的上游`systemd`文件，或 AL2023 執行個體`systemd.resource-control`上的 man頁面。 [https://www.freedesktop.org/software/systemd/man/latest/systemd.resource-control.html](https://www.freedesktop.org/software/systemd/man/latest/systemd.resource-control.html)

 以下範例將使用 `stress-ng` CPU 壓力測試 （來自 `stress-ng`套件） 來模擬 CPU 繁重的應用程式，以及`memcached`模擬記憶體繁重的應用程式。

 下列範例涵蓋將 CPU 限制放置在一次性命令上，以及將記憶體限制放在服務上。`systemd` 提供的大多數資源限制條件都可以在`systemd`將執行程序的任何位置使用，並且可以同時使用多個資源限制條件。以下範例僅限於單一限制條件，以供 illustrive 使用。

## 使用 `systemd-run` 執行一次性命令的資源控制
<a name="resource-limiting-systemd-interactive"></a>

 雖然通常與系統服務相關聯，但非根使用者`systemd`也可以使用 來執行服務、排程計時器或執行一次性程序。在下列範例中，我們將使用 `stress-ng`做為範例應用程式。在第一個範例中，我們將在`ec2-user`預設帳戶中使用 `systemd-run` 執行它，而在第二個範例中，我們將對其 CPU 使用量設定限制。

**Example 在命令列`systemd-run`上使用 來執行程序，而非限制資源使用量**  

1.  確保套件已安裝，因為我們將使用此`stress-ng`套件做為範例。

   ```
   [ec2-user ~]$ sudo dnf install -y stress-ng
   ```

1.  使用 `systemd-run`執行 10 秒的 CPU 壓力測試，而不會限制其可以使用的 CPU 數量。

   ```
   [ec2-user ~]$ systemd-run --user --tty --wait --property=CPUAccounting=1 stress-ng --cpu 1 --timeout 10
   Running as unit: run-u6.service
   Press ^] three times within 1s to disconnect TTY.
   stress-ng: info:  [339368] setting to a 10 second run per stressor
   stress-ng: info:  [339368] dispatching hogs: 1 cpu
   stress-ng: info:  [339368] successful run completed in 10.00s
   Finished with result: success
   Main processes terminated with: code=exited/status=0
   Service runtime: 10.068s
   CPU time consumed: 9.060s
   ```

    `--user` 選項會指示 `systemd-run`以登入身分的使用者身分執行命令、 `--tty`選項表示TTY已連接 、 `--wait` 表示等待服務完成，而 `--property=CPUAccounting=1`選項會指示 `systemd-run`記錄執行程序所使用的 CPU 時間。`--property` 命令列選項可用來傳遞可在`systemd.unit`組態檔案中設定的`systemd-run`設定。

 當指示在 CPU 上放置負載時，`stress-ng`程式將使用所有可用的 CPU 時間，在您要求它執行的期間執行其測試。對於真實世界應用程式，可能想要限制程序的總執行時間。在下列範例中，我們會要求 `stress-ng`執行的時間比使用 對其設定的最大持續時間限制更長`systemd-run`。

**Example 在命令列`systemd-run`上使用 來執行程序，將 CPU 用量限制為 1 秒**  

1. 確保`stress-ng`已安裝 以執行此範例。

1.  `LimitCPU` 屬性相當於 `ulimit -t`，其將限制允許此程序在 CPU 上使用的時間上限。在此情況下，由於我們要求執行 10 秒壓力，而且將 CPU 用量限制為 1 秒，因此命令將收到`SIGXCPU`訊號並失敗。

   ```
   [ec2-user ~]$ systemd-run --user --tty --wait --property=CPUAccounting=1 --property=LimitCPU=1 stress-ng --cpu 1 --timeout 10
   Running as unit: run-u12.service
   Press ^] three times within 1s to disconnect TTY.
   stress-ng: info:  [340349] setting to a 10 second run per stressor
   stress-ng: info:  [340349] dispatching hogs: 1 cpu
   stress-ng: fail:  [340349] cpu instance 0 corrupted bogo-ops counter, 1370 vs 0
   stress-ng: fail:  [340349] cpu instance 0 hash error in bogo-ops counter and run flag, 3250129726 vs 0
   stress-ng: fail:  [340349] metrics-check: stressor metrics corrupted, data is compromised
   stress-ng: info:  [340349] unsuccessful run completed in 1.14s
   Finished with result: exit-code
   Main processes terminated with: code=exited/status=2
   Service runtime: 1.201s
   CPU time consumed: 1.008s
   ```

 更常見的是，您可能想要限制特定程序可以使用的 CPU 時間百分比。在下列範例中，我們將限制 可以使用的 CPU 時間百分比`stress-ng`。對於真實世界的服務，建議您限制背景程序可以使用的 CPU 時間上限百分比，以便為提供使用者請求的程序釋出資源。

**Example 使用 `systemd-run` 將程序限制在一個 CPU 上 10% 的 CPU 時間**  

1. 確保`stress-ng`已安裝 以執行此範例。

1.  我們將使用 `CPUQuota` 屬性來告知 ，`systemd-run`限制要執行之命令的 CPU 使用量。我們不會限制程序可以執行的時間量，以及程序可以使用的 CPU 數量。

   ```
   [ec2-user ~]$ systemd-run --user --tty --wait --property=CPUAccounting=1 --property=CPUQuota=10% stress-ng --cpu 1 --timeout 10
   Running as unit: run-u13.service
   Press ^] three times within 1s to disconnect TTY.
   stress-ng: info:  [340664] setting to a 10 second run per stressor
   stress-ng: info:  [340664] dispatching hogs: 1 cpu
   stress-ng: info:  [340664] successful run completed in 10.08s
   Finished with result: success
   Main processes terminated with: code=exited/status=0
   Service runtime: 10.140s
   CPU time consumed: 1.014s
   ```

    請注意，CPU會計如何告訴我們，當服務執行 10 秒時，它只會耗用 1 秒的實際 CPU 時間。

 設定 以`systemd`限制 CPU、記憶體、聯網和 IO 的資源用量的方法有很多。如需完整`systemd`文件，請參閱 [systemd.resource-control](https://www.freedesktop.org/software/systemd/man/latest/systemd.resource-control.html) 的上游文件，或 AL2023 執行個體`systemd.resource-control`上的 man頁面。

 在幕後， `systemd` 使用 Linux 核心的功能，例如 `cgroups`實作這些限制，同時避免您手動設定這些限制。[的 Linux 核心文件`cgroup-v2`](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html)包含有關`cgroups`工作的廣泛詳細資訊。

## `systemd` 服務中的資源控制
<a name="resource-limiting-systemd-service"></a>

 有幾個參數可以新增到 `systemd` 服務的 `[Service]`區段，以控制系統資源使用量。這些包括硬性限制和軟性限制。如需每個選項的確切行為，請參閱 [systemd.resource-control](https://www.freedesktop.org/software/systemd/man/latest/systemd.resource-control.html) 的上游`systemd`文件，或 AL2023 執行個體`systemd.resource-control`上的 man頁面。

 常用的限制是`MemoryHigh`指定記憶體用量的限流限制、`MemoryMax`設定硬性上限 （達到上限後，即叫用 OOM Killer) 和 `CPUQuota`（如上一節所示）。您也可以設定權重和優先順序，而不是固定數字。

**Example 使用 `systemd` 設定 服務的記憶體用量限制**  
 在此範例中，我們將為 設定硬性記憶體用量限制`memcached`，即簡單的鍵值快取，並顯示如何針對該服務叫用 OOM Killer，而不是整個系統。  

1.  首先，我們需要安裝此範例所需的套件。

   ```
   [ec2-user ~]$ sudo dnf install -y memcached libmemcached-awesome-tools
   ```

1.  啟用 ，`memcached.service`然後啟動 服務，讓 `memcached` 執行。

   ```
   [ec2-user ~]$ sudo systemctl enable memcached.service
   Created symlink /etc/systemd/system/multi-user.target.wants/memcached.service → /usr/lib/systemd/system/memcached.service.
   [ec2-user ~]$ sudo systemctl start memcached.service
   ```

1.  檢查 `memcached.service`是否正在執行。

   ```
   [ec2-user ~]$ sudo systemctl status memcached.service
   ● memcached.service - memcached daemon
        Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; preset: disabled)
        Active: active (running) since Fri 2025-01-31 22:36:42 UTC; 1s ago
      Main PID: 356294 (memcached)
         Tasks: 10 (limit: 18907)
        Memory: 1.8M
           CPU: 20ms
        CGroup: /system.slice/memcached.service
        └─356294 /usr/bin/memcached -p 11211 -u memcached -m 64 -c 1024 -l 127.0.0.1,::1
   
   Jan 31 22:35:36 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: Started memcached.service - memcached daemon.
   ```

1.  現在`memcached`已安裝並執行 ，我們可以觀察它是否可運作，方法是將一些隨機資料插入快取 

    在 `/etc/sysconfig/memcached` `CACHESIZE`變數中，預設會設為 64，這表示 64 MB。透過將比快取大小上限更多的資料插入快取，我們可以看到快取已填滿，而某些項目會使用 移出`memcached-tool`，而 `memcached.service` 使用的記憶體約為 64MB。

   ```
   [ec2-user ~]$ for i in $(seq 1 150); do dd if=/dev/random of=$i bs=512k count=1; memcp -s localhost $i; done
   [ec2-user ~]$ memcached-tool localhost display
     #  Item_Size  Max_age   Pages   Count   Full?  Evicted Evict_Time OOM
     2     120B         0s       1       0      no        0        0    0
    39   512.0K         4s      63     126     yes       24        2    0
   [ec2-user ~]$ sudo systemctl status memcached.service
   ● memcached.service - memcached daemon
        Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; preset: disabled)
        Active: active (running) since Fri 2025-01-31 22:36:42 UTC; 7min ago
      Main PID: 356294 (memcached)
         Tasks: 10 (limit: 18907)
        Memory: 66.7M
           CPU: 203ms
        CGroup: /system.slice/memcached.service
                └─356294 /usr/bin/memcached -p 11211 -u memcached -m 64 -c 1024 -l 127.0.0.1,::1
   
   Jan 31 22:36:42 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: Started memcached.service - memcached daemon.
   ```

1.  使用 `MemoryMax` 屬性為 設定硬性限制`memcached.service`，如果命中，則會叫用 OOM Killer。將服務新增至覆寫檔案，即可為服務設定其他選項。您可以直接編輯`/etc/systemd/system/memcached.service.d/override.conf`檔案或使用 的 `edit`命令以互動方式完成此操作`systemctl`。

   ```
   [ec2-user ~]$ sudo systemctl edit memcached.service
   ```

   將以下項目新增至覆寫，以設定服務的 32MB 記憶體硬性限制。

   ```
   [Service]
   MemoryMax=32M
   ```

1. `systemd` 告知 重新載入其組態

   ```
   [ec2-user ~]$ sudo systemctl daemon-reload
   ```

1. 請注意， `memcached.service` 目前正在執行，記憶體限制為 32MB。

   ```
   [ec2-user ~]$ sudo systemctl status memcached.service
   ● memcached.service - memcached daemon
        Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; preset: disabled)
       Drop-In: /etc/systemd/system/memcached.service.d
                └─override.conf
        Active: active (running) since Fri 2025-01-31 23:09:13 UTC; 49s ago
      Main PID: 358423 (memcached)
         Tasks: 10 (limit: 18907)
        Memory: 1.8M (max: 32.0M available: 30.1M)
           CPU: 25ms
        CGroup: /system.slice/memcached.service
                └─358423 /usr/bin/memcached -p 11211 -u memcached -m 64 -c 1024 -l 127.0.0.1,::1
   
   Jan 31 23:09:13 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: Started memcached.service - memcached daemon.
   ```

1.  服務會在使用少於 32MB 的記憶體時正常運作，我們可以檢查將少於 32MB 的隨機資料載入快取，然後檢查服務的狀態。

   ```
   [ec2-user ~]$ for i in $(seq 1 30); do dd if=/dev/random of=$i bs=512k count=1; memcp -s localhost $i; done
   ```

   ```
   [ec2-user ~]$ sudo systemctl status memcached.service
   ● memcached.service - memcached daemon
        Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; preset: disabled)
       Drop-In: /etc/systemd/system/memcached.service.d
                └─override.conf
        Active: active (running) since Fri 2025-01-31 23:14:48 UTC; 3s ago
      Main PID: 359492 (memcached)
         Tasks: 10 (limit: 18907)
        Memory: 18.2M (max: 32.0M available: 13.7M)
           CPU: 42ms
        CGroup: /system.slice/memcached.service
                └─359492 /usr/bin/memcached -p 11211 -u memcached -m 64 -c 1024 -l 127.0.0.1,::1
   
   Jan 31 23:14:48 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: Started memcached.service - memcached daemon.
   ```

1.  我們現在可以嘗試`memcached`使用預設`memcached`組態的完整 64MB 快取，讓 使用超過 32MB 的記憶體。 64MB 

   ```
   [ec2-user ~]$ for i in $(seq 1 150); do dd if=/dev/random of=$i bs=512k count=1; memcp -s localhost $i; done
   ```

    您會發現在上述命令的某些時間點，`memcached`伺服器發生連線錯誤。這是因為 OOM Killer 已因我們對程序施加的限制而終止程序。系統的其餘部分將正常運作，OOM Killer 不會考慮任何其他程序，因為它只是我們限制`memcached.service`的 。

   ```
   [ec2-user ~]$ sudo systemctl status memcached.service
   ● memcached.service - memcached daemon
        Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; preset: disabled)
       Drop-In: /etc/systemd/system/memcached.service.d
                └─override.conf
        Active: failed (Result: oom-kill) since Fri 2025-01-31 23:20:28 UTC; 2s ago
      Duration: 2.901s
       Process: 360130 ExecStart=/usr/bin/memcached -p ${PORT} -u ${USER} -m ${CACHESIZE} -c ${MAXCONN} $OPTIONS (code=killed, signal=KILL)
      Main PID: 360130 (code=killed, signal=KILL)
           CPU: 94ms
   
   Jan 31 23:20:25 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: Started memcached.service - memcached daemon.
   Jan 31 23:20:28 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: memcached.service: A process of this unit has been killed by the OOM killer.
   Jan 31 23:20:28 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: memcached.service: Main process exited, code=killed, status=9/KILL
   Jan 31 23:20:28 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: memcached.service: Failed with result 'oom-kill'.
   ```