Tomcat,Weblogic,Redis等应用优化汇总

一、 Tomcat优化

  1. 禁用tomcat的AJP协议

在服务状态页面中可以看到,默认状态下会启用AJP服务,并且占用8009端口。

在这里插入图片描述
在这里插入图片描述
注释:
可以看到AJP服务不存在了。

2. 使用线程池提高性能

在tomcat中每一个用户请求都是一个线程,所以可以使用线程池提高性能。

vim server.xml

<!‐‐将注释打开‐‐>

<!‐‐

参数说明:

maxThreads:最大并发数,默认设置 200,一般建议在 500 ~ 1000,根据硬件设施和业务来判断

minSpareThreads:Tomcat 初始化时创建的线程数,默认设置 25

prestartminSpareThreads: 在 Tomcat 初始化的时候就初始化 minSpareThreads 的参数值,如果不等于 true,minSpareThreads
的值就没啥效果了

maxQueueSize,最大的等待队列数,超过则拒绝请求

‐‐>

<!‐‐在Connector中设置executor属性指向上面的执行器‐‐>

保存退出,重新启动,查看效果。

3. Tomcat的3种运行方式(nio,bio,apr)

tomcat默认采用的BIO模型,在几百并发下性能会有很严重的下降。tomcat自带还有NIO的模型,另外也可以调用APR的库来实现操作系统级别控制。

NIO模型是内置的,调用很方便,只需要将上面配置文件中protocol修改成org.apache.coyote.http11.Http11NioProtocol,重启即可生效。上面配置我已经改过了,默认的是HTTP/1.1。

APR则需要安装第三方库,在高并发下会让性能有明显提升。安装完成后重启即可生效。如使用默认protocal就是apr,但最好把将protocol修改成org.apache.coyote.http11.Http11AprProtocol,会更加明确。

改为apr模式

protocol="org.apache.coyote.http11.Http11AprProtocol"

配置APR

1)安装APR tomcat-native

apr-1.3.8.tar.gz 安装在/usr/local/apr

#tar zxvf

apr-1.3.8.tar.gz

#cd apr-1.3.8

#./configure;make;make install

apr-util-1.3.9.tar.gz 安装在/usr/local/apr/lib

#tar zxvf  apr-util-1.3.9.tar.gz

#cd  apr-util-1.3.9  

#./configure

–with-apr=/usr/local/apr ----with-java-home=JDK;make;make install

#cd

apache-tomcat-6.0.20/bin

#tar zxvf

tomcat-native.tar.gz

#cd

tomcat-native/jni/native

#./configure

–with-apr=/usr/local/apr;make;make install

(2)设置 Tomcat 整合 APR

修改 tomcat 的启动 shell (startup.sh),在该文件中加入启动参数:

CATALINA_OPTS="$CATALINA_OPTS
-Djava.library.path=/usr/local/apr/lib" 。

(3)判断安装成功:

如果看到下面的启动日志,表示成功。

  2007-4-26

15:34:32 org.apache.coyote.http11.Http11AprProtocol init

推荐使用nio,不过,在tomcat
8中有最新的nio2,速度更快,建议使用nio2.

设置nio2:,修改server.xml,将原来8080端口的Connector修改为:

<Connector
executor=“tomcatThreadPool” port=“8080” protocol=“org.apache.coyote.http11.Http11Nio2Protocol” connectionTimeout="20000"redirectPort=“8443” />

4. 禁用DNS查询

当web应用程序向要记录客户端的信息时,它也会记录客户端的IP地址或者通过域名服务器查找机器名 转换为IP地址。

DNS查询需要占用网络,并且包括可能从很多很远的服务器或者不起作用的服务器上去获取对应的IP的过程,这样会消耗一定的时间。

修改server.xml文件中的Connector元素,修改属性enableLookups参数值: enableLookups=“false”

如果为true,则可以通过调用request.getRemoteHost()进行DNS查询来得到远程客户端的实际主机名,若为false则不进行DNS查询,而是返回其ip地址

5. JVM调优生产配置

编辑catalina.sh配置文件

vim /app/tomcat8/bin/catalina.sh 

$var must be set to either true or false.下面添加

JAVA_HOME=/usr/java/jdk1.8 CATALINA_HOME=/app/tomcat8
JAVA_OPTS="-server -Xms4096m -Xmx16g -Xss1024K -XX:MetaspaceSize=128m
-XX:MaxMetaspaceSize=1024m
-Dmdm.home=/app/weblogic12/wls12213/user_projects/domains/base_domain/conf"

6. 设置session过期时间

conf\web.xml中通过参数指定:

<session-config>           <session-timeout>180</session-timeout>            </session-config> 单位为分钟。

二、 weblogic优化

1、Weblogic启动过慢问题

1)在Tomcat环境中解决

可以通过配置JRE使用非阻塞的Entropy Source。

在catalina.sh中加入这么一行:-Djava.security.egd=file:/dev/./urandom
即可。

加入后再启动Tomcat,整个启动耗时下降到Server startup in 2912 ms。

2)在JVM环境中解决

修改Linux上Weblogic使用的jdk $JAVA_HOME/jre/lib/security/java.security文件 将 securerandom.source=file:/dev/urandom 修改为
securerandom.source=file:/dev/./urandom

经测试:在JVM环境中解决比较有效。

2、免密码登录

1、 编辑口令文件

在刚才创建的域目录下建立boot.properties文件,内容为:

username=weblogic password=weblogic123

2、编辑启动管理服务器的文件

在刚才创建的域目录下的bin目录中创建startAdminServer.sh,内容为:

./startWebLogic.sh

3、 编辑启动代理服务器的文件

在刚才创建的域目录下的bin目录中创建startProxyServer.sh,内容为:

./startManagedWebLogic.sh
Proxy_Server http://10.68.156.40:7001

4、编辑启动受管理服务器(ManagedServer_a)的文件

在刚才创建的域目录下的bin目录中创建startManagedServer_1.sh,内容为:

./startManagedWebLogic.sh
Managed_Server_1 http://10.68.156.40:7001

(注:Proxy_Server, Managed_Server_a名称一定要和规划的名称一致。)

5、注意:新创建的.sh文件一定要先加权限再运行,否则会提示权限不够

chmod 777 filename

后台启动

nohup ./startManagedWebLogic.sh &

3、设置weblogic集群自启动

在etc目录下编辑rc.local文件

cd /etc vi rc.local

在文件末尾添加如下代码

su – weblogic –c “ nohup
/home/weblogic/wls12213/user_projects/domains/base_domain

/startWebLogic.sh &”

  1. 优化weblogic的JVM

每个weblogic server 都是运行在一个java虚拟机上 ,对weblogic的内存设置也就是对java虚拟机的内存设置。

MEM_ARGS=-Xms512m -Xmx1024m -XX:MaxPermSize=128m

-Xms512m表示jvm内存下限为512m

-Xmx512m表示jvm内存上限为1024m

-XX:MaxPermSize=128m表示永久内存为128m

我们主要设置的为jvm内存,永久内存设置为128m或者256m即可。

设置jvm内存时,根据经验32位机器最大可启动1.8G内存的jvm,64位机器最大可启动3G内存的jvm;

而在设置上下限的时候最好将两者设为一致,以避免浪费频繁的申请和释放内存的开销。

经过实践后的经验如下,四个步骤即可:

1、打开setDomainEnv.sh文件,该文件的路径位于:
/weblogic/user_projects/domains/你的服务器域名/bin/setDomainEnv.sh

2、修改内存大小

默认的内存配置为:

if [ “${JAVA_VENDOR}” = “Sun” ] ; then   WLS_MEM_ARGS_64BIT="-Xms256m -Xmx512m"  //64位   export WLS_MEM_ARGS_64BIT   WLS_MEM_ARGS_32BIT="-Xms256m -Xmx512m"  //32位   export WLS_MEM_ARGS_32BIT else   WLS_MEM_ARGS_64BIT="-Xms512m -Xmx512m"   export WLS_MEM_ARGS_64BIT   WLS_MEM_ARGS_32BIT="-Xms512m
-Xmx512m"   export WLS_MEM_ARGS_32BIT fi

增加内存大小后:

if [ “${JAVA_VENDOR}” = “Sun” ] ; then   WLS_MEM_ARGS_64BIT="-Xms512m -Xmx1024m"  //64位   export WLS_MEM_ARGS_64BIT   WLS_MEM_ARGS_32BIT="-Xms512m -Xmx1024m"  //32位   export WLS_MEM_ARGS_32BIT else   WLS_MEM_ARGS_64BIT="-Xms512m -Xmx1024m"   export WLS_MEM_ARGS_64BIT   WLS_MEM_ARGS_32BIT="-Xms512m
-Xmx1024m"   export WLS_MEM_ARGS_32BIT fi

3、保存修改后的文件,重启weblogic。

先查看进程 ps -ef|grep java

杀掉进程 kill -9 进程ID

后台启动 nohup ./startWebLogic.sh &

4、重新访问web应用,测试成功。

5、设置线程数

修改/home/weblogic/wls12213/user_projects/domains/base_domain/bin

/setDomainEnv.sh 在JAVA_OPTIONS中添加如下:

set
JAVA_OPTIONS=%JAVA_OPTIONS%-Dweblogic.threadpool.MinPoolSize=2000

set
JAVA_OPTIONS=%JAVA_OPTIONS%-Dweblogic.threadpool.MaxPoolSize=4000

说明: JDK5.0以后每个线程栈大小为1M,但是操作系统对一个进程内的线程数还是有限制的,不能无限生成。

32位操作系统根据JVM最大堆内存设置;64位操作系统经验值在3000~5000左右。

6、weblogic文件连接数

修改
/home/weblogic/wls12213/oracle_common/common/bin/commEnv.sh,文件中的方法resetFd限制了weblogic打开的文件连接数不大于1024,我们把这方法注释掉以去掉这个限制。在文件的最后一行由resetFd修改为#resetFd (#号表示注释)

7、修改linux操作系统的文件句柄数限制(这个未做测试,仅供参考)

因为linux系统里都是以文件来表示的,所以在做高并发的web系统时,修改文件句柄限制那是必须的。

查看某个进程使用了的文件句柄数

sudo ps -ef | grep java

root 1663 1 0 02:37 ? 00:00:43 /opt/bitnami/java/bin/java

从结果中可得知进程的pid,然后根据pid查看该进程当前使用的文件句柄数

#sudo ls /proc/1663/fd | wc -l 1022

发现句柄数一直就停留在1022,同时top查看发现load持续增高。

于是先查看了下当前进程的句柄数限制。

#sudo cat /proc/1663/limits | grep “files” Max open files
1024 1024 files 发现限制卡在这了,

于是修改/etc/sysctl.conf文件,添加一行如下:

fs.file-max=30720 保存。

并执行

#sudo sysctl -p

然后再查看就发现已经改过来了。

Google发现linux系统里有两种文件句柄限制,一种是系统级的,一种是用户级的。

修改系统级的:

www.2cto.com #echo “30720” > /proc/sys/fs/file-max

修改用户级的:

#sudo vi /etc/security/limits.conf

增加如下行:

  • soft nofile 2048 * hard nofile 32768

星号表示任何用户,

soft/hard表示软限制、硬限制。

修改/etc/pam.d/login文件指定使用PAM session required
/lib/security/pam_limits.so

不过需要注意的是系统是32位还是64位,若是64位的那就是/lib64/security/pam_limits.so 上面的修改后,

reboot,

再次查看

三、 redis优化

1
缩短键值对的存储长度;

在保证完整语义的同时,我们要尽量的缩短键值对的存储长度,必要时要对数据进行序列化和压缩再存储,以 Java 为例,序列化我们可以使用 protostuff 或 kryo,压缩我们可以使用 snappy。

2
使用 lazy free(延迟删除)特性;

lazy free 特性是
Redis 4.0 新增的一个非常使用的功能,它可以理解为惰性删除或延迟删除。意思是在删除的时候提供异步延时释放键值的功能,把键值释放操作放在
BIO(Background I/O) 单独的子线程处理中,以减少删除删除对
Redis 主线程的阻塞,可以有效地避免删除
big key 时带来的性能和可用性问题。

lazy
free 对应了 4 种场景,默认都是关闭的:

lazyfree-lazy-eviction
no

lazyfree-lazy-expire no

lazyfree-lazy-server-del no

slave-lazy-flush no

它们代表的含义如下:

· lazyfree-lazy-eviction:表示当 Redis 运行内存超过 maxmeory 时,是否开启 lazy free 机制删除;

· lazyfree-lazy-expire:表示设置了过期时间的键值,当过期之后是否开启 lazy free 机制删除;

· lazyfree-lazy-server-del:有些指令在处理已存在的键时,会带有一个隐式的 del 键的操作,比如 rename 命令,当目标键已存在,Redis 会先删除目标键,如果这些目标键是一个 big key,就会造成阻塞删除的问题,此配置表示在这种场景中是否开启 lazy free 机制删除;

· slave-lazy-flush:针对 slave(从节点) 进行全量数据同步,slave 在加载 master 的 RDB 文件前,会运行 flushall 来清理自己的数据,它表示此时是否开启 lazy free 机制删除。

建议开启其中的 lazyfree-lazy-eviction、lazyfree-lazy-expire、lazyfree-lazy-server-del 等配置,这样就可以有效的提高主线程的执行效率。

3
设置键值的过期时间;

我们应该根据实际的业务情况,对键值设置合理的过期时间,这样 Redis 会帮你自动清除过期的键值对,以节约对内存的占用,以避免键值过多的堆积,频繁的触发内存淘汰策略。

4
禁用长耗时的查询命令;

Redis 绝大多数读写命令的时间复杂度都在 O(1) 到 O(N) 之间,在官方文档对每命令都有时间复杂度说明,地址:https://redis.io/commands, O(1) 表示可以安全使用的,而 O(N) 就应该当心了,N 表示不确定,数据越大查询的速度可能会越慢。因为 Redis 只用一个线程来做数据查询,如果这些指令耗时很长,就会阻塞 Redis,造成大量延时。

要避免 O(N) 命令对 Redis 造成的影响,可以从以下几个方面入手改造:

· 决定禁止使用 keys 命令;

· 避免一次查询所有的成员,要使用 scan 命令进行分批的,游标式的遍历;

· 通过机制严格控制 Hash、Set、Sorted Set 等结构的数据大小;

· 将排序、并集、交集等操作放在客户端执行,以减少 Redis 服务器运行压力;

· 删除 (del) 一个大数据的时候,可能会需要很长时间,所以建议用异步删除的方式 unlink,它会启动一个新的线程来删除目标数据,而不阻塞 Redis 的主线程。

5
使用 slowlog 优化耗时命令;

使用 slowlog 功能找出最耗时的 Redis 命令进行相关的优化,以提升 Redis 的运行速度,慢查询有两个重要的配置项:

· slowlog-log-slower-than :用于设置慢查询的评定时间,也就是说超过此配置项的命令,将会被当成慢操作记录在慢查询日志中,它执行单位是微秒 (1 秒等于 1000000 微秒);

· slowlog-max-len :用来配置慢查询日志的最大记录数。

我们可以根据实际的业务情况进行相应的配置,其中慢日志是按照插入的顺序倒序存入慢查询日志中,我们可以使用 slowlog get n 来获取相关的慢查询日志,再找到这些慢查询对应的业务进行相关的优化。

6
使用 Pipeline 批量操作数据;

Pipeline (管道技术) 是客户端提供的一种批处理技术,用于一次处理多个
Redis 命令,从而提高整个交互的性能。

Java 代码来测试一下 Pipeline 和普通操作的性能对比,Pipeline
的测试代码如下:

public class PipelineExample {

public static void main(String[] args) {

    Jedis jedis = new Jedis("127.0.0.1", 6379);

    // 记录执行开始时间

    long beginTime = System.currentTimeMillis();

    // 获取 Pipeline 对象

    Pipeline pipe = jedis.pipelined();

    // 设置多个 Redis 命令

    for (int i = 0; i < 100; i++) {

        pipe.set("key" + i, "val" + i);

        pipe.del("key"+i);

    }

    // 执行命令

    pipe.sync();

    // 记录执行结束时间

    long endTime = System.currentTimeMillis();

    System.out.println("执行耗时:" + (endTime - beginTime) + "毫秒");

}

}

以上程序执行结果为:

执行耗时:297毫秒

普通的操作代码如下:

public class PipelineExample {

public static void main(String[] args) {

    Jedis jedis = new Jedis("127.0.0.1", 6379);

    // 记录执行开始时间

    long beginTime = System.currentTimeMillis();

    for (int i = 0; i < 100; i++) {

        jedis.set("key" + i, "val" + i);

        jedis.del("key"+i);

    }

    // 记录执行结束时间

    long endTime = System.currentTimeMillis();

    System.out.println("执行耗时:" + (endTime - beginTime) + "毫秒");

}

}

以上程序执行结果为:

执行耗时:17276毫秒

从以上的结果可以看出,管道的执行时间是 297 毫秒,而普通命令执行时间是 17276 毫秒,管道技术要比普通的执行大约快了 58 倍。

7
避免大量数据同时失效;

Redis 过期键值删除使用的是贪心策略,它每秒会进行 10 次过期扫描,此配置可在 redis.conf 进行配置,默认值是 hz
10,Redis 会随机抽取 20 个值,删除这
20 个键中过期的键,如果过期 key 的比例超过 25% ,重复执行此流程,如下图所示:

如果在大型系统中有大量缓存在同一时间同时过期,那么会导致 Redis 循环多次持续扫描删除过期字典,直到过期字典中过期键值被删除的比较稀疏为止,而在整个执行过程会导致
Redis 的读写出现明显的卡顿,卡顿的另一种原因是内存管理器需要频繁回收内存页,因此也会消耗一定的
CPU。

预防大量的缓存在同一时刻一起过期,就简单的解决方案就是在过期时间的基础上添加一个指定范围的随机数。

8
客户端使用优化;

客户端方面除了要尽量使用 Pipeline 的技术外,还需要注意要尽量使用 Redis 连接池,而不是频繁创建销毁 Redis 连接,这样就可以减少网络传输次数和减少了非必要调用指令。

9
限制 Redis 内存大小;

在 64 位操作系统中 Redis 的内存大小是没有限制的,也就是配置项 maxmemory 是被注释掉的,这样就会导致在物理内存不足时,使用 swap 空间既交换空间,而当操心系统将 Redis 所用的内存分页移至 swap 空间时,将会阻塞 Redis 进程,导致 Redis 出现延迟,从而影响 Redis 的整体性能。因此我们需要限制 Redis 的内存大小为一个固定的值,当 Redis 的运行到达此值时会触发内存淘汰策略,内存淘汰策略在 Redis 4.0 之后有 8 种:

noeviction:不淘汰任何数据,当内存不足时,新增操作会报错,Redis 默认内存淘汰策略;

allkeys-lru:淘汰整个键值中最久未使用的键值;

allkeys-random:随机淘汰任意键值;

volatile-lru:淘汰所有设置了过期时间的键值中最久未使用的键值;

volatile-random:随机淘汰设置了过期时间的任意键值;

volatile-ttl:优先淘汰更早过期的键值。

在 Redis 4.0 版本中又新增了 2 种淘汰策略:

volatile-lfu:淘汰所有设置了过期时间的键值中,最少使用的键值;

allkeys-lfu:淘汰整个键值中最少使用的键值。

其中 allkeys-xxx 表示从所有的键值中淘汰数据,而 volatile-xxx 表示从设置了过期键的键值中淘汰数据。

我们可以根据实际的业务情况进行设置,默认的淘汰策略不淘汰任何数据,在新增时会报错。

10 使用物理机而非虚拟机安装 Redis 服务;

虚拟机中运行 Redis 服务器,因为和物理机共享一个物理网口,并且一台物理机可能有多个虚拟机在运行,因此在内存占用上和网络延迟方面都会有很糟糕的表现,我们可以通过 ./redis-cli --intrinsic-latency 100 命令查看延迟时间,如果对 Redis 的性能有较高要求的话,应尽可能在物理机上直接部署 Redis 服务器。

11 检查数据持久化策略;

Redis 的持久化策略是将内存数据复制到硬盘上,这样才可以进行容灾恢复或者数据迁移,但维护此持久化的功能,需要很大的性能开销。


Redis 4.0 之后,Redis 有 3 种持久化的方式:

·
RDB(Redis
DataBase,快照方式)将某一个时刻的内存数据,以二进制的方式写入磁盘;

·
AOF(Append
Only File,文件追加方式),记录所有的操作命令,并以文本的形式追加到文件中;

·
混合持久化方式,Redis
4.0 之后新增的方式,混合持久化是结合了
RDB 和 AOF 的优点,在写入的时候,先把当前的数据以 RDB 的形式写入文件的开头,再将后续的操作命令以 AOF 的格式存入文件,这样既能保证 Redis 重启时的速度,又能减低数据丢失的风险。

RDB 和 AOF 持久化各有利弊,RDB
可能会导致一定时间内的数据丢失,而 AOF 由于文件较大则会影响 Redis 的启动速度,为了能同时拥有
RDB 和 AOF 的优点,Redis 4.0 之后新增了混合持久化的方式,因此我们在必须要进行持久化操作时,应该选择混合持久化的方式。

查询是否开启混合持久化可以使用 config get aof-use-rdb-preamble 命令,执行结果如下图所示:

其中
yes 表示已经开启混合持久化,no 表示关闭,Redis 5.0 默认值为
yes。如果是其他版本的 Redis 首先需要检查一下,是否已经开启了混合持久化,如果关闭的情况下,可以通过以下两种方式开启:

·
通过命令行开启

·
通过修改
Redis 配置文件开启

① 通过命令行开启

使用命令 config set aof-use-rdb-preamble yes 执行结果如下图所示:

命令行设置配置的缺点是重启
Redis 服务之后,设置的配置就会失效。

② 通过修改 Redis 配置文件开启


Redis 的根路径下找到 redis.conf
文件,把配置文件中的 aof-use-rdb-preamble no 改为 aof-use-rdb-preamble
yes 如下图所示:

配置完成之后,需要重启
Redis 服务器,配置才能生效,但修改配置文件的方式,在每次重启
Redis 服务之后,配置信息不会丢失。

需要注意的是,在非必须进行持久化的业务中,可以关闭持久化,这样可以有效的提升
Redis 的运行速度,不会出现间歇性卡顿的困扰。

12 禁用 THP 特性;

a) Linux
kernel 在 2.6.38 内核增加了 Transparent Huge Pages (THP) 特性 ,支持大内存页
2MB 分配,默认开启。

b) 当开启了 THP 时,fork
的速度会变慢,fork 之后每个内存页从原来 4KB 变为
2MB,会大幅增加重写期间父进程内存消耗。同时每次写命令引起的复制内存页单位放大了
512 倍,会拖慢写操作的执行时间,导致大量写操作慢查询。例如简单的
incr 命令也会出现在慢查询中,因此 Redis 建议将此特性进行禁用,禁用方法如下:

c) echo
never > /sys/kernel/mm/transparent_hugepage/enabled

d) 为了使机器重启后 THP 配置依然生效,可以在
/etc/rc.local 中追加 echo never >
/sys/kernel/mm/transparent_hugepage/enabled。

13 使用分布式架构来增加读写速度。

Redis 分布式架构有三个重要的手段:

· 主从同步

· 哨兵模式

· Redis Cluster 集群

#使用主从同步功能我们可以把写入放到主库上执行,把读功能转移到从服务上,因此就可以在单位时间内处理更多的请求,从而提升的 Redis 整体的运行速度。

#而哨兵模式是对于主从功能的升级,但当主节点奔溃之后,无需人工干预就能自动恢复 Redis 的正常使用。

#Redis Cluster 是 Redis 3.0 正式推出的,Redis 集群是通过将数据库分散存储到多个节点上来平衡各个节点的负载压力。

#Redis Cluster 采用虚拟哈希槽分区,所有的键根据哈希函数映射到 0 ~ 16383 整数槽内,计算公式:slot = CRC16(key) & 16383,每一个节点负责维护一部分槽以及槽所映射的键值数据。这样 Redis 就可以把读写压力从一台服务器,分散给多台服务器了,因此性能会有很大的提升。

#在这三个功能中,我们只需要使用一个就行了,毫无疑问 Redis Cluster 应该是首选的实现方案,它可以把读写压力自动的分担给更多的服务器,并且拥有自动容灾的能力。

四、 nginx优化

(1)nginx运行工作进程个数,一般设置cpu的核心或者核心数x2

如果不了解cpu的核数,可以top命令之后按1看出来,也可以查看/proc/cpuinfo文件

grep ^processor /proc/cpuinfo | wc -l

[root@lx~]# vi/usr/local/nginx1.10/conf/nginx.conf

worker_processes 4;

[root@lx~]# /usr/local/nginx1.10/sbin/nginx-s
reload

[root@lx~]# ps -aux | grep nginx |grep -v grep

root 9834
0.0 0.0 47556 1948
? Ss
22:36 0:00 nginx: master processnginx

www 10135
0.0
0.0 50088 2004
? S 22:58 0:00 nginx:
worker process

www 10136
0.0 0.0 50088 2004
? S 22:58 0:00 nginx:
worker process

www 10137
0.0 0.0 50088 2004
? S 22:58 0:00 nginx:
worker process

www 10138
0.0 0.0 50088 2004
? S 22:58 0:00 nginx:
worker process

1.Nginx运行CPU亲和力

比如4核配置

worker_processes 4;

worker_cpu_affinity 0001 0010 0100 1000

比如8核配置

worker_processes 8;

worker_cpu_affinity 00000001 00000010 00000100 0000100000010000 00100000
01000000 10000000;

worker_processes最多开启8个,8个以上性能提升不会再提升了,而且稳定性变得更低,所以8个进程够用了。

2.Nginx最多可以打开文件数

worker_rlimit_nofile 65535;

这个指令是指当一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(ulimit -n)与nginx进程数相除,但是nginx分配请求并不是那么均匀,所以最好与ulimit -n的值保持一致。

注:

文件资源限制的配置可以在/etc/security/limits.conf设置,针对root/user等各个用户或者*代表所有用户来设置。

  • soft nofile 65535

  • hard nofile 65535

用户重新登录生效(ulimit -n)

(2)Nginx事件处理模型

events {

use epoll;

worker_connections 65535;

multi_accept on;

}

nginx采用epoll事件模型,处理效率高

work_connections是单个worker进程允许客户端最大连接数,这个数值一般根据服务器性能和内存来制定,实际最大值就是worker进程数乘以work_connections

实际我们填入一个65535,足够了,这些都算并发值,一个网站的并发达到这么大的数量,也算一个大站了!

multi_accept 告诉nginx收到一个新连接通知后接受尽可能多的连接,默认是on,设置为on后,多个worker按串行方式来处理连接,也就是一个连接只有一个worker被唤醒,其他的处于休眠状态,设置为off后,多个worker按并行方式来处理连接,也就是一个连接会唤醒所有的worker,直到连接分配完毕,没有取得连接的继续休眠。当你的服务器连接数不多时,开启这个参数会让负载有一定的降低,但是当服务器的吞吐量很大时,为了效率,可以关闭这个参数。

(3)开启高效传输模式

http {

include
mime.types;

default_type
application/octet-stream;

……

sendfile on;

tcp_nopush on;

……

Include mime.types; //媒体类型,include 只是一个在当前文件中包含另一个文件内容的指令

default_type application/octet-stream; //默认媒体类型足够

sendfile on;//开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。

注意:如果图片显示不正常把这个改成off。

tcp_nopush on;必须在sendfile开启模式才有效,防止网路阻塞,积极的减少网络报文段的数量(将响应头和正文的开始部分一起发送,而不一个接一个的发送。)

(4)连接超时时间

主要目的是保护服务器资源,CPU,内存,控制连接数,因为建立连接也是需要消耗资源的

keepalive_timeout 60;

tcp_nodelay on;

client_header_buffer_size 4k;

open_file_cache max=102400 inactive=20s;

open_file_cache_valid 30s;

open_file_cache_min_uses 1;

client_header_timeout 15;

client_body_timeout 15;

reset_timedout_connection on;

send_timeout 15;

server_tokens off;

client_max_body_size 10m;

keepalived_timeout客户端连接保持会话超时时间,超过这个时间,服务器断开这个链接

tcp_nodelay;也是防止网络阻塞,不过要包涵在keepalived参数才有效

client_header_buffer_size 4k;

客户端请求头部的缓冲区大小,这个可以根据你的系统分页大小来设置,一般一个请求头的大小不会超过 1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。分页大小可以用命令getconf PAGESIZE取得。

open_file_cache max=102400 inactive=20s;

这个将为打开文件指定缓存,默认是没有启用的,max指定缓存数量,建议和打开文件

数一致,inactive 是指经过多长时间文件没被请求后删除缓存。

open_file_cache_valid 30s;

这个是指多长时间检查一次缓存的有效信息。

open_file_cache_min_uses 1;

open_file_cache指令中的inactive 参数时间内文件的最少使用次数,如果超过这个数字,文

件描述符一直是在缓存中打开的,如上例,如果有一个文件在inactive 时间内一次没被使用,它将被移除。

client_header_timeout设置请求头的超时时间。我们也可以把这个设置低些,如果超过这个时间没有发送任何数据,nginx将返回request time out的错误

client_body_timeout设置请求体的超时时间。我们也可以把这个设置低些,超过这个时间没有发送任何数据,和上面一样的错误提示

reset_timeout_connection 告诉nginx关闭不响应的客户端连接。这将会释放那个客户端所占有的内存空间。

send_timeout响应客户端超时时间,这个超时时间仅限于两个活动之间的时间,如果超过这个时间,客户端没有任何活动,nginx关闭连接

server_tokens 并不会让nginx执行的速度更快,但它可以关闭在错误页面中的nginx版本数字,这样对于安全性是有好处的。

client_max_body_size上传文件大小限制

(5)fastcgi调优

fastcgi_connect_timeout 600;

fastcgi_send_timeout
600;

fastcgi_read_timeout
600;

fastcgi_buffer_size
64k;

fastcgi_buffers
4 64k;

fastcgi_busy_buffers_size
128k;

fastcgi_temp_file_write_size
128k;

fastcgi_temp_path/usr/local/nginx1.10/nginx_tmp;

fastcgi_intercept_errors
on;

fastcgi_cache_path/usr/local/nginx1.10/fastcgi_cache
levels=1:2 keys_zone=cache_fastcgi:128minactive=1d max_size=10g;

fastcgi_connect_timeout
600; #指定连接到后端FastCGI的超时时间。

fastcgi_send_timeout
600; #向FastCGI传送请求的超时时间。

fastcgi_read_timeout 600; #指定接收FastCGI应答的超时时间。

fastcgi_buffer_size 64k; #指定读取FastCGI应答第一部分需要用多大的缓冲区,默认的缓冲区大小为fastcgi_buffers指令中的每块大小,可以将这个值设置更小。

fastcgi_buffers 4 64k; #指定本地需要用多少和多大的缓冲区来缓冲FastCGI的应答请求,如果一个php脚本所产生的页面大小为256KB,那么会分配4个64KB的缓冲区来缓存,如果页面大小大于256KB,那么大于256KB的部分会缓存到fastcgi_temp_path指定的路径中,但是这并不是好方法,因为内存中的数据处理速度要快于磁盘。一般这个值应该为站点中php脚本所产生的页面大小的中间值,如果站点大部分脚本所产生的页面大小为256KB,那么可以把这个值设置为“8 32K”、“4 64k”等。

fastcgi_busy_buffers_size 128k; #建议设置为fastcgi_buffers的两倍,繁忙时候的buffer

fastcgi_temp_file_write_size 128k; #在写入fastcgi_temp_path时将用多大的数据块,默认值是fastcgi_buffers的两倍,该数值设置小时若负载上来时可能报502BadGateway

fastcgi_temp_path #缓存临时目录

fastcgi_intercept_errors on;#这个指令指定是否传递4xx和5xx错误信息到客户端,或者允许nginx使用error_page处理错误信息。

注:静态文件不存在会返回404页面,但是php页面则返回空白页!!

fastcgi_cache_path /usr/local/nginx1.10/fastcgi_cachelevels=1:2 keys_zone=cache_fastcgi:128minactive=1d
max_size=10g;# fastcgi_cache缓存目录,可以设置目录层级,比如1:2会生成16*256个子目录,cache_fastcgi是这个缓存空间的名字,cache是用多少内存(这样热门的内容nginx直接放内存,提高访问速度),inactive表示默认失效时间,如果缓存数据在失效时间内没有被访问,将被删除,max_size表示最多用多少硬盘空间。

fastcgi_cache cache_fastcgi; #表示开启FastCGI缓存并为其指定一个名称。开启缓存非常有用,可以有效降低CPU的负载,并且防止502的错误放生。cache_fastcgi为proxy_cache_path指令创建的缓存区名称

fastcgi_cache_valid 200 302 1h; #用来指定应答代码的缓存时间,实例中的值表示将200和302应答缓存一小时,要和fastcgi_cache配合使用

fastcgi_cache_valid 301 1d; #将301应答缓存一天

fastcgi_cache_valid any 1m; #将其他应答缓存为1分钟

fastcgi_cache_min_uses 1; #该指令用于设置经过多少次请求的相同URL将被缓存。

fastcgi_cache_key http:// h o s t host hostrequest_uri; #该指令用来设置web缓存的Key值,nginx根据Key值md5哈希存储.一般根据 h o s t ( 域 名 ) 、 host(域名)、 host()request_uri(请求的路径)等变量组合成proxy_cache_key 。

fastcgi_pass #指定FastCGI服务器监听端口与地址,可以是本机或者其它

总结:

nginx的缓存功能有:proxy_cache / fastcgi_cache

proxy_cache的作用是缓存后端服务器的内容,可能是任何内容,包括静态的和动态。

fastcgi_cache的作用是缓存fastcgi生成的内容,很多情况是php生成的动态的内容。

proxy_cache缓存减少了nginx与后端通信的次数,节省了传输时间和后端宽带。

fastcgi_cache缓存减少了nginx与php的通信的次数,更减轻了php和数据库(mysql)的压力。

(6)gzip调优

使用gzip压缩功能,可能为我们节约带宽,加快传输速度,有更好的体验,也为我们节约成本,所以说这是一个重点。

Nginx启用压缩功能需要你来ngx_http_gzip_module模块,apache使用的是mod_deflate

一般我们需要压缩的内容有:文本,js,html,css,对于图片,视频,flash什么的不压缩,同时也要注意,我们使用gzip的功能是需要消耗CPU的!

gzip on;

gzip_min_length 2k;

gzip_buffers 4 32k;

gzip_http_version
1.1;

gzip_comp_level
6;

gzip_typestext/plain
text/css text/javascriptapplication/json application/javascript
application/x-javascriptapplication/xml;

gzip_vary on;

gzip_proxied
any;

gzip on; #开启压缩功能

gzip_min_length 1k; #设置允许压缩的页面最小字节数,页面字节数从header头的Content-Length中获取,默认值是0,不管页面多大都进行压缩,建议设置成大于1K,如果小与1K可能会越压越大。

gzip_buffers 4 32k; #压缩缓冲区大小,表示申请4个单位为32K的内存作为压缩结果流缓存,默认值是申请与原始数据大小相同的内存空间来存储gzip压缩结果。

gzip_http_version 1.1; #压缩版本,用于设置识别HTTP协议版本,默认是1.1,目前大部分浏览器已经支持GZIP解压,使用默认即可

gzip_comp_level 6; #压缩比例,用来指定GZIP压缩比,1压缩比最小,处理速度最快,9压缩比最大,传输速度快,但是处理慢,也比较消耗CPU资源。

gzip_types text/css text/xml application/javascript; #用来指定压缩的类型,‘text/html’类型总是会被压缩。

默认值:
gzip_types text/html (默认不对js/css文件进行压缩)

压缩类型,匹配MIME��型进行压缩

不能用通配符 text/*

(无论是否指定)text/html默认已经压缩

设置哪压缩种文本文件可参考 conf/mime.types

gzip_vary on; #varyheader支持,改选项可以让前端的缓存服务器缓存经过GZIP压缩的页面,例如用Squid缓存经过nginx压缩的数据

(7)expires缓存调优

缓存,主要针对于图片,css,js等元素更改机会比较少的情况下使用,特别是图片,占用带宽大,我们完全可以设置图片在浏览器本地缓存365d,css,js,html可以缓存个10来天,这样用户第一次打开加载慢一点,第二次,就非常快了!缓存的时候,我们需要将需要缓存的拓展名列出来, Expires缓存配置在server字段里面

location ~*
.(ico|jpe?g|gif|png|bmp|swf|flv)$ {

expires 30d;

#log_not_found off;

access_log off;

}

location ~*
.(js|css)$ {

expires 7d;

log_not_found off;

access_log off;

}

注:log_not_found
off;是否在error_log中记录不存在的错误。默认是。

总结:

expire功能优点 (1)expires可以降低网站购买的带宽,节约成本(2)同时提升用户访问体验(3)减轻服务的压力,节约服务器成本,是web服务非常重要的功能。 expire功能缺点:被缓存的页面或数据更新了,用户看到的可能还是旧的内容,反而影响用户体验。解决办法:第一个缩短缓存时间,例如:1天,但不彻底,除非更新频率大于1天;第二个对缓存的对象改名。

网站不希望被缓存的内容 1)网站流量统计工具2)更新频繁的文件(google的logo)

(8)防盗链

防止别人直接从你网站引用图片等链接,消耗了你的资源和网络流量,那么我们的解决办法由几种: 1:水印,品牌宣传,你的带宽,服务器足够 2:防火墙,直接控制,前提是你知道IP来源 3:防盗链策略下面的方法是直接给予404的错误提示

location
~*^.+.(jpg|gif|png|swf|flv|wma|wmv|asf|mp3|mmf|zip|rar)$ {

valid_referers noneblocked  www.benet.com benet.com;

if($invalid_referer) {

  #return 302 

http://www.benet.com/img/nolink.jpg;

  return 404;

    break;

}

access_log off;

}

参数可以使如下形式:

none 意思是不存在的Referer头(表示空的,也就是直接访问,比如直接在浏览器打开一个图片)

blocked 意为根据防火墙伪装Referer头,如:“Referer:XXXXXXX”。

server_names 为一个或多个服务器的列表,0.5.33版本以后可以在名称中使用“*”通配符。

(9)内核参数优化

一个完整的内核优化设置:

fs.file-max =
999999

net.ipv4.ip_forward
= 0

net.ipv4.conf.default.rp_filter
= 1

net.ipv4.conf.default.accept_source_route
= 0

kernel.sysrq =
0

kernel.core_uses_pid
= 1

net.ipv4.tcp_syncookies
= 1

kernel.msgmnb
= 65536

kernel.msgmax
= 65536

kernel.shmmax
= 68719476736

kernel.shmall
= 4294967296

net.ipv4.tcp_max_tw_buckets
= 6000

net.ipv4.tcp_sack
= 1

net.ipv4.tcp_window_scaling
= 1

net.ipv4.tcp_rmem
= 10240 87380 12582912

net.ipv4.tcp_wmem
= 10240 87380 12582912

net.core.wmem_default
= 8388608

net.core.rmem_default
= 8388608

net.core.rmem_max
= 16777216

net.core.wmem_max
= 16777216

net.core.netdev_max_backlog
= 262144

net.core.somaxconn
= 40960

net.ipv4.tcp_max_orphans
= 3276800

net.ipv4.tcp_max_syn_backlog
= 262144

net.ipv4.tcp_timestamps
= 0

net.ipv4.tcp_synack_retries
= 1

net.ipv4.tcp_syn_retries
= 1

net.ipv4.tcp_tw_recycle
= 1

net.ipv4.tcp_tw_reuse
= 1

net.ipv4.tcp_mem
= 94500000 915000000 927000000

net.ipv4.tcp_fin_timeout
= 1

net.ipv4.tcp_keepalive_time
= 30

net.ipv4.ip_local_port_range
= 1024 65000

执行sysctl -p使内核修改生效

细致剖析:

fs.file-max = 999999:这个参数表示进程(比如一个worker进程)可以同时打开的最大句柄数,这个参数直线限制最大并发连接数,需根据实际情况配置。

net.ipv4.tcp_max_tw_buckets = 6000 #这个参数表示操作系统允许TIME_WAIT套接字数量的最大值,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。该参数默认为180000,过多的TIME_WAIT套接字会使Web服务器变慢。

注:主动关闭连接的服务端会产生TIME_WAIT状态的连接

net.ipv4.ip_local_port_range = 1024 65000 #允许系统打开的端口范围。

net.ipv4.tcp_tw_recycle = 1#启用timewait快速回收。

net.ipv4.tcp_tw_reuse = 1#开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接。这对于服务器来说很有意义,因为服务器上总会有大量TIME-WAIT状态的连接。

net.ipv4.tcp_keepalive_time = 30:这个参数表示当keepalive启用时,TCP发送keepalive消息的频度。默认是2小时,若将其设置的小一些,可以更快地清理无效的连接。

net.ipv4.tcp_syncookies = 1#开启SYN Cookies,当出现SYN等待队列溢出时,启用cookies来处理。

net.core.somaxconn = 40960 #web 应用中 listen 函数的 backlog 默认会给我们内核参数的 net.core.somaxconn 限制到128,而nginx定义的NGX_LISTEN_BACKLOG
默认为511,所以有必要调整这个值。

注:对于一个TCP连接,Server与Client需要通过三次握手来建立网络连接.当三次握手成功后,我们可以看到端口的状态由LISTEN转变为ESTABLISHED,接着这条链路上就可以开始传送数据了.每一个处于监听(Listen)状态的端口,都有自己的监听队列.监听队列的长度与如somaxconn参数和使用该端口的程序中listen()函数有关

somaxconn参数:定义了系统中每一个端口最大的监听队列的长度,这是个全局的参数,默认值为128,对于一个经常处理新连接的高负载 web服务环境来说,默认的 128 太小了。大多数环境这个值建议增加到 1024 或者更多。大的侦听队列对防止拒绝服务 DoS 攻击也会有所帮助。

net.core.netdev_max_backlog = 262144 #每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。

net.ipv4.tcp_max_syn_backlog = 262144 #这个参数标示TCP三次握手建立阶段接受SYN请求队列的最大长度,默认为1024,将其设置得大一些可以使出现Nginx繁忙来不及accept新连接的情况时,Linux不至于丢失客户端发起的连接请求。

net.ipv4.tcp_rmem = 10240 87380 12582912#这个参数定义了TCP接受缓存(用于TCP接受滑动窗口)的最小值、默认值、最大值。

net.ipv4.tcp_wmem = 10240 87380 12582912:这个参数定义了TCP发送缓存(用于TCP发送滑动窗口)的最小值、默认值、最大值。

net.core.rmem_default = 6291456:这个参数表示内核套接字接受缓存区默认的大小。

net.core.wmem_default = 6291456:这个参数表示内核套接字发送缓存区默认的大小。

net.core.rmem_max = 12582912:这个参数表示内核套接字接受缓存区的最大大小。

net.core.wmem_max = 12582912:这个参数表示内核套接字发送缓存区的最大大小。

net.ipv4.tcp_syncookies = 1:该参数与性能无关,用于解决TCP的SYN攻击。

(10)关于系统连接数的优化:

linux 默认值
open files为1024

#ulimit -n

1024

说明server只允许同时打开1024个文件

使用ulimit
-a 可以查看当前系统的所有限制值,使用ulimit -n 可以查看当前的最大打开文件数。

新装的linux
默认只有1024 ,当作负载较大的服务器时,很容易遇到error:
too many open files。因此,需要将其改大

在/etc/security/limits.conf最后增加:

  •           soft    nofile          65535
    
  •           hard    nofile          65535
    
  •           soft    noproc          65535
    
  •            hard    noproc          65535
    

猜你喜欢

转载自blog.csdn.net/qq_34362409/article/details/106013553