CPU优化


我们从以下几个方面来介绍常用的优化措施:

CPU优化

我们可以通过修改NginxCPU相关指令来提升服务器的性能。
这里主要涉及到两个指令,分别是worker_processesworker_cpu_affinity指令。

worker_processes指令

这个指令用来设置Nginxworker进程数量。我们在本系列文章的开始时候就介绍过,Nginx是一种Master-Worker机制,真正干活的是worker进程,所以适当的提高worker进程的数量,可以提高服务器处理请求的速度。但是worker进程的数量也不是越多越好,worker进程数量太多的话会增加CPU切换进程的负担,一般建议设置为和当前服务器核心数量相同。

worker_cpu_affinity指令

我们先看一下affinity的意思是亲和力。那么cpu_affinity就是cpu亲和力。那么什么是cpu亲和力呢?
这个概念是对于进程来说的。我们知道,在现代的多核处理器上面,OS在多次调度同一个进程的时候,可能将进程分配到不同的处理器上面进行处理,这样就可能导致进程的缓存不可用,会增加进程执行的时间。所以就产生了cpu亲和力这个东西,这个功能可以把一个进程和一个处理核绑定在一起,这样就可以充分利用CPU的缓存,提高缓存命中率,加快进程的执行速度。
它的值是一个二进制,对应物理核心数量,置1的那一位表示绑定到该物理核。
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000

缓存控制

对于任何一个优秀的软件来说,都离不开缓存buffer。在Nginx中对buffer处理的方法都比较一致,一般情况下我们设置单个buffer的大小以及使用buffer的数量。如果单个buffer不够,那么继续分配buffer,直到达到指定数量。如果还不够,还可能使用临时文件来保存。这里就要尽量的避免开辟临时文件,这样可以保证所有的内容都保存在内存中,可以提高响应速度。
我们要合理的评估相关内容的大小,分配适应的缓存。
buffer相关的几个常用配置指令如下:

  • client_max_body_size:客户端请求服务器最大的body大小
  • client_body_buffer_size:Nginx分配给请求数据的Buffer大小,如果请求的数据小于client_body_buffer_size直接将数据先在内存中存储。如果请求的值大于client_body_buffer_size小于client_max_body_size,就会将数据先存储到临时文件中
  • client_header_buffer_size: 指定用于请求header的缓存区大小
    此外还有很多类似的buffer大小,功能都是大同小异。

超时时间

这个时间用于控制一些时间参数,比如从客户端接收请求头的时间,接收请求体的时间,反向代理服务器接收请求内容的时间等等。通过对他们设置一些合理的值,可以让一些请求直接结束。
常用的超时时间有下面几个:
client_body_timeout : 客户端和服务器建立连接之后接收一个完整body体的时间。
client_header_timeout: 服务器接收一个完整的请求header的时间

默认的操作系统内核参数考虑的是最通用场景,不太符合用于支持高并发访问的Web服务器的场景,所以需要修改一些操作系统内核参数,使得Nginx可以拥有更高的性能。

优化内核参数

内核有非常多的参数,所以我们在在优化的时候,要根据业务特点来进行调整。在不同的场景下,比如当Nginx作为静态web服务器、或者反向代理或者提供压缩服务器的时候,其内核参数的调整都是不同的。下面我们就看看有哪些常用的参数可以提高Nginx的性能:

文件句柄

我们知道,在Linux系统中,所有的东西都是文件,对于一个TCP连接也一样,Linux使用一个文件句柄来标识一个连接。每个进程可以使用的文件句柄数量是有限的,所以我们要调节这个值用以满足要求,防止因为文件句柄数量达到上限而导致建立TCP连接失败。

fs.file-max = 999999  # 单进程可以使用的最大文件句柄数量

建连参数

建连队列

建立TCP连接的时候有两个队列(大家可以查阅相关的文档),通过设置队列的长度,可以加快建连的速度。

net.ipv4.tcp_max_syn_backlog = 8192

这个参数是设置三次握手阶段时候处于SYN状态的队列大小。

端口号范围

其实这个参数影响的是客户端可以使用的端口号数量,和服务端没有关系。但是我还是要在这里说一下这个参数,因为我们的Nginx服务器可能会作为客户端去请求其他服务器,这个情况下,该参数就会影响到Nginx服务器了。

net.ipv4.ip_local_port_range = 1024 65000 # tcp和upd使用的端口号范围

这个值由空格分隔的两部分组成,分别代表start portend port,要把这个值调节的稍微大一点。

TCP状态参数

我们先看一下TCP的时序状态转移图:

TIME_WAIT状态

正常情况下,处于TIME_WAIT状态的套接字是不能使用的,这是为了防止识别错误的报文。但是如果有大量的套接字处于TIME_WAIT的话,就会导致服务端的套接字数量不够,所以我们可以让处于这个状态的套接字可以服用。

# 让处于TIME_WAIT状态的套接字可复用
net.ipv4.tcp_tw_reuse = 1

#设置处于TIME_WAIT状态的套接字的最大数量
net.ipv4.tcp_max_tw_buckets = 5000
FIN_WAIT2状态
net.ipv4.tcp_fin_timeout = 30

设置这个时间也是为了尽快的释放套接字资源。

套接字参数

也有很多选项可以控制套接字相关的性能,我们来简单的了解一下。因为这些配置项都非常的简单易懂。

套接字缓冲区

共有四个常用的参数控制着套接字缓冲区的性能,分别如下:

#内核套接字接受缓存区默认大小
net.core.rmem_default = 6291456

#内核套接字发送缓存区默认大小
net.core.wmem_default = 6291456

#内核套接字接受缓存区较大大小
net.core.rmem_max = 12582912

#内核套接字发送缓存区较大大小
net.core.wmem_max = 12582912

上面几个参数要根据服务器的硬件进行相应的设定。

长连接事件

我把长连接也放到了这个部分,因为我认为因为长连接,所以可以让一个套接字被循环使用,避免了重复建立连接,销毁连接的操作。但是如果一个连接一直没有数据,我们应该及时的把他销毁,避免消耗一个套接字。

# 长连接保持的事件
ner.ipv4.tcp_keepalive_time = 600

Nginx 配置

在这里我们要了解两个一个配置指令,这是 Nginx 专门为防盗链准备的。

valid_referers 指令
$invalid_referer 变量 

顾名思义,valid_referers 就是设置一些符合要求的 Referer。如果遇到我们符合我们设置的 Referer,那么 $invalid_referer 变量的值就是 0,否则就是 1

所以我们可以在 Nginx 的配置文件中增加下面的代码段:

location ~* \.(jpeg|png|gif|jpg)$ {
    valid_referers none www.test.com;
    if ($invalid_referer){
        return 200 "don't steal my pic";
    }
}

这段代码的作用是这样:
如果请求的 Referer 为空,或者为 www.test.com,那么 $valud_referer 的值是 0,否则是 1
当 $valud_referer 的值是 1 的时候,会返回一个固定的字符串 don't steal my pic。当然了,真实的线上环境中,应该返回 404,或者一张其他固定的图片。我们这里是为了测试才这样做的。

OpenResty 的目标是让你的Web服务直接跑在 Nginx 服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQLPostgreSQLMemcached 以及 Redis 等都进行一致的高性能响应。


发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注