[TOC]
一、Nginx
1、概念
Nginx是一个 Web 服务器和反向代理服务器用于 HTTP、HTTPS、SMTP、POP3 和 IMAP 协议。因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名
1、工作原理
Nginx 由内核和模块组成。
Nginx 本身做的工作实际很少,当它接到一个 HTTP 请求时, 它仅仅是通过查找配置文件将此次请求映射到一个 location 模块,而此 location 中所配 置的各个指令则会启动不同的模块去完成工作,因此模块可以看做 Nginx 真正的劳动工作者。
通常一个 location 中的指令会涉及一个 handler 模块和多个 filter 模块(当然,多个 location 可以复用同一个模块)。handler 模块负责处理请求,完成响应内容的生成,而 filter 模块对响应内容进行处理。 用户根据自己的需要所开发的模块都属于第三方模块。正是有了这么多模块的支撑, Nginx 的功能才会如此强大。
2、Nginx模块
https://www.w3cschool.cn/nginx/
vim /etc/nginx/conf.d/default.conf
vim /usr/local/nginx/conf/nginx.conf
nginx模块分为两种,官方和第三方,我们通过命令 nginx -V 查看 nginx已经安装的模块!
如果需要添加某个模块,需要将工作目录切换至nginx的源码包中,执行“nginx -V”命令查看之前配置时的选项进行复制,然后增加需要添加的模块配置项,进行配置并编译,将新生成的nginx命令覆盖掉原有的nginx命令,然后重载nginx服务,即可实现在线添加模块。
[root@localhost ~]# nginx -V
1 | nginx version: nginx/1.15.9 |
Nginx模块名称 | 模块作用 |
---|---|
ngx_http_access_module | 四层基于IP的访问控制,可以通过匹配客户端源IP地址进行限制 |
ngx_http_auth_basic_module | 状态页,使用basic机制进行用户认证,在编译安装nginx的时候需要添加编译参数–withhttp_stub_status_module,否则配置完成之后监测会是提示语法错误 |
ngx_http_stub_status_module | 状态统计模块 |
ngx_http_gzip_module | 文件的压缩功能 |
ngx_http_gzip_static_module | 静态压缩模块 |
ngx_http_ssl_module | nginx 的https 功能 |
ngx_http_rewrite_module | 实现URL地址重写,URL看起来更规范、合理 |
ngx_http_referer_module | 防盗链功能,基于访问安全考虑 |
ngx_http_proxy_module | 将客户端的请求以http协议转发至指定服务器进行处理 |
ngx_stream_proxy_module | tcp负载,将客户端的请求以tcp协议转发至指定服务器处理 |
ngx_http_fastcgi_module | 将客户端对php的请求以fastcgi协议转发至指定服务器助理 |
ngx_http_uwsgi_module | 将客户端对Python的请求以uwsgi协议转发至指定服务器处理 |
ngx_http_headers_module | 可以实现对头部报文添加指定的key与值 |
ngx_http_upstream_module | 负载均衡模块,提供服务器分组转发、权重分配、状态监测、调度算法等高级功能 |
ngx_stream_upstream_module | 后端服务器分组转发、权重分配、状态监测、调度算法等高级功能 |
ngx_http_fastcgi_module | 实现通过fastcgi协议将指定的客户端请求转发至php-fpm处理 |
ngx_http_flv_module | 为flv伪流媒体服务端提供支持 |
1、Nginx 的模块从结构上分为核心模块、基础模块和第三方模块
核心模块:HTTP 模块、EVENT 模块和 MAIL 模块;
基础模块:HTTP Access 模块、HTTP FastCGI 模块、HTTP Proxy 模块和 HTTP Rewrite 模块;
第三方模块:HTTP Upstream Request Hash 模块、Notice 模块和 HTTP Access Key 模 块。
2、Nginx 的模块从功能上分为如下三类:
Handlers(处理器模块):此类模块直接处理请求,并进行输出内容和修改 headers 信息等操作。Handlers 处理器模块一般只能有一个;
Filters(过滤器模块):此类模块主要对其他处理器模块输出的内容进行修改操作,最后由 Nginx 输出;Proxies(代理类模块):此类模块是 Nginx 的 HTTP
Upstream 之类的模块,这些模块主要与后端一些服务比如 FastCGI 等进行交互,实现服务代理和负载均衡等功能。
Nginx rewrite概述
https://blog.csdn.net/July_jojo/article/details/109739494
3、Nginx 的进程模型
在工作方式上,Nginx 分为单工作进程和多工作进程两种模式。
1、在单工作进程模式下,除主进程外,还有一个工作进程,工作进程是单线程的;
2、在多工作进程模式下,每个工作进程包含多个线程。Nginx 默认为单工作进程模式。
Nginx 在启动后,会有一个 master 进程和多个 worker 进程。
master 进程主要用来管理 worker 进程,主要包含:接收来自外界的信号,向各 worker 进程发送信号,监控 worker 进程的运行状态,当 worker 进程退出后(异常情况下),会自动 重新启动新的 worker 进程。 master 进程充当整个进程组与用户的交互接口,同时对进程进行监护。它不需要处理网络事件,不负责业务的执行,只会通过管理worker 进程来实现重启服务、平滑升级、更换日志文件、配置文件实时生效等功能。
二、Nginx优点
1、优点
跨平台、配置简单。
非阻塞、高并发连接
处理 2-3 万并发连接数,官方监测能支持 5 万并发。
内存消耗小
开启 10 个 Nginx 才占 150M 内存
成本低廉,且开源。
稳定性高,宕机的概率非常小。
主要功能:
1)正向、反向代理
2)负载均衡、分流
2)充当一个虚拟主机(绑定host)
1 | 1、工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名、目录结构,它的正则规则比HAProxy更为强大和灵活,这也是它目前广泛流行的主要原因之一,Nginx单凭这点可利用的场合就远多于LVS了。 |
缺点
1 | Nginx的缺点是: |
2、正向代理和反向代理的区别
1)正向代理
是一个位于客户端和目标服务器之间的服务器,为了从目标服务器取得内容,客户端向代理发送一个请求并指定目标服务器,然后代理向目标服务器转交请求并将获得的内容返回给客户端。代理服务器和客户端处于同一个局域网内。
比如说fanqiang。我知道我要访问谷歌,于是我就告诉它让它帮我转发。
2)反向代理
up
实际运行方式是代理服务器接受网络上的连接请求。它将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给网络上请求连接的客户端 。代理服务器和目标服务器处于同一个局域网内。
比如说我要访问taobao,对我来说不知道图片、json、css 是不是同一个服务器返回回来的,但是我不关心,是反向代理 处理的,我不知道目标服务器。
反向代理配置:vim /etc/nginx/nginx.conf
1 | stream { |
3、Nginx如何处理HTTP请求的?
它结合多进程机制(单线程)和异步非阻塞方式。
1)多进程机制(单线程)
服务器每当收到一个客户端时,就有 服务器主进程 ( master process )生成一个 子进程( worker process )出来和客户端建立连接进行交互,直到连接断开,该子进程就结束了。
2)异步非阻塞机制
每个工作进程 使用 异步非阻塞方式 ,可以处理 多个客户端请求 。 运用了epoll模型,提供了一个队列,排队解决。
当某个 工作进程 接收到客户端的请求以后,调用 IO 进行处理,如果不能立即得到结果,就去 处理其他请求 (即为 非阻塞 );而 客户端 在此期间也 无需等待响应 ,可以去处理其他事情(即为 异步 )。
当 IO 返回时,就会通知此 工作进程 ;该进程得到通知,暂时 挂起 当前处理的事务去 响应客户端请求
4、Nginx的master和worker
这跟Nginx的多进程、单线程有关。(一个进程只有一个主线程)。
为什么要用单线程?
采用单线程来异步非阻塞处理请求(管理员可以配置Nginx主进程的工作进程的数量),不会为每个请求分配cpu和内存资源,节省了大量资源,同时也减少了大量的CPU的上下文切换,所以才使得Nginx支持更高的并发。
简单过程:
主程序 Master process 启动后,通过一个 for 循环来 接收 和 处理外部信号 ;
主进程通过 fork() 函数产生 worker 子进程 ,每个子进程执行一个 for循环来实现Nginx服务器对事件的接收和处理 。
详细过程:
1、Nginx 在启动后,会有一个 master 进程和多个相互独立的 worker 进程。 2、master 接收来自外界的信号,先建立好需要 listen 的 socket(listenfd) 之后,然后再 fork 出多个 worker 进程,然后向各worker进程发送信号,每个进程都有可能来处理这个连接。 3、所有 worker 进程的 listenfd 会在新连接到来时变得可读 ,为保证只有一个进程处理该连接,所有 worker 进程在注册 listenfd 读事件前抢占 accept_mutex ,抢到互斥锁的那个进程注册 listenfd 读事件 ,在读事件里调用 accept 接受该连接。 4、当一个 worker 进程在 accept 这个连接之后,就开始读取请求、解析请求、处理请求,产生数据后,再返回给客户端 ,最后才断开连接。
5、Nginx 常用命令
启动 nginx 。
停止 nginx -s stop 或 nginx -s quit 。
重启 nginx -s reload 或 service nginx reload 。
重载指定配置文件 .nginx -c /usr/local/nginx/conf/nginx.conf 。
查看 nginx 版本 nginx -v 。
6、Nginx状态码
https://www.php.cn/course/1020.html
1)3开头
1 | 301:请求资源已被永久移动位置 |
2)4开头
1 | 400:错误请求。 |
3)5开头
1 | 500:Internal Server Error 内部服务错误,比如脚本错误,编程语言语法错误。 |
7、Nginx 压缩
为什么要开启压缩?
开启nginx gzip压缩后,图片、css、js等静态资源的大小会减小,可节省带宽,提高传输效率,但是会消耗CPU资源。
开启:
# 开启gzip
1 | gzip off; |
# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
1 | gzip_min_length 1k; |
# gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间
1 | gzip_comp_level 1; |
# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
1 | gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml; |
8、Nginx 和 Apache、Tomcat 之间的不同点
1、Nginx/Apache 是Web Server,而Apache Tomact是一个servlet container
2、tomcat可以对jsp进行解析,nginx和apache只是web服务器,可以简单理解为只能提供html静态文件服务。
Nginx和Apache区别:
1)Nginx轻量级,同样起web 服务,比apache占用更少的内存及资源 。
2)Nginx 抗并发,nginx 处理请求是异步非阻塞的,而apache 则是阻塞型的,在高并发下nginx 能保持低资源低消耗高性能 。
3)Nginx提供负载均衡,可以做做反向代理,前端服务器
4)Nginx多进程单线程,异步非阻塞;Apache多进程同步,阻塞。
9、Nginx动静态资源分离
动态资源、静态资源分离,是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来
比如说 js、css、hrml从A服务器返回。图片 从B服务器返回,其他请求从Tomcat服务器C返回。
后台应用分开部署,提高用户访问静态代码的速度。而且现在还有CDN服务,不需要限制于服务器的带宽。
10、ngx_http_upstream_module
ngx_http_upstream_module模块用于将多个服务器定义成服务器组,可通过fastcgi传递、proxy传递、uwsgi传递、memcached传递和scgi传递指令来引用的服务器组。
比如访问www.a.com 缓存+调度:
1 | http{ |
11、限流了解吗,怎么限流的?
Nginx 提供两种限流方式,一是控制速率,二是控制并发连接数。
1、控制速率
ngx_http_limit_req_module 模块提供了漏桶算法(leaky bucket),可以限制单个IP的请求处理频率。
如:
1.1 正常限流:
1 | http { |
参数解释:
key: 定义需要限流的对象。
zone: 定义共享内存区来存储访问信息。
rate: 用于设置最大访问速率。
表示基于客户端192.168.1.1进行限流,定义了一个大小为10M,名称为myLimit的内存区,用于存储IP地址访问信息。rate设置IP访问频率,rate=5r/s表示每秒只能处理每个IP地址的5个请求。Nginx限流是按照毫秒级为单位的,也就是说1秒处理5个请求会变成每200ms只处理一个请求。如果200ms内已经处理完1个请求,但是还是有有新的请求到达,这时候Nginx就会拒绝处理该请求。
1.2 突发流量限制访问频率
上面rate设置了 5r/s,如果有时候流量突然变大,超出的请求就被拒绝返回503了,突发的流量影响业务就不好了。
这时候可以加上burst 参数,一般再结合 nodelay 一起使用。
1 | server { |
burst=20 nodelay 表示这20个请求立马处理,不能延迟,相当于特事特办。不过,即使这20个突发请求立马处理结束,后续来了请求也不会立马处理。burst=20 相当于缓存队列中占了20个坑,即使请求被处理了,这20个位置这只能按 100ms一个来释放。
2、控制并发连接数
ngx_http_limit_conn_module 提供了限制连接数功能。
1 | limit_conn_zone $binary_remote_addr zone=perip:10m; |
limit_conn perip 10 作用的key 是 $binary_remote_addr,表示限制单个IP同时最多能持有10个连接。
limit_conn perserver 100 作用的key是 $server_name,表示虚拟主机(server) 同时能处理并发连接的总数。
注:limit_conn perserver 100 作用的key是 $server_name,表示虚拟主机(server) 同时能处理并发连接的总数。
拓展:
如果不想做限流,还可以设置白名单:
利用 Nginx ngx_http_geo_module 和 ngx_http_map_module 两个工具模块提供的功能。
##定义白名单ip列表变量
1 | geo $limit { |
# 正常限流设置
1 | limit_req_zone $limit_key zone=myRateLimit:10m rate=10r/s; |
geo 对于白名单 将返回0,不限流;其他IP将返回1,进行限流。
具体参考:http://nginx.org/en/docs/http/ngx_http_geo_module.html
除此之外:
ngx_http_core_module 还提供了限制数据传输速度的能力(即常说的下载速度)
1 | location /flv/ { |
针对每个请求,表示客户端下载前500m的大小时不限速,下载超过了500m后就限速50k/s。
12、nginx重定向,重写URL
URL重写有利于网站首选域的确定,对于同一资源页面多条路径的301重定向有助于URL权重的集中
处理高并发:
https://blog.csdn.net/asqi1/article/details/41478111
单个Nginx并发尽量不要超过2w,如果你的并发都达到10w了,是时候做DNS分流了,还不行的话,就应该像Google那样直接从网卡驱动层分流了
13、nginx是如何实现高并发的?
答:nginx之所以可以实现高并发,与它采用的epoll模型有很大的关系。epoll模型采用异步非阻塞的事件处理机制。这种机制可让nginx进程同时监控多个事件。
简单来说,就是异步非阻塞,使用了epoll模型和大量的底层代码优化。如果深入一点的话,就是nginx的特殊进程模型和事件模型的设计,才使其可以实现高并发。
进程模型
1 | 它是采用一个master进程和多个worker进程的工作模式。 |
事件模型
nginx是异步非阻塞的。
一个master进程,多个worker进程,每个worker进程可以处理多个请求。每进来一个request,都会有worker进程去处理。但不是全程的处理,那么处理到的程度就是可能发生阻塞的地方,比如向后端服务器转发request,并等待请求返回。那么,在等待期间,这个处理的worker不会这么傻等着,他会在发送完请求后,注册一个事件:“如果upstream返回了,告诉我一声,我再接着干”。于是它就去休息了,此时,如果再有request进来,它就可以很快再按这种方式处理。而一旦后端服务器返回了,就会触发这个事件,worker才会来接手,这个request才会接着往下走。
由于nginx的的这个工作性质决定了每个请求大部分的生命都是在网络传输中,所以实际上花费在nginx 服务器上的时间并不多,这就是它几进程就能解决高并发的秘密所在。
14、使用nginx代理后,获取用户真实ip
使用nginx转发请求时,应用中获取到的用户ip 都是127.0.0.1,获取真实ip必须重写一些头部才行。通常在WSGI环境中经常使用的变量:REMOTE_ADDR ,在nginx转发时设置头部携带这个变量
nginx设置
1 | server { |
可以从proxy_add_x_forwarded_for中获取到用户的真实IP,
也可以通过后台的程序,从请求的header里获取X-Forwarded-For,然后取起一个值即可,使用正则匹配获取第一个即可,如下:
1 | location / { |
proxy_set_header 和add_header 的区别
区别: proxy_set_header是Nginx设置请求头信息给上游服务器, add_header是Nginx设置响应头信息给浏览器。
proxy_set_header
假如Nginx请求上游服务器时,添加额外的请求头,就需要使用proxy_set_header。
三、Nginx的优化
配置nginx的proxy缓存;
对静态页面开启压缩功能,如br压缩或者gzip压缩;
调整nginx运行工作进程个数,最多开启8个,8个以上话性能就不会再提升了,而且稳定性变得更低,所以8个足够用了;
调整nginx运行CPU的亲和力;
修改nginx最多可打开的文件数,若超过系统限制的最多打开文件数(ulimit -n命令查看系统的最多打开文件数),还需要修改系统默认的文件数;
修改单个worker的最大连接数;
开启高效传输;
设置连接超时时间,以便保护服务器资源,因为建立连接也是需要消耗资源的;
优化fastCGI的一个超时时间,也可以根据实际情况对其配置缓存动态页面;
expires缓存调优,主要针对图片、css、js等元素更改较少的情况下使用。
配置防盗链;
优化内核参数,如进程可以同时打开的最大句柄数;开启tcp重用机制,以便允许TIME_WAIT sockets重新用于新的TCP连接….
1、隐藏版本号
隐藏Nginx版本号有两种方式:
第一种是修改Nginx源码文件,指定不显示版本号
第二种是修改Nginx的主配置文件
1 | [root@localhost ~]# curl -I http://20.0.0.6 ### 查看网站版本号 |
1)修改配置文件方式
将Nginx的配置文件中的server_tokens选项值设置为off,如果有该配置项,加上即可
1 | [root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf |
测试:然后用Wireshark抓包软件抓包测试一下,版本号还能看到吗
2)设置版本信息
Nginx源码文件/opt/nginx-1.15.9/src/core/nginx.h包含了版本信息,可以随意设置,然后重新编译安装,隐藏版本信息。
1 | [root@localhost ~]# vi /opt/nginx-1.15.9/src/core/nginx.h |
2、修改用户与组
1)指定用户与组参数
configure编译过程中指定用户和组参数为nginx
1 | [root@localhost ~]# cd /opt/nginx-1.15.9/ |
2)配置用户与组
修改Nginx配置文件的Nginx指定用户与组
1 | [root@localhost opt]# cd /usr/local/nginx/conf/ |
重启Nginx查看进程运行情况,主进程由root账户创建,子进程由Nginx创建。
3、配置网页缓存时间
1、以图片作为缓存对象,上传51xit.jpg图片到/usr/local/nginx/html的工作目录,访问http://20.0.0.6/51xit.jpg,用wireshark工具进行抓包,查看响应报文,没有图片的缓存信息查看报文没有缓存信息
2、修改Nginx的配置文件,在新location段加入expires参数,指定缓存的时间1d一天
1 | [root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf |
3、重启Nginx服务,访问wireshark抓包
[root@localhost ~]# systemctl restart nginx ### 重启nginx服务
测试:在/usr/local/nginx/html里面添加一张51xit.jpg图片,然后wireshark抓包查看一下缓存时间对不对
4、日志分割
日志切割 随着Nginx运行时间的增加, 产生的日志也会逐渐增加,为了方便掌握Nginx的运行 状态, 需要时刻关注Nginx日志文件。太大的日志文件对监控是一个大灾难,不便于分析排查,需要定期的进行日志文件的切割。
##编写脚本/opt/feng e.sh##
把Nginx的日志文件/usr/local/nginx/logs/access.log移动到, 目录/var/log/ng in x下面, 以当前时间做为日志文件的名称, 然后用kill-USR1创建新的日志文件/usr/local/nginx/logs/access.log, 最后删除30天之前的日志文件。
1 | [root@localhost ~]# vi /opt/fenge.sh |
—————上面解释—————————————————————-
1 | #!/bin/bash |
-—————————————————————————————–
1 | [root@localhost ~]# chmod +x /opt/fenge.sh ###给执行权限 |
5、设置连接超时
在企业网站中,为了避免同一个客户长时间占用连接,造成资源浪费,可设置相应的连 接超时参数, 实现控制连接访问时间。可以修改配置文件nginx.conf, 设置keepalive_timeout 超时时间。
1 | [root@localhost opt]# vi /usr/local/nginx/conf/nginx.conf |
测试:浏览器输入20.0.0.6,然后wireshark抓包查看一下连接超时时间
##########深入优化##############
6、更改进程数
在高并发环境中,需要启动更多的Nginx进程以保证快速响应,用以处理用户的请求,避免造成阻塞。使用ps aux命令查看Nginx运行进程的个数。
1 | [root@localhost ~]# ps aux |grep nginx |
其中master是Nginx的主进程,开启了1个,worker 是子进程,进程也是开启了1个。
修改Nginx的配置文件的worker_processes参数, 一般设为CPU的个数或者核数, 在高并发的情况下可设置为CPU个数或者核数的2倍, 可以查看CPU的核数以确定参数
1 | [root@localhost ~]# cat /proc/cpuinfo |grep -c "physical" ###查看CPU的核数以确定参数。 |
7、配置网页压缩
1 | [root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf |
###上面的配置解释###
1 | gzip on:开启gzip压缩输出; |
[root@localhost ~]# vi /usr/local/nginx/html/index.html
xxxxxx
###在这里面随便加东西,让index.html大于1k就行 测试:浏览器输入20.0.0.6/index.html,然后wireshark抓包查看一下压缩情况。8、配置防盗链
###防盗链需要准备两台主机模拟盗链###
20.0.0.6 www.51xit.top 源主机
20.0.0.5 www.52xit.top 盗链主机
### 修改windows的 C:\Windows\System32\drivers\etc\host文件,设置域名和映射关系
20.0.0.6 www.51xit.top
20.0.0.5 www.52xit.top
###在盗链主机的工作目录编写盗链页面index.html,即盗源主机的图片###
1 | [root@localhost ~]# cd /usr/local/httpd/htdocs/ |
测试:浏览器输入20.0.0.5,查看能不能正常盗链
###在主机配置Nginx防盗链###
1 | [root@localhost ~]# cd /usr/local/nginx/conf/ |
测试:浏览器输入20.0.0.5,查看能不能防止盗链!!!
9、FPM参数优化
####################安装PHP环境#####
1 | yum -y install \ |
#######上传php-7.1.10.tar.bz2包到opt目录下#####
1 | cd /opt |
1 | make -j3 && make install |
#####FPM参数优化###
1 | [root@localhost php-7.1.10]# cd /usr/local/php/etc/php-fpm.d |
FPM启动时有5个进程,最小空闲2个进程,最大空闲8个进程,最多可以有20个进程存在。
一、pm.max_children多大合适?
这个值原则上是越大越好, php-cgi的进程多了就会处理的很快, 排队的请求就会很少。
设置”max children”也需要根据服务器的性能进行设定。
计算方式如下:
一般来说一台服务器正常情况下每一个php-cgi所耗费的内存在20M~30M左右, 因此我的”max_children”我设置成40个,
20M*40=800M也就是说在峰值的时候所有PHP-CGI所耗内存在800M以内, 低于我的有效内存2Gb。
而如果我的”max_children”设置的较小, 比如5-10个, 那么php-cgi就会“很累“, 处理速度也很慢, 等待的时间也较长,占用的CPU也很高。
如果长时间没有得到处理的请求就会出现504 Gateway Time-out这个错误, 而正在处理的很累的那几个php-cgi如果遇到了问题就会出现502Bad gateway这个错误。
max_children较好的设置方式根据req/s(吞吐率, 单位时间里服务器处理的最大请求数, 单位req/s) 来设置, 若程序是100D req/s的处理能力, 那么就设置100比较好, 这是动态来调整的。
10、内核优化
默认的Linux内核参数考虑的是最通用的场景,不符合用于支持高并发访问的Web服务器的定义,所以需要修改Linux内核参数,使得Nginx可以拥有更高的性能。
内核优化基本上会根据业务特点来进行调整,当Nginx作为静态Web内容服务器、反向代理服务器或是提供图片缩略功能(实时压缩图片)的服务器时,其内核参数的调整都是不同的。这里只针对最通用的、使Nginx支持更多并发请求的TCP网络参数做简单说明。
首先,需要修改/etc/sysctl.conf来更改内核参数
1 | net.ipv4.tcp_max_tw_buckets = 6000 timewait 的数量,默认是180000。 |
下面贴一个完整的内核优化设置:
vi /etc/sysctl.conf CentOS5.5中可以将所有内容清空直接替换为如下内容:
1 | net.ipv4.ip_forward = 0 |
使配置立即生效可使用如下命令: /sbin/sysctl -p
四、Nginx负载均衡
1、四层和七层
1 | 1)四层负载 |
2、热备
如果你有2台服务器,当一台服务器发生事故时,才启用第二台服务器给提供服务。服务器处理请求的顺序:AAAAAA突然A挂啦,BBBBBBBBBBBBBB…
1 | upstream mysvr { |
3、负载均衡策略(算法)
Nginx 默认提供的负载均衡策略:
1)轮询(默认)round_robin
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
虽然这种方式简便、成本低廉。但缺点是:可靠性低和负载分配不均衡。
例如:
1 | upstream backserver { |
2)权重 weight
weight的值越大分配到的访问概率越高,主要用于后端每台服务器性能不均衡的情况下,达到合理的资源利用率。
配置方式:
1 | upstream backserver { |
3)IP 哈希 ip_hash
ip_hash: 来自同一个IP的请求会分发到相同的后端服务器
每个请求按访问 ip 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决 session 共享的问题。
当然,实际场景下,一般不考虑使用 ip_hash 解决 session 共享。
例如:
1 | upstream backserver { |
4)最少连接 least_conn
把请求转发给连接数较少的后端服务器。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果。
1 | #动态服务器组 |
5)fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
1 | upstream backserver { |
6)url_hash(第三方)
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
1 | upstream backserver { |
补充:
1 | sticky:通过nginx-sticky模块,来实现cookie黏贴的方式将来自同一个客户端的请求发送到同一个后端服务器上处理,这样一定程度上可以解决多个后端服务器的session会话同步的问题; |
4、负载均衡状态
在nginx upstream模块中,可以设定每台后端服务器在负载均衡调度中的状态。
1 | 常用的状态有: |
六、FastCG、php-fpm
1、Nginx+FastCGI运行原理
Nginx 不支持对外部程序的直接调用或者解析,所有的外部程序(包括 PHP)必须通过FastCGI 接口来调用。FastCGI 接口在 Linux 下是 socket(这个 socket 可以是文件 socket, 也可以是 ip socket)。 wrapper 为了调用 CGI 程序,还需要一个 FastCGI 的 wrapper(wrapper 可以理解为用于启动另一个程序的程序),这个 wrapper 绑定在某个固定 socket 上,如端口或者文件 socket。当 Nginx 将 CGI 请求发送给这个 socket 的时候,通过 FastCGI 接口,wrapper 接收到请求,然后 Fork(派生)出一个新的线程,这个线程调用解释器或者外部程序处理脚本并读取返回数据;接着 wrapper 再将返回的数据通过 FastCGI 接口,沿着固定的 socket传递给 Nginx;最后 Nginx 将返回的数据(html 页面或者图片)发送给客户端。
2、缺省安装的Nginx+php-fpm环境
假设用户浏览一个耗时的网页,但是却在服务端渲染页面的中途中关闭了浏览器,那么请问服务端的PHP脚本是继续执行还是退出执行?
答:正常情况下,如果client异常退出了,Server端的程序还是会继续执行,直到与IO进行了两次交互操作。Server端发现client端已经断开连接,这个时候会出发一个User_abort,如果这个没有设置ignore_user_abort,那么这个php-fpm的程序才会被中断。
1 | fpm模块,对接nginx处理动态请求,端口9000 |
3、已知nginx和php-fpm安装在同一台服务器上,nginx连接php-fpm有两种方式:一种是类似127.0.0.1:9000的TCP socket,另一种是类似/tmp/php-fpm.sock的Unix domain socket,请问如何选择?需要注意什么?
Unix domain socket的流程不会走到TCP那层,直接以文件的形式,以stream socket通信。如果是TCP Socket,则需要走到IP层。说的通俗一点,追求可靠性就是选择TCP(需要占用一个端口,更稳定,如:127.0.0.1:9000),追求高性能就是Unix Socket(不需要占用端口,更快,但可靠性不如TCP的方式)。