gitbook/高楼的性能工程实战课/docs/366020.md
2022-09-03 22:05:03 +08:00

456 lines
28 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 15 | 查询商品:资源不足有哪些性能表现?
你好,我是高楼。
这节课我们来收拾“查询商品”这个接口。虽然这次的现象同样是TPS低、响应时间长但是这个接口走的路径和之前的不一样所以在分析过程中会有些新鲜的东西你将看到在资源真的不足的情况下我们只有增加相应节点的资源才能提升性能。
在我的项目中,我一直都在讲,**不要轻易给出资源不足的结论。因为但凡有优化的空间,我们都要尝试做优化,而不是直接告诉客户加资源。而给出“增加资源”这个结论,也必须建立在有足够证据的基础上**。在这节课中,你也将看到这一点。
话不多说,我们直接开始今天的内容。
## 压力场景数据
对于查询商品接口,我们第一次试执行性能场景的结果如下:
![](https://static001.geekbang.org/resource/image/75/a2/75ef8d040cdbcef4556bbfa7fd7098a2.png)
你看TPS只有250左右并且响应时间也明显随着压力的增加而增加了看起来瓶颈已经出现了对吧根据哥的逻辑下一步就是看架构图啦。
## 先看架构图
我们用APM工具来看看这个接口的架构。
![](https://static001.geekbang.org/resource/image/6b/70/6bcbe3236d91fd7628fa5a6186243870.png)
你看从压力机到Gateway服务、到Search服务、再到ES-Client这个APM工具也只能帮我们到这里了。因为我们用的是ElasticSearch 7来做的搜索服务的支撑而这个skywalking工具也没有对应的Agent所以后面并没有配置skywalking。
在这里我要多啰嗦几句。现在的APM工具大多是基于应用层来做的有些运维APM采集的数据会更多一些但也是响应时间、吞吐量等这样的信息。对于性能分析而言现在的APM工具有减少排查时间的能力但是在组件级的细化定位上还有待提高。虽然AI OPS也被提到了台面但是也没见过哪个公司上了AIOPS产品后就敢不让人看着。
总之,从细化分析的角度,我们在定位问题的根本原因时,手头有什么工具就可以用什么工具,即使什么工具都没有,撸日志也是照样能做到的,所以我建议你不要迷信工具,要“迷信”思路。
下面我们来拆分下这个接口的响应时间,看看这个案例的问题点在哪里。
## 拆分响应时间
**“在RESAR性能分析逻辑中拆分响应时间只是一个分析的起点**。”这是我一直在强调的一句话。如果性能工程师连这个都不会做,就只能好好学习天天向上了。
根据架构图,我们拆分响应时间如下。
* Gateway服务上的响应时间
![](https://static001.geekbang.org/resource/image/dc/0d/dc64c9e8ace689c86d6584b64f9f230d.png)
* Search服务上的响应时间
![](https://static001.geekbang.org/resource/image/a6/c9/a6dc83d1b51445464d3db3e5421798c9.png)
* ES Client的响应时间
![](https://static001.geekbang.org/resource/image/0b/81/0b168cdd73f30b5565c52a6d97b45081.png)
一层层看过之后我们发现查询商品这个接口的响应时间消耗在了ES client上面。而在我们这个查询的路径上在gateway/search服务上我们并没有做什么复杂的动作。
既然知道了响应时间消耗在哪里下面我们就来定位它看能不能把TPS优化起来。
## 全局监控
根据高老师的经验,我们还是从全局监控开始,看全局监控可以让我们更加有的放矢。在分析的过程中,经常有人往下走了几步之后,就开始思维混乱、步伐飘逸。因为数据有很多,所以分析时很容易从一个数据走到不重要的分支上去了。而这时候,如果你心里有全局监控数据,思路就会更清晰,不会在无关的分支上消耗时间。
回到我们这个例子中从下面的k8s worker也就是k8s中的node在我们的环境中我习惯叫成worker就是为了体现在我的地盘我爱叫啥就叫啥的数据上来看似乎没有一个worker的资源使用率是特别高的。
![](https://static001.geekbang.org/resource/image/25/e5/25bb0386561be19b9615a4b0130fe4e5.png)
请你注意在k8s中看资源消耗一定不要只看worker这个层面因为这个层面还不够一个worker上可能会运行多个pod。从上图来看由于worker层面没有资源消耗但是时间又明显是消耗在ES client上的所以接下来我们要看一下每一个pod的资源使用情况。
![](https://static001.geekbang.org/resource/image/13/f3/13f919d42a29f2d37f699036658006f3.png)
有红色。你看有两个与ES相关的POD它们的CPU都飘红了这下可有得玩了。既然是与ES相关的POD那我们就把ES所有的POD排个序看看。
![](https://static001.geekbang.org/resource/image/62/bd/624d7bc2fe25f731aa42037d8d9f29bd.png)
从上图的数据来看有一个ES Client 消耗了67%的CPU有两个ES Data消耗了99%的CPUES本来就是吃CPU的大户所以我们接下来要着重分析它。
这里我再说明一点我们从前面的worker资源使用率一步一步走到这里在分析方向上是合情合理的因为这些都是属于我提到的全局监控的内容。
## 定向分析
现在我们就来扒一扒ES看看它在哪个worker节点上。罗列Pod信息如下
```
[root@k8s-master-1 ~]# kubectl get pods -o wide | grep elasticsearch
elasticsearch-client-0 1/1 Running 0 6h43m 10.100.230.2 k8s-worker-1 <none> <none>
elasticsearch-client-1 1/1 Running 0 6h45m 10.100.140.8 k8s-worker-2 <none> <none>
elasticsearch-data-0 1/1 Running 0 7h8m 10.100.18.197 k8s-worker-5 <none> <none>
elasticsearch-data-1 1/1 Running 0 7h8m 10.100.5.5 k8s-worker-7 <none> <none>
elasticsearch-data-2 1/1 Running 0 7h8m 10.100.251.67 k8s-worker-9 <none> <none>
elasticsearch-master-0 1/1 Running 0 7h8m 10.100.230.0 k8s-worker-1 <none> <none>
elasticsearch-master-1 1/1 Running 0 7h8m 10.100.227.131 k8s-worker-6 <none> <none>
elasticsearch-master-2 1/1 Running 0 7h8m 10.100.69.206 k8s-worker-3 <none> <none>
[root@k8s-master-1 ~]#
```
现在就比较清晰了可以看到在整个namespace中有两个ES client三个ES data三个ES master。
我们来画一个细一点的架构图,以便在脑子里记下这个逻辑:
![](https://static001.geekbang.org/resource/image/2e/0f/2e8a4fe8b5e214a8463d918dea8cyy0f.jpg)
再结合我们在全局分析中看到的资源使用率图,现在判断至少有两个问题:
1. ES client请求不均衡
2. ES data CPU 高。
下面我们一个一个来分析。
### ES client请求不均衡
从上面的架构图中可以看到search服务连两个ES client但是只有一个ES client的CPU使用率高。所以我们需要查一下链路看看ES的service
```
[root@k8s-master-1 ~]# kubectl get svc -o wide | grep search
elasticsearch-client NodePort 10.96.140.52 <none> 9200:30200/TCP,9300:31614/TCP 34d app=elasticsearch-client,chart=elasticsearch,heritage=Helm,release=elasticsearch-client
elasticsearch-client-headless ClusterIP None <none> 9200/TCP,9300/TCP 34d app=elasticsearch-client
elasticsearch-data ClusterIP 10.96.16.151 <none> 9200/TCP,9300/TCP 7h41m app=elasticsearch-data,chart=elasticsearch,heritage=Helm,release=elasticsearch-data
elasticsearch-data-headless ClusterIP None <none> 9200/TCP,9300/TCP 7h41m app=elasticsearch-data
elasticsearch-master ClusterIP 10.96.207.238 <none> 9200/TCP,9300/TCP 7h41m app=elasticsearch-master,chart=elasticsearch,heritage=Helm,release=elasticsearch-master
elasticsearch-master-headless ClusterIP None <none> 9200/TCP,9300/TCP 7h41m app=elasticsearch-master
svc-mall-search ClusterIP 10.96.27.150 <none> 8081/TCP 44d app=svc-mall-search
[root@k8s-master-1 ~]#
```
你看整个namespace中有一个client service解析出来的是VIP访问此服务时不会绕过K8s的转发机制还有一个client-headless service解析出来的是POD IP访问这个服务时会绕过K8s的转发机制
接下来,我们查一下为什么会出现访问不均衡的情况。
通过查看search服务的ES配置我们看到如下信息
```
elasticsearch:
rest:
uris: elasticsearch-client:9200
username: elastic
password: admin@123
```
看到我们这里是用的elasticsearch-client:9200我们再来看一下client service的配置
```
---
apiVersion: v1
kind: Service
metadata:
annotations:
meta.helm.sh/release-name: elasticsearch-client
meta.helm.sh/release-namespace: default
creationTimestamp: '2020-12-10T17:34:19Z'
labels:
app: elasticsearch-client
app.kubernetes.io/managed-by: Helm
chart: elasticsearch
heritage: Helm
release: elasticsearch-client
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
'f:metadata': {}
'f:spec':
'f:ports': {}
manager: Go-http-client
operation: Update
time: '2020-12-10T17:34:19Z'
name: elasticsearch-client
namespace: default
resourceVersion: '4803428'
selfLink: /api/v1/namespaces/default/services/elasticsearch-client
uid: 457e962e-bee0-49b7-9ec4-ebfbef0fecdd
spec:
clusterIP: 10.96.140.52
externalTrafficPolicy: Cluster
ports:
- name: http
nodePort: 30200
port: 9200
protocol: TCP
targetPort: 9200
- name: transport
nodePort: 31614
port: 9300
protocol: TCP
targetPort: 9300
selector:
app: elasticsearch-client
chart: elasticsearch
heritage: Helm
release: elasticsearch-client
sessionAffinity: None
type: NodePort
```
从上面的配置来看sessionAffinity也配置为None了也就是说这个service不以客户端的IP来保持session。因为在这个环境配置中Type为NodePort而我们在k8s中配置的转发规则是iptables。所以说service是依赖iptables的规则来做后端转发的。
接下来我们检查一下iptables的转发规则。
我们先来看iptables中关于ES client的规则
```
[root@k8s-master-1 ~]# iptables -S KUBE-SERVICES -t nat|grep elasticsearch-client|grep 9200
-A KUBE-SERVICES ! -s 10.100.0.0/16 -d 10.96.140.52/32 -p tcp -m comment --comment "default/elasticsearch-client:http cluster IP" -m tcp --dport 9200 -j KUBE-MARK-MASQ
-A KUBE-SERVICES -d 10.96.140.52/32 -p tcp -m comment --comment "default/elasticsearch-client:http cluster IP" -m tcp --dport 9200 -j KUBE-SVC-XCX4XZ2WPAE7BUZ4
[root@k8s-master-1 ~]#
```
可以看到service的规则名是KUBE-SVC-XCX4XZ2WPAE7BUZ4那我们再去查它对应的iptables规则
```
[root@k8s-master-1 ~]# iptables -S KUBE-SVC-XCX4XZ2WPAE7BUZ4 -t nat
-N KUBE-SVC-XCX4XZ2WPAE7BUZ4
-A KUBE-SVC-XCX4XZ2WPAE7BUZ4 -m comment --comment "default/elasticsearch-client:http" -j KUBE-SEP-LO263M5QW4XA6E3Q
[root@k8s-master-1 ~]#
[root@k8s-master-1 ~]# iptables -S KUBE-SEP-LO263M5QW4XA6E3Q -t nat
-N KUBE-SEP-LO263M5QW4XA6E3Q
-A KUBE-SEP-LO263M5QW4XA6E3Q -s 10.100.227.130/32 -m comment --comment "default/elasticsearch-client:http" -j KUBE-MARK-MASQ
-A KUBE-SEP-LO263M5QW4XA6E3Q -p tcp -m comment --comment "default/elasticsearch-client:http" -m tcp -j DNAT --to-destination 10.100.227.130:9200
```
问题来了这里好像没有负载均衡的配置没有probability参数并且根据iptables规则也只是转发到了一个ES client上。到这里其实我们也就能理解为什么在全局监控的时候我们只看到一个ES client有那么高的CPU使用率而另一个ES client却一点动静都没有。
但是这里的iptables规则并不是自己来配置的而是在部署k8s的时候自动刷进去的规则。现在只有一条规则了所以只能转发到一个POD上去。
那我们就再刷一遍ES的POD重装一下ES的POD看k8s自己能不能刷出来负载均衡的iptables规则。重来一遍之后我们再来看iptables规则
```
[root@k8s-master-1 ~]# iptables -S KUBE-SVC-XCX4XZ2WPAE7BUZ4 -t nat
-N KUBE-SVC-XCX4XZ2WPAE7BUZ4
-A KUBE-SVC-XCX4XZ2WPAE7BUZ4 -m comment --comment "default/elasticsearch-client:http" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-IFM4L7YNSTSJP4YT
-A KUBE-SVC-XCX4XZ2WPAE7BUZ4 -m comment --comment "default/elasticsearch-client:http" -j KUBE-SEP-5RAP6F6FATXC4DFL
[root@k8s-master-1 ~]#
```
现在刷出来两条iptables规则了看来之前在我们不断折腾的部署过程中ES client一直是有问题的。
在上面的iptables规则里那两条iptables的上一条中有一个关键词“——probability 0.50000000000”。我们知道iptables的匹配规则是从上到下的既然上一条的匹配是随机0.5也就是说只有50%的请求会走第一条规则那下一条自然也是随机0.5了,因为总共只有两条规则嘛。这样一来就均衡了。
我们再接着做这个接口的压力场景,看到如下信息:
![](https://static001.geekbang.org/resource/image/40/67/408592f11401e1yyb1c06ef48f3f8167.png)
看起来ES client均衡了对不对
它对应的TPS如下
![](https://static001.geekbang.org/resource/image/61/99/614e849f975cf983747e080329c0d699.png)
明显TPS提升了60左右。
ES client请求不均衡的问题解决了现在我们还要来看一下ES data单节点CPU高的问题。
### ES Data CPU使用率高
* **第一阶段加一个CPU**
在TPS提升之后我们再来看一下全局监控数据。
![](https://static001.geekbang.org/resource/image/2e/79/2ec7cce680e81f57717c642cf7834279.png)
看起来比一开始好多了。基于前面分析ES client的经验我们就先来查一下ES data的iptables规则
```
-- 查看下有哪些ES data的POD
[root@k8s-master-1 ~]# kubectl get pods -o wide | grep data
elasticsearch-data-0 1/1 Running 0 10h 10.100.18.197 k8s-worker-5 <none> <none>
elasticsearch-data-1 1/1 Running 0 10h 10.100.5.5 k8s-worker-7 <none> <none>
elasticsearch-data-2 1/1 Running 0 10h 10.100.251.67 k8s-worker-9 <none> <none>
-- 查看ES data对应的iptables规则
[root@k8s-master-1 ~]# iptables -S KUBE-SERVICES -t nat|grep elasticsearch-data
-A KUBE-SERVICES ! -s 10.100.0.0/16 -d 10.96.16.151/32 -p tcp -m comment --comment "default/elasticsearch-data:http cluster IP" -m tcp --dport 9200 -j KUBE-MARK-MASQ
-A KUBE-SERVICES -d 10.96.16.151/32 -p tcp -m comment --comment "default/elasticsearch-data:http cluster IP" -m tcp --dport 9200 -j KUBE-SVC-4LU6GV7CN63XJXEQ
-A KUBE-SERVICES ! -s 10.100.0.0/16 -d 10.96.16.151/32 -p tcp -m comment --comment "default/elasticsearch-data:transport cluster IP" -m tcp --dport 9300 -j KUBE-MARK-MASQ
-A KUBE-SERVICES -d 10.96.16.151/32 -p tcp -m comment --comment "default/elasticsearch-data:transport cluster IP" -m tcp --dport 9300 -j KUBE-SVC-W4QKPGOO4JGYQZDQ
-- 查看9200外部通信对应的规则
[root@k8s-master-1 ~]# iptables -S KUBE-SVC-4LU6GV7CN63XJXEQ -t nat
-N KUBE-SVC-4LU6GV7CN63XJXEQ
-A KUBE-SVC-4LU6GV7CN63XJXEQ -m comment --comment "default/elasticsearch-data:http" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-ZHLKOYKJY5GV3ZVN
-A KUBE-SVC-4LU6GV7CN63XJXEQ -m comment --comment "default/elasticsearch-data:http" -m statistic --mode random --probability 1 -j KUBE-SEP-6ILKZEZS3TMCB4VJ
-A KUBE-SVC-4LU6GV7CN63XJXEQ -m comment --comment "default/elasticsearch-data:http" -j KUBE-SEP-JOYLBDPA3LNXKWUK
-- 查看以上三条规则的转发目标
[root@k8s-master-1 ~]# iptables -S KUBE-SEP-ZHLKOYKJY5GV3ZVN -t nat
-N KUBE-SEP-ZHLKOYKJY5GV3ZVN
-A KUBE-SEP-ZHLKOYKJY5GV3ZVN -s 10.100.18.197/32 -m comment --comment "default/elasticsearch-data:http" -j KUBE-MARK-MASQ
-A KUBE-SEP-ZHLKOYKJY5GV3ZVN -p tcp -m comment --comment "default/elasticsearch-data:http" -m tcp -j DNAT --to-destination 10.100.18.197:9200
[root@k8s-master-1 ~]# iptables -S KUBE-SEP-6ILKZEZS3TMCB4VJ -t nat
-N KUBE-SEP-6ILKZEZS3TMCB4VJ
-A KUBE-SEP-6ILKZEZS3TMCB4VJ -s 10.100.251.67/32 -m comment --comment "default/elasticsearch-data:http" -j KUBE-MARK-MASQ
-A KUBE-SEP-6ILKZEZS3TMCB4VJ -p tcp -m comment --comment "default/elasticsearch-data:http" -m tcp -j DNAT --to-destination 10.100.251.67:9200
[root@k8s-master-1 ~]# iptables -S KUBE-SEP-JOYLBDPA3LNXKWUK -t nat
-N KUBE-SEP-JOYLBDPA3LNXKWUK
-A KUBE-SEP-JOYLBDPA3LNXKWUK -s 10.100.5.5/32 -m comment --comment "default/elasticsearch-data:http" -j KUBE-MARK-MASQ
-A KUBE-SEP-JOYLBDPA3LNXKWUK -p tcp -m comment --comment "default/elasticsearch-data:http" -m tcp -j DNAT --to-destination 10.100.5.5:9200
[root@k8s-master-1 ~]
```
Everything is perfect!规则很合理。ES Data总共有三个pod从逻辑上来看它们各占了三分之一。
在前面的ES client分析中我们讲到第一个POD是0.5下一条自然也只剩下0.5这很容易理解。现在ES data的部分有三条iptables规则我们来简单说明一下。
> 通常我们理解的iptables就是一个防火墙。不过要是从根本上来讲它不算是一个防火墙只是一堆规则列表而通过iptables设计的规则列表请求会对应到netfilter框架中去而这个netfilter框架才是真正的防火墙。其中netfilter是处于内核中的iptables就只是一个用户空间上的配置工具而已。
> 我们知道iptables有四表五链。四表是fileter表负责过滤、nat表负责地址转换、mangle表负责解析、raw表关闭nat表上启用的连接追踪五链是prerouting链路由前、input链输入规则、forward链转发规则、output链输出规则、postrouting链路由后
> 而在这一部分我们主要是看nat表以及其上的链。对于其他的部分如果你想学习可自行查阅iptables相关知识。毕竟我还时刻记得自己写的是一个性能专栏而不是计算机基础知识专栏哈哈。
从上面的信息可以看到我们的这个集群中有三个ES data服务对应着三条转发规则其中第一条规则的匹配比例是0.33333333349第二条比例0.50000000000第三条是1。而这三条转发规则对应的POD IP和端口分别是10.100.18.197:9200、10.100.251.67:9200、10.100.5.5:9200这也就意味着通过这三条iptables规则可以实现负载均衡画图理解如下
![](https://static001.geekbang.org/resource/image/5e/88/5e9c08e967c62d9e9a84084d8c2de888.jpg)
我们假设有30个请求进来那ES Data 0上就会有30x0.33333333349=10个请求对于剩下的20个请求在ES Data 1上就会有20x0.50000000000=10个请求而最后剩下的10个请求自然就到了ES Data 2上。这是一个非常均衡的逻辑只是在iptables规则中我看着这几个数据比例实在是觉得别扭。
既然明白了这个逻辑,下面我们还是把查询商品接口的场景压起来看一下:
![](https://static001.geekbang.org/resource/image/06/49/06eb3b24a57226cd9a6717cd1e3f6049.png)
从数据上来看经常会出现ES data 某个节点消耗CPU高的情况。可是对应到我们前面看到的全局worker监控界面中并没有哪个worker的CPU很高。所以在这里我们要查一下ES Data中的cgroup配置看它的限制是多少。
![](https://static001.geekbang.org/resource/image/8y/3c/8yyd469d83c9a346aff8c659f6c4ae3c.png)
也就是说ES data的每个POD都是配置了一颗CPU难怪CPU使用率动不动就红了。
还有一点你要记住前面我们在查看data列表的时候发现ES data 0 在worker-5上ES data 1 在worker-7上ES data 2 在worker-9上。而我们现在看到的却是它们都各自分到了一个CPU。既然如此那我们就再添加一个CPU然后再回去看一下worker-5/7/9的反应。为什么只加一个CPU呢因为从worker-7上来看现在的CPU使用率已经在50%左右了,要是加多了,我怕它吃不消。
![](https://static001.geekbang.org/resource/image/f5/01/f57acfca05yy43bd882a57404ea50d01.png)
看一下压力场景执行的效果:
![](https://static001.geekbang.org/resource/image/29/9c/299bbd39759ca90bdc4953334bc0c39c.png)
似乎……不怎么样TPS并没有增加。
* **第二阶段:加副本**
我们再看加了CPU之后的全局POD监控
![](https://static001.geekbang.org/resource/image/92/94/925d14923a3bfac75ef84b9b21622294.png)
还是只有一个ES data的CPU使用率高所以我想查一下ES中的数据分布。因为负载均衡的问题解决了并且知道有三个ES data节点。现在我们就要知道是不是每个节点都被访问到了。
```
pms 0 p 10.100.18.199 _w 32 17690 18363 6.7mb 7820 true true 8.5.1 false
pms 0 p 10.100.18.199 _15 41 2110 0 465.7kb 5500 true true 8.5.1 true
pms 0 p 10.100.18.199 _16 42 21083 30255 9.5mb 5900 true true 8.5.1 false
pms 0 p 10.100.18.199 _17 43 2572 0 568kb 5500 true true 8.5.1 true
pms 0 p 10.100.18.199 _18 44 1403 0 322.9kb 5500 true true 8.5.1 true
pms 0 p 10.100.18.199 _19 45 1856 0 414.1kb 5500 true true 8.5.1 true
pms 0 p 10.100.18.199 _1a 46 1904 0 423kb 5500 true true 8.5.1 true
```
为啥数据都在一个节点上都是10.100.18.199)?看起来只有一个数据副本的原因了。
```
green open pms A--6O32bQaSBrJPJltOLHQ 1 0 48618 48618 55.1mb 18.3mb
```
所以我们先把副本数加上去因为我们有三个data节点所以这里加三个副本
```
PUT /pms/_settings
{
"number_of_replicas": 3
}
我们再次查看ES中的数据分布如下所示
pms 0 r 10.100.18.200 _w 32 17690 18363 6.7mb 7820 true true 8.5.1 false
pms 0 r 10.100.18.200 _15 41 2110 0 465.7kb 5500 true true 8.5.1 true
pms 0 r 10.100.18.200 _16 42 21083 30255 9.5mb 5900 true true 8.5.1 false
pms 0 r 10.100.18.200 _17 43 2572 0 568kb 5500 true true 8.5.1 true
pms 0 r 10.100.18.200 _18 44 1403 0 322.9kb 5500 true true 8.5.1 true
pms 0 r 10.100.18.200 _19 45 1856 0 414.1kb 5500 true true 8.5.1 true
pms 0 r 10.100.18.200 _1a 46 1904 0 423kb 5500 true true 8.5.1 true
pms 0 p 10.100.251.69 _w 32 17690 18363 6.7mb 7820 true true 8.5.1 false
pms 0 p 10.100.251.69 _15 41 2110 0 465.7kb 5500 true true 8.5.1 true
pms 0 p 10.100.251.69 _16 42 21083 30255 9.5mb 5900 true true 8.5.1 false
pms 0 p 10.100.251.69 _17 43 2572 0 568kb 5500 true true 8.5.1 true
pms 0 p 10.100.251.69 _18 44 1403 0 322.9kb 5500 true true 8.5.1 true
pms 0 p 10.100.251.69 _19 45 1856 0 414.1kb 5500 true true 8.5.1 true
pms 0 p 10.100.251.69 _1a 46 1904 0 423kb 5500 true true 8.5.1 true
pms 0 r 10.100.140.10 _w 32 17690 18363 6.7mb 7820 true true 8.5.1 false
pms 0 r 10.100.140.10 _15 41 2110 0 465.7kb 5500 true true 8.5.1 true
pms 0 r 10.100.140.10 _16 42 21083 30255 9.5mb 5900 true true 8.5.1 false
pms 0 r 10.100.140.10 _17 43 2572 0 568kb 5500 true true 8.5.1 true
pms 0 r 10.100.140.10 _18 44 1403 0 322.9kb 5500 true true 8.5.1 true
pms 0 r 10.100.140.10 _19 45 1856 0 414.1kb 5500 true true 8.5.1 true
pms 0 r 10.100.140.10 _1a 46 1904 0 423kb 5500 true true 8.5.1 true
```
我们接着压起来看看POD的资源
![](https://static001.geekbang.org/resource/image/11/cc/11ayy743164f36a8d0b04bc76af52ccc.png)
现在看着是不是开心多了data节点的CPU都用起来了。
我们再看一下worker的资源
```
[root@k8s-master-1 ~]# kubectl get pods -o wide | grep data
elasticsearch-data-0 1/1 Running 0 16m 10.100.18.199 k8s-worker-5 <none> <none>
elasticsearch-data-1 1/1 Running 0 17m 10.100.251.68 k8s-worker-9 <none> <none>
elasticsearch-data-2 1/1 Running 0 18m 10.100.140.9 k8s-worker-2 <none> <none>
```
现在ES Data的POD分布到2、5、9三这个worker上去了我们查看下全局监控
![](https://static001.geekbang.org/resource/image/53/b1/53a522a2754d7fcea550fde05cd791b1.png)
不错ES data的POD把资源用起来了。其实这里要想继续调还可以把CPU加大ES本来就是吃CPU、内存的大户。不过我们前面在配置的时候给ES data的CPU也确实太小了。这个问题并不是我故意设计出来的而是当时在部署的时候没考虑到这些。
最后,我们来看优化后的效果:
![](https://static001.geekbang.org/resource/image/1f/24/1fb93ff5yycfc2bb6049244820e73b24.png)
呀呀呀你看TPS压都压不住呀很快涨到900左右了这个优化结果很好。
现在回过头来看第一个阶段我们加CPU没有效果主要还是因为副本数量太少。其实在ES的优化中还有很多细节可以玩。只不过在我们这个课程中我希望给你的是一个整体的分析思路和逻辑而不是纠结于每个细节上的参数。所以在这里我们就不再说具体参数的调整了。
如果你想在ES上做更多的优化可以在分析完业务之后确定一下ES的架构、数据索引、分片等信息然后再来设计一个合理的ES部署。
## 总结
在这节课中我们看到APM工具也有无能为力的地方。所以说当我们分析到一个具体组件之后要想再往下分析就得靠自己的技术功底了。
在出现请求不均衡的时候我们一定要先去看负载均衡的逻辑有没有问题。当看到ES client不均衡时我们去看了iptables的原理在发现iptables只有一个转发规则的时候接下来要做的当然就是重刷转发规则了。
在ES client转发均衡了之后我们在ES data单节点上又看到CPU使用率过高。由于ES data在POD当中我们自然就要想到去看cgroup的限制。
而在添加了CPU之后我们发现TPS并没有提高这时候就要去看ES的逻辑了。ES的强大之处就在于多副本多分片的查询能力所以我们增加了副本之后CPU就用起来了这是一个合理的优化结果TPS也自然提高了。
经过一系列的动作,我们终于把资源给用起来了。这也是我一直在强调的,**性能优化第一个阶段的目标,就是把资源给用起来,然后再考虑更细节的优化**。
## 课后作业
最后,我给你留两道题,请你思考一下:
1. 当负载出现不均衡时,主要的分析方向是什么?
2. 什么时候才需要去看组件内部的实现逻辑?
记得在留言区和我讨论、交流你的想法,每一次思考都会让你更进一步。
如果你读完这篇文章有所收获,也欢迎你分享给你的朋友,共同学习进步。我们下一讲再见!