Linux性能优化实战
倪朋飞
微软资深工程师,Kubernetes项目维护者
立即订阅
23324 人已学习
课程目录
已完结 64 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (2讲)
开篇词 | 别再让Linux性能问题成为你的绊脚石
免费
01 | 如何学习Linux性能优化?
CPU 性能篇 (13讲)
02 | 基础篇:到底应该怎么理解“平均负载”?
03 | 基础篇:经常说的 CPU 上下文切换是什么意思?(上)
04 | 基础篇:经常说的 CPU 上下文切换是什么意思?(下)
05 | 基础篇:某个应用的CPU使用率居然达到100%,我该怎么办?
06 | 案例篇:系统的 CPU 使用率很高,但为啥却找不到高 CPU 的应用?
07 | 案例篇:系统中出现大量不可中断进程和僵尸进程怎么办?(上)
08 | 案例篇:系统中出现大量不可中断进程和僵尸进程怎么办?(下)
09 | 基础篇:怎么理解Linux软中断?
10 | 案例篇:系统的软中断CPU使用率升高,我该怎么办?
11 | 套路篇:如何迅速分析出系统CPU的瓶颈在哪里?
12 | 套路篇:CPU 性能优化的几个思路
13 | 答疑(一):无法模拟出 RES 中断的问题,怎么办?
14 | 答疑(二):如何用perf工具分析Java程序?
内存性能篇 (8讲)
15 | 基础篇:Linux内存是怎么工作的?
16 | 基础篇:怎么理解内存中的Buffer和Cache?
17 | 案例篇:如何利用系统缓存优化程序的运行效率?
18 | 案例篇:内存泄漏了,我该如何定位和处理?
19 | 案例篇:为什么系统的Swap变高了(上)
20 | 案例篇:为什么系统的Swap变高了?(下)
21 | 套路篇:如何“快准狠”找到系统内存的问题?
22 | 答疑(三):文件系统与磁盘的区别是什么?
I/O 性能篇 (10讲)
23 | 基础篇:Linux 文件系统是怎么工作的?
24 | 基础篇:Linux 磁盘I/O是怎么工作的(上)
25 | 基础篇:Linux 磁盘I/O是怎么工作的(下)
26 | 案例篇:如何找出狂打日志的“内鬼”?
27 | 案例篇:为什么我的磁盘I/O延迟很高?
28 | 案例篇:一个SQL查询要15秒,这是怎么回事?
29 | 案例篇:Redis响应严重延迟,如何解决?
30 | 套路篇:如何迅速分析出系统I/O的瓶颈在哪里?
31 | 套路篇:磁盘 I/O 性能优化的几个思路
32 | 答疑(四):阻塞、非阻塞 I/O 与同步、异步 I/O 的区别和联系
网络性能篇 (13讲)
33 | 关于 Linux 网络,你必须知道这些(上)
34 | 关于 Linux 网络,你必须知道这些(下)
35 | 基础篇:C10K 和 C1000K 回顾
36 | 套路篇:怎么评估系统的网络性能?
37 | 案例篇:DNS 解析时快时慢,我该怎么办?
38 | 案例篇:怎么使用 tcpdump 和 Wireshark 分析网络流量?
39 | 案例篇:怎么缓解 DDoS 攻击带来的性能下降问题?
40 | 案例篇:网络请求延迟变大了,我该怎么办?
41 | 案例篇:如何优化 NAT 性能?(上)
42 | 案例篇:如何优化 NAT 性能?(下)
43 | 套路篇:网络性能优化的几个思路(上)
44 | 套路篇:网络性能优化的几个思路(下)
45 | 答疑(五):网络收发过程中,缓冲区位置在哪里?
综合实战篇 (13讲)
46 | 案例篇:为什么应用容器化后,启动慢了很多?
47 | 案例篇:服务器总是时不时丢包,我该怎么办?(上)
48 | 案例篇:服务器总是时不时丢包,我该怎么办?(下)
49 | 案例篇:内核线程 CPU 利用率太高,我该怎么办?
50 | 案例篇:动态追踪怎么用?(上)
51 | 案例篇:动态追踪怎么用?(下)
52 | 案例篇:服务吞吐量下降很厉害,怎么分析?
53 | 套路篇:系统监控的综合思路
54 | 套路篇:应用监控的一般思路
55 | 套路篇:分析性能问题的一般步骤
56 | 套路篇:优化性能问题的一般方法
57 | 套路篇:Linux 性能工具速查
58 | 答疑(六):容器冷启动如何性能分析?
加餐篇 (4讲)
加餐(一) | 书单推荐:性能优化和Linux 系统原理
加餐(二) | 书单推荐:网络原理和 Linux 内核实现
用户故事 | “半路出家 ”,也要顺利拿下性能优化!
用户故事 | 运维和开发工程师们怎么说?
结束语 (1讲)
结束语 | 愿你攻克性能难关
Linux性能优化实战
登录|注册

26 | 案例篇:如何找出狂打日志的“内鬼”?

倪朋飞 2019-01-18
你好,我是倪朋飞。
前两节,我们学了文件系统和磁盘的 I/O 原理,我先带你复习一下。
文件系统,是对存储设备上的文件进行组织管理的一种机制。为了支持各类不同的文件系统,Linux 在各种文件系统上,抽象了一层虚拟文件系统 VFS。
它定义了一组所有文件系统都支持的数据结构和标准接口。这样,应用程序和内核中的其他子系统,就只需要跟 VFS 提供的统一接口进行交互。
在文件系统的下层,为了支持各种不同类型的存储设备,Linux 又在各种存储设备的基础上,抽象了一个通用块层。
通用块层,为文件系统和应用程序提供了访问块设备的标准接口;同时,为各种块设备的驱动程序提供了统一的框架。此外,通用块层还会对文件系统和应用程序发送过来的 I/O 请求进行排队,并通过重新排序、请求合并等方式,提高磁盘读写的效率。
通用块层的下一层,自然就是设备层了,包括各种块设备的驱动程序以及物理存储设备。
文件系统、通用块层以及设备层,就构成了 Linux 的存储 I/O 栈。存储系统的 I/O ,通常是整个系统中最慢的一环。所以,Linux 采用多种缓存机制,来优化 I/O 的效率,比方说,
为了优化文件访问的性能,采用页缓存、索引节点缓存、目录项缓存等多种缓存机制,减少对下层块设备的直接调用。
同样的,为了优化块设备的访问效率,使用缓冲区来缓存块设备的数据。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Linux性能优化实战》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(29)

  • hua168
    大神,能问一个题外话吗,关于自己人生规划,水平和眼界所限,想不通,
    都说大神级见识很广也多,能给我这个35岁只维护过四五十台linux服务器的运维指条路吗?
    现在很迷茫和压力大~~
    能力如下:
    一.网络:CCNA水平,自过了CCNP忘记了,当过2年网管
    二、维护过asp.net电商网站,3年,只有简单的,兼职网管
    三、linux运维,只在一家电商做了3年多,会
    1.web:nginx、tomcat配置(少用)+php:nignx的rewirte和反代
    2.数据库:mysql、mongoDB、redis 配置及主从,不会mycat、Cetus之类
    3.反代:会nginx、haproxy简单配置
    4.存储:NFS、fastDFS、hadoop简单看了一下
    5.版本控制:只会git及搭建gitlab+jenkins(简单的CI/CD)
    6.监控:简单配置zabbix+shell脚本
    7.虚拟化:kvm安装及配置、docker(k8s还没学)
    8.云计算:openstack只会安装做过实验
    9.测试:只会ab工具
    10.日志:ELK安装配置,还没结合java(在学中)
    11.大数据:没使用过(不会flume、storm、spark、flink、kafka)
    12.脚本:主要是shell为主、会点python

    四、编程能力:自学,没项目经验
    1.前端:
      1)HTML(HTML5不怎看)
      2)css(laiui、学了一下vue)
      3) js、jquery框架、ES6简单看了一下
    2.PHP:语法简单的thinkphp5框架
    3.java:考虑要维护java web在学
    只看了java、jsp及servet、spring、springMVC、spring Boot(这个为主)
    4.python:考虑运维用到
    python:会简单的脚本
    django:只会官网简单的

    问题是:现在已35岁了,失业,怎办?年龄摆在那里,能力好像不强,学历大专。
    能给个建议吗?非常感谢~~

    作者回复: 看前面的经历,技术面还是挺广的,但可能很多地方都不太深入。

    建议还是先找份工作吧,长期待业可能会加重焦虑。然后可以根据实际工作需要,先把工作需要的知识技能加深掌握。等到可以从容应对工作的时候,再考虑在某个领域加强深入。

    2019-01-19
    3
    39
  • Christmas
    pcstat(page cache stat)这个可以查看目标log文件在cache中的大小

    作者回复: 嗯嗯 是的,并且这个工具需要知道哪个文件

    2019-01-18
    12
  • 无名老卒
    查看buffer/cache占用,建议使用pcstat或者hcache,hcache是基于pcstat的,pcstat可以查看某个文件是否被缓存和根据进程pid来查看都缓存了哪些文件。hcache在其基础上增加了查看整个操作系统Cache和根据使用Cache大小排序的特性。

    [root@linjx ~]# hcache --top 3
    +--------------------------+----------------+------------+-----------+---------+
    | Name | Size (bytes) | Pages | Cached | Percent |
    |--------------------------+----------------+------------+-----------+---------|
    | /usr/bin/containerd | 44250880 | 10804 | 10804 | 100.000 |
    | /usr/bin/dockerd-ce | 81622264 | 19928 | 8319 | 041.745 |
    | /usr/bin/containerd-shim | 4972896 | 1215 | 1215 | 100.000 |
    +--------------------------+----------------+------------+-----------+---------+
    2019-01-22
    8
  • 划时代
    指出老师的一个问题,“日志回滚文件”,打印日志的过程中从直觉来看很容易误认为日志是在“回滚”,我也犯过这样的错误;rotating英文直译为“旋转”或“轮流”,实际的日志打印过程中,日志名称是“旋转”的,例如log.1(当前打印的日志文件并且一直会打印这个文件),log.2(较早日志),log.3(更早日志),当触发“旋转”条件时,日志名称会发生变更,假如log.3是上限数,那么log.3发生“旋转”就被remove,log.2被rename为log.3。更形象一点的描述是,日志名称发生了滚动,log.1=>log.2=>log.3不断的更新。

    作者回复: 谢谢指出,确实只是文件名称的旋转,内容并没有回滚

    2019-01-18
    8
  • 郭江伟
    buffers/cached使用情况可以从proc文件系统看:
    gjw@gjw:~$ cat /proc/meminfo
    MemTotal: 7588504 kB
    MemFree: 3621800 kB
    MemAvailable: 6335912 kB
    Buffers: 473920 kB
    Cached: 2491192 kB
    2019-01-18
    7
  • 我来也
    [D26打卡]
    又是老套路了,哈哈。
    先是top看%iowait到升高,再看pidstat是哪个进程在操作磁盘,再strace看进程的调用栈。
    看/proc/meminfo就可以看到系统的buffer和cache各占了多少吧。前后一对比就知道是谁了。😄
    2019-01-18
    6
  • J
    logger.info(message)的情况下,还可以使用logger.setLevel修改日志级别吗?

    作者回复: 可以的,比如调高到警告级别,那么 info() 实际上就不写了

    2019-01-20
    2
  • 小老鼠
    我觉的应该是cache,写日志,日志是文件
    2019-01-20
    2
  • Geek_41dcba
    在回答今天的思考题前,我想需要明确两个前提,一个是Buffer到底在整个系统结构的哪一层,会不会是不是在IO调度器的下一层,我想应该会,理由是Buffer缓存磁盘内容调度器合并后再去写磁盘效率更好;另一个是之前有看到留言对于文件系统使用带Cache的IO操作底层为了性能Buffer和Cache是合并的,如果是这样那我就从逻辑上认为它们是分开的,这样好回答问题(声明我没看过底层代码都是没有代码依据的)。 我认为增长的地方都在Buffer里面,Cache里面的内容可以经过IO调度器整理后放Buffer,没有理由说磁盘阻塞,Cache就不能移动到Buffer 查看数据的地方在/proc/meminfo。

    上面的都想法今天没有时间验证,要明天了!

    作者回复: 嗯 可以实际操作验证一下

    2019-01-18
    2
  • wtcctw
    逻辑清晰,步骤详细,赞
    2019-01-18
    2
  • 张洁
    老师,你好。测试中遇到的情况跟你说的不太一样。
    iostat -d -x 1得到的结果
    %util达到99%,IOPS 90,吞吐量 700KB/S,响应时间 10ms,平均等待队列1.1;
    top 看到iowait 30%,不到60%;
    并发数增加,cpu、内存使用率都没有增加,磁盘使用率99%;
    如何判断出磁盘是否已经达到了饱和?对于这个结果,我不能分析出磁盘是否达到了瓶颈。
    是否可以指点下?可否利用磁盘最大的IOPS来判断是否磁盘达到了瓶颈?谢谢!
    2019-10-17
    1
  • 小苏
    strace -p 18923
    Process 18923 attached
    futex(0x7fbe2c2e39d0, FUTEX_WAIT, 18924, NULL
    我好像对每个进程执行该命令都会卡在这地方.这个命令基本上用不上,不知道怎么回事.
    2019-08-18
    1
  • hinimix
    老师,代码里怎么写能接受sigusr这个参数呢,现在每次改级别我都是改配置文件然后重启

    作者回复: 不同编程语言都有相应的库函数可以调用。案例中Python的使用方法可以参考https://github.com/feiskyer/linux-perf-examples/blob/master/logging-app/app.py#L47

    2019-07-19
    1
    1
  • 小肥皂酱
    老师,我运行docker run -v /tmp:/tmp --name=app -itd feisky/logapp 这个命令几秒后这个进程就不在了。怎么回事呢

    作者回复: 应该是退出了,docker logs app看看是什么错误信息

    2019-04-12
    1
    1
  • 安小依
    Ubuntu 16.04, 使用 strace 应该需要先临时修改系统一个配置:echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope。另外用 java 模拟写文件,strace 发现还是不行,一直卡在这个地方:

    zk@zk-pc:~/Documents$ strace -p 6526
    strace: Process 6526 attached
    futex(0x7f934a93a9d0, FUTEX_WAIT, 6527, NULL

    老师帮忙看一下,Java 源代码如下。注释掉的部分 System.out 是疯狂打日志 (标准输出),线上环境出现过,疯狂 println 结果磁盘打满的问题,想模拟一下,结果发现不行。然后换成了写文件,结果 strace 还是看不出来,卡在那个地方一直不动:

        public static void main(String...args) throws Exception {
            File file = new File("/tmp/aaa");
            PrintWriter printWriter = new PrintWriter(file);

            while (true) {
                printWriter.write(UUID.randomUUID().toString());
                // System.out.println("------------------------------NULL-------------------");
                LockSupport.parkNanos(1);
            }
        }

    另外问一下老师,一直向标准输出打印的话,最终的那个文件是放在哪里呢了?怎么就把磁盘打满了呢?

    作者回复: 你这个例子是向文件 /tmp/aaa 写,不是标准输出

    2019-01-18
    1
  • 汤🐠🥣昱
    老师,我用linux的一个1核的 内存1G的服务器,没有出现io瓶颈的问题,通过top命令到是发现了cpu使用率飚到93%,64.5 us, 29.2 sy。这是是trace跟踪的情况:怎么反应不了是io的问题尼?
    mmap(NULL, 393220096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)
    munmap(0x7f2cc8098000, 314576896) = 0
    write(2, "--- Logging error ---\n", 22) = 22
    stat("/usr/local/lib/python3.7/logging/handlers.py", {st_mode=S_IFREG|0644, st_size=57674, ...}) = 0
    write(2, "Traceback (most recent call last"..., 35) = 35
    write(2, " File \"/usr/local/lib/python3.7"..., 108) = 108
    write(2, " File \"/usr/local/lib/python3.7"..., 122) = 122
    write(2, "MemoryError\n", 12) = 12
    write(2, "Call stack:\n", 12) = 12
    stat("/app.py", {st_mode=S_IFREG|0664, st_size=1289, ...}) = 0
    write(2, " File \"/app.py\", line 52, in <m"..., 63) = 63
    write(2, " File \"/app.py\", line 43, in wr"..., 65) = 65
    mmap(NULL, 314576896, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2cc8098000
    mmap(NULL, 393220096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)
    munmap(0x7f2cc8098000, 314576896) = 0
    write(2, "Unable to print the message and "..., 119) = 119
    select(0, NULL, NULL, NULL, {0, 100000}) = 0 (Timeout)
    getpid() = 1
    mmap(NULL, 314576896, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2cc8098000
    mmap(NULL, 393220096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)
    munmap(0x7f2cc8098000, 314576896) = 0
    write(2, "--- Logging error ---\n", 22) = 22
    stat("/usr/local/lib/python3.7/logging/handlers.py", {st_mode=S_IFREG|0644, st_size=57674, ...}) = 0
    write(2, "Traceback (most recent call last"..., 35) = 35
    write(2, " File \"/usr/local/lib/python3.7"..., 108) = 108
    write(2, " File \"/usr/local/lib/python3.7"..., 122) = 122
    write(2, "MemoryError\n", 12) = 12
    write(2, "Call stack:\n", 12) = 12

    2019-10-22
  • Shane
    老师,我今天才看完这篇文章。想要提几个问题,不知道该专栏过了这么长时间了,还会不会被老师看到。不过还是提着把,万一看到并且回复了呢?

    有一点困惑难以理解?在运行app.py命令之后,使用top查看时,发现cpu的wait使用率在80,90徘徊。

    但是top下面的python进程的cpu使用率只有6%。

    在我的理解中,现在总的cpu使用率是1 - idle。也就是90%左右。其中大量都是wait,sys之占用了6%左右。

    但是,top下面所有进程的使用率总和不是应该是1-idle,90%左右吗?难道所有的进程的cpu使用率的总和和上面的不是相等的吗?

    如果不是相等的,我还想到了一种可能是: 进程显示的是所有cpu的使用率,某一个进程的使用率应该会超过100%(如果有多个逻辑核心)。还是不应该出现总和小于上面的总cpu使用率的情况吧??

    希望老师答疑解惑。

    作者回复: 请参考 05 篇,有对这个问题的详细讲解

    2019-10-20
  • 老师你好,make init后一直报错连不上mysql是为啥呢?
    curl http://127.0.0.1:10000/db/insert/products/10000后报错:
    pymysql.err.OperationalError: (2003, &quot;Can't connect to MySQL server on '127.0.0.1' ([Errno 111] Connection refused)&quot;)
    实际是起来了的

    作者回复: 可能mysql还没初始化好,重启一下mysql容器试试

    2019-08-20
  • 飞鸟
    老师好, 我前段时间我们生产集群 遇到过 jbd2引起IO过高,导致kudu 平均负载超载,严重影响正常的读写,当时我定位到了是 jbd2导致的, 可是我不知改咋办,最后无奈,停掉作业重启了Kudu。 对这个问题我不知改如何解决, 老师指点指点。
    2019-08-19
  • lisi
    cachetop
    2019-06-26
收起评论
29
返回
顶部