1、什么是nginx
是一个高性能的HTTP和反向代理web服务器;主要功能是反向代理,也可以通过配置文件实现集群和负载均衡,静态资源虚拟化。
2、什么是反向代理
了解反向代理之前,我们先来了解一下正向代理:请求会经过代理服务器,然后再转发请求到目标服务器,获得内容后最后响应给客户端
反向代理:用户请求目标服务器,由代理服务器决定访问哪个IP
3、Nginx的进程模型
Nginx默认采用多进程工作方式,Nginx启动后,会运行一个master进程和多个worker进程。其中master充当整个进程组与用户的交互接口,同时对进程进行监护,管理worker进程来实现重启服务、平滑升级、更换日志文件、配置文件实时生效等功能。worker用来处理基本的网络事件,worker之间是平等的,他们共同竞争来处理来自客户端的请求。
4、worker抢占机制
a、 在创建master进程时,先建立需要监听的socket(listenfd),然后从master进程中fork(fork函数将运行着的程序分成2个(几乎)完全一样的进程,每个进程都启动一个从代码的同一位置开始执行的线程)出多个worker进程,如此一来每个worker进程都可以监听用户请求的socket。一般来说,当一个连接进来后,所有Worker都会收到通知,但是只有一个进程可以接受这个连接请求,其它的都失败,这是所谓的惊群现象。nginx提供了一个accept_mutex(互斥锁),有了这把锁之后,同一时刻,就只会有一个进程在accpet连接,这样就不会有惊群问题了。
b、 先打开accept_mutex选项,只有获得了accept_mutex的进程才会去添加accept事件。nginx使用一个叫ngx_accept_disabled的变量来控制是否去竞争accept_mutex锁。ngx_accept_disabled = nginx单进程的所有连接总数 / 8 -空闲连接数量,当ngx_accept_disabled大于0时,不会去尝试获取accept_mutex锁,ngx_accept_disable越大,让出的机会就越多,这样其它进程获取锁的机会也就越大。不去accept,每个worker进程的连接数就控制下来了,其它进程的连接池就会得到利用,这样,nginx就控制了多进程间连接的平衡。
c、每个worker进程都有一个独立的连接池,连接池的大小是worker_connections。这里的连接池里面保存的其实不是真实的连接,它只是一个worker_connections大小的一个ngx_connection_t结构的数组。并且,nginx会通过一个链表free_connections来保存所有的空闲ngx_connection_t,每次获取一个连接时,就从空闲连接链表中获取一个,用完后,再放回空闲连接链表里面。一个nginx能建立的最大连接数,应该是worker_connections * worker_processes。当然,这里说的是最大连接数,对于HTTP请求本地资源来说,能够支持的最大并发数量是worker_connections * worker_processes,而如果是HTTP作为反向代理来说,最大并发数量应该是worker_connections * worker_processes/2。因为作为反向代理服务器,每个并发会建立与客户端的连接和与后端服务的连接,会占用两个连接。
5、nginx.conf配置结构
6、nginx.conf配置详解
# worker进行的执行者,默认是worker
#user nobody;
# worker进程数量,可以设为和CPU的数量一样
worker_processes 2;
# 错误日志:存放路径(以下为默认配置);日志级别:debug info notice warn error crit
error_log logs/error.log;
error_log logs/error.log notice;
error_log logs/error.log info;
# pid(进程标识符):存放路径。(以下为默认配置)
pid logs/nginx.pid;
# 这个指令是指当一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(ulimit -n)与nginx进程数相除(65535 / worker_processes ),但是nginx分配请求并不是那么均匀,所以最好将这个值设置成最多打开文件数(ulimit -n)
worker_rlimit_nofile 65535;
events {
# 默认使用epoll的I/O 模型
# use epoll;
# 没个工作进程的最大连接数量。根据硬件调整,和前面工作进程配合起来用,尽量大,但是别把cpu跑到100%就行。每个进程允许的最多连接数,理论上每台nginx服务器的最大连接数为。worker_processes*worker_connections
woker_connections 204800;
# 处理完一个请求后保持这个 TCP 连接的时间(s)(与请求客户端的连接)
keepalive_timeout 60;
# 客户端请求头部的缓冲区大小。这个可以根据你的系统分页大小来设置,一般一个请求头的大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。
# 分页大小可以用命令getconf PAGESIZE 取得。
# [root@web001 ~]# getconf PAGESIZE
# 4096
# 但也有client_header_buffer_size超过4k的情况,但是client_header_buffer_size该值必须设置为“系统分页大小”的整倍数。
client_header_buffer_size 4k;
# 这个将为打开文件指定缓存,默认是没有启用的,max指定缓存数量,建议和打开文件数一致,inactive是指经过多长时间文件没被请求后删除缓存。
open_file_cache max=65535 inactive=60s;
# 这个是指多长时间检查一次缓存的有效信息。
open_file_cache_valid 80s;
# open_file_cache指令中的inactive参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个文件在inactive时间内一次没被使用,它将被移除。
open_file_cache_min_uses 1;
}
http {
# 将支持的数据类型存放在mime.type文件中,再引入到配置中
include mime.type;
# 默认数据类型
default_type application/octet-stream;
# 日志格式设置。
# $remote_addr与$http_x_forwarded_for用以记录客户端的ip地址;
# $remote_user:用来记录客户端用户名称;
# $time_local: 用来记录访问时间与时区;
# $request: 用来记录请求的url与http协议;
# $status: 用来记录请求状态;成功是200,
# $body_bytes_sent :记录发送给客户端文件主体内容大小;
# $http_referer:用来记录从那个页面链接访问过来的;
# $http_user_agent:记录客户浏览器的相关信息;
# 通常web服务器放在反向代理的后面,这样就不能获取到客户的IP地址了,通过$remote_add拿到的IP地址是反向代理服务器的iP地址。反向代理服务器在转发请求的http头信息中,可以增加x_forwarded_for信息,用以记录原有客户端的IP地址和原来客户端的请求的服务器地址。
# main 表示定义的格式名称(日志格式和存儲地址都有默认,没有特殊需求无需配置)
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# 用了log_format指令设置了日志格式之后,需要用access_log指令指定日志文件的存放路径;
access_log logs/host.access.log main;
# 参数sendfile on 用于开启文件高效传输模式,同时将tcp_nopush on 和tcp_nodelay on 两个指令设置为on,可防止网络及磁盘I/O阻塞,提升Nginx工作效率
sendfile on;
tcp_nopush on;
# 后端服务器连接的超时时间_发起握手等候响应超时时间
proxy_connect_timeout 90;
# 连接成功后_等候后端服务器响应时间_其实已经进入后端的排队之中等候处理(也可以说是后端服务器处理请求的时间)
proxy_read_timeout 180;
# 后端服务器数据回传时间_就是在规定时间之内后端服务器必须传完所有的数据
proxy_send_timeout 180;
# 处理完一个请求后保持这个 TCP 连接的时间(s)(与被代理的服务器的连接)
keepalive_timeout 120;
# 开启gzip压缩功能,目的:提高传输效率,节约宽带(用cpu运行能力换取传输效率)
gzip on;
# 定义压缩的级别(压缩比,文件越大,压缩越多,但是cpu使用会越多)
gzip_min_length 3;
# 定义压缩文件的类型
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/json;
# 负载均衡:1、默认配置就是轮询策略(可通过weight来提升服务器权重,越大权重越高)
# 2、ip_hash:每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器
# 3、fair:按后端服务器的响应时间来分配请求,响应时间短的优先分配。
# 4、url_hash:按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效
upstream server-test {
server 127.0.0.1:8080;
server 127.0.0.1:8081 weight=10;
server 127.0.0.1:8082 weight=10;
}
server {
# 配置监听端口
listen 80;
# 配置访问域名(IP)
server_name www.test.com;
# 允许跨域请求的域,*表示所有
add_header 'Access-Control-Allow-Origin' *;
# 请求允许带上cookie
add_header 'Access-Control-Allow-Credentials' 'true';
# 允许请求的方法,比如 GET/POST/PUT/DELETE
add_header 'Access-Control-Allow-Methods' *;
# 允许请求的header
add_header 'Access-Control-Allow-Headers' *;
# 访问静态页面路由,(location后面的/为匹配规则)
location / {
# 此处讲解下root和alias的区别
# 例:
# location /images/ {
#http://www.aaa.com/images/a.jpg 请求的资源地址为==> /data/web/images/a.jpg
# root /data/web;
# }
# 例:
# location /images/ {
# http://www.aaa.com/images/a.jpg 请求的资源地址为==> /data/web/a.jpg
# alias /data/web;
# }
root html; # 定义网站根目录,目录可以是相对路径(相对与conf文件夹的目录)也可以是绝对路径。
index index.html index.htm; # 定义站点的默认页。
}
# 当状态码为500、502、503、504时,则访问50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
# 定义50x.html所在路径
root html;
}
location /a {
# http://www.test.com/a => http://127.0.0.1:8080
proxy http://127.0.0.1:8080;
}
}
# HTTPS server
#
#server {
# listen 443 ssl; //监听443端口,即ssl
# server_name localhost;
### 以下为ssl相关配置
# ssl_certificate cert.pem; //指定pem文件路径
# ssl_certificate_key cert.key; //指定key文件路径
# ssl_session_cache shared:SSL:1m; //指定session cache大小
# ssl_session_timeout 5m; //指定session超时时间
# ssl_protocols TLSv1 TLSv1.1 TLSv1.2; //指定ssl协议
# ssl_ciphers HIGH:!aNULL:!MD5; //指定ssl算法
# ssl_prefer_server_ciphers on; //优先采取服务器算法
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
7、server配置实列
#### http前后端分离请求配置:前端vue开发,后端springboot
server {
# 监听端口
location 80;
# 监听域名或者IP
server_name location;
# 配置前端页面路由:拦截location/front开头的请求
location /front {
# 存放前端页面的绝对路径
alias /home/front/dist;
# 默认访问页面
index index.html;
}
# 配置后端请求路由
location /admin {
# 访问http://location/admin/test 相当于⇒ http://IP:port/test
proxy_pass http://IP:port/;
}
}
#### https前后端分离请求配置:前端vue开发,后端springboot
server {
listen 443 ssl;
server_name www.test.com;
ssl on;
ssl_certificate cert/cert.pem;
ssl_certificate_key cert/key.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;
# 前端代码
location /front {
alias /home/front/dist;
index index.html index.htm;
}
# 后端请求,代理证实的应用服务器,一般用内网
location /admin {
proxy_pass http://ip:port/;
}
}
# 监听80端口,映射到443端口
server{
listen 80;
server_name www.test.com;
rewrite ^/(.*) https://$server_name$request_uri? permanent;
}
完毕!