nginx配置使用, 入门到实践
基础篇
一、环境
服务器版本:CentOS 7.2
为了保证学习阶段不遇到奇怪的事情,请保证以下四点(大神选择性无视)
1. 确认系统网络
2. 确认yum可用
3. 确认关闭iptables
4. 确认停用selinux
1 #查看iptables状态 2 systemctl status firewalld.service 3 #关闭防火墙(临时关闭) 4 systemctl stop firewalld.service 5 #查看SELinux状态 6 getenforce 7 #临时关闭SELinux 8 setenforce 0
安装一些系统基本工具,正常情况系统都会自带(没有在装哦)
1 yum -y install gcc gcc-c++ autoconf pcre pcre-devel make automake 2 yum -y install wget httpd-tools vim
二、Nginx是什么?
Nginx是一个开源且高性能、可靠的HTTP中间件、代理服务
其他的HTTP服务:
1. HTTPD-Apache基金会
2. IIS-微软
3. GWS-Google(不对外开放)
近几年,Nginx的市场占有率越来越高,一度飙升,为什么呢?接下来我们就知道了!
三、我们为什么选择Nginx?
1. IO多路复用epoll(IO复用)
2. 轻量级
- 功能模块少 - Nginx仅保留了HTTP需要的模块,其他都用插件的方式,后天添加
- 代码模块化 - 更适合二次开发,如阿里巴巴Tengine
3. CPU亲和把CPU核心和Nginx工作进程绑定,把每个worker进程固定在一个CPU上执行,减少切换CPU的cache miss,从而提高性能。
三、安装与目录
本人使用了鸟哥的lnmp集成包 https://lnmp.org,简单方便-推荐!
1 #执行这句语句,根据指引,将安装 nginx php mysql 可进入lnmp官网查看更详细的过程 2 #默认安装目录/usr/local 3 wget -c http://soft.vpser.net/lnmp/lnmp1.4.tar.gz && tar zxf lnmp1.4.tar.gz && cd lnmp1.4 && ./install.sh lnmp 4 5 #默认安装目录 6 /usr/local
四、基本配置
1 #打开主配置文件,若你是用lnmp环境安装 2 vim /usr/local/nginx/conf/nginx.conf 3 4 ---------------------------------------- 5 6 user #设置nginx服务的系统使用用户 7 worker_processes #工作进程数 一般情况与CPU核数保持一致 8 error_log #nginx的错误日志 9 pid #nginx启动时的pid 10 11 events { 12 worker_connections #每个进程允许最大连接数 13 use #nginx使用的内核模型 14 }
我们使用 nginx 的 http 服务,在配置文件 nginx.conf 中的 http 区域内,配置无数个 server ,每一个 server 对应这一个虚拟主机或者域名
1 http { 2 ... ... #后面再详细介绍 http 配置项目 3 4 server { 5 listen 80 #监听端口; 6 server_name localhost #地址 7 8 location / { #访问首页路径 9 root /xxx/xxx/index.html #默认目录 10 index index.html index.htm #默认文件 11 } 12 13 error_page 500 504 /50x.html #当出现以上状态码时从新定义到50x.html 14 location = /50x.html { #当访问50x.html时 15 root /xxx/xxx/html #50x.html 页面所在位置 16 } 17 } 18 19 server { 20 ... ... 21 } 22 }
一个 server 可以出现多个 location ,我们对不同的访问路径进行不同情况的配置.
我们再来看看 http 的配置详情
1 http { 2 sendfile on #高效传输文件的模式 一定要开启 3 keepalive_timeout 65 #客户端服务端请求超时时间 4 log_format main XXX #定义日志格式 代号为main 5 access_log /usr/local/access.log main #日志保存地址 格式代码 main 6 }
五、模块
查看 nginx 已开启和编联进去的模块,模块太多了,就不在这长篇大论,有需要自行百度吧~
1 #大写V查看所有模块,小写v查看版本 2 nginx -V 3 # 查看此配置文件 是否存在语法错误 4 nginx -tc /usr/local/nginx/conf/nginx.conf
场景实现篇
一、静态资源WEB服务
1.静态资源类型
非服务器动态运行生成的文件,换句话说,就是可以直接在服务器上找到对应文件的请求
- 浏览器端渲染:HTML,CSS,JS
- 图片:JPEG,GIF,PNG
- 视频:FLV,MPEG
- 文件:TXT,任意下载文件
2.静态资源服务场景-CDN
什么是CDN?例如一个北京用户要请求一个文件,而文件放在的新疆的资源存储中心,如果直接请求新疆距离太远,延迟久。使用nginx静态资源回源,分发给北京的资源存储中心,让用户请求的动态定位到北京的资源存储中心请求,实现传输延迟的最小化
3.nginx静态资源配置
1 配置域:http、server、location 2 #文件高速读取 3 http { 4 sendfile on; 5 } 6 #在 sendfile 开启的情况下,开启 tcp_nopush 提高网络包传输效率 7 #tcp_nopush 将文件一次性一起传输给客户端,就好像你有十个包裹,快递员一次送一个,来回十趟,开启后,快递员讲等待你十个包裹都派件,一趟一起送给你 8 http { 9 sendfile on; 10 tcp_nopush on; 11 } 12 #tcp_nodelay 开启实时传输,传输方式与 tcp_nopush 相反,追求实时性,但是它只有在长连接下才生效 13 http { 14 sendfile on; 15 tcp_nopush on; 16 tcp_nodelay on; 17 } 18 19 #将访问的文件压缩传输 (减少文件资源大小,提高传输速度) 20 #当访问内容以gif或jpg结尾的资源时 21 location ~ .*\.(gif|jpg)$ { 22 gzip on; #开启 23 gzip_http_version 1.1; #服务器传输版本 24 gzip_comp_level 2; #压缩比,越高压缩越多,压缩越高可能会消耗服务器性能 25 gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml application/xml+rss image/jpeg image/gif image/png; #压缩文件类型 26 root /opt/app/code; #对应目录(去该目录下寻找对应文件) 27 } 28 29 #直接访问已压缩文件 30 #当访问路径以download开头时,如www.baidu.com/download/test.img 31 #去/opt/app/code目录下寻找test.img.gz文件,返回到前端时已是可以浏览的img文件 32 location ~ load^/download { 33 gzip_static on #开启; 34 tcp_nopush on; 35 root /opt/app/code; 36 }
二、浏览器缓存
HTTP协议定义的缓存机制(如:Expires; Cache-control等 )
减少服务端的消耗,降低延迟
1.浏览器无缓存
浏览器请求 -> 无缓存 -> 请求WEB服务器 -> 请求相应 -> 呈现
在呈现阶段会根据缓存的设置在浏览器中生成缓存
2.浏览器有缓存浏览器请求 -> 有缓存 -> 校验本地缓存时间是否过期 -> 没有过期 -> 呈现
若过期从新请求WEB服务器
3.语法配置
1 location ~ .*\.(html|htm)$ { 2 expires 12h; #缓存12小时 3 }
服务器响应静态文件时,请求头信息会带上 etag 和 last_modified_since 2个标签值,浏览器下次去请求时,头信息发送这两个标签,服务器检测文件有没有发生变化,
如无,直接头信息返 etag 和last_modified_since,状态码为 304 ,浏览器知道内容无改变,于是直接调用本地缓存,这个过程也请求了服务,但是传着的内容极少
三、跨站访问
开发nginx跨站访问设置
1 location ~ .*\.(html|htm)$ { 2 add_header Access-Control-Allow-Origin *; 3 add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS; 4 #Access-Control-Allow-Credentials true #允许cookie跨域 5 }
在响应中指定 Access-Control-Allow-Credentials 为 true 时,Access-Control-Allow-Origin 不能指定为 *,需要指定到具体域名相关跨域内容可参考 Laravel 跨域功能中间件 使用代码实现跨域,原理与nginx跨域配置相同
四、防盗链
防止服务器内的静态资源被其他网站所套用
此处介绍的 nginx 防盗链为基础方式,其它更加深入的方式将在之后的文章介绍首先,需要理解一个nginx变量
1 $http_referer #表示当前请求上一次页面访问的地址,换句话说,访问 www.baidu.com 主页,这是第一次访问,所以 $http_referer 为空,但是 访问此页面的时候还需要获取一张首页图片,再请求这张图片的时候 $http_referer 就为 www.baidu.com
然后配置
1 location ~ .*\.(jpg|gif)$ { 2 #valid_referers 表示我们允许哪些 $http_referer 来访问 3 #none 表示没有带 $http_referer,如第一次访问时 $http_referer 为空 4 #blocked 表示 $http_referer 不是标准的地址,非正常域名等 5 #只允许此ip 6 valid_referers none blocked 127.xxx.xxx.xx 7 if ($invalid_referer) { #不满足情况下变量值为1 8 return 403; 9 } 10 }
五、HTTP代理服务
Nginx可以实现多种代理方式
- HTTP
- ICMPPOPIMAP
- HTTPS
- RTMP
1. 代理区别
区别在于代理的对象不一样正向代理代理的对象是客户端
反向代理代理的对象是服务端
2. 反向代理
1 语法:proxy_pass URL 2 默认:—— 3 位置:loaction 4 5 #代理端口 6 #场景:服务器80端口开放,8080端口对外关闭,客户端需要访问到8080 7 #在nginx中配置proxy_pass代理转发时,如果在proxy_pass后面的url加/,表示绝对根路径;如果没有/,表示相对路径,把匹配的路径部分也给代理走 8 server { 9 listen 80; 10 location / { 11 proxy_pass http://127.0.0.1:8080/; 12 proxy_redirect default; 13 14 proxy_set_header Host $http_host; 15 proxy_set_header X-Real-IP $remote_addr; #获取客户端真实IP 16 17 proxy_connect_timeout 30; #超时时间 18 proxy_send_timeout 60; 19 proxy_read_timeout 60; 20 21 proxy_buffer_size 32k; 22 proxy_buffering on; #开启缓冲区,减少磁盘io 23 proxy_buffers 4 128k; 24 proxy_busy_buffers_size 256k; 25 proxy_max_temp_file_size 256k; #当超过内存允许储蓄大小,存到文件 26 } 27 }
负载均衡和缓存服务
一、负载均衡
负载均衡的实现方法就是我们上章介绍的反向代理 。将客户的请求通过 nginx 分发(反向代理)到一组多台不同的服务器上.
这一组服务器我们称为 服务池(upstream server),池内的每一个服务器称为一个 单元,服务池内将对每一个单元进行请求轮训,实现负载均衡
1 #配置 2 语法:upstream name ... 3 默认:—— 4 位置:http 5 6 upstream #自定义组名 { 7 server x1.baidu.com; #可以是域名 8 server x2.baidu.com; 9 #server x3.baidu.com 10 #down 不参与负载均衡 11 #weight=5; 权重,越高分配越多 12 #backup; 预留的备份服务器 13 #max_fails 允许失败的次数 14 #fail_timeout 超过失败次数后,服务暂停时间 15 #max_coons 限制最大的接受的连接数 16 #根据服务器性能不同,配置适合的参数 17 18 #server 106.xx.xx.xxx; 可以是ip 19 #server 106.xx.xx.xxx:8080; 可以带端口号 20 #server unix:/tmp/xxx; 支出socket方式 21 }
假设我们有三台服务器,并且假设它们的IP地址,前端负载均衡服务器A(127.0.0.1),后台服务器B(127.0.0.2),后台服务器C(127.0.0.3)
新建文件 proxy.conf
,内容如下,上一章介绍的反向代理配置
1 proxy_redirect default; 2 proxy_set_header Host $http_host; 3 proxy_set_header X-Real-IP $remote_addr; 4 proxy_connect_timeout 30; 5 proxy_send_timeout 60; 6 proxy_read_timeout 60; 7 proxy_buffer_size 32k; 8 proxy_buffering on; 9 proxy_buffers 4 128k; 10 proxy_busy_buffers_size 256k; 11 proxy_max_temp_file_size 256k; 12 13 #服务器A的配置 14 http { 15 ... 16 upstream xxx { 17 server 127.0.0.2; 18 server 127.0.0.3; 19 } 20 server { 21 liseten 80; 22 server_name localhost; 23 location / { 24 proxy_pass http://xxx #upstream 对应自定义名称 25 include proxy.conf; 26 } 27 } 28 } 29 30 #服务器B、服务器C的配置 31 server { 32 liseten 80; 33 server_name localhost; 34 location / { 35 index index.html 36 } 37 }
调度算法
- 轮训:按时间顺序逐一分配到不同的后端服务器
- 加权轮训:weight值越大,分配到的几率越高
- ip_hash:每个请求按访问IP的hash结果分配,这样来自同一个IP固定访问一个后端服务器
- least_conn:最少链接数,哪个机器连接数少就分发给谁
- url_hash:按照访问的URL的hash结果来分配请求,每一个URL定向到同一个后端服务器
- hash关键数值:hash自定义key
ip_hash
配置
1 upstream xxx { 2 ip_hash; 3 server 127.0.0.2; 4 server 127.0.0.3; 5 }
ip_hash存在缺陷,当前端服务器再多一层时,将获取不到用户的正确IP,获取的将是前一个前端服务器的IP,因此 nginx1.7.2版本推出了 url_hash
url_hash
配置
1 upstream xxx { 2 hash $request_uri; 3 server 127.0.0.2; 4 server 127.0.0.3; 5 }
二、缓存服务
1. 缓存类型
- 服务端缓存:缓存存储在后端服务器,如redis,memcache
- 代理缓存:缓存存储在代理服务器或者中间件上,它的内容是从后端服务器获取的,但是保存在自己本地
- 客户端缓存:缓存在浏览器内的
2. nginx 代理缓存
客户端请求nginx,nginx查看本地是否有缓存数据,若有直接返回给客户端,若没有再去后端服务器请求
1 http { 2 proxy_cache_path /var/www/cache #缓存地址 3 levels=1:2 #目录分级 4 keys_zone=test_cache:10m #开启的keys空间名字:空间大小(1m可以存放8000个key) 5 max_size=10g #目录最大大小(超过时,不常用的将被删除) 6 inactive=60m #60分钟内没有被访问的缓存将清理 7 use_temp_path=pff; #是否开启存放临时文件目录,关闭默认存储在缓存地址 8 9 server { 10 ... 11 location / { 12 proxy_cache test_cache; #开启缓存对应的名称,在keys_zone命名好 13 proxy_cache_valid 200 304 12h; #状态码为200 304的缓存12小时 14 proxy_cache_valid any 10m; #其他状态缓存10小时 15 proxy_cache_key $host$uri$is_args$args; #设置key值 16 add_header Nginx-Cache "$upstream_cache_status"; 17 } 18 } 19 }
当有个特定请求我们不需要缓存的时候,在上面配置的内容中加入以下配置
1 server { 2 ... 3 if ($request_uri ~ ^/(login|register) ) { #当请求地址有login或register时 4 set $nocache = 1; #设置一个自定义变量为true 5 } 6 location / { 7 proxy_no_cache $nocache $arg_nocache $arg_comment; 8 proxy_no_cache $http_pragma $http_authoriztion; 9 } 10 }
3. 分片请求
早期版本 nginx 对大文件的分片请求不支持缓存,1.9版本后slice模块实现了这个功能
前端发起请求,nginx去获取这个请求文件的大小,若超过我们的定义slice的大小,会进行切片,分割成多个小的请求去请求后端,到前端就成为一个一个独立的缓存文件
优势:每个子请求收到的数据都会形成独立文件,一个请求中断了,其他请求不受影响,原本情况请求中断,再次请求文件将从头开始,而开启分片请求,就接下去获取未请求的小文件.
劣势:当文件很大或者slice很小时,可能会导致文件描述符耗尽等情况.
1 语法:slice size; #当大文件请求时,设置size为每个小文件的大小 2 默认:slice 0; 3 位置:http/server/location
常见问题
一、相同 server_name 多个虚拟主机优先级
1 #当出现虚拟主机域名相同的情况,重启nginx时,会出现警告⚠️处理,但是并不不会阻止nginx继续使用 2 3 server { 4 listen 80; 5 server_name www.baidu.com 6 ... 7 } 8 9 server { 10 listen 80; 11 server_name www.baidu.com 12 ... 13 } 14 15 ... 16 17 优先选择最新读取到的配置文件,当多个文件是通过include时,文件排序越靠前,越早被读取
二、location 匹配优先级
1 = #进行普通字符精确匹配,完全匹配 2 ^~ #进行普通字符匹配,当前表示前缀匹配 3 ~\~* #表示执行一个正则匹配() 4 5 #当程序使用精确匹配时,一但匹配成功,将停止其他匹配 6 #当正则匹配成功时,会继续接下来的匹配,寻找是否还有更精准的匹配
三、try_files的使用
按顺序检查文件是否存在
1 location / { 2 try_files $uri $uri/ /index.php; 3 } 4 5 #先查找$uri下是否有文件存在,若存在直接返回给用户 6 #若$url下没有文件存在,再次访问$uri/的路径是否有文件存在 7 #还是没有文件存在,交给index.php处理 8 9 例: 10 location / { 11 root /test/index.html 12 try_files $uri @test 13 } 14 15 location @test { 16 proxy_pass http://127.0.0.1:9090; 17 } 18 19 #访问 / 时,查看 /test/index.html 文件是否存在 20 #若不存在,让9090端口的程序去处理这个请求
四、alias和root的区别
1 location /request_path/image/ { 2 root /local_path/image/; 3 } 4 5 #当我们访问 http://xxx.com/request_path/image/cat.png时 6 #将访问 http://xxx.com/request_path/image/local_path/image/cat.png 下的文件 7 8 location /request_path/image/ { 9 alias /local_path/image/; 10 } 11 12 #当我们访问 http://xxx.com/request_path/image/cat.png时 13 #将访问 http://xxx.com/local_path/image/cat.png 下的文件
五、如果用户真实IP
当一个请求通过多个代理服务器时,用户的IP将会被代理服务器IP覆盖
1 #在第一个代理服务器中设置 2 set x_real_ip=$remote_addr 3 #最后一个代理服务器中获取 4 $x_real_ip=IP1
六、Nginx 常见错误码
1 413 Request Entity Too Large #上传文件过大,设置 client_max_body_size 2 503 bad gateway #后端服务无响应 3 504 Gateway Time-out #后端服务执行超时