1. 什么是 nginx
nginx 有两个作用
1)web 服务器(接收 HTTP 请求,解析 HTTP 请求,响应 HTTP 请求)
2) 代理服务器(中间人,客户端和目标服务器之间通过代理服务器访问)
2. 代理服务器
代理服务器分为两种,正向代理和反向代理
1) 正向代理
客户端 A== 代理服务器 B== 服务器 C
客户端 A 访问服务器 C,实际上是先访问的代理服务器 B,服务器 B 再去访问服务器 C;
服务器 C 返回响应给服务器 B,服务器 B 再将响应返回给服务器 A
2) 反向代理
客户端 A== 代理服务器 B== 服务器 C
客户端 A 访问服务器 B,服务器 B 再将请求转发给服务器 C;
服务器 C 返回响应给服务器 B,服务器 B 再将响应返回给服务器 A
3.nginx 作为反向代理服务器
nginx 作为反向代理服务器的网络拓扑图如下所示:
这是一种常见的负载均衡的技术,首先,大量的并发访问或数据流量分担到多台节点设备上分别处理,减少用户等待响应的时间;其次,单个重负载的运算分担到多台节点设备上做并行处理,系统处理能力得到大幅度提高。
nginx 作代理服务器的特点:
1) 与后端 web 服务器无需长连接
2) 接收用户请求是异步的,即将用户请求全部接收下来,再一次性发送给后端 web 服务器,极大的减轻后端 web 服务器的压力
3) 发送响应报文时,是边接收来自后端 web 服务器的数据,边发送给客户端的
4.nginx 作 web 服务器
nginx 可像 IIS,Apache 一样作为一个 web 服务器来使用
nginx 作为 web 服务器有以下特点:
1) 跨平台
可在 Unix like OS 编译运行,也有 Windows 的移植版本
2) 非阻塞,高并发
关于 IO 四种模型的介绍分析,参见:
http://www.cnblogs.com/shijingjing07/p/6111655.html
http 请求的基本过程:建立连接 --- 接收数据 --- 发送数据,上述过程在系统底层是 IO 输入输出事件。
阻塞模式下,IO 第一阶段数据没有准备好时,不能进行第二阶段,读写事件。nginx 进程会阻塞。cpu 就会让出去给其他的进程用了,当有越来越多的请求阻塞时,nginx 进程基本上一直处于阻塞状态,更别谈高并发了。
非阻塞模式下,nginx 进程不断轮询检查事件的状态,判断数据有没有准备好,没有马上返回 EAGAIN,进程可以去做其他的事情,过一会,再来检查一下事件,直到事件准备好了为止。
非阻塞模式要不断轮询事件状态,同样是笔很大的开销。
异步非阻塞模式(根据 IO 模型的介绍,觉得是 IO multiplexing:多 Socket 连接 IO 更准确),像 select/poll/epoll/kqueue 这样的系统调用,优势在于可以监控多个事件,这样就可以处理高并发的情况了,nginx 进程使用的是 epoll 调用,epoll 会不断的轮询所负责的所有 socket,当某个数据达到了,就通知用户进程。在这个过程中,nginx 进程一直是被 epoll 函数 block 的。
这里指的并发请求,是指未处理完的请求,线程只有一个,所以同时能处理的请求只有一个,只是在请求间进行不断地切换而已,切换也是因为异步事件未准备好,而主动让出的。
与多线程相比,这种事件处理方式有很多的优势,不需要创建线程,每个请求占用的内存也很少,没有上下午切换,并发数再多也不会导致武威的资源浪费(上下文切换)
5.nginx 内部进程模型
nginx 是以多进程的方式来工作的,nginx 启动后,会有一个 master 进程和多个 worker 进程
1)master 进程,管理 worker 进程,接收外界新信号,向各 worker 进程发送信号,监控 worker 进程的运行状态,当 worker 进程退出后(异常情况下),会自动重新启动新的 worker 进程。
2)worker 进程,处理基本的网络事件,各 worker 进程之间是对等的,一般我们设置 worker 进程数和 cpu 核数一致,这样不会导致进程来竞争 cpu 资源,从而带来不必要的上下文切换。nginx 为了更好地利用多核特性,提供了 cpu 亲缘性绑定,可将某个进程绑定在某一个核上,这样就不会因为进程的切换带来 cache 的失效。
3)master 进程接收到信号后的处理(./nginx -s reload),首先重新加载配置文件,然后启动新的 worker 进程,向老的 worker 进程发信号,告诉他们可以光荣退休了。
4)worker 进程如何处理请求,在 master 进程中,会先建立好需要 listen 的 socket,然后 fork 出多个 worker 进程,这样 worker 进程都可以去 accept 这个 socket(不是同一个 socket,但不同 socket 监听同一个 ip 和端口,是允许的)。这样,当一个连接进来后,所有在 accept 这个 socket 上面的进程,都会收到通知,只有一个进程可以 accept 这个连接,其他的 accept 失败。nginx 提供了一个 accept_mutex 共享锁,有了这个锁之后,就只会有一个进程在 accept 连接。当 worker 进程 accept 这个连接后,就开始读取请求,解析请求,处理请求,返回响应给客户端,最后断开连接。请求就完成了,一个请求只在一个 worker 进程中处理。
5)nginx 进程模型的好处,worker 进程间独立,一个进程退出,其他进程还在工作,服务不会中断。
6.nginx 处理请求的过程
1) 解析配置文件,得到需要监听的 IP 地址和端口
2) 在 master 进程中,初始化这个监控的 socket
3)fork 多个 worker 进程
4) 客户端向 nginx 发起连接请求
5)worker 进程与客户端三次握手,建立连接
6) 创建 nginx 对连接的封装,即 ngx_connection_t 结构体
7) 设置读写事件处理函数并添加读写事件来与客户端进行数据的交换
8)nginx 或客户端主动关掉连接,连接结束。
nginx 作为代理服务器时,nginx 是作为客户端来请求其他服务器的数据的(如 upstream 模块),此时,与其他 server 创建的连接,也封装在 ngx_connection_t 中,然后创建 socket,并设置 socket 的属性(非阻塞)。然后再通过添加读写事件,调用 connect/read/write 来调用连接,最后关掉连接,并释放 ngx_connection_t。
7.nginx 连接池
ngxin 是通过一个连接池来管理的,每个 worker 进程都有一个独立的连接池,连接池的大小是 worker_connections,这里的连接池里面保存的不是真实的连接,它只是一个 worker_connections 大小的 ngx_connection_t 结构的数组。并且 nginx 会通过一个链表 free_connections 来保存所有的空闲 ngx_connection_t,每次获取一个连接时,就从空闲链表中获取一个,用完后,再放回空闲连接链表里面。
所以,一个 nginx 能建立的最大连接数,应该是 worker_connections*worker_processes,这个连接数是针对 nginx 作 web 服务器时。
如果 nginx 是作反向代理,那么最大并发量应是 worker_connections*worker_processes/2,因为每个并发会建立与客户端的连接和与后端服务器的连接两个连接。
8.nginx 作 web 服务器,反向代理的具体配置
- #定义Nginx运行的用户和用户组
- user www www;
- #nginx进程数,建议设置为等于CPU总核心数。
- worker_processes 8;
- #全局错误日志定义类型,[ debug | info | notice | warn | error | crit ]
- error_log ar/loginx/error.log info;
- #进程文件
- pid ar/runinx.pid;
- #一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(系统的值ulimit -n)与nginx进程数相除,但是nginx分配请求并不均匀,
- 所以建议与ulimit -n的值保持一致。
- worker_rlimit_nofile 65535;
- #工作模式与连接数上限
- events
- {
- #参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型是Linux 2.6以上版本内核中的高性能网络I/O模型,
- 如果跑在FreeBSD上面,就用kqueue模型。
- use epoll;
- #单个进程最大连接数(最大连接数=连接数*进程数)
- worker_connections 65535;
- }
- #设定http服务器
- http
- {
- include mime.types; #文件扩展名与文件类型映射表
- default_type application/octet-stream; #默认文件类型
- #charset utf-8; #默认编码
- server_names_hash_bucket_size 128; #服务器名字的hash表大小
- client_header_buffer_size 32k; #上传文件大小限制
- large_client_header_buffers 4 64k; #设定请求缓
- client_max_body_size 8m; #设定请求缓
- sendfile on; #开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,
- 可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
- autoindex on; #开启目录列表访问,合适下载服务器,默认关闭。
- tcp_nopush on; #防止网络阻塞
- tcp_nodelay on; #防止网络阻塞
- keepalive_timeout 120; #长连接超时时间,单位是秒
- #FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。下面参数看字面意思都能理解。
- fastcgi_connect_timeout 300;
- fastcgi_send_timeout 300;
- fastcgi_read_timeout 300;
- fastcgi_buffer_size 64k;
- fastcgi_buffers 4 64k;
- fastcgi_busy_buffers_size 128k;
- fastcgi_temp_file_write_size 128k;
- #gzip模块设置
- gzip on; #开启gzip压缩输出
- gzip_min_length 1k; #最小压缩文件大小
- gzip_buffers 4 16k; #压缩缓冲区
- gzip_http_version 1.0; #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
- gzip_comp_level 2; #压缩等级
- gzip_types text/plain application/x-javascript text/CSS application/xml;
- #压缩类型,默认就已经包含textml,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn。
- gzip_vary on;
- #limit_zone crawler $binary_remote_addr 10m; #开启限制IP连接数的时候需要使用
- upstream blog.ha97.com {
- #upstream的负载均衡,weight是权重,可以根据机器配置定义权重。weigth参数表示权值,权值越高被分配到的几率越大。
- server 192.168.80.121:80 weight=3;
- server 192.168.80.122:80 weight=2;
- server 192.168.80.123:80 weight=3;
- }
- #虚拟主机的配置
- server
- {
- #监听端口
- listen 80;
- #域名可以有多个,用空格隔开
- server_name www.ha97.com ha97.com;
- index index.html index.htm index.php;
- root /data/www/ha97;
- location ~ .*.(php|php5)?$
- {
- fastcgi_pass 127.0.0.1:9000;
- fastcgi_index index.php;
- include fastcgi.conf;
- }
- #图片缓存时间设置
- location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
- {
- expires 10d;
- }
- #JS和CSS缓存时间设置
- location ~ .*.(js|css)?$
- {
- expires 1h;
- }
- #日志格式设定
- log_format access '$remote_addr - $remote_user [$time_local] "$request" '
- '$status $body_bytes_sent "$http_referer" '
- '"$http_user_agent" $http_x_forwarded_for';
- #定义本虚拟主机的访问日志
- access_log ar/loginx/ha97access.log access;
- #对 "/" 启用反向代理
- location / {
- proxy_pass http://127.0.0.1:88;
- proxy_redirect off;
- proxy_set_header X-Real-IP $remote_addr;
- #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- #以下是一些反向代理的配置,可选。
- proxy_set_header Host $host;
- client_max_body_size 10m; #允许客户端请求的最大单文件字节数
- client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数,
- proxy_connect_timeout 90; #nginx跟后端服务器连接超时时间(代理连接超时)
- proxy_send_timeout 90; #后端服务器数据回传时间(代理发送超时)
- proxy_read_timeout 90; #连接成功后,后端服务器响应时间(代理接收超时)
- proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
- proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的设置
- proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2)
- proxy_temp_file_write_size 64k;
- #设定缓存文件夹大小,大于这个值,将从upstream服务器传
- }
- #设定查看Nginx状态的地址
- location /NginxStatus {
- stub_status on;
- access_log on;
- auth_basic "NginxStatus";
- auth_basic_user_file confpasswd;
- #htpasswd文件的内容可以用apache提供的htpasswd工具来产生。
- }
- #本地动静分离反向代理配置
- #所有jsp的页面均交由tomcat或resin处理
- location ~ .(jsp|jspx|do)?$ {
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_pass http://127.0.0.1:8080;
- }
- #所有静态文件由nginx直接读取不经过tomcat或resin
- location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$
- { expires 15d; }
- location ~ .*.(js|css)?$
- { expires 1h; }
- }
- }
来源: http://www.bubuko.com/infodetail-1960296.html