博客地址:https://blog.csdn.net/Weiye__Lee/article/details/79700730
写在前面
对nginx的折腾做个汇总记录,部分内容参考出处见文章末尾.
nginx概述
nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器;同时也是一个IMAP、POP3、SMTP代理服务器;nginx可以作为一个HTTP服务器进行网站的发布处理,另外nginx可以作为反向代理进行负载均衡的实现。
正向代理
正向代理是一般意义上的代理。在如今的网络环境下,我们如果由于技术需要要去访问国外的某些网站,此时你会发现位于国外的某网站我们通过浏览器是没有办法访问的,此时大家可能都会用一个操作FQ进行访问,FQ的方式主要是找到一个可以访问国外网站的代理服务器,我们将请求发送给代理服务器,代理服务器去访问国外的网站,然后将访问到的数据传递给我们
上述这样的代理模式称为正向代理,正向代理最大的特点是客户端非常明确要访问的服务器地址;服务器只清楚请求来自哪个代理服务器,而不清楚来自哪个具体的客户端;正向代理模式屏蔽或者隐藏了真实客户端信息。
反向代理
反向代理多用于分布式部署;也就是通过部署多台服务器来解决访问并发问题。
通过上述的图解大家就可以看清楚了,多个客户端给服务器发送的请求,nginx服务器接收到之后,按照一定的规则分发给了后端的业务处理服务器进行处理了。此时,请求的来源也就是客户端是明确的,但是请求具体由哪台服务器处理的并不明确了,nginx扮演的就是一个反向代理角色
反向代理,主要用于服务器集群分布式部署的情况下,反向代理隐藏了服务器的信息。对于反向这个词,刚开始接触的时候没理解为啥叫反向,这里的抽取出来注明下:
正向代理
代理服务器实现对被代理服务端隐藏客户端信息,对客户端的请求进行转发处理.此时,客户端是明确知道被代理的服务端信息的,而被代理服务端是不知道客户端信息的反向代理
代理服务器实现对客户端的被代理服务器信息的隐藏,对客户端的请求进行转发处理.此时,客户端是不知道被代理服务端的信息的,而被代理服务端是知道客户端信息的,注意到了吧,后半句两边整好反过来
安装
ubantu包管理器安装
使用包管理器直接安装是最快捷方便的,但是缺点也明显,想自由装对应的版本就困难了。anyway,在terminal里敲如下命令:
$ sudo apt-get install nginx
安装完成即可,在/usr/sbin/目录下是nginx命令所在目录,在/etc/nginx/目录下是nginx所有的配置文件,用于配置nginx服务器以及负载均衡等信息
查看nginx进程是否启动:
$ ps -ef | grep nginx
启动nginx服务器,直接执行nginx会按照默认的配置文件进行服务器的启动
$ nginx # 启动 $ nginx -s stop 停止 $ nginx -s quit 停止
ubantu源码安装
#安装gcc g++的依赖库
$ apt-get install build-essential
$ apt-get install libtool
# 安装pcre依赖库
$ sudo apt-get install libpcre3 libpcre3-dev
#安装 zlib依赖库
$ sudo apt-get install zlib1g-dev
# 安装 ssl依赖库
$ sudo apt-get install openssl
#下载nginx最新版本:参考用nginx-1.10.3/
$ wget http://nginx.org/download/nginx-1.11.3.tar.gz
#解压:
$ tar -zxvf nginx-1.11.3.tar.gz
#进入解压目录:
$ cd nginx-1.11.3
#配置:
$ ./configure --prefix=/usr/local/nginx
#编辑nginx:
$ make
#安装nginx:
$ sudo make install
#启动nginx:
$ sudo /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
注意:-c 指定配置文件的路径,不加的话,nginx会自动加载默认路径的配置文件,可以通过 -h查看帮助命令。
#查看nginx进程:
$ ps -ef|grep nginx
#检查配置文件是否正确
$ sudo /usr/local/nginx/sbin/nginx -t
-----
$ /usr/local/nginx/sbin/nginx -s reload # Nginx重新加载配置
$ /usr/local/nginx/sbin/nginx -s stop #停止
nginx配置
nginx.conf
修改部署目录下conf子目录的nginx.conf文件(如上面源码安装的/usr/local/nginx/conf/nginx.conf)内容
main # 全局配置
events { # nginx工作模式配置
}
http { # http设置
....
server { # 服务器主机配置
....
location { # 路由配置
....
}
location path {
....
}
location otherpath {
....
}
}
server {
....
location {
....
}
}
upstream name { # 负载均衡配置
....
}
}
如上述配置文件所示,主要由6个部分组成:
- main:用于进行nginx全局信息的配置
- events:用于nginx工作模式的配置
- http:用于进行http协议信息的一些配置
- server:用于进行服务器访问信息的配置
- location:用于进行访问路由的配置
- upstream:用于进行负载均衡的配置
main模块
# user nobody nobody;
worker_processes 2;
# error_log logs/error.log
# error_log logs/error.log notice
# error_log logs/error.log info
# pid logs/nginx.pid
worker_rlimit_nofile 1024;
上述配置都是放在main全局配置模块中的配置项
- user 用来指定进程运行的用户及用户组,默认为nobody
- work_processes 用来指定nginx开启的子进程数量,数量通常是cpu内核的2倍,官方宣称一般开1个就可以了
- error_log 定义错误日志文件的位置及输出级别[debug/info/notice/warn/error/crit]
- pid 用来指定进程pid的存储文件的位置
- worker_rlimit_nofile 指定一个进程可以打开的最多文件描述符数量
event 模块
event {
worker_connections 1024;
# 并发总数是 worker_processes 和 worker_connections 的乘积
# 即 max_clients = worker_processes * worker_connections
# 在设置了反向代理的情况下,max_clients = worker_processes * worker_connections / 4 为什么
# 为什么上面反向代理要除以4,应该说是一个经验值
# 根据以上条件,正常情况下的Nginx Server可以应付的最大连接数为:4 * 8000 = 32000
# worker_connections 值的设置跟物理内存大小有关
# 因为并发受IO约束,max_clients的值须小于系统可以打开的最大文件数
# 而系统可以打开的最大文件数和内存大小成正比,一般1GB内存的机器上可以打开的文件数大约是10万左右
# 我们来看看360M内存的VPS可以打开的文件句柄数是多少:
# $ cat /proc/sys/fs/file-max
# 输出 34336
# 32000 < 34336,即并发连接总数小于系统可以打开的文件句柄总数,这样就在操作系统可以承受的范围之内
# 所以,worker_connections 的值需根据 worker_processes 进程数目和系统可以打开的最大文件总数进行适当地进行设置
# 使得并发总数小于操作系统可以打开的最大文件数目
# 其实质也就是根据主机的物理CPU和内存进行配置
# 当然,理论上的并发总数可能会和实际有所偏差,因为主机还有其他的工作进程需要消耗系统资源。
# ulimit -SHn 65535
multi_accept on;
use epoll;
}
- worker_connections 指定单个进程最大可以接收的连接数量.注意,nginx最大连接数和worker_processes、worker_connections、能打开的文件描述符数量、系统资源等因素共同决定
- multi_accept 指定nginx在收到一个新连接通知后,尽可能多的接收更多的l连接
- use epoll 指定线程轮询的方法,如果是linux2.6+,使用epoll。如果是BSD如mac,请使用Kqueue
http 模块
作为web服务器,http模块是nginx最核心的一个模块,配置项也是比较多的,项目中会设置到很多的实际业务场景,需要根据硬件信息进行适当的配置,常规情况下,使用默认配置即可
server模块
srever模块配置是http模块中的一个子模块,用来定义一个虚拟访问主机,也就是一个虚拟服务器的配置信息
server {
listen 80;
server_name localhost 192.168.1.100;
root /nginx/www;
index index.php index.html index.html;
charset utf-8;
access_log logs/access.log;
error_log logs/error.log;
......
}
核心配置信息如下:
- server:一个虚拟主机的配置,一个http中可以配置多个server
- server_name:指定ip地址或者域名,多个配置之间用空格分隔
- root:表示整个server虚拟主机内的根目录,所有当前主机中web项目的根目录
- index:用户访问web网站时的全局首页
- charset:用于设置www/路径中配置的网页的默认编码格式
- access_log:用于指定该虚拟主机服务器中的访问记录日志存放路径
- error_log:用于指定该虚拟主机服务器中访问错误日志的存放路径
location 模块
location模块是nginx配置中出现最多的一个配置,主要用于配置路由访问信息
在路由访问信息配置中关联到负载均衡、url重写等等各项功能,所以location模块也是一个非常重要的配置模块,而其中匹配模式则是玩转转发的秘籍
匹配语法
location [ = | ~ | ~* | ^~ ] uri { ... }location @name { ... }
没错,就这么多,实际写在loacation中大概是这样的
location = / {
}
-----
location [指令模式] url匹配模式 {
}
指令模式指用于匹配的方式,即精确匹配,前缀匹配还是正则匹配,当然这个是可选的,如果不写,则退化成正常匹配或者全匹配。url匹配模式则需要匹配的url,可以看成是web开发中的路由
匹配模式
精确匹配
= 指令用于精确字符匹配(模式),不能使用正则,区分大小写,为了直观的观察匹配命中的location,使用rewrite指令,用于转发。目前只要理解命中了就重定向到rewrite后面的url即可
location = /demo { rewrite ^ http://google.com; }
上述的配置表示只有访问 http://host:port/demo 这样的url,才能跳转到google的页面。除此之外的任何地址都无法访问,那怕是访问http://host:port/demo/ 这个地址也不行。因为url匹配模式是/demo
前缀匹配
^~指令用于字符前缀匹配,和=精确匹配一样,也是用于字符确定的匹配,不能使用正则且区分大小写。和=不同的在于,^~指令下,访问的url无需url匹配模式一模一样,只需要其开头前缀和url匹配模式一样即可
location ^~ /demo { rewrite ^ http://google.com; }
对于该模式(/demo),访问下列的地址都能匹配:
- http://127.0.0.1/demo
- http://127.0.0.1/demo/
- http://127.0.0.1/demo/aaa
- http://127.0.0.1/demo/aaa/bbb
- http://127.0.0.1/demo/AAA
- http://127.0.0.1/demoaaa
- http://127.0.0.1/demo.aaa
只需要以/demo为前缀开头的url都能匹配。与该模式后的是否大小写无关。
^~不支持正则。模式/demo$中的$并不代表字符模式结束,而是一个是实实在在的$,只有访问/demo$开头的url才能匹配,http://host:port/demo 则不再匹配。前缀匹配通常用于匹配文件夹,如配置静态文件。正则匹配
众所周知,nginx的url功能强大,配置灵活。字符匹配中,支持正则和不支持正则完全是两个境界。前面的两种方式都不能使用正则,未免让人觉得nginx有点虚夸。
实际上,nginx支持正则匹配。所使用的指令是~和~*,前者表示使用正则,区分大小写,后者表示使用正则,不区分大小写。与前缀匹配一样,正则匹配也是只需匹配以url模式开头的即可。
location ~ /[0-9]emo { rewrite ^ http://google.com; }
对于上述的模式,可以匹配的url如下:
- http://127.0.0.1/5emo
- http://127.0.0.1/9emo
- http://127.0.0.1/5emo/aaa
- http://127.0.0.1/5emo/AAA
- http://127.0.0.1/5emoaaa
使用~*则不区分大小写
location ~ /[0-9]EmO { rewrite ^ http://google.com; }
下面的都能匹配
正常匹配
正常匹配的指令为空,即没有指定匹配指令的即为正常匹配。其形式类似 /XXX/YYY.ZZZ正常匹配中的url匹配模式可以使用正则,不区分大小写。
location /demo { rewrite ^ http://google.com; }
上述模式指的是匹配/demo的url,下面的都能匹配
- http://192.168.33.10/demo
- http://192.168.33.10/demo/
- http://192.168.33.10/demo/aaa
- http://192.168.33.10/demo/aaa/bbb
- http://192.168.33.10/demo/AAA
- http://192.168.33.10/demoaaa
- http://192.168.33.10/demo.aaa
正常匹配和前缀匹配的差别在于优先级。前缀的优先级高于正常匹配
全匹配
全匹配与正常匹配一样,没有匹配指令,匹配的url模式仅一个斜杠/
location / { rewrite ^ http://google.com; }
全匹配也可以配合 精确匹配和正则匹配一些指令,只不过这样的设定意义不大。通过都会有一个默认的location,这个就是全匹配
命名匹配
命名匹配指的是使用@绑定一个模式,类似变量替换的用法。
error_page 404 = @not_found location @not_found { rewrite http://google.com; }
上述的作用是如果访问没有匹配的url会触发404指令,然后就匹配到@not_found 这个 location上。
反向代理配置示例:
主要修改的节点为http节点,http { omitted... upstream backend_6001{ #ip_hash; server 192.168.1.207:6001; server 192.168.1.207:6002; } server { listen 5000; server_name lwy.com;
}
}
匹配优先级
nginx的匹配优先级遵循一个大原则和两个小细节。
大原则是关于匹配模式的优先级:
精确匹配 > 前缀匹配 > 正则匹配 > 正常匹配 > 全匹配
小细节则是同一优先级中:
- 细节一:正则匹配成功之后停止匹配,非正则匹配成功还会接着匹配。
- 细节二:在所有匹配成功的url中,选取匹配度最大的url字符地址。
反向代理配置
location / {
#设置主机头和客户端真实地址,以便服务器获取客户端真实IP
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_buffering off;
#设置反向代理的地址 可设为下面介绍的upstream模块
proxy_pass http://192.168.1.1;
}
proxy_redirect
proxy_redirect指定修改被代理服务器返回的响应头中的location头域
location / {
proxy_pass http://192.168.1.207:6001;
proxy_redirect http://192.168.1.207:([1-9][0-9]*)/ http://lwy.cn:5000/lwy$1/;
}
上面proxy_redirect配置将被代理服务器的重定向端口全部映射为/lwy$1/路由上了。然后,可以根据浏览器重定向进来的特殊路由url进行相应的配置,即配置多个location
location ~ /conwin([1-9][0-9]*)/ {
remainder omitted...
}
在指令中可以使用一些变量:
proxy_redirect http://localhost:8000/ http://$host:$server_port/;
proxy_pass
在nginx中配置proxy_pass代理转发时,如果在proxy_pass后面的url加/,表示绝对根路径;如果没有/,表示相对路径,把匹配的路径部分也给代理走。
假设下面四种情况分别用 http://192.168.1.1/proxy/test.html 进行访问。
第一种:
location proxy {
proxy_pass http://127.0.0.1/;
}
代理到URL:http://127.0.0.1/test.html
第二种(相对于第一种,最后少一个 / )
location proxy {
proxy_pass http://127.0.0.1;
}
代理到URL:http://127.0.0.1/proxy/test.html
第三种:
location proxy {
proxy_pass http://127.0.0.1/aaa/;
}
代理到URL:http://127.0.0.1/aaa/test.html
第四种(相对于第三种,最后少一个 / )
location proxy {
proxy_pass http://127.0.0.1/aaa;
}
代理到URL:http://127.0.0.1/aaatest.html
upstream模块
upstream模块主要负责负载均衡的配置,通过默认的轮询调度方式来分发请求到后端服务器
upstream backend {
ip_hash;
server 192.168.1.100:8000;
server 192.168.1.100:8001 down;
server 192.168.1.100:8002 max_fails=3;
server 192.168.1.100:8003 fail_timeout=20s;
server 192.168.1.100:8004 max_fails=3 fail_timeout=20s;
}
location / {
#反向代理的地址
proxy_pass http://backend;
}
核心配置信息如下
- ip_hash:指定请求调度算法,默认是weight权重轮询调度,可以指定
- server host:port:分发服务器的列表配置
- – down:表示该主机暂停服务
- – max_fails:表示失败最大次数,超过失败最大次数暂停服务
- – fail_timeout:表示如果请求受理失败,暂停指定的时间之后重新发起请求
其中,nginx支持的负载均衡调度算法方式如下:
- weight轮询(默认):接收到的请求按照顺序逐一分配到不同的后端服务器,即使在使用过程中,某一台后端服务器宕机,nginx会自动将该服务器剔除出队列,请求受理情况不会受到任何影响。 这种方式下,可以给不同的后端服务器设置一个权重值(weight),用于调整不同的服务器上请求的分配率;权重数据越大,被分配到请求的几率越大;该权重值,主要是针对实际工作环境中不同的后端服务器硬件配置进行调整的。
- ip_hash:每个请求按照发起客户端的ip的hash结果进行匹配,这样的算法下一个固定ip地址的客户端总会访问到同一个后端服务器,这也在一定程度上解决了集群部署环境下session共享的问题。
- fair:智能调整调度算法,动态的根据后端服务器的请求处理到响应的时间进行均衡分配,响应时间短处理效率高的服务器分配到请求的概率高,响应时间长处理效率低的服务器分配到的请求少;结合了前两者的优点的一种调度算法。但是需要注意的是nginx默认不支持fair算法,如果要使用这种调度算法,请安装upstream_fair模块
- url_hash:按照访问的url的hash结果分配请求,每个请求的url会指向后端固定的某个服务器,可以在nginx作为静态服务器的情况下提高缓存效率。同样要注意nginx默认不支持这种调度算法,要使用的话需要安装nginx的hash软件包
遇到的问题
遇到301、302这种重定向的http状态码,浏览器被重定向到其他服务器地址或端口(如内网)。
这种问题通常出现在被代理的服务端不知道代理服务器的存在,直接返回302重定向到另外一个服务器或端口(server2),nginx如果不做处理则浏览器会直接取访问server2,这样便绕过了nginx,如果是内网地址,呵呵,就访问失败了.这时候可以使用location匹配下的proxy_redirect来拦截节点被代理服务器的重定向信息
本文由Weiye Lee原创,转载请注明来源,谢谢:
http://blog.csdn.net/Weiye__Lee/article/details/79472815
参考
Nginx安装及配置详解:https://www.cnblogs.com/zhouxinfei/p/7862285.html
Nginx高级应用之Location Url 配置:https://www.linuxidc.com/Linux/2017-03/141910.htm