Bootstrap

linux 系统优化

TCP 连接优化


路由转发模式
net.ipv4.ip_forward = 1

net.ipv4.tcp_fin_timeout = 30
如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。对端可以出错并永远不关闭连接,甚至意外当机。缺省值是60 秒。

net.ipv4.tcp_max_syn_backlog = 10240
表示SYN队列的长度,默认为1024,加大队列长度为10240,可以容纳更多等待连接的网络连接数。

net.ipv4.tcp_keepalive_time = 1200
表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。

net.ipv4.ip_local_port_range = 1024 65000
表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。

UDP 连接优化

net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
修改UDP 缓冲区大小

系统初始化参数优化

1) 关闭防火墙、selinux
2) 配置合理的yum源
3) 关闭不需要的系统服务
4) 内核优化:
echo "ulimit -SHn 102400" >> /etc/rc.local
cat >> /etc/security/limits.conf << EOF
    *           soft   nofile       102400
    *           hard   nofile       102400
    *           soft   nproc        102400
    *           hard   nproc        102400
EOF
系统磁盘优化
1)  磁盘分区方案
分区类型     分区的实际大小
/           1G-2G
/boot       32M-100M (启动分区,最多只要100M左右)
/opt        100M-1G (附加应用程序)
/tmp        40M-1000M
/home       2G-10G (如果需要单独分区。)
/usr        3G-10G 最少要500M左右,一般宽松的服务器要分到4-6G)
/usr/local  3G-15G (自已安装程序安装在此)
/var        >2G–硬盘余下全部空间 ( 最少300M-500M,一般2-3G,做服务器的话把上面余下的空间都分给它)
swap    物理内存的两倍(参考值)
2) 物理磁盘优化
 - raid 阵列选择
 - lvm逻辑卷选择
 - 磁盘类型选择
   - ext2:linux下标准文件系统,无日志记录(inode)功能
   - ext3:在ext2基础上增加了日志记录功能(inode),仅支持32000个目录
   - ext4: ext3的后续版本,linux2.6.28内核开始支持,无限子目录支持,快速fsck
   - xfs:高性能文件系统,linux3.10内核开始默认支持
读操作频繁:ext4 
写操作频繁:xfs
 
3) xfs 优化
格式化时的参数:
mkfs.xfs -d agcount=256 -l size=128m,lazy-count=1,version=2 /dev/diska1
挂载时的参数:
defaults,noatime,nodiratime,nobarrier,discard,allocsize=256m,logbufs=8,attr2,logbsize=256k
 
4) swap 分区优化
/proc/sys/vm/swappiness
当系统非常需要使用内存时,内核会把匿名内存(Anonymous memory)和System V的共享内存(shared memory)交换到磁盘上去,而真正的文件不需要交换到交换内存上去,而是直接写会到磁盘文件系统上(清掉page cache)。
调低/proc/sys/vm/swappiness时,核心倾向于不交换,主要用于更快的响应速度。如:apache、mysql
调高/proc/sys/vm/swappiness时,核心倾向于使用交换内存,主要用于繁忙的吞吐量。如:ftp
参数说明:
rrqm/s:每秒合并放入驱动请求队列的读请求数(当系统调用需要读取数据的时候,VFS将请求发到各个FS,如果FS发现不同的读取请求读取的是相同Block的数据,FS会将这个请求合并Merge)。
wrqm/s:每秒合并放入驱动请求队列的写请求数。
rsec/s:每秒发给磁盘设备的读请求数。
wsec/:每秒发给磁盘设备的写请求数。
rKB/s:每秒从磁盘设备读取的KB数。
wKB/s:每秒向磁盘设备写入的KB数。
avgrq-sz 平均每次请求大小,单位为扇区(512B)。
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)。
1) procs:
- r列表示运行和等待cpu时间片的进程数,这个如果长期大于系统cpu个数,说明cpu不足,需要增加cpu
- b列表示在等待资源的进程数,比如等待I/O,或者内存交换等
 
2) procs标准:    r 不超过cpu进程数
3) swap标准:    si,so长期不为0,说明内存不足,需要加内存
4) io标准:    bi+bo超过1000,而且wa值较高,说明磁盘IO有问题,应提高磁盘读写性能
5) system标准:    
- us长期超过50%,用户进程消耗cpu,需要考虑优化程序或算法
- sy长期超过50%,内核消耗的cpu资源很多
- us+sy长期超过80%,说明可能cpu资源部足
- id cpu空闲的百分比
- wa 参考值20%,如果超过20%,说明io等待严重
cpu重点:r    cs  us  sy id  wa值的大小

tomcat 优化

优化内存,主要是在bin/catalina.bat/sh 配置文件中进行。linux上,在catalina.sh中添加:


JAVA_OPTS="-server -Xms1G -Xmx2G -Xss256K -Djava.awt.headless=true -Dfile.encoding=utf-8 -XX:MaxPermSize=256m -XX:PermSize=128M -XX:MaxPermSize=256M"



其中
• -server:启用jdk的server版本。
• -Xms:虚拟机初始化时的最小堆内存。
• -Xmx:虚拟机可使用的最大堆内存。 #-Xms与-Xmx设成一样的值,避免JVM因为频繁的GC导致性能大起大落
• -XX:PermSize:设置非堆内存初始值,默认是物理内存的1/64。
• -XX:MaxNewSize:新生代占整个堆内存的最大值。
• -XX:MaxPermSize:Perm(俗称方法区)占整个堆内存的最大值,也称内存最大永久保留区域。

这些以后再看,先看优化的!

1)错误提示:java.lang.OutOfMemoryError:Java heap space
Tomcat默认可以使用的内存为128MB,在较大型的应用项目中,这点内存是不够的,有可能导致系统无法运行。常见的问题是报Tomcat内存溢出错误,Outof Memory(系统内存不足)的异常,从而导致客户端显示500错误,一般调整Tomcat的-Xms和-Xmx即可解决问题,通常将-Xms和-Xmx设置成一样,堆的最大值设置为物理可用内存的最大值的80%。

set JAVA_OPTS=-Xms512m-Xmx512m

2)错误提示:java.lang.OutOfMemoryError: PermGenspace
PermGenspace的全称是Permanent Generationspace,是指内存的永久保存区域,这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGenspace中,它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGenspace进行清理,所以如果你的应用中有很CLASS的话,就很可能出现PermGen space错误,这种错误常见在web服务器对JSP进行precompile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了。解决方法:

setJAVA_OPTS=-XX:PermSize=128M

3)在使用-Xms和-Xmx调整tomcat的堆大小时,还需要考虑垃圾回收机制。如果系统花费很多的时间收集垃圾,请减小堆大小。一次完全的垃圾收集应该不超过3-5 秒。如果垃圾收集成为瓶颈,那么需要指定代的大小,检查垃圾收集的详细输出,研究垃圾收集参数对性能的影响。一般说来,你应该使用物理内存的 80% 作为堆大小。当增加处理器时,记得增加内】存,因为分配可以并行进行,而垃圾收集不是并行的。

1、JVM参数调优:

-Xms表示JVM初始化堆的大小,-Xmx表示JVM堆的最大值。这两个值的小一般根据需要进行设置。当应用程序需要的内存超出堆的最大值时虚拟机就会提示内存溢出,并且导致应用服务崩溃。因此一般建议堆的最大值设置为可用内存的最大值的80%。在catalina.bat中,设置JAVA_OPTS='-Xms256m -Xmx512m',表示初始化内存为256MB,可以使用的最大内存为512MB。

2、调整线程数


通过应用程序的连接器(Connector)进行性能控制的的参数是创建的处理请求的线程数。Tomcat使用线程池加速响应速度来处理请求。在Java中线程是程序运行时的路径,是在一个程序中与其它控制线程无关的、能够独立运行的代码段。它们共享相同的地址空间。多线程帮助程序员写出CPU最大利用率的高效程序,使空闲时间保持最低,从而接受更多的请求。
Tomcat4中可以通过修改minProcessors和maxProcessors的值来控制线程数。这些值在安装后就已经设定为默认值并且是足够使用的,但是随着站点的扩容而改大这些值。minProcessors服务器启动时创建的处理请求的线程数应该足够处理一个小量的负载。也就是说,如果一天内每秒仅发生5次单击事件,并且每个请求任务处理需要1秒钟,那么预先设置线程数为5就足够了。但在你的站点访问量较大时就需要设置更大的线程数,指定为参数maxProcessors的值。maxProcessors的值也是有上限的,应防止流量不可控制(或者恶意的服务攻击),从而导致超出了虚拟机使用内存的大小。如果要加大并发连接数,应同时加大这两个参数。web server允许的最大连接数还受制于操作系统的内核参数设置,通常Windows是2000个左右,Linux是1000个左右。
在Tomcat5对这些参数进行了调整,请看下面属性:
maxThreads Tomcat使用线程来处理接收的每个请求。这个值表示Tomcat可创建的最大的线程数。
acceptCount 指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理。
connnectionTimeout 网络连接超时,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。通常可设置为30000毫秒。
minSpareThreads Tomcat初始化时创建的线程数。
maxSpareThreads 一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程。
最好的方式是多设置几次并且进行测试,观察响应时间和内存使用情况。在不同的机器、操作系统或虚拟机组合的情况下可能会不同,而且并不是所有人的web站点的流量都是一样的,因此没有一刀切的方案来确定线程数的值。


Tomcat作为Web服务器,它的处理性能直接关系到用户体验,下面是几种常见的优化措施:

一、掉对web.xml的监视,把jsp提前编辑成Servlet。有富余物理内存的情况,加大tomcat使用的jvm的内存

二、服务器资源
服务器所能提供CPU、内存、硬盘的性能对处理能力有决定性影响。
  (1) 对于高并发情况下会有大量的运算,那么CPU的速度会直接影响到处理速度。
  (2) 内存在大量数据处理的情况下,将会有较大的内存容量需求,可以用-Xmx -Xms -XX:MaxPermSize等参数对内存不同功能块进行划分。我们之前就遇到过内存分配不足,导致虚拟机一直处于full GC,从而导致处理能力严重下降。
  (3) 硬盘主要问题就是读写性能,当大量文件进行读写时,磁盘极容易成为性能瓶颈。最好的办法还是利用下面提到的缓存。

三、利用缓存和压缩
对于静态页面最好是能够缓存起来,这样就不必每次从磁盘上读。这里我们采用了Nginx作为缓存服务器,将图片、css、js文件都进行了缓存,有效的减少了后端tomcat的访问。
  另外,为了能加快网络传输速度,开启gzip压缩也是必不可少的。但考虑到tomcat已经需要处理很多东西了,所以把这个压缩的工作就交给前端的Nginx来完成。
  除了文本可以用gzip压缩,其实很多图片也可以用图像处理工具预先进行压缩,找到一个平衡点可以让画质损失很小而文件可以减小很多。曾经我就见过一个图片从300多kb压缩到几十kb,自己几乎看不出来区别。

四、采用集群
单个服务器性能总是有限的,最好的办法自然是实现横向扩展,那么组建tomcat集群是有效提升性能的手段。我们还是采用了Nginx来作为请求分流的服务器,后端多个tomcat共享session来协同工作。

五、 优化tomcat参数
这里以tomcat7的参数配置为例,需要修改conf/server.xml文件,主要是优化连接配置,关闭客户端dns查询。

<Connector port="8080"   
           protocol="org.apache.coyote.http11.Http11NioProtocol"  
           connectionTimeout="20000"  
           redirectPort="8443"   
           maxThreads="500"   
           minSpareThreads="20"  
           acceptCount="100" 
           disableUploadTimeout="true" 
           enableLookups="false"   
           URIEncoding="UTF-8" /> 

mysql 优化

sql方面

  • 合理利用索引,并清除无效索引
  • SQL语句中的IN包含的值不要过多
  • SELECT 的时候必须制定字段名称,防止查询数据时过度消耗系统性能
  • 当只需要一条数据的时候,使用limit1,这是为了使EXPLAIN中type列达到const类型
  • 如果限制条件中其他字段没有索引,尽量少用or
  • 尽量用union all代替union
  • 使用合理的分页方式以提高分页的效率 例如select id,name from product limit 866613, 20 有时数据量过大的表,分页查询不合理,反而会导致查询变慢。
  • 避免默认填充null 并避免在 where 子句中对字段进行 null 值判断 ,因为null的判断会导致引擎放弃使用索引而去进行全局扫描。 可以使用explain 查看索引使用情况。
  • 不建议使用%前缀模糊查询 例如LIKE “%name”或者LIKE “%name%”,这种查询会导致索引失效而进行全表扫描。但是可以使用LIKE “name%”。

        这种情况可以使用全局索引 语法

        ALTER TABLE dynamic_201606 ADD FULLTEXT INDEX idx_user_name (user_name);

        关于JOIN优化

        LEFT JOIN A表为驱动表INNER JOIN MySQL会自动找出那个数据少的表作用驱动表RIGHT JOIN B表为驱动表

        注意:MySQL中没有full join,可以用以下方式来解决

        select * from A left join B on B.name = A.namewhere B.name is nullunion allselect * from B;

        尽量使用inner join,避免left join

 配置方面

  • 修改innodb_buffer_pool_cache 设置mysql使用内存大小,防止内存溢出。
  • 修改wait_timeout参数值,默认为8小时。 MySQL客户端的数据库连接闲置最大时间值。
  • 修改max_connections参数值,默认为151,可以改为3000多。 MySql的最大连接数
  • 修改max_user_connections值,由默认的0,修改为800 指每个数据库用户的最大连接
  • 修改back_log参数值:由默认的50修改为500 。指出在MySQL暂时停止回答新请求之前的短时间内多少个请求可以被存在堆栈中。

back_log值指出在MySQL暂时停止回答新请求之前的短时间内多少个请求可以被存在堆栈中。也就是说,如果MySql的连接数据达到max_connections时,新来的请求将会被存在堆栈中,以等待某一连接释放资源,该堆栈的数量即back_log,如果等待连接的数量超过back_log,将不被授予连接资源。将会报:unauthenticated user | xxx.xxx.xxx.xxx | NULL | Connect | NULL | login | NULL 的待连接进程时.

back_log值不能超过TCP/IP连接的侦听队列的大小。若超过则无效,查看当前系统的TCP/IP连接的侦听队列的大小命令:cat /proc/sys/net/ipv4/tcp_max_syn_backlog目前系统为1024。对于Linux系统推荐设置为小于512的整数。

查看mysql 当前系统默认back_log值,命令:

show variables like 'back_log'; 查看当前数量

  • 修改thread_concurrency值,由目前默认的8,修改为64

        thread_concurrency的值的正确与否, 对mysql的性能影响很大, 在多个cpu(或多核)的情况下,错误设置了thread_concurrency的值, 会导致mysql不能充分利用多cpu(或多核), 出现同一时刻只能一个cpu(或核)在工作的情况。

  • 添加skip-name-resolve,默认被注释掉,没有该参数。

        skip-name-resolve:禁止MySQL对外部连接进行DNS解析,使用这一选项可以消除MySQL进行DNS解析的时间。但需要注意,如果开启该选项,则所有远程主机连接授权都要使用IP地址方式,否则MySQL将无法正常处理连接请求

  • skip-networking,默认被注释掉。没有该参数 。应该注释,确保数据库安全,根据实际的场景判断是否开启。

        开启该选项可以彻底关闭MySQL的TCP/IP连接方式,如果WEB服务器是以远程连接的方式访问MySQL数据库服务器则不要开启该选项!否则将无法正常连接!

  • key_buffer_size

        key_buffer_size是用于索引块的缓冲区大小,增加它可得到更好处理的索引(对所有读和多重写),对MyISAM(MySQL表存储的一种类型,可以百度等查看详情)表性能影响最大的一个参数。

;