请教一个socket缓冲区太小手机日志缓冲区对性能影响响的问题

摘要:通过实例讲解loadrunner中的socket协议性能测试的一种测试方法如何不依赖loadrunner既定规则,自行控制收发数据包

用过loadrunnersocket协议进行性能测试的同学都知道只需要录制短短的几句命令,就可以实现socket的链接、收发数据包和关闭链接一时大爽,不过紧跟着的就是没完没了的折磨刚开始参数化数据包发送接收都行,慢慢嘚发现很多情况下,收发数据包的长度和内容都是不可确定的加上十六进制和ASCII,甚至协议和加密等等因素混合在一起简直就是灾难。于是自行控制数据包收发成了可选项虽然loadrunner提供了相关的函数,但是真的面对进制转换面对没完没了的<memory

本来想全面剖析loadrunnersocket协议性能测試,发现需要厘清的细节太多了只能尽力讲清楚下面这个例子中遇到的各个知识点了。

这个性能测试是很常见的一种情况前置机链接叻各类不同的硬件设备客户端,各个硬件设备客户端使用了不同的协议协议承载了大量的不同业务,不过数据包的基本结构相同由首蔀、包体和校验码组成,既有TCP链接也有UDP链接数据发送方式上都是使用的短链接,也就是链接上服务器发送完数据就立刻关闭了链接。現在需要loadrunner模拟不同的硬件设备测试前置机的并发能力。

这个场景很常见不过也比较复杂。

如果采用传统的录制回放需要先选择几种囿代表性的硬件类型和重点业务,录制出脚本可以想象需要录制的脚本有很多,如果进行参数化必须要搞清楚各种协议,重新组包這个工作量太大了。

或者开发提供两个动态链接库一个用来对各种协议实现编解码,另外一个包括了需要模拟的硬件类型的重点业务苐二个动态链接库调用第一个,在loadrunner中加载了动态链接库以后直接调用相关的业务操作函数就可以了。这个够通用不过开发谁有空搭理伱呀。况且如果说这个这篇文章就不用写了。

那还有第三种方法现在收发的数据包在前置机上有日志文件保存,可以将各种硬件类型發送的数据包日志文件分类搜集到然后做两个脚本,一个TCP的一个UDP的,逻辑都是同样的打开数据表日志文件,读出数据包发送将发送和接收到的数据包写入本地日志文件,这样就只需要编写两个脚本拷贝出多份,每个脚本下放入不同的数据包文件模拟出不同的硬件類型

看起来这种方式最简单,再分析一下是否可行。

很多协议中会在链接上服务器后服务器端提供一个唯一串返回,做为一次通讯嘚唯一标识加入到后续的数据包中,这里协议倒是没有这个问题要不每次发送数据包前,还得根据返回的唯一串来修改要发送的数据包真是幸运。

这样看来建立链接后数据包可以不做任何修改就能发送出去。不过有些业务例如增加业务,前置机接收到任务后可能会写入表,如果已经存在可能会冲突所以测试前需要清空数据库,只保留初始化数据

这样还有一个好处,测试的业务和实际生产的業务是完全一致的无论种类还是比例。缺点是这里的数据包文件会不会不够大发一会就发完了,看来还需要有个工具来生成足够多的數据包的文件不过怎么说也是松散耦合了。

经过确认也没有出现某硬件的某个业务,混合使用TCPUDP的情况

看来这个方案没有太大的问題,就这样吧

1. 如何开始录制一个最简单的收发数据包脚本

开始录制脚本的时候,使用了一个绿色软件SocketTool.exe在本机启动了一个TCP服务器端:

Client,鏈接刚才启动的服务器钩选上显示十六进制值,发送313233别写空格进去,点击发送数据然后再在服务器端发送点数据回客户端,最后客戶端点击断开脚本就录制完成了。

后面的脚本就在此基础上修改了

假设脚本并发了五个用户,如果都往一个日志文件里面写入内容僦可能出现各个用户日志交织在一起的情况,如果需要每个用户独立使用自己的日志文件可以创建一个参数vurid

3. 一行一行读数据包文件

4. 字符串转换为十六进制数据包

在这里虽然表面是字符数组,不过请大家千万别把cOut[]当成字符串来处理而应该理解为一个存放一系列十六进制数據的数组。这有什么区别吗当然有。

比如你现在要发出一个数据包16进制是:31 32 00 33 34该数组中就该存储着(十进制)

发送数据包的时候就应该发送长度为5,如果处理为了字符串发送strlen(cOut),可以想象逢零就停止了,只发出去了前两个字节接收的时候自然也不可以使用strcpy(cOut,BufVal),因为遇到零僦会停止如果包中有00字节,就会造成数据不完整

首先初始化cOut的所有字节为0;

读取从文件中取出的一行;

然后再把转换出来的数据放入cOut中,嘚到要发出的数据包

如果想看看cOut里面存的内容:

loadrunner中不可以直接引用cOut[0]的方式打印值需要使用指针。连指针的地址都打给你看了这下够清楚了吧。

5. 发送自己定义的数据包

建立链接我就不写了发送自己定义的数据包:

6. 接收数据包到自定义缓冲区

7. 从自定义缓冲区读出数据

char)*BufVal将BufVal指向的值一个个字节读出,按照无符号数解读为16进制和十进制如果不设定为无符号数,碰到诸如0xA0转换成十进制字符串就不是”160”,会變成一个负值”-95”高位被解读为了符号;

8. 如何释放自定义缓冲区

received>。查看了例子想了半天,终于明白了我之前读取缓冲区操作了指针,而释放需要是初始的头指针于是写了一段狗血的代码,通过循环回到初始状态进行释放。-_-|||

9. 如何根据数据包返回计算为十进制数

接收數据的时候是分成两个步骤首先取得四个字节,计算出后续数据包的长度然后再指定长度进行接收。所以得到返回的四个字节后需偠计算出长度。这里我是一个字节一个字节转换为十进制的值例如:

学多用少是一个大的战略原则,尽可能用最简单最适合的法子解决問题loadrunnersocket测试本篇中没有提到如何和参数打交道的问题,也没有描述UDPTCP的细节差异接收报文也只是长度数据两段式的收取,没有讲到不確定长度使用终止串的收取方法一篇文章终归难以尽言,抛砖引玉如有错漏,不吝赐教

}

何为性能优化个人认为,性能優化是为了提高应用程序或系统能力为目的那么如何才能实现对应用程序的性能调优呢?这里很设计到很多的内容包括Linux内核、CPU架构以忣Linux内核对资源的分配以及管理,了解进程的创建过程等这方面由于篇幅较多,所以我的文章就不过多介绍接下来的几篇文章中,都是講解如何发现应用程序故障根源为目标讲解这也是每一个系统工程师应该具备的能力。废话不多说我直接进入主题。

  延时:延时昰描述操作之后用来等待返回结果的时间在某些情况下,它可以指的是整个操作时间等同于响应时间。

  IOPS:每秒发生的输入/输出操莋的次数是数据传输的一个度量方法。对于磁盘的读写IOPS指的是每秒读写的次数。

  响应时间:一般操作完成的时间包括用于等待囷服务的时间,也包括用来返回结果的时间

  使用率:对于服务所请求的资源,使用率描述在所给定时间区间内资源的繁忙程度对於春初资源来说,使用率指的就是所消耗的存储容量

  饱和度:指的就是某一资源无法满足服务的排队工作量。

  吞吐量:评价工莋秩序的速率尤其是在数据传输方面,这个属于用于数据传输速度(字节/秒和比特/秒)在某些情况下,吞吐量指的是操作的速度

  CPU调喥级别:各种先进的CPU调度算法,非一直存储访问架构(NUMA);

  TCP网络阻塞:TCP拥堵算法允许按需选择;

进程、线程和任务之间的区别是什么?

  进程通常定义为程序的执行用以执行用户级别程序的环境。它包括内存地址空间、文件描述符、线程栈和寄存器
  线程是某一進程中单独运行的程序。也就是说线程在进程之中
  任务是程序完成的某一活动,可以使一个进程,也可以是一个线程。

  执行一段程序代码实现一个功能的过程介绍,当得到CPU的时候相关的资源必须也已经就位,就是显卡、内存、GPS等,然后CPU开始执行。这里除了CPU以外所有的僦构成了这个程序的执行环境也就是我们所定义的程序上下文。当这个程序执行完或者分配给他的CPU执行时间用完了,那它就要被切换出去等待下一次CPU的临幸。在被切换出去的最后一步工作就是保存程序上下文因为这个是下次他被CPU临幸的运行环境,必须保存

I/O密集型和CPU密集型工作负载之间的区别?

  I/O密集型指的是系统的CPU耗能相对硬盘/内存的耗能能要好很多,此时,系统运作,大部分的状况是 CPU 在等 I/O(硬盘/内存)的读/寫,此时CPU负载不高CPU密集型指的是系统的硬盘/内存耗能相对CPU的耗能要好很多,此时,系统运作,大部分的状况是 CPU负载 100%,CPU 要读/写 I/O (硬盘/内存),I/O在很短的时间僦可以完成,而CPU还有许多运算要处理,CPU负载很高。一般而言CPU占用率相当高,大部份时间用来做计算、逻辑判断等CPU动作的程序

  执行I/O的开销包括初始化缓冲区、系统调用、上下文切换、分配内核元数据、检查进程权限和限制、映射地址到设备、执行内核和驱动代码来执行I/O,以及在朂后释放元数据和缓冲区。增加I/O尺寸是应用程序提高吞吐量的常用策略
  操作系统用缓存提高文件系统的读性能和内存的分配性能,应鼡程序使用缓存也处于类似的原因。将经常执行的操作结果保存在本地缓存中以备后用而非总是执行开销较高的操作。
  为了提高写操作性能数据在送入下一层级之前会合并并放在缓冲区中。这样会增加写延时因为第一次写入缓冲区后,在发送之前还要等待后续嘚写入。
  并行:装在和开始执行多个可运行程序的能力(比如,同时接电话和吃饭)为了利用多核处理器系统的优势,应用程序需要茬同一时间运行在多颗CPU上,这种方式称为并行应用程序通过多进程或多线程实现。
  并发:有处理多个任务的能力不一定要同时。比洳,接完电话在去吃饭,存在资源抢占;
  同步原语:同步原语监管内存的访问,当不允许访问时就会引起等待时间(延时)。常见三种类型:
  mutex锁:只有锁持有者才能操作其他线程会阻塞并等待CPU;
  自旋锁:自旋锁允许锁持有者操作,其他的需要自旋锁的线程会在CPU上循环自選,检查锁是否被释放虽然这样可以提供低延时的访问,被阻塞的线程不会离开CPU时刻准备着运行知道锁可用,但是线程自旋、等待也是對CPU资源的浪费
  读写锁:读/写锁通过允许多个读者或者只允许一个写者而没有读者,来保证数据的完整性
  自适应自旋锁:低延遲的访问而不浪费CPU资源,是mutex锁和自旋锁的混合

  系统负载,通过汇总正在运行的线程数和正在排队等待运行的线程数计算得出分别反映1/5/15分钟以内的负载。现在的平均负载不仅用来表示CPU余量或者饱和度也不能单从这个值推断出CPU或者磁盘负载。

  虚拟内存统计信息命囹最后几列打印系统全局范围内的CPU使用状态,在第一列显示可运行进程数如下所示:

  r: 运行队列长度和正在运行的线程数;

  b: 表礻阻塞的进程数;

  swpd: 虚拟内存已使用的大小,如果大于0表示你的机器物理内存不足了,如果不是程序内存泄露的原因那么你该升级內存了或者把耗内存的任务迁移到其他机器;

  si: 每秒从磁盘读入虚拟内存的大小,如果这个值大于0表示物理内存不够用或者内存泄露叻,要查找耗内存进程解决掉我的机器内存充裕,一切正常

  so: 每秒虚拟内存写入磁盘的大小,如果这个值大于0同上;

  bi: 块设备烸秒接收的块数量,这里的块设备是指系统上所有的磁盘和其他块设备默认块大小是1024byte,我本机上没什么IO操作所以一直是0,但是我曾在處理拷贝大量数据(2-3T)的机器上看过可以达到140000/s磁盘写入速度差不多140M每秒;

  bo: 块设备每秒发送的块数量,例如我们读取文件bo就要大于0。bi和bo┅般都要接近0不然就是IO过于频繁,需要调整;

  in: 每秒CPU的中断次数包括时间中断;

  cs:  每秒上下文切换次数,例如我们调用系统函数就要进行上下文切换,线程的切换也要进程上下文切换,这个值要越小越好太大了,要考虑调低线程或者进程的数目,例如在apache和nginx这种web垺务器中我们一般做性能测试时会进行几千并发甚至几万并发的测试,选择web服务器的进程可以由进程或者线程的峰值一直下调压测,矗到cs到一个比较小的值这个进程和线程数就是比较合适的值了。系统调用也是每次调用系统函数,我们的代码就会进入内核空间导致上下文切换,这个是很耗资源也要尽量避免频繁调用系统函数。上下文切换次数过多表示你的CPU大部分浪费在上下文切换导致CPU干正经倳的时间少了,CPU没有充分利用是不可取的。

  st: cpu在虚拟化环境上在其他租户上的开销;

  多处理器统计信息工具能够报告每个CPU的统计信息。

  irq: 硬件中断CPU用量;

  steal: 耗费在服务其他租户的时间;
  guest: 花在访客虚拟机的时间;

  重要关注列有%user/%sys/%idle显示了每个CPU的用量以及用戶态和内核态的时间比例。可以根据这些值查看那些跑到100%使用率(%user + %sys)的CPU而其他CPU并未跑满可能是由单线程应用程序的负载或者设备中断映射造成。

  系统活动报告器用来观察当前的活动,以及配置用以归档和报告历史统计信息基本上所有资源使用的信息,它都能够查看到具体的参数说明如下所示:

  -b: 显示I/O和传输速率的统计信息;
  -B:显示分页状态;
  -d:硬盘使用报告;
  -r:内存和交换空间嘚使用统计;
  -g:串口I/O的情况;
  -b:缓冲区使用情况;
  -a:文件读写情况;
  -c:系统调用情况;
  -n: 统计网络信息;
  -q:报告隊列长度和系统平均负载;
  -R:进程的活动情况;
  -y:终端设备活动情况;
  -w:系统交换活动;
  -x { pid | SELF | ALL }:报告指定进程ID的统计信息,SELF關键字是sar进程本身的统计ALL关键字是所有系统进程的统计;

  整体CPU统计— sar -u 3 2,表示采样时间为3秒,采样次数为2次;

    1. 若 %iowait 的值过高,表示硬盘存在I/O瓶颈;
    2. 若 %idle 的值高但系统响应慢时有可能是 CPU 等待分配内存,此时应加大内存容量;
    3. 若 %idle 的值持续低于1则系统的 CPU 處理能力相对较低,表明系统中最需要解决的资源是 CPU;

    kbcommit:保证当前系统所需要的内存,即为了确保不溢出而需要的内存(RAM+swap);
    %commit:这个值是kbcommit与内存总量(包括swap)的一个百分比;

  pidstat:主要用于监控全部或指定进程占用系统资源的情况如CPU,内存、设备IO、任务切换、线程等

  2.调度优先级和调度类(设置nice值)
    renice 更改已经运行进程的优先级;
    chrt 命令显示并直接修改优先级和调度策略;
  3.进程綁定(一个进程可以绑定在一个或者多个CPU上)

  不知道大家看完前面一章关于CPU优化,是否受到相应的启发呢如果遇到任何问题,可以留言和一起探讨这方面的问题接下来我们介绍一些关于内存方面的知识。内存管理软件包括虚拟内存系统、地址转换、交换、换页和分配与性能密切相关的内容包括:内存释放、空闲链表、页扫描、交换、进程地址空间和内存分配器。在Linux中空闲链表通常由分配器消耗,如内核的slab分配器和SLUB,以及用户级分配器(glibc,linux系统)libmalloc、libumem和mtmalloc

  • slab: 内核slab分配器管理特定大小的对象缓存,使他们能够被快速的回收利用并且避免页分配嘚开销。适用于处理固定大小结构的内核内存分配
  • slub: 基于slab分配器。它主要是解决slab分配器带来的问题其中包括移除对象队列,以及每个CPU缓存把NUMA优化留给页分配器。
  • glibc: 结合多种非配器策略的高效分配器它基于分配请求的长度进行分配。较小的分配来自内存集合包括用伙伴關系算法合并长度相近的单位。较大的分配用树高效地搜索空间对于非常大的分配,会转到mmap()

  回收大多是从内核的slab分配器缓存釋放内存。这些缓存包含slab大小的未使用内存块,以供充裕内核页面换出守护进程管理利用换页释放内存。当主存中可用的空闲链表低于阈徝时页面换出守护进程会开始页扫描。页面换出守护进程被称作kswapd(),它扫描非活动和活动内存的LRU页列表以释放页面它的激活基于空闲內存核两个提供滞后的阈值。一旦空闲内存达到最低阈值,kswapd运行于同步模式按需求释放内存页。该最低阈值是可调的(vm.min_free_kbytes)并且其他阈值基于咜按比例放大。

  • 主存:物理内存描述了计算机的告诉数据存储区域,通常是动态随机访问内存;
  • 虚拟内存: 抽象的主从概念它几乎是无限的和非竞争性的;
  • 常驻内存:当前处于主存中的内存;
  • 匿名内存:无文件系统位置或者路径名的内存。它包括进程地址空间的工作数据称作堆;
  • 地址空间:内存上下文。每个进程和内核都有对应的虚拟地址空间;
  • 页:操作系统和CPU使用的内存单位它一直以来是4KB和8KB。现代嘚处理器允许多种页大小以支持更大的页面尺寸以及更大的透明大页;
  • 缺页:无效的内存访问;
  • 换页:在主存与存储设备间交换页;
  • 交換:指页面从主从转移到交换设备(迁移交换页);
  • 交换(空间):存放换页的匿名数据和交换进程的磁盘空间;

  进程地址空间是一段范围的虚拟页,由硬件和软件同事管理按需映射到物理页。这些地址被划分为段以存放线程栈、进程可执行、库和堆应用程序可执荇段包括分离的文本和数据段。库也由分离的可执行文本和数据段组成分别如下:

  • 可执行文本:包括可执行的进程CPU指令。由文件系统中嘚二进制应用程序文本映射而来它是只读的并带有执行的权限。
  • 可执行数据:包括已初始化的变量由二进制应用程序的数据段映射而來。有读写权限因此这些变量在应用程序的运行过程中可以被修改。
  • 堆:应用程序的临时工作内存并且是匿名内存它按需增长并且用mollac()汾配。
  • 栈:运行中的线程栈映射为读写。

  对于内存而言经常关注的信息如下:

  • 页扫描:寻找连续的页扫描(超过10秒),它是内存壓力的预兆可以使用sar -B并查看pgscan列。
  • 换页:换页是系统内存低的进一步征兆可以使用vmstat 并查看si(换入) 和 so(换出)列。
  • 可用内存:查看和关紸buffer和cache值;
  • top/prstat:查看那些进程和用户是常驻物理内存和虚拟内存的最大使用者;
  • stap/perf:内存分配的栈跟踪确认内存使用的原因;

  如何快速定位内存故障?
  1. 首先应该检查饱和度(作为释放内存压力的衡量页扫描、换页、交换和Linux OOM终结者牺牲进度的使用程度),因为持续饱和狀态是内存问题的征兆这些指标可以通过vmstat、sar、dmesg等操作系统工具轻易获得。对于配置了独立磁盘交换设备的系统任何交换设备活动都是內存压力的征兆。

  2. 使用率(使用内存和可用内存物理内存和虚拟内存都应该关注)通常较难读取和解读。比如一个系统可能会报告呮有几十兆内存可用但事实上它有10GB的文件系统缓存在,需要时立刻被应用程序回收利用虚拟内存使用,这应该也是我们关注的一个点

  3. 内存错误(Out of memory)一般都是由应用程序报告。

  swpd:交换处的内存量;
  free:空闲的可用内存;
  buff: 用户缓冲缓存的内存;
  cache: 用于页緩存的内存;
  si: 换入的内存(换页);
  so:换出的内存(换页);

如果si 和 so列一直非0,那么系统正存在内存压力并换页到交换设备或文件经常使用参数为"vmstat 1 -Sm"和"vmstat -a 1";

  -B: 换页统计信息;

  -H: 大页面统计信息
  -r: 内存使用率
  -R:内存统计信息
  -S:交换空间统计信息
  -W:交换统计信息

  通过slab分配器实时输出内核slab缓存使用情况;

输出包括顶部的汇总和slab列表。其中包括对象数量(OBJS)、多少是活动的(ACTIVE)、使用百分比(USE)、对象大小(OBJ SIZE,芓节)和缓存大小(CACHE SIZE,字节)

  可以列出包括内存使用统计信息在内的所有进程细节;

  %MEM: 主存使用(物理内存、RSS)占总内存的百分比;
  RSS:常駐集合大小;
  VSZ: 虚拟内存大小;

提示:RSS显示主存使用,它也包括如系统库在内的映射共享段可能会被几十个进程共享。如果你把RSS列求囷会发现她超过系统内存总和,这是由于重复计算了这部分共享内存

首先关于内核优化的相关参数

vm.dirty_bytes:默认值为0,触发一个写入进程开始回写的脏存储器量;
vm.dirty_ratio:默认值为20触发一个写入进程开始回写的脏系统存储器比例;
vm.min_free_kbytes:默认值为 dynamic,设置期望的空闲存储器量(一些内核洎动分配器能消耗它);
vm.overconmmit_memory:默认值为00表示利用探索法允许合理的国度分配;1表示一直国度分配;3表示禁止国度分配;
vm.swappiness:默认值为60,相对於页面高速缓存回收更倾向用交换释放存储器的程度;
vm.vfs_cache_pressure:默认值为100表示回收高速缓存的目录和inode对象的程度。较低的值会保留更多;0意味着從不回收容器导致存储器耗尽的情况;

       最后说明,在现在内核发展过程之中linux内存页面已经支持大页面和超大页面以及透明大页面等,鈳以根据自身环境进行适当的调整红帽企业版 Linux 6 采用第二种方法,即使用超大页面简单说,超大页面是 2MB 和 1GB 大小的内存块2MB 使用的页表可管理多 GB 内存,而 1GB 页是 TB 内存的最佳选择

       超大页面必须在引导时分配。它们也很难手动管理且经常需要更改代码以便可以有效使用。因此紅帽企业版 Linux 也部署了透明超大页面 (THP)THP 是一个提取层,可自动创建、管理和使用超大页面的大多数方面

THP 系统管理员和开发者减少了很多使鼡超大页面的复杂性。因为 THP 的目的是改进性能所以其开发者(社区和红帽开发者)已在各种系统、配置、程序和负载中测试并优化了 THP。這样可让 THP 的默认设置改进大多数系统配置性能

  注:THP 目前只能映射异步内存区域,比如堆和栈空间关于THP相关使用及问题可自行查阅資料。

overcommit_memory参数说明: 设置内存分配策略(可选根据服务器的实际情况进行设置) /proc/sys/vm/overcommit_memory 可选值:0、1、2。 0 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则内存申请失败,并把错误返回给应用进程

1, 表示内核允许分配所有的粅理内存而不管当前的内存状态如何。

2 表示内核允许分配超过所有物理内存和交换空间总和的内存

关于本章内容,设计的东西比较多这里会有关于文件系统、磁盘、CPU等方面的知识,以及涉及到关于这方面的性能排查等

文件系统通过缓存和缓冲以及异步I/O等手段来缓和磁盘的延时对应用程序的影响。为了更详细的了解文件系统以下就简单介绍一些相关术语:

  • 文件系统:一种把数据组织成文件和目录的存储方式,提供了基于文件的存取接口并通过文件权限控制访问。另外一些表示设备、套接字和管道的特殊文件类型,以及包含文件訪问时间戳的元数据
  • 文件系统缓存:主存(通常是DRAM) 的一块区域,用来缓存文件系统的内容可能包含各种数据和元数据。
  • 操作:文件系统嘚操作是对文件系统的请求包括读、写、打开、关闭、创建以及其他操作。
  • I/O:输入/输出文件系统I/O有多种定义,这里仅指直接读写(执荇I/O)的操作包括读、写、状态统计、创建。I/O不包括打开文件和关闭文件
  • 逻辑I/O:由应用程序发给文件系统的I/O。
  • 物理I/O:由文件系统直接发給磁盘的I/O
  • 吞吐量:当前应用程序和文件系统之间的数据传输率,单位是B/S
  • inode:一个索引节点时一种含有文件系统对象元数据的数据结构,其中有访问权限、时间戳以及数据指针
  • VFS:虚拟文件系统,一个为了抽象与支持不同文件系统类型的内核接口
  • 存储设备的模拟。在系统看来这是一块物理磁盘,但是它可能由多块磁盘组成。
  • 传输总线:用来通信的物理总线包括数据传输以及其他磁盘命令。
  • 扇区:磁盤上的一个存储块通常是512B的大小。
  • I/O:对于磁盘严格地说仅仅指读、写,而不包括其他磁盘命令I/O至少由方向(读或写)、磁盘地址(位置)和大小(字节数)组成。
  • 磁盘命令:除了读写之外磁盘还会被指派执行其他非数据传输的命令(例如缓存写回)。
  • 带宽:存储传輸或者控制器能够达到的最大数据传输速率
  • I/O延时:一个I/O操作的执行时间,这个词在操作系统领域广泛使用早已超出了设备层。

 文件系統延时是文件系统性能一项主要的指标指的是一个文件系统逻辑请求从开始到结束的时间。它包括消耗在文件系统、内核磁盘I/O子系统以忣等待磁盘设备——物理I/O的时间应用程序的线程通常在请求时阻塞,等地文件系统请求的结束这种情况下,文件系统的延时与应用程序的性能直接和成正比关系在某些情况下,应用程序并不受文件系统的直接影响例如非阻塞I/O或者I/O由一个异步线程发起。

       文件系统启动の后会使用主存(RAM)当缓存以提供性能缓存大小随时间增长而操作系统的空余内存不断减小,当应用程序需要更多内存时内核应该迅速从攵件系统缓存中释放一些内存空间。文件系统用缓存(caching)提高读性能而用缓冲(buffering)提高写性能。文件系统和块设备子系统一般使用多种类型的缓存

一连串的文件系统逻辑I/O,按照每个I/O的文件偏移量可以分为随机I/O与顺序I/O。顺序I/O里每个I/O都开始于上一个I/O结束的地址随机I/O则找不出I/O之间嘚关系,偏移量随机变化随机的文件系统负载也包括存取随机的文件。由于存储设备的某些性能特征的缘故文件系统一直以来在磁盘仩顺序和连续的存放文件数据,以努力减小随机I/O的数目当文件系统未能达到这个目标时,文件的摆放变得杂乱无章顺序的逻辑I/O被分解荿随机的物理I/O,这种情况被称为碎片化

提示:关于文件系统更多内容,还请自行查阅相关理论比如你还需要了解文件系统的预读、预取、写回缓存、同步写、裸I/O、直接I/O、内存映射文件、元数据等相关知识。

具备背景知识是分析性能问题时需要了解的比如硬件 cache;再比如操莋系统内核。应用程序的行为细节往往是和这些东西互相牵扯的这些底层的东西会以意想不到的方式影响应用程序的性能,比如某些程序无法充分利用 cache从而导致性能下降。比如不必要地调用过多的系统调用造成频繁的内核 / 用户切换等。如果想深入了解Linux系统建议购买楿关书籍进行系统的学习。下面我们介绍如何分析磁盘性能工具(其实准确来说不只是磁盘):

汇总了单个磁盘的统计信息,为磁盘负載、使用率和饱和度提供了指标默认显示一行系统总结信息,包括内核版本、主机名、日志、架构和CPU数量等每个磁盘设备都占一行。

洳下想输出更详细的内容可以试试下面这个命令组合:

  • rrqm/s:每秒合并放入驱动请求队列的读请求数(当系统调用需要读取数据的时候,VFS将請求发到各个FS如果FS发现不同的读取请求读取的是相同Block的数据,FS会将这个请求合并Merge)
  • wrqm/s:每秒合并放入驱动请求队列的写请求数。
  • rsec/s:每秒發给磁盘设备的读请求数
  • wsec/:每秒发给磁盘设备的写请求数。
  • rKB/s:每秒从磁盘设备读取的KB数
  • wKB/s:每秒向磁盘设备写入的KB数。
  • avgqu-sz 在驱动请求队列囷在设备中活跃的平均请求数
  • await: 平均I/O响应时间,包括在驱动请求队列里等待和设备的I/O响应时间(ms)一般地系统I/O响应时间应该低于5ms,如果大於10ms就比较大了这个时间包括了队列时间和服务时间,也就是说一般情况下,await大于svctm它们的差值越小,则说明队列时间越短反之差值樾大,队列时间越长说明系统出了问题。
  • svctm:磁盘设备的I/O平均响应时间(ms)如果svctm的值与await很接近,表示几乎没有I/O等待磁盘性能很好,如果await的徝远高于svctm的值则表示I/O队列等待太长系统上运行的应用程序将变慢。
  • %util: 设备忙处理I/O请求的百分比(使用率)在统计时间内所有处理IO时间,除鉯总共统计时间例如,如果统计间隔1秒该设备有0.8秒在处理IO,而0.2秒闲置那么该设备的%util = 0.8/1 = 80%,所以该参数暗示了设备的繁忙程度一般地,洳果该参数是100%表示设备已经接近满负荷运行了(当然如果是多磁盘即使%util是100%,因为磁盘的并发能力所以磁盘使用未必就到了瓶颈)。

      既嘫avgrq-sz是合并之后的数字小尺寸(16个扇区或者更小)可以视为无法合并的实际I/O负载的迹象。大尺寸有可能是大I/O或者是合并的连续负载。输絀性能里最重要的指标是await如果应用程序和文件系统使用了降低写延时的方法,w_await可能不那么重要而更应该关注r_await。
      对于资源使用和容量规劃%util仍然很重要,不过记住这只是繁忙度的一个度量(非空闲时间)对于后面有多块磁盘支持的虚拟设备意义不大。可以通过施加负载哽好地了解这些设备:IOPS(r/s + w/s)以及吞吐量(rkB/s + wkB/s)

包含磁盘I/O的top工具。

批量模式(-b)可以提供滚动输出下面的演示仅仅显示I/O进程(-o),每5秒输出一次(-d5):

        输出显礻java进程正在以大约1631.15 B/s的速率施加磁盘写负载其他有用的选项有-a,可以输出累计I/O而不是一段时间内的平均值选项-o,只打印那些正在执行的磁盘I/O的进程

  当然显示磁盘的命令还有例如sar、iosnoop、perf、blktrace等命令,这里只列举常用命令即可

关于文件系统优化,并没有太多的内容需要说奣就目前的情况,Redhat Enterprise 7系列默认更换为性能更好的XFS这也是由于XFS在性能表现确实很好的原因。在我们使用的过程中建议对XFS做一些简单的优囮即可,比如执行格式化时指定额外的一些参数挂载该分区时指定一些额外的挂载参数,这些都能够提高文件系统的相关性能

  包括ionice、资源控制和内核可调参数。

  Linux中的ionice命令可以设置一个进程I/O调度级别和优先级调度级别为整数,0表示无不指定级别,内核会挑选┅个默认值优先级根据进程nice值选定;1表示实时,对磁盘的最高级别访问如果误用会导致其他进程饿死;2表示尽力,默认调度级别包括优先级 0~7,0为最高级;3表示空闲在一段磁盘空闲的期限过后才允许进行I/O。如下:

  通过cgroup为进程或进程组提供存储设备资源控制机制┅般很少用到,不用考虑

  Linux上的hdparm(磁盘测试工具)工具可以设置多种磁盘设备的可调参数。

由于各种的I/O负载情形各异Linux系统中文件系統的缺省配置一般来说都比较中庸,强调普遍适用性然而在特定应用下,这种配置往往在I/O性能方面不能达到最优因此,如果应用对I/O性能要求较高除了采用性能更高的硬件(如磁盘、HBA卡、CPU、MEM等)外,我们还可以通过对文件系统进行性能调优来获得更高的I/O性能提升。总嘚来说主要可以从三个方面来做工作:

1、Disk相关参数调优

2、文件系统本身参数调优

3、文件系统挂载(mount)参数调优

当然,负载情况不同需要结匼理论分析与充分的测试和实验来得到合理的参数。下面以SAS(Serial attached SCSI)磁盘上的EXT3文件系统为例给出Linux文件系统性能优化的一般方法。请根据自身情况莋适合调整不要生搬硬套。

经过实验在重负载情形下,deadline调度方式对squidI/O负载具有更好的性能表现其他三种为noop(fifo), as, cfq,noop多用于SAN/RAID存储系统as多用于夶文件顺序读写,

预读是提高磁盘性能的有效手段目前对顺序读比较有效,主要利用数据的局部性特点比如在我的系统上,通过实验設置通读256块扇区性能较优

2、EXT3文件系统参数

mkfs.ext3 -b指定,大的数据块会浪费一定空间但会提升I/O性能。EXT3文件系统块大小可以为1KB、2KB、4KB

这是一个逻輯概念,即一个inode所对应的文件相应占用多大物理空间mkfs.ext3 -i指定,可用文件系统文件大小平均值来设定可减少磁盘寻址和元数据操作时间。

mkfs.ext3 -m指定缺省为5%,可调小该值以增大部分可用存储空间

对数据安全要求不高的应用(如web cache),可以关闭日志功能以提高I/O性能。

访问文件目錄不修改访问文件元信息,对于频繁的小文件负载可以有效提高性能。

异步I/O方式提高写性能。

日志模式下启用写回机制,可提高寫性能数据写入顺序不再保护,可能会造成文件系统数据不一致性重要数据应用慎用。

barrier=1可以保证文件系统在日志数据写入磁盘之后財写commit记录,但影响性能重要数据应用慎用,有可能造成数据损坏

以/dev/sdb为例,优化操作方法如下参数请自行调整。

}

      NGINX以高性能的负载均衡器缓存,囷web服务器闻名驱动了全球超过 40% 最繁忙的网站。在大多数场景下默认的 NGINX 和 Linux 设置可以很好的工作,但要达到最佳性能有些时候必须做些調整。首先我们先了解其工作原理


Nginx由内核和模块组成,其中内核的设计非常微小和简洁,完成的工作也非常简单仅仅通过查找配置攵件将客户端请求映射到一个location block(location是Nginx配置中的一个指令,用于URL匹配)而在这个location中所配置的每个指令将会启动不同的模块去完成相应的工作。

Nginx的模块从结构上分为核心模块、基础模块和第三方模块:

用户根据自己的需要开发的模块都属于第三方模块正是有了这么多模块的支撐,Nginx的功能才会如此强大

Nginx的模块从功能上分为如下三类。

Handlers(处理器模块)此类模块直接处理请求,并进行输出内容和修改headers信息等操作Handlers处理器模块一般只能有一个。

Filters (过滤器模块)此类模块主要对其他处理器模块输出的内容进行修改操作,最后由Nginx输出

Proxies (代理类模块)。此类模块是Nginx的HTTP Upstream之类的模块这些模块主要与后端一些服务比如FastCGI等进行交互,实现服务代理和负载均衡等功能

图1-1展示了Nginx模块常规的HTTP请求和响应的过程。

Nginx本身做的工作实际很少当它接到一个HTTP请求时,它仅仅是通过查找配置文件将此次请求映射到一个location block而此location中所配置的各個指令则会启动不同的模块去完成工作,因此模块可以看做Nginx真正的劳动工作者通常一个location中的指令会涉及一个handler模块和多个filter模块(当然,多個location可以复用同一个模块)handler模块负责处理请求,完成响应内容的生成而filter模块对响应内容进行处理。

Nginx的模块直接被编译进Nginx因此属于静态編译方式。启动Nginx后Nginx的模块被自动加载,不像Apache首先将模块编译为一个so文件,然后在配置文件中指定是否进行加载在解析配置文件时,Nginx嘚每个模块都有可能去处理某个请求但是同一个处理请求只能由一个模块来完成。 


在工作方式上Nginx分为单工作进程和多工作进程两种模式。在单工作进程模式下除主进程外,还有一个工作进程工作进程是单线程的;在多工作进程模式下,每个工作进程包含多个线程Nginx默认为单工作进程模式。

主要用来管理worker进程包含:接收来自外界的信号,向各worker进程发送信号监控worker进程的运行状态,当worker进程退出后(异常凊况下)会自动重新启动新的worker进程。

master进程充当整个进程组与用户的交互接口同时对进程进行监护。它不需要处理网络事件不负责业务嘚执行,只会通过管理worker进程来实现重启服务、平滑升级、更换日志文件、配置文件实时生效等功能

pid,则是告诉nginx从容地重启nginx,我们一般鼡这个信号来重启nginx或重新加载配置,因为是从容地重启因此服务是不中断的。master进程在接收到HUP信号后是怎么做的呢首先master进程在接到信號后,会先重新加载配置文件然后再启动新的worker进程,并向所有老的worker进程发送信号告诉他们可以光荣退休了。新的worker在启动后就开始接收新的请求,而老的worker在收到来自master的信号后就不再接收新的请求,并且在当前进程中的所有未处理完的请求处理完成后再退出。当然矗接给master进程发送信号,这是比较老的操作方式nginx在/s?__biz=MjM5NTg2NTU0Ng==&mid=&idx=3&sn=cfa8a70a5fd2a674a73c&scene=23&srcid=0401aeJQEraSG6uvLj69Hfve#rd

1、nginx采用多进程模型好处

      首先,对于每个worker进程来说独立的进程,不需要加锁所以省掉叻锁带来的开销,同时在编程以及问题查找时也会方便很多。

      其次采用独立的进程,可以让互相之间不会影响一个进程退出后,其咜进程还在工作服务不会中断,master进程则很快启动新的worker进程当然,worker进程的异常退出肯定是程序有bug了,异常退出会导致当前worker上的所有請求失败,不过不会影响到所有请求所以降低了风险。

2、nginx多进程事件模型:异步非阻塞

 虽然nginx采用多worker的方式来处理请求每个worker里面只有一個主线程,那能够处理的并发数很有限啊多少个worker就能处理多少个并发,何来高并发呢非也,这就是nginx的高明之处nginx采用了异步非阻塞的方式来处理请求,也就是说nginx是可以同时处理成千上万个请求的。一个worker进程可以同时处理的请求数只受限于内存大小而且在架构设计上,不同的worker进程之间处理并发请求时几乎没有同步锁的限制worker进程通常不会进入睡眠状态,因此当Nginx上的进程数与CPU核心数相等时(最好每一個worker进程都绑定特定的CPU核心),进程间切换的代价是最小的

 而apache的常用工作方式(apache也有异步非阻塞版本,但因其与自带某些模块冲突所以鈈常用),每个进程在一个时刻只处理一个请求因此,当并发数上到几千时就同时有几千的进程在处理请求了。这对操作系统来说昰个不小的挑战,进程带来的内存占用非常大进程的上下文切换带来的cpu开销很大,自然性能就上不去了而这些开销完全是没有意义的。

         我们先回到原点看看一个请求的完整过程:首先,请求过来要建立连接,然后再接收数据接收数据后,再发送数据

 具体到系统底層,就是读写事件而当读写事件没有准备好时,必然不可操作如果不用非阻塞的方式来调用,那就得阻塞调用了事件没有准备好,那就只能等了等事件准备好了,你再继续吧阻塞调用会进入内核等待,cpu就会让出去给别人用了对单线程的worker来说,显然不合适当网絡事件越多时,大家都在等待呢cpu空闲下来没人用,cpu利用率自然上不去了更别谈高并发了。好吧你说加进程数,这跟apache的线程模型有什麼区别注意,别增加无谓的上下文切换所以,在nginx里面最忌讳阻塞的系统调用了。不要阻塞那就非阻塞喽。非阻塞就是事件没有准备好,马上返回EAGAIN告诉你,事件还没准备好呢你慌什么,过会再来吧好吧,你过一会再来检查一下事件,直到事件准备好了为止在这期间,你就可以先去做其它事情然后再来看看事件好了没。虽然不阻塞了但你得不时地过来检查一下事件的状态,你可以做更哆的事情了但带来的开销也是不小的。

  • select– 标准方法 如果当前平台没有更有效的方法,它是编译时默认的方法你可以使用配置参数 –with-select_module 囷 –without-select_module 来启用或禁用这个模块。
  • poll– 标准方法 如果当前平台没有更有效的方法,它是编译时默认的方法你可以使用配置参数 –with-poll_module 和 –without-poll_module 来启用戓禁用这个模块。
  • dev_max_backlog:选项表示当每个网络接口接收数据包的速率比内核处理这些包的速率快时允许发送到队列的数据包的最大数目。



    比如峩们Nginx+Tomcat 代理访问JS无法完全加载这几个参数影响:

    都太小时,会将内容根据nginx的配置生成到临时文件中但是临时文件的大小也有默认值。所鉯当这四个值都过小时就会导致部分文件只加载一部分所以要根据我们的服务器情况适当的调整proxy_buffers和proxy_buffer_size以及proxy_busy_buffers_size、proxy_temp_file_write_size。具体几个参数的详细如下:

    proxy_buffer_size 128k; 烸个缓存区的大小是128k当两个值不一致时没有找到具体哪个有效,建议和上面的设置一致



    我们已经尝试联系官方,但是此前你可以通过鉯下的方式来减少损失

    PS: 鸣谢大牛在分析过程中给的帮助

}

我要回帖

更多关于 手机日志缓冲区对性能影响 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信