一文搞懂 K8S request 和 limit 最佳实践

1,989次阅读

共计 12881 个字符,预计需要花费 33 分钟才能阅读完成。

1 Kubernetes对资源的限制

在Kubernetes中,对资源(CPU、内存等)的限制,需要定义在yaml中,以Deployment举例:

apiVersion: v1
kind: Pod
metadata:
  name: cpu-overload
  namespace: test
spec:
  containers:
  - name: cpu-overload
    image: stress/stress:latest
    resources:
      limits:
        cpu: "2"
        memory: 1000Mi
      requests:
        cpu: "1"
        memory: 500Mi
    command: ["stress"]
    args: ["-c", "2"]

其中,CPU 有2个限制:

  • requests:相对限制,是容器的最低申请资源,这个限制是相对的,无法做到绝对严格。
  • limits:绝对限制,这个是限制的绝对的,不可能超越。

本例中,对容器cpu-overload的 CPU 的限制,是,申请1个核的运算资源,最多可以使用2个核。

这里需要特别说明一点,所谓的最多2个核,其实是均摊的,如果这个容器真的触发了计算瓶颈,在docker中看,CPU使用率是200%,但在宿主机去看,其实并非是将2个核占满了,而是将压力分摊到了多个CPU的核上。

对Kubernetes来说,只能做到限制容器资源,无法对pod资源做限制,Kubernetes官方认为,要计算一个pod的资源限制,将pod中各个容器的资源做加和就行了。

2 资源限制的传递

Kubernetes其实可以认为是一系列组件包装起来的一个大型工具。关于资源限制,其实Kubernetes自己做不了这些,而是将对资源限制,通过yaml中的定义,传递到Docker容器中。比如,之前我们在Deployment中容器的CPU,限制为最多使用2个核,这个限制,Kubernetes会传递给Docker来做,所以本质上,Kubernetes资源的限制能力,来源于Docker,而Docker能做到什么程度的限制,又取决于Linux的cgroups,所以在很早之前的Docker是不支持在Windows平台运行的,归根结底,还是因为cgroups是Linux内核支持的产物。

说了这么多,我们可以通过一个实例来说明这个传递性。在开始前,简单说一下步骤:

  • 1、在Kubernetes中启动一个单独的pod,资源限制为最多4个CPU核。

  • 2、找到这个pod对应的容器,看一下容器的运行配置,是 不是限制了4个核。

  • 3、找到这个容器对应的Cgroups配置,看是否对容器限制了4个核。

3 实验

3.1 创建一个限制了1个核的pod

apiVersion: v1
kind: Pod
metadata:
  labels:
    system: centos7
  name: centos7
  namespace: test
spec:
  containers:
  - image: centos:7
    imagePullPolicy: IfNotPresent
    name: centos7
    command: [ "/bin/bash", "-c", "--" ]
    args: [ "while true; do sleep 30; done;" ]
    ports:
    - containerPort: 30008
      hostPort: 30008
      name: http
      protocol: TCP
    resources:
      limits:
        cpu: "1"
        memory: 2000Mi
      requests:
        cpu: "0.1"
        memory: 100Mi
  hostNetwork: true
  restartPolicy: Always

在这个yaml中,我们对centos容器,限制为1核2G内存。我们通过

kubectl apply -f centos.yaml

将pod运行起来。

3.2 查看容器的运行时限制

运行为容器后,查看此pod所在节点,进入到节点,找到这个容器,通过下面指令查看此容器的运行时配置

[root@kubernetes-master ~]# kubectl get po -n test -o wide
NAME      READY   STATUS    RESTARTS   AGE     IP            NODE               NOMINATED NODE   READINESS GATES
centos7   1/1     Running   0          2m10s   172.20.5.11   kubernetes-node1   <none>           <none>
docker inspect 7e5f03672fb6

然后,从一大堆输出中,找到下面的重点部分:

"Isolation": "",
"CpuShares": 102,
"Memory": 2097152000,
"NanoCpus": 0,
"CgroupParent": "kubepods-burstable-podb4283fa0_6576_4bd2_8c52_2183a5e2a566.slice",
"BlkioWeight": 0,
"BlkioWeightDevice": null,
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 100000,
"CpuQuota": 100000,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"MemoryReservation": 0,
"MemorySwap": 2097152000,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,

其中:

  • Memory:限制内存资源,单位为byte,2097152000 = 2G
  • CpuShares:CPU使用的相对权重,一个核为1024,我们设置的request cpu为 0.1 ,所以就是 102
  • CpuPeriod:一个CPU为100000,也就是100个milicpu,这个一般不需要改。
  • CpuQuota:CPU资源的绝对限制,一般和CpuPeriod结合在一起,CpuQuota/CpuPeriod,就是能够使用的核数,100000/100000=1,表示我们能最多使用1个CPU核心。
  • CpusetCpus:这个值表示当前容器运行时,绑定到哪几个CPU编号上,注意:这个不是CPU个数,而是绑定到哪几个CPU上,多个CPU编号用逗号分割。

从上面的docker运行时限制看,和Kubernetes的Pod的定义完全吻合。下面再看Cgroups的限制,这才是核心。

3.3 根据容器,查Cgroups的限制内容

首先,我们看一下pod的名称:

[root@kubernetes-master ~]# kubectl get po -n test -o wide
NAME      READY   STATUS    RESTARTS   AGE     IP            NODE               NOMINATED NODE   READINESS GATES
centos7   1/1     Running   0          2m10s   172.20.5.11   kubernetes-node1   <none>           <none>

然后,在pod所在的宿主机,找到这个pod对应的容器Id

docker ps | grep centos7
[root@kubernetes-node1 ~]# docker ps | grep centos7
7e5f03672fb6        7e6257c9f8d8               "/bin/bash -c -- 'wh…"   6 minutes ago       Up 6 minutes                            k8s_centos7_centos7_test_b4283fa0-6576-4bd2-8c52-2183a5e2a566_0
67d02f7cf04d        k8s.gcr.io/pause:3.2       "/pause"                 6 minutes ago       Up 6 minutes                            k8s_POD_centos7_test_b4283fa0-6576-4bd2-8c52-2183a5e2a566_0

我们可以注意到,一个匹配出来2个容器,一个是 centos7 容器,一个是pause容器,pause容器,是 Kubernetes pod 的基础容器。我们只需要 centos7:7e5f03672fb6,我们要通过它拿到这个容器的Cgroup信息

[root@kubernetes-node1 ~]# docker inspect 7e5f03672fb6 | grep Cgroup
            "Cgroup": "",
            "CgroupParent": "kubepods-burstable-podb4283fa0_6576_4bd2_8c52_2183a5e2a566.slice",
            "DeviceCgroupRules": null,

好了,完事具备,我们直接进入Cgroup配置目录:

cd /sys/fs/cgroup/cpu/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podb4283fa0_6576_4bd2_8c52_2183a5e2a566.slice

在这个目录下,有很多文件:

[root@kubernetes-node1 kubepods-burstable-podb4283fa0_6576_4bd2_8c52_2183a5e2a566.slice]# ll
total 0
-rw-r--r-- 1 root root 0 Nov 17 14:50 cgroup.clone_children
--w--w--w- 1 root root 0 Nov 17 14:50 cgroup.event_control
-rw-r--r-- 1 root root 0 Nov 17 14:50 cgroup.procs
-r--r--r-- 1 root root 0 Nov 17 14:50 cpuacct.stat
-rw-r--r-- 1 root root 0 Nov 17 14:50 cpuacct.usage
-r--r--r-- 1 root root 0 Nov 17 14:50 cpuacct.usage_percpu
-rw-r--r-- 1 root root 0 Nov 17 14:50 cpu.cfs_period_us
-rw-r--r-- 1 root root 0 Nov 17 14:50 cpu.cfs_quota_us
-rw-r--r-- 1 root root 0 Nov 17 14:50 cpu.rt_period_us
-rw-r--r-- 1 root root 0 Nov 17 14:50 cpu.rt_runtime_us
-rw-r--r-- 1 root root 0 Nov 17 14:50 cpu.shares
-r--r--r-- 1 root root 0 Nov 17 14:50 cpu.stat
drwxr-xr-x 2 root root 0 Nov 17 14:50 docker-67d02f7cf04d6eb6ed637e40e1ccebd18b09eb323ad262c1fe3e8aa75ea46edf.scope
drwxr-xr-x 2 root root 0 Nov 17 14:50 docker-7e5f03672fb63500910b092ecfcc793a8f21450528bb32c9d078d31dc4846cb2.scope
-rw-r--r-- 1 root root 0 Nov 17 14:50 notify_on_release
-rw-r--r-- 1 root root 0 Nov 17 14:50 tasks

其中,当前目录下有很多Cgroup内容,而有2个子目录:

docker-67d02f7cf04d6eb6ed637e40e1ccebd18b09eb323ad262c1fe3e8aa75ea46edf.scope
docker-7e5f03672fb63500910b092ecfcc793a8f21450528bb32c9d078d31dc4846cb2.scope

这2个目录,其实就是 pod 中的2个容器(pause容器,centos7容器),我们进入 centos7容器的目录下

cd docker-7e5f03672fb63500910b092ecfcc793a8f21450528bb32c9d078d31dc4846cb2.scope

查看下目录下的内容

-rw-r--r-- 1 root root 0 Nov 17 14:50 cgroup.clone_children
--w--w--w- 1 root root 0 Nov 17 14:50 cgroup.event_control
-rw-r--r-- 1 root root 0 Nov 17 14:50 cgroup.procs
-r--r--r-- 1 root root 0 Nov 17 14:50 cpuacct.stat
-rw-r--r-- 1 root root 0 Nov 17 14:50 cpuacct.usage
-r--r--r-- 1 root root 0 Nov 17 14:50 cpuacct.usage_percpu
-rw-r--r-- 1 root root 0 Nov 17 14:50 cpu.cfs_period_us
-rw-r--r-- 1 root root 0 Nov 17 14:50 cpu.cfs_quota_us
-rw-r--r-- 1 root root 0 Nov 17 14:50 cpu.rt_period_us
-rw-r--r-- 1 root root 0 Nov 17 14:50 cpu.rt_runtime_us
-rw-r--r-- 1 root root 0 Nov 17 14:50 cpu.shares
-r--r--r-- 1 root root 0 Nov 17 14:50 cpu.stat
-rw-r--r-- 1 root root 0 Nov 17 14:50 notify_on_release
-rw-r--r-- 1 root root 0 Nov 17 14:50 tasks

其中,能够看到好几个熟悉的词,比如 cpu.cfs_quota_us,这个正是对CPU资源做限制的。我们查看一下其内容:

[root@kubernetes-node1 ...scope]# cat cpu.cfs_quota_us
100000

没错,这个值正是100000,也就是1个CPU。

3.4 Linux Cgroup 是如何与Dock而关联的?

上面的方式,已经层层找到了对CPU、内存等限制,是如何通过Kubernets的Deployment,一步步追查到Cgroup的。那么,Linux Cgroup,怎么与容器关联起来的呢?

我们看一个cgroup目录中的tasks

[root@kubernetes-node1 docker-7e5f03672fb63500910b092ecfcc793a8f21450528bb32c9d078d31dc4846cb2.scope]# cat tasks 
22552

这个值,就是进程ID,所以,Cgroup对资源的限制,就是对进程ID来限制的。我们看一下这个进程ID

[root@kubernetes-node1 docker-7e5f03672fb63500910b092ecfcc793a8f21450528bb32c9d078d31dc4846cb2.scope]# ps -ef | grep 22552
root     22552 22534  0 14:50 ?        00:00:00 /bin/bash -c -- while true; do sleep 30; done;
root     30414 22552  0 15:08 ?        00:00:00 sleep 30
root     30443 23532  0 15:08 pts/0    00:00:00 grep --color=auto 22552

此进程ID,正是cadvisor的进程ID,其实这个进程,是容器内的进程,换句话说,其父进程,肯定是一个容器进程:

[root@kubernetes-node1 docker-7e5f03672fb63500910b092ecfcc793a8f21450528bb32c9d078d31dc4846cb2.scope]# ps -ef | grep 22534
root     22534   906  0 14:50 ?        00:00:00 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/7e5f03672fb63500910b092ecfcc793a8f21450528bb32c9d078d31dc4846cb2 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc -systemd-cgroup
root     22552 22534  0 14:50 ?        00:00:00 /bin/bash -c -- while true; do sleep 30; done;
root     30875 23532  0 15:09 pts/0    00:00:00 grep --color=auto 22534

3.5 测试

在 Linux 中,cgroups 给用户暴露出来的操作接口是文件系统,即它以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下。在 Ubuntu 16.04 机器里,可以用 mount 指令把它们展示出来:

$ mount -t cgroup
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,name=systemd)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,rdma)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)

它的输出是一些文件系统目录,这些目录名就是当前系统所支持的子系统,这些子系统都在 /sys/fs/cgroup/目录内,如对于cpu子系统来说,相关的几个配置文件为

root@VM-236-165-centos ~]# ll /sys/fs/cgroup/cpu/
total 0
-rw-r--r--  1 root root 0 Sep  9 12:01 cgroup.clone_children
-rw-r--r--  1 root root 0 Sep  8 17:59 cgroup.procs
-r--r--r--  1 root root 0 Sep  9 12:01 cgroup.sane_behavior
-r--r--r--  1 root root 0 Sep  9 12:01 cpuacct.stat
-r--r--r--  1 root root 0 Sep  9 12:01 cpuacct.uptime
-rw-r--r--  1 root root 0 Sep  9 12:01 cpuacct.usage
-r--r--r--  1 root root 0 Sep  9 12:01 cpuacct.usage_all
-r--r--r--  1 root root 0 Sep  9 12:01 cpuacct.usage_percpu
-r--r--r--  1 root root 0 Sep  9 12:01 cpuacct.usage_percpu_sys
-r--r--r--  1 root root 0 Sep  9 12:01 cpuacct.usage_percpu_user
-r--r--r--  1 root root 0 Sep  9 12:01 cpuacct.usage_sys
-r--r--r--  1 root root 0 Sep  9 12:01 cpuacct.usage_user
-rw-r--r--  1 root root 0 Sep  9 12:01 cpu.bt_shares
-rw-r--r--  1 root root 0 Sep  9 12:01 cpu.bt_suppress_percent
-rw-r--r--  1 root root 0 Sep  9 12:01 cpu.cfs_burst_us
-rw-r--r--  1 root root 0 Sep  9 11:49 cpu.cfs_period_us
-rw-r--r--  1 root root 0 Sep  8 17:59 cpu.cfs_quota_us
-rw-r--r--  1 root root 0 Sep  9 12:01 cpu.offline
-rw-r--r--  1 root root 0 Sep  9 12:01 cpu.pressure
-rw-r--r--  1 root root 0 Sep  8 17:59 cpu.rt_period_us
-rw-r--r--  1 root root 0 Sep  9 12:01 cpu.rt_runtime_us
-rw-r--r--  1 root root 0 Sep  8 17:59 cpu.shares
-r--r--r--  1 root root 0 Sep  9 12:01 cpu.stat
drwxr-xr-x  2 root root 0 Sep  9 11:49 docker
drwxr-xr-x  4 root root 0 Sep  9 12:01 kubepods
drwxr-xr-x  2 root root 0 Dec  9 16:14 mycontainer
-rw-r--r--  1 root root 0 Sep  9 12:01 notify_on_release
drwxr-xr-x 19 root root 0 Sep  8 18:00 onion
-rw-r--r--  1 root root 0 Sep  8 18:00 release_agent
drwxr-xr-x 96 root root 0 Sep  8 17:59 system.slice
-rw-r--r--  1 root root 0 Sep  9 12:01 tasks
drwxr-xr-x  2 root root 0 Sep  8 17:59 user.slice

其中 cpu.cfs_quota_uscpu.cfs_period_us 是经常使用的两个配置项,两者必须组合使用,表示一个进程组在 cpu.cfs_period_us 段时间内,分配给CPU的时间比例为 cpu.cfs_quota_us

另外输出结果中包含一些子目录,如 aegis、assist、kubepods.slice、system.slice、user.slice、test 和 init.scope。

现在我们看下这些子系统配置文件如何使用,首先我们在 /sys/fs/cgroup/cpu/ 目录下创建一个目录 mycontainer,这个目录称为cgroup,即"控制组"。

$ cd /sys/fs/cgroup/cpu/
$ mkdir mycontainer
$ sys/fs/cgroup/cpu# ls mycontainer/
cgroup.clone_children  cpu.cfs_period_us  cpu.shares  cpu.uclamp.max  cpuacct.stat   cpuacct.usage_all     cpuacct.usage_percpu_sys   cpuacct.usage_sys   notify_on_release
cgroup.procs           cpu.cfs_quota_us   cpu.stat    cpu.uclamp.min  cpuacct.usage  cpuacct.usage_percpu  cpuacct.usage_percpu_user  cpuacct.usage_user  tasks

会发现 mycontainer 目录时会自动出现一些 cpu 配置文件,有些配置文件内容为 -1,表示不限制,其中tasks文件里表示要控制的进程 pid。

我们现在做个实现执行一下死循环脚本,便其完全占用CPU达到100%,然后再对此PID进行CPU限制,看下效果如果。

$ while : ; do : ; done &
[1] 1626025

执行top查看

PID     USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
1626025 root      20   0   12724   1768      0 R 100.0   0.0   0:28.60 bash

发现这个进程的CPU已经达到了100%,下面我们对其进行一下限制。先将进程PID写到 mycontainer 控制组下的tasks文件里,然后限制 cpu 使用率

$ echo 1626025 > /sys/fs/cgroup/cpu/mycontainer/tasks
$ cat /sys/fs/cgroup/cpu/mycontainer/tasks
1626025

现在我们已成功将其进程号写入tasks文件。上面我们提到过对cpu的限制主要使用两个文件,分别为cpu.cfs_quota_uscpu.cfs_quota_us, 先看一下他们的默认值。

$ cat /sys/fs/cgroup/cpu/mycontainer/cpu.cfs_quota_us 
-1
$ cat /sys/fs/cgroup/cpu/mycontainer/cpu.cfs_period_us 
100000

表示在100ms内分配给cpu的机会为不限制,也就是表示100%的资源。我们要做一下限制,让其在100ms时间内,只分配给 20% 的cpu机会

$ echo 20000 > /sys/fs/cgroup/cpu/mycontainer/cpu.cfs_quota_us

然后再执行一下top命令发现cpu使用率立即降下来了,最多为20%左右,可能会有一点点的超出,这个很正常。

PID     USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
1626025 root      20   0   12724   1768      0 R  20.0   0.0  12:43.38 bash

这里我们只对cpu做了限制,你也可以做内在memory做一下限制,由于这里的脚本只会占用cpu,所以不再演示

4 总结

  • Kubernete对资源的限制,靠的是Docker,Docker对资源的限制,靠的是Linux Cgroup 。
  • Linux Cgroup 限制资源,是限制进程,只需要在Cgroup配置目录的tasks文件中,添加进程ID,限制立即生效。
  • Linux Cgroup 不仅仅可以限制CPU,内存,还可以限制磁盘IO等。

5 如何更好的设置Requests和Limits

5.1 所有容器都应该设置 request

request 的值并不是指给容器实际分配的资源大小,它仅仅是给调度器看的,调度器会 “观察” 每个节点可以用于分配的资源有多少,也知道每个节点已经被分配了多少资源。

被分配资源的大小就是节点上所有 Pod 中定义的容器 request 之和,它可以计算出节点剩余多少资源可以被分配(可分配资源减去已分配的 request 之和)。

如果发现节点剩余可分配资源大小比当前要被调度的 Pod 的 reuqest 还小,那么就不会考虑调度到这个节点,反之,才可能调度。

所以,如果不配置 request,那么调度器就不能知道节点大概被分配了多少资源出去,调度器得不到准确信息,也就无法做出合理的调度决策,很容易造成调度不合理,有些节点可能很闲,而有些节点可能很忙,甚至 NotReady。

所以,建议是给所有容器都设置 request,让调度器感知节点有多少资源被分配了,以便做出合理的调度决策,让集群节点的资源能够被合理的分配使用,避免陷入资源分配不均导致一些意外发生。

5.2 老是忘记设置怎么办

有时候我们会忘记给部分容器设置 request 与 limit,其实我们可以使用 LimitRange 来设置 namespace 的默认 request 与 limit 值,同时它也可以用来限制最小和最大的 request 与 limit。
示例:

apiVersion: v1
kind: LimitRange
metadata:
  name: mem-limit-range
  namespace: test
spec:
  limits:
  - default:
      memory: 512Mi
      cpu: 500m
    defaultRequest:
      memory: 256Mi
      cpu: 100m
    type: Container

5.3 重要的线上应用改如何设置

节点资源不足时,会触发自动驱逐,将一些低优先级的 Pod 删除掉以释放资源让节点自愈。

  • 没有设置 request,limit 的 Pod 优先级最低,容易被驱逐;

  • request 不等于 limit 的其次;

  • request 等于 limit 的 Pod 优先级较高,不容易被驱逐。

    所以如果是重要的线上应用,不希望在节点故障时被驱逐导致线上业务受影响,就建议将 request 和 limit 设成一致。

5.4 怎样设置才能提高资源利用率

如果给应用设置较高的 request 值,而实际占用资源长期远小于它的 request 值,导致节点整体的资源利用率较低。

当然这对时延非常敏感的业务除外,因为敏感的业务本身不期望节点利用率过高,影响网络包收发速度。

所以对一些非核心,并且资源不长期占用的应用,可以适当减少 request 以提高资源利用率。

如果你的服务支持水平扩容,单副本的 request 值一般可以设置到不大于 1 核,CPU 密集型应用除外。比如 coredns,设置到 0.1 核就可以,即 100m。

5.5 尽量避免设置过大的 requests 和 limit

如果你的服务使用单副本或者少量副本,给很大的 request 与 limit,让它分配到足够多的资源来支撑业务,那么某个副本故障对业务带来的影响可能就比较大,并且由于 request 较大,当集群内资源分配比较碎片化,如果这个 Pod 所在节点挂了,其它节点又没有一个有足够的剩余可分配资源能够满足这个 Pod 的 request 时,这个 Pod 就无法实现漂移,也就不能自愈,加重对业务的影响。

相反,建议尽量减小 request 与 limit,通过增加副本的方式来对你的服务支撑能力进行水平扩容,让你的系统更加灵活可靠。

正文完
 1
mervinwang
版权声明:本站原创文章,由 mervinwang 2022-12-08发表,共计12881字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
文章搜索