一、nginx Proxy 反向代理
1、代理原理
反向代理产生的背景:
在计算机世界里,由于单个服务器的处理客户端(用户)请求能力有一个极限,当用户的接入请求蜂拥而入时,会造成服务器忙不过来的局面,可以使用多个服务器来共同分担成千上万的用户请求,这些服务器提供相同的服务,对于用户来说,根本感觉不到任何差别。
反向代理服务的实现:
需要有一个负载均衡设备(即反向代理服务器)来分发用户请求,将用户请求分发到后端真正提供服务的服务器上。服务器返回自己的服务到负载均衡设备。负载均衡设备将服务器的服务返回用户。
在反向代理中,Nginx代表服务器端,接收和处理客户端的请求。与正向代理(如代理服务器)不同的是,反向代理是位于服务器端的代理服务器。客户端对其发送请求,并不知道实际处理请求的是后端服务器。
Nginx Proxy反向代理的主要优点包括:
负载均衡:Nginx可以将请求平均分发给多个后端服务器,以实现负载均衡,提高系统的性能和可扩展性。
高可用性:当某个后端服务器发生故障或不可用时,Nginx可以自动将请求转发给其他可用的后端服务器,确保服务的高可用性。
缓存功能:Nginx可以缓存静态资源,如图片、CSS和JavaScript文件等,减轻后端服务器的压力,加快访问速度。
安全性:Nginx可以作为反向代理服务器,过滤和防护恶意请求,提高系统的安全性。
2、正/反向代理的区别
正向代理
正向代理的过程隐藏了真实的请求客户端,服务器不知道真实的客户端是谁,客户端请求的服务都被代理服务器代替请求。我们常说的代理也就是正向代理,正向代理代理的是请求方,也就是客户端;比如我们要访问youtube,可是不能访问,只能先安装个FQ软件代你去访问,通过FQ软件才能访问,FQ软件就叫作正向代理。
正向代理的作用
- 为在防火墙内的局域网客户端提供访问Internet的途径
- 可以使用缓冲特性减少网络使用率
- 访问受地理位置限制的网络
- 使用代理后会隐藏真实的IP地址
反向代理
反向代理:(reverse proxy),指的是代理外网用户的请求到内部的指定的服务器,并将数据返回给用户的一种方式。客户端不直接与后端服务器进行通信,而是与反向代理服务器进行通信,隐藏了后端服务器的 IP 地址
反向代理的过程隐藏了真实的服务器,客户不知道真正提供服务的人是谁,客户端请求的服务都被代理服务器处理。反向代理代理的是响应方,也就是服务端;我们请求www.baidu.com时这www.baidu.com就是反向代理服务器,真实提供服务的服务器有很多台,反向代理服务器会把我们的请求分转发到真实提供服务的各台服务器。Nginx就是性能非常好的反向代理服务器,用来做负载均衡。
访问www.baidu.com是反向代理的过程
两者的区别在于代理的对象不一样:正向代理中代理的对象是客户端。反向代理中代理的对象是服务端。
反向代理可实现的功能
反向代理的主要作用是提供负载均衡和高可用性。
- 负载均衡:Nginx可以将传入的请求分发给多个后端服务器,以平衡服务器的负载,提高系统性能和可靠性。
- 缓存功能:Nginx可以缓存静态文件或动态页面,减轻服务器的负载,提高响应速度。
- 动静分离:将动态生成的内容(如 PHP、Python、Node.js 等)和静态资源(如 HTML、CSS、JavaScript、图片、视频等)分别存放在不同的服务器或路径上。
- 多站点代理:Nginx可以代理多个域名或虚拟主机,将不同的请求转发到不同的后端服务器上,实现多个站点的共享端口。
反向代理的可用模块
ngx_http_proxy_module: #将客户端的请求以http协议转发至指定服务器进行处理
ngx_http_upstream_module #用于定义为proxy_pass,fastcgi_pass,uwsgi_pass等指令引用的后端服务器分组
ngx_stream_proxy_module:#将客户端的请求以tcp协议转发至指定服务器处理
ngx_http_fastcgi_module:#将客户端对php的请求以fastcgi协议转发至指定服务器助理
ngx_http_uwsgi_module: #将客户端对Python的请求以uwsgi协议转发至指定服务器处理
3、nginx Proxy 配置
1、代理模块
ngx_http_proxy_module
2、启用 nginx proxy 代理
环境两台nginx真实服务器
a、nginx-1 应用服务器启动
nginx-1的ip:192.168.175.130(作为应用服务器)
已经编译安装好,检查nginx是否启动是否可以访问
b、nginx-2 代理服务器配置
nginx-2的ip:192.168.175.128
编辑nginx的子配置文件: /etc/nginx/conf.d/default.conf
[root@nginx-server ~]# vim /etc/nginx/conf.d/default.conf
server {
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://192.168.175.130:80;
proxy_redirect default;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;
}
}
为了不影响访问可以先把主配置文件里的server块注释掉
重新加载nginx配置文件
[root@nginx-server ~]# nginx -s reload
c、nginx proxy 具体配置详解
proxy_pass :指定后端服务器的地址,可以是ip也可以是域名和url地址 proxy_set_header:设置要传递给后端服务器的HTTP请求头。 proxy_set_header X-Real-IP $remote_addr #只记录连接服务器的上一个ip地址信息。(一般为代理服务器的ip地址) proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #$proxy_add_x_forwarded_for会将客户端的IP地址添加到X-Forwarded-For请求头中,然后传递给后端服务器。X-Forwarded-For的请求头值为客户端的IP地址。通过这个选项可以记录真正客户端机器的ip地址。实现了IP透传 proxy_redirect :如果真实服务器使用的是的真实IP:非默认端口。则改成IP:默认端口。 proxy_connect_timeout:指定连接到后端服务器的超时时间,即发起三次握手等候响应超时时间。 proxy_send_timeout:指定向后端服务器发送请求的超时时间,即在规定时间之内后端服务器必须传完所有的数据。 proxy_read_timeout :指定从后端服务器读取响应的超时时间。 nginx接收upstream(上游/真实) server数据超时, 默认60s, 如果连续的60s内没有收到1个字节, 连接关闭,如长连接。
注意:proxy_pass http:// 填写nginx-1实际应用服务器的地址。
使用PC客户端访问nginx-2服务器地址 浏览器中输入http://192.168.175.128 (nginx-2代理服务器的ip) 成功访问nginx-1应用服务器页面
观察nginx-1服务器的日志
# tail -f /var/log/nginx/access.log
10.0.105.202 - - [27/Jun/2019:15:54:17 +0800] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" "10.0.105.207"
10.0.105.202 代理服务器地址 10.0.105.207 客户机地址。 访问成功。 记录了客户机的IP和代理服务器的IP
二、Nginx负载均衡
1、upstream配置
upstream指令来配置反向代理的后端服务器池。 upstream 配置:写一组被代理的服务器地址,然后配置负载均衡的算法.(80,443一般在七层,upstream做七层负载)
upstream testapp { server 10.0.105.199:8081; server 10.0.105.202:8081; } server { .... location / { proxy_pass http://testapp; #请求转向 testapp 定义的服务器列表 }
2、负载均衡算法(nginx调度策略)
upstream 负载均衡调度算法 1. 轮询算法(Round Robin):每个请求按时间顺序逐一分配到不同的后端服务器;(默认不用写) 2. 加权轮询算法(Weighted Round Robin):根据服务器的处理能力分配权重,按照权重的比例分发请求。 3. IP地址散列算法(IP Hash):每个请求按访问IP的hash结果分配,同一个IP客户端固定访问一个后端服务器。保证来自同一ip的请求被打到固定的机器上,解决session问题。(没有实现负载均衡) 4. 哈希算法(Hash)(也叫url hash):按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器。根据请求的某一特定属性(如源IP地址或请求URL),通过哈希函数计算后得到一个固定的值,再将该值与服务器列表进行匹配,将请求分发给对应的服务器。(没有实现负载均衡) 5. fair算法:基于请求处理时间的负载均衡算法。此种算法可依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx本身是不支持 fair的,如果需要使用这种调度算法,必须下载Nginx的 upstream_fair模块。实现:通过维护一个请求队列,并记录每个后端服务器的处理时间。当新的请求到达时,Fair算法会选择处理时间最短的服务器来处理该请求,并将该请求加入到该服务器的请求队列中。当服务器的处理时间相差不大时,Fair算法的效果较为明显,可以达到较好的负载均衡效果。
3、配置实例
1、热备:如果你有2台服务器,当一台服务器发生事故时,才启用第二台服务器给提供服务。服务器处理请求的顺序:AAAAAA突然A挂啦,BBBBBBBBBBBBBB.....
upstream myweb { server 172.17.14.2:8080; server 172.17.14.3:8080 backup; #热备 }
2、轮询:nginx默认就是轮询其权重都默认为1,服务器处理请求的顺序:ABABABABAB....
upstream myweb { server 172.17.14.2:8080; server 172.17.14.3:8080; }
3、加权轮询:跟据配置的权重的大小而分发给不同服务器不同数量的请求。如果不设置,则默认为1。下面服务器的请求顺序为:ABBABBABBABBABB....
upstream myweb { server 172.17.14.2:8080 weight=1; server 172.17.14.3:8080 weight=2; }
4、ip_hash:nginx会让相同的客户端ip请求相同的服务器。
upstream myweb { server 172.17.14.2:8080; server 172.17.14.3:8080; ip_hash; }
5、nginx负载均衡配置状态参数
- down,表示当前的server暂时不参与负载均衡。 - backup,预留的备份机器。当其他所有的非backup机器出现故障或者忙的时候,才会请求backup机器,因此这台机器的压力最轻。 - max_fails,允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误。(缺点:请求处理失败后需要重新转发请求,多一次请求转发) - fail_timeout,在经历了max_fails次失败后,暂停服务的时间单位秒。max_fails可以和fail_timeout一起使用。(缺点:请求处理失败后需要重新转发请求,多一次请求转发)
upstream myweb { server 172.17.14.2:8080 weight=2 max_fails=2 fail_timeout=2 down; server 172.17.14.3:8080 weight=1 max_fails=2 fail_timeout=1; }
4、nginx配置7层协议
举例讲解下什么是7层协议,什么是4层协议。
(1)7层协议
OSI(Open System Interconnection)是一个开放性的通行系统互连参考模型,他是一个定义的非常好的协议规范,共包含七层协议。直接上图,这样更直观些:
好,详情不进行仔细讲解,可以自行百度!
(2)协议配置
这里我们举例,在nginx做负载均衡,负载多个服务,部分服务是需要7层的,部分服务是需要4层的,也就是说7层和4层配置在同一个配置文件中。
准备三台机器:
代理服务IP:10.0.105. --配置本地host解析域名; 后端服务器IP:nginx-a :10.0.105.199/nginx-b:10.0.105.202(yum安装)后端服务器将nginx服务启动 配置代理服务器的nginx配置文件
worker_processes 4;
worker_rlimit_nofile 102400;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
keepalive_timeout 65;
gzip on;
upstream testweb {
#ip_hash;
server 10.0.105.199:80 weight=2 max_fails=2 fail_timeout=2s;
server 10.0.105.202:80 weight=2 max_fails=2 fail_timeout=2s;
}
server {
listen 80;
server_name www.test.com;
charset utf-8;
#access_log logs/host.access.log main;
location / {
proxy_pass http://testweb;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
202服务器yum安装的创建新的配置文件:
[root@nginx-server ~]# cd /etc/nginx/conf.d/
[root@nginx-server conf.d]# cp default.conf test.conf
[root@nginx-server conf.d]# cat test.conf
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
[root@nginx-server ~]# nginx -s reload
浏览器测试访问:
http://www.test.com/
nginx 配置后端健康检查模块
ngx_http_proxy_module VS nginx_upstream_check_module
nginx自带的针对后端节点健康检查的功能比较简单,通过默认自带的ngx_http_proxy_module 模块和ngx_http_upstream_module模块中的参数来完成,当后端节点出现故障时,自动切换到健康节点来提供访问。但是nginx不能事先知道后端节点状态是否健康,后端即使有不健康节点,负载均衡器依然会先把请求转发给该不健康节点,然后再转发给别的节点,这样就会浪费一次转发,而且自带模块无法做到预警。所以我们可以使用第三方模块 nginx_upstream_check_module模块 nginx_upstream_check_module模块由淘宝团队开发 淘宝自己的 tengine 上是自带了该模块的。我们使用原生Nginx,采用添加模块的方式
获取nginx_upstream_check_module模块
从github上面获取就可以了。
[root@nginx-server ~]# yum install -y unzip
下载模块
[root@nginx-server ~]# wget https://github.com/yaoweibin/nginx_upstream_check_module/archive/refs/heads/master.zip
[root@nginx-server ~]# unzip -d /usr/local/ master.zip
安装补丁:
注意 check版本和Nginx版本要求有限制 1.12以上版本的nginx,补丁为check_1.20.1+.patch 具体参考github
# ls nginx_upstream_check_module-master/
# -p0,是“当前路径” -p1,是“上一级路径”
[root@nginx-server ~]# cd /usr/local/nginx-1.22.1/ #进入nginx的解压目录中
[root@nginx-server nginx-1.22.1]# yum install -y patch
[root@nginx-server nginx-1.22.1]# patch -p1 < ../nginx_upstream_check_module-master/check_1.20.1+.patch
[root@nginx-server nginx-1.22.1]# nginx -V #查看nginx配置路径
[root@nginx-server nginx-1.22.1]# ./configure --prefix=/usr/local/nginx --group=nginx --user=nginx --sbin-path=/usr/local/nginx/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/tmp/nginx/client_body --http-proxy-temp-path=/tmp/nginx/proxy --http-fastcgi-temp-path=/tmp/nginx/fastcgi --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_gzip_static_module --with-pcre --with-http_realip_module --with-stream --add-module=../nginx_upstream_check_module-master/
[root@nginx-server nginx-1.22.1]# make #如果是添加模块只需要make 第一次安装需要make install
[root@nginx-server nginx-1.22.1]# mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak #将原来的nginx二进制命令备份
[root@nginx-server nginx-1.22.1]# ls objs/
[root@nginx-server nginx-1.22.1]# /usr/local/nginx/sbin/nginx
[root@nginx-server nginx-1.22.1]# /usr/local/nginx/sbin/nginx stop
[root@nginx-server nginx-1.22.1]# cp objs/nginx /usr/local/nginx/sbin/ #将新生成的命令cp到nginx的命令目录中。# \cp不提醒,覆盖粘贴复制
配置健康检查
# vim /etc/nginx/nginx.conf
http {
upstream app {
server 192.168.209.128 weight=1;
server 192.168.209.130 weight=1;
check interval=5000 rise=2 fall=3 timeout=4000 type=http port=80;
check_http_send "HEAD / HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://app;
proxy_redirect default;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /status { #开启监控状态页面,自定义如serverup
check_status;
access_log off;
}
}
}
参数解释:
interval:表示每隔多少毫秒向后端发送健康检查包;
rise:表示如果连续成功次数达到2 服务器就被认为是up;
fail:表示如果连续失败次数达到3 服务器就被认为是down;
timeout:表示后端健康请求的超时时间是多少毫秒;
type:表示发送的健康检查包是什么类型的请求;
port: 表示发送检查到后端的服务的端口;
check_http_send:表示http健康检查包发送的请求内容。为了减少传输数据量,推荐采用“head”方法;
check_http_expect_alive:指定HTTP回复的成功状态,默认认为2XX和3XX的状态是健康的;
浏览器查看访问状态
5、层协议方法(扩展)
(2)4层协议
TCP/IP协议
之所以说TCP/IP是一个协议族,是因为TCP/IP协议包括TCP、IP、UDP、ICMP、RIP、SMTP、ARP、TFTP等许多协议,这些协议一起称为TCP/IP协议。
从协议分层模型方面来讲,TCP/IP由四个层次组成:网络接口层、网络层、传输层、应用层。
nginx在1.9.0的时候,增加了一个 stream 模块,用来实现四层协议(网络层和传输层)的转发、代理、负载均衡等。stream模块的用法跟http的用法类似,允许我们配置一组TCP或者UDP等协议的监听.
配置案例: stream块是与http块同一级别
#4层tcp负载
stream {
upstream ssh_01 {
server 192.168.209.129:22;
}
server {
listen 6666;
proxy_pass ssh_01;
proxy_timeout 60s;
proxy_connect_timeout 30s;
}
}
三、nginx 会话保持
nginx会话保持主要有以下几种实现方式。
1、ip_hash
ip_hash使用源地址哈希算法,将同一客户端的请求总是发往同一个后端服务器,除非该服务器不可用。 ip_hash语法:
upstream backend {
ip_hash;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com down;
}
ip_hash简单易用,但有如下问题: 当后端服务器宕机后,session会丢失; 来自同一局域网的客户端会被转发到同一个后端服务器,可能导致负载失衡;
2、sticky_cookie_insert---基于cookie实现
使用sticky_cookie_insert启用会话亲缘关系,让来自同一客户端的请求被传递到一组服务器的同一台服务器。与ip_hash不同之处在于,它不是基于IP来判断客户端的,而是基于cookie来判断。 第三方模块---sticky模块,可以避免上述ip_hash中来自同一局域网的客户端和前段代理导致负载失衡的情况。
过程:
编译安装sticky模块,#给yum安装的nginx添加模块
[root@nginx-server ~]# yum install -y pcre* openssl* gcc gcc-c++ make 安装编译环境
[root@nginx-server ~]# wget https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng/get/08a395c66e42.zip #下载sticky模块
[root@nginx-server ~]# nginx -v
nginx version: nginx/1.18.0
[root@nginx-server ~]# wget http://nginx.org/download/nginx-1.18.0.tar.gz #下载yum安装nginx对应版本的源码包
[root@nginx-server ~]# yum install -y unzip #安装解压工具
[root@nginx-server ~]# unzip 08a395c66e42.zip #解压模块包
[root@nginx-server ~]# mv nginx-goodies-nginx-sticky-module-ng-08a395c66e42/ nginx-sticky-module-ng/ #重命名一个简洁的文件名
[root@nginx-server ~]# tar xzvf nginx-1.18.0.tar.gz -C /usr/local/ #解压nginx的源码包
[root@nginx-server ~]# cd /usr/local/nginx-1.18.0/
[root@nginx-server nginx-1.18.0]# nginx -V #查看yum安装nginx所有模块
[root@nginx-server nginx-1.18.0]# ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie' --add-module=/root/nginx-sticky-module-ng
[root@nginx-server nginx-1.18.0]# make && make install
配置基于cookie会话保持
[root@nginx-server conf.d]# vim upstream.conf
upstream web1 {
server 192.168.198.143;
server 192.168.198.145;
sticky;
}
[root@nginx-server conf.d]# vim proxy.conf
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
proxy_pass http://qfedu;
}
}
[root@nginx-server conf.d]# nginx -t
[root@nginx-server conf.d]# nginx -s reload
或者:
upstream web1 {
server 192.168.198.143;
server 192.168.198.145;
sticky expires=1h domain=testpm.com path=/;
}
说明:
expires:设置浏览器中保持cookie的时间
domain:定义cookie的域
path:为cookie定义路径
浏览器测试访问
# nginx -s reload
# curl -I ip地址
注意:使用后端服务器自身通过相关机制保持session同步,如:使用数据库、redis、memcached 等做session复制
四、nginx 实现动静分离
为了加快网站的解析速度,可以把动态页面和静态页面由不同的服务器来解析,加快解析速度。降低原来单个服务器的压力。 简单来说,就是使用正则表达式匹配过滤,然后交个不同的服务器。动态内容通常是由后端应用程序生成的,而静态内容是指不经常变化的文件,如HTML、CSS、JavaScript、图片等。
准备环境
准备一个nginx代理 两个http 分别处理动态和静态。
expires功能说明---(为客户端配置缓存时间) nginx缓存的设置可以提高网站性能,对于网站的图片,尤其是新闻网站,图片一旦发布,改动的可能是非常小的,为了减小对服务器请求的压力,提高用户浏览速度,我们可以通过设置nginx中的expires,让用户访问一次后,将图片缓存在用户的浏览器中,且时间比较长的缓存。 原理:当nginx设置了expires后,例如设置为:expires 10d; 那么用户在10天内请求的时候,都只会访问浏览器中的缓存,而不会去请求nginx。 注:需要注意的是,这种缓存方式只能在用户不对浏览器强制刷新的情况下生效,如果用户通过url来进行访问,是可以访问到缓存的。
1.静态资源配置
server {
listen 80;
server_name localhost;
location ~ \.(html|jpg|png|js|css) {
root /home/www/nginx;
expires 1d; #为客户端设置静态资源缓存时间,如1h,1m
}
}
# \ 转义
测试:
[root@nginx-yum2 conf.d]# curl -I http://10.0.105.200/test.jpg
HTTP/1.1 200 OK
Server: nginx/1.16.0
Date: Mon, 07 Sep 2019 11:35:08 GMT
Content-Type: image/jpeg
Content-Length: 27961
Last-Modified: Mon, 07 Sep 2019 11:31:17 GMT
Connection: keep-alive
ETag: "5f561a05-6d39"
Expires: Tue, 08 Sep 2019 11:35:08 GMT #缓存到期时间
Cache-Control: max-age=86400 #缓存持续时间(秒)
Accept-Ranges: bytes
2.动态资源配置
yum 安装php7.1
~]# yum install -y epel-release
~]# rpm -ivh http://rpms.remirepo.net/enterprise/remi-release-7.rpm
~]# cd /etc/yum.repos.d/
~]# ls
remi-php73.repo remi-php74.repo
remi-php80.repo nginx.repo
remi-php81.repo remi-modular.repo
remi-php82.repo remi-php54.repo
remi-php83.repo remi-php70.repo
remi.repo remi-php71.repo
remi-safe.repo epel.repo
remi-php72.repo
~]# yum install -y yum-utils
~]# yum-config-manager --enable remi-php71 #启用remi-php71软件仓库
~]# yum install php-xsl php php-ldap php-cli php-common php-devel php-gd php-pdo php-mysql php-mbstring php-bcmath php-mcrypt -y
~]# yum install -y php-fpm
~]# systemctl start php-fpm
~]# systemctl enable php-fpm
动态服务器编辑nginx连接php
~]# vim /etc/nginx/conf.d/default.conf #编辑nginx的配置文件:
server {
listen 80;
server_name localhost;
location ~ \.php$ {
root usr/share/nginx/html; #指定网站目录
fastcgi_pass 127.0.0.1:9000; #开启fastcgi连接php地址
fastcgi_index index.php; #指定默认文件
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
#站点根目录,取决于root配置项
include fastcgi_params; #包含fastcgi使用的常量
}
}
~]# cd /usr/share/nginx/html
html]# vim index.php
3.配置nginx反向代理upstream,并实现客户端缓存时间
# vim /etc/nginx/conf.d/upstream.conf
upstream static {
server 10.0.105.196:80 weight=1 max_fails=1 fail_timeout=60s;
}
upstream php {
server 10.0.105.200:80 weight=1 max_fails=1 fail_timeout=60s;
}
server {
listen 80;
server_name localhost
#动态资源加载
location ~ \.(php|jsp)$ {
proxy_pass http://php;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
#静态资源加载
location ~ .*\.(html|jpg|png|css|js)$ {
proxy_pass http://static;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
当访问静态页面的时候location 匹配到 (html|jpg|png|js|css) 通过转发到静态服务器,
静态服务通过location的正则匹配来处理请求。
当访问动态页面时location匹配到 .\php 结尾的文件转发到后端php服务处理请求。
五、nginx的localtion指令详解
nginx中的location指令用于指定请求的处理位置。它可以根据请求的URI进行匹配,并且根据匹配结果执行相应的操作。
location指令的语法如下:location [修饰符] 匹配规则 { ...操作内容... }
Nginx 的 HTTP 配置主要包括三个区块,结构如下:
http { # 这个是协议级别
include mime.types;
default_type application/octet-stream;
keepalive_timeout 65;
gzip on;
server { # 这个是服务器级别
listen 80;
server_name localhost;
location / { # 这个是请求级别
root html;
index index.html index.htm;
}
}
}
1、location 区段
- location 是在 server 块中配置,根据不同的 URI 使用不同的配置,来处理不同的请求。
- location 是有顺序的,会根据不同请求配置的优先级来匹配的location 处理。
基本语法如下:
location [=|~|~*|^~|@] pattern{……}
2、location 前缀含义
= 表示精确匹配,优先级最高,只有请求的URI与匹配规则完全一致时才会执行操作
^~ 普通字符串前缀匹配,表示uri以某个常规字符串开头
~ 区分大小写的正则匹配
~* 不区分大小写的正则匹配
!~ 表示区分大小写不匹配的正则
!~* 表示不区分大小写不匹配的正则
/ 通用匹配,任何请求都会匹配到,优先级最低
查找顺序和优先级
= 大于 ^~ 大于 ~|~*|!~|!~* 大于 /
多个location配置的情况下匹配顺序为:
首先匹配 =,其次匹配^~, 其次是按正则匹配,最后是交给 / 通用匹配。
当有匹配成功时候,停止匹配,按当前匹配规则处理请求。
3、location 配置示例
1、没有修饰符 表示:必须以指定模式开始
# mkdir -p /data/www/abc
# echo abc >> /data/www/abc/1.html
# vim vim /etc/nginx/conf.d/app.conf
server {
listen 80;
server_name localhost;
location /abc {
root /data/www;
index 1.html;
}
# nginx -t
# systemctl restart nginx
访问测试
http://192.168.1.9/abc
2、=表示:必须与指定的模式精确匹配
# vim /etc/nginx/conf.d/app.conf
server {
listen 80;
server_name localhost;
access_log /var/log/nginx/http_access.log main;
location /abc {
root /data/www;
index 1.html;
}
location / {
return https://www.baidu.com;
}
location = / {
return https://www.jd.com;
}
}
# nginx -s reload
测试:访问192.168.1.9/abc(注意浏览器无缓存)
可以看的直接跳转到京东
3、~ 表示:指定的正则表达式要区分大小写
# mkdir /data/www/nginx
# ls /data/www/
#
server {
server_name localhost;
location ~ /abc {
root /data/www/nginx;
index 2.html index.html;
}
}
测试访问:
http://192.168.1.9/abc
不正确的
http://192.168.1.9/ABC
========================================
如果将配置文件修改为
location ~ /ABC {
root /home/www/nginx;
index 2.html index.html;
}
创建目录和文件:
[root@ansible-server html]# cd /home/www/nginx/
[root@ansible-server nginx]# mkdir ABC
[root@ansible-server nginx]# vim ABC/2.html
访问:
http://192.168.1.9/ABC/
结论:~ 需要区分大小写。而且目录需要根据大小写定义。
404原因:访问路径是否正确;访问目录是否存在;路径大小写是否正确;
4、^~和~*匹配案例
~*:表示不区分大小写的正则匹配
[root@localhost conf.d]# vim /etc/nginx/conf.d/default.conf
server {
listen 80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location ~* /a/b/ {
return 888;
}
}
测试:
[root@localhost ~]# curl -I http://192.168.209.200/a/b/
HTTP/1.1 888
Server: nginx/1.24.0
Date: Fri, 24 Nov 2023 08:14:09 GMT
Content-Length: 0
Connection: keep-alive
[root@localhost ~]# curl -I http://192.168.209.200/A/B/
HTTP/1.1 888
Server: nginx/1.24.0
Date: Fri, 24 Nov 2023 08:16:52 GMT
Content-Length: 0
Connection: keep-alive
^~:表示uri以某个常规字符串开头,理解为匹配url路径即可
例如:下面配置文件有两条规则,分别匹配url以字母a开头,但是长度不同,首先将长的规则先注释掉,如下:
# vim /etc/nginx/conf.d/default.conf
server {
listen 80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location ^~ /a/ {
return 123;
}
#location ^~ /a/b/ { #注释掉/a/b
#return 12345;
#}
}
测试:
# curl -I http://192.168.209.200/a/
HTTP/1.1 678
Server: nginx/1.24.0
Date: Fri, 24 Nov 2023 08:28:03 GMT
Content-Length: 0
Connection: keep-alive
[root@localhost ~]# curl -I http://192.168.209.200/a/b/
HTTP/1.1 678
Server: nginx/1.24.0
Date: Fri, 24 Nov 2023 08:28:07 GMT
Content-Length: 0
Connection: keep-alive
[root@localhost ~]# curl -I http://192.168.209.200/a/b/dsdfsdf
HTTP/1.1 678
Server: nginx/1.24.0
Date: Fri, 24 Nov 2023 08:28:10 GMT
Content-Length: 0
Connection: keep-alive
结论:
当前只有一个规则开启,因此当匹配url以/a/开头的任何url时,都会返回状态码678
# vim /etc/nginx/conf.d/default.conf
server {
listen 80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location ^~ /a/ {
return 678;
}
location ^~ /a/b/ { # 取消注释
return 876;
}
}
测试:
# curl -I http://192.168.209.200/a/
HTTP/1.1 678
Server: nginx/1.24.0
Date: Fri, 24 Nov 2023 08:44:52 GMT
Content-Length: 0
Connection: keep-alive
# curl -I http://192.168.209.200/a/b/
HTTP/1.1 876
Server: nginx/1.24.0
Date: Fri, 24 Nov 2023 08:44:56 GMT
Content-Length: 0
Connection: keep-alive
# curl -I http://192.168.209.200/a/b/sdgsdgdg
HTTP/1.1 876
Server: nginx/1.24.0
Date: Fri, 24 Nov 2023 08:44:58 GMT
Content-Length: 0
Connection: keep-alive
结论:
两条规则同时被匹配成功,但是第二条规则比较长,因此第二条规则优先被匹配。(最长匹配)
六、nginx 地址重写 rewrite
1、什么是Rewrite
Rewrite对称URL Rewrite,即URL重写,就是把传入Web的请求重定向到其他URL的过程
-
从安全角度上讲,如果在URL中暴露太多的参数,无疑会造成一定量的信息泄漏,可能会被一些黑客利用,对你的系统造成一定的破坏,所以静态化的URL地址可以给我们带来更高的安全性。
-
实现网站地址跳转,例如用户访问360buy.com,将其跳转到jd.com。例如当用户访问tianyun.com的80端口时,将其跳转到443端口。
2、Rewrite 相关指令
-
Nginx Rewrite 相关指令有 if、rewrite、set、return
-
语法
rewrite regex replacement [flag];
regex是用来匹配请求URI的正则表达式,
replacement是用来替换匹配到的部分的字符串。
flag是可选的标志,用于指定重写规则的行为。
2.1、if 语句
-
应用环境
作用域: server块 location块
语法:
if (condition) { … } if 可以支持如下条件判断匹配符号 ~ 正则匹配 (区分大小写) ~* 正则匹配 (不区分大小写) !~ 正则不匹配 (区分大小写) !~* 正则不匹配 (不区分大小写) -f 和!-f 用来判断是否存在文件 -d 和!-d 用来判断是否存在目录 -e 和!-e 用来判断是否存在文件或目录 -x 和!-x 用来判断文件是否可执行 在匹配过程中可以引用一些Nginx的全局变量 $args 请求中的参数; $document_root 针对当前请求的根路径设置值; $host 请求信息中的"Host",如果请求中没有Host行,则等于设置的服务器名; $limit_rate 对连接速率的限制; $request_method 请求的方法,比如"GET"、"POST"等; $remote_addr 客户端地址; $remote_port 客户端端口号; $remote_user 客户端用户名,认证用; $request_filename 当前请求的文件路径名(带网站的主目录/usr/local/nginx/html/images/a.jpg) $request_uri 当前请求的文件路径名(不带网站的主目录/images/a.jpg) $query_string 与$args相同; $scheme 用的协议,比如http或者是https $server_protocol 请求的协议版本,"HTTP/1.0"或"HTTP/1.1"; $server_addr 服务器地址,如果没有用listen指明服务器地址,使用这个变量将发起一次系统调用以取得地址(造成资源浪费); $server_name 请求到达的服务器名; $document_uri 与$uri一样,URI地址; $server_port 请求到达的服务器端口号;
2.2、Rewrite flag
rewrite 指令根据表达式来重定向URI,或者修改字符串。可以应用于server,location, if环境下每行rewrite指令最后跟一个flag标记,支持的flag标记有:
last 表示完成rewrite。默认为last。 break 本条规则匹配完成后,终止匹配,不再匹配后面的规则 redirect 返回302临时重定向,浏览器地址会显示跳转后的URL地址 permanent 返回301永久重定向,浏览器地址会显示跳转后URL地址
redirect 和 permanent区别则是返回的不同方式的重定向:
对于客户端来说一般状态下是没有区别的。而对于搜索引擎,相对来说301的重定向更加友好,如果我们把一个地址采用301跳转方式跳转的话,搜索引擎会把老地址的相关信息带到新地址,同时在搜索引擎索引库中彻底废弃掉原先的老地址。
使用302重定向时,搜索引擎(特别是google)有时会查看跳转前后哪个网址更直观,然后决定显示哪个,如果它觉的跳转前的URL更好的话,也许地址栏不会更改。
1、Rewrite匹配参考示例
本地解析host文件--wind
# http://www.testpm.com/a/1.html ==> http://www.testpm.com/b/2.html
location /a {
root /html; #可不写
index 1.html index.htm; #可不写
rewrite .* /b/2.html permanent;
}
location /b {
root /html;
index 2.html index.htm;
}
例2:(二级目录跳转,(.*)捕获了所有/2019/二级目录后面的路径和查询参数)
# http://www.testpm.com/2019/a/1.html ==> http://www.testpm.com/2018/a/1.html
location /2019/a {
root /var/www/html;
index 1.html index.hml;
rewrite ^/2019/(.*)$ /2018/$1 permanent;
}
location /2018/a {
root /var/www/html;
index 1.html index.htl;
}
例3:
# http://www.qf.com/a/1.html ==> http://jd.com
location /a {
root /html;
if ($host ~* www.baidu.com ) {
rewrite .* http://jd.com permanent;
}
}
例4:
# http://www.qf.com/a/1.html ==> http://jd.com/a/1.html
location /a {
root /html;
if ( $host ~* baidu.com ){
rewrite .* http://jd.com$request_uri permanent;
}
}
例5:
# http://www.tianyun.com/login/tianyun.html ==> http://www.tianyun.com/reg/login.html?user=tianyun
location /login {
root /usr/share/nginx/html;
rewrite ^/login/(.*)\.html$ http://$host/reg/login.html?user=$1;
}
location /reg {
root /usr/share/nginx/html;
index login.html;
}
例6:
#http://www.tianyun.com/qf/11-22-33/1.html ==> http://www.tianyun.com/qf/11/22/33/1.html
location /qf {
rewrite ^/qf/([0-9]+)-([0-9]+)-([0-9]+)(.*)$ /qf/$1/$2/$3$4 permanent;
}
location /qf/11/22/33 {
root /html;
index 1.html;
}
2、set 指令
set 指令是用于定义一个变量,并且赋值
应用环境:
server,location,if
应用示例
例8:
#http://alice.testpm.com ==> http://www.testpm.com/alice
#http://jack.testpm.com ==> http://www.testpm.com/jack
[root@nginx-server conf.d]# cd /usr/share/nginx/html/
[root@nginx-server html]# mkdir jack alice
[root@nginx-server html]# echo "jack.." >> jack/index.html
[root@nginx-server html]# echo "alice.." >> alice/index.html
本地解析域名host文件
打开windows本地文件:C:\Windows\System32\drivers\etc\hosts
10.0.105.202 www.testpm.com
10.0.105.202 alice.testpm.com
10.0.105.202 jack.testpm.com
# echo alice >> /usr/share/nginx/html/alice/index.html
# echo jack >> /usr/share/nginx/html/jack/index.html
# vim /etc/nginx/conf.d/app.conf
#编辑配置文件,不同配置文件需要区别域名或者端口,如下端口设置为81
server {
listen 81;
server_name www.testpm.com;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
if ( $host ~* ^www.testpm.com$) {
break;
}
if ( $host ~* "^(.*)\.testpm\.com$" ) {
set $user $1;
rewrite .* http://www.testpm.com/$user permanent;
}
}
location /jack {
root /usr/share/nginx/html;
index index.html;
}
location /alice {
root /usr/share/nginx/html;
index index.html;
}
}
3、return 指令
return 指令用于返回状态码给客户端
server,location,if
应用示例:
例9:如果访问的.sh结尾的文件则返回403操作拒绝错误
server {
listen 80;
server_name www.testpm.cn;
#access_log /var/log/nginx/http_access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location ~* \.sh$ {
return 403;
}
}
例10:80 ======> 443 :80转443端口
server {
listen 80;
server_name www.testpm.cn;
access_log /var/log/nginx/http_access.log main;
return 301 https://www.testpm.cn$request_uri;
}
server {
listen 443 ssl;
server_name www.testpm.cn;
access_log /var/log/nginx/https_access.log main;
#ssl on;
ssl_certificate /etc/nginx/cert/2447549_www.testpm.cn.pem;
ssl_certificate_key /etc/nginx/cert/2447549_www.testpm.cn.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 / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
[root@nginx-server ~]# curl -I http://www.testpm.cn
HTTP/1.1 301 Moved Permanently
Server: nginx/1.16.0
Date: Wed, 03 Jul 2019 13:52:30 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://www.testpm.cn/
4、last,break详解
last
指令:当使用last
指令时,Nginx会重新开始处理匹配的location块。它会重新解析URI,并在重新匹配的location块中继续处理请求。
break
指令:当使用break
指令时,Nginx会停止在当前的location块中处理请求,并直接返回对应的内容。这个指令在重写URI时特别有用,它会停止后续的location匹配过程。
[root@localhost test]# cat /etc/nginx/conf.d/last_break.conf
server {
listen 80;
server_name localhost;
access_log /var/log/nginx/last.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /break/ {
root /usr/share/nginx/html;
rewrite .* /test/break.html break;
}
location /last/ {
root /usr/share/nginx/html;
rewrite .* /test/last.html last;
}
location ~ /test/ { #二级目录test后要加/,因为要进入test匹配内容
root /usr/share/nginx/html;
rewrite .* /test/test.html break;
}
}
[root@localhost conf.d]# cd /usr/share/nginx/html/
[root@localhost html]# mkdir test #最终跳转路径需要有对应目录和文件内容
[root@localhost html]# echo "last" > test/last.html
[root@localhost html]# echo "break" > test/break.html
[root@localhost html]# echo "test" > test/test.html
http://10.0.105.196/break/break.html
http://10.0.105.196/last/last.html
注意:
- last 标记在本条 rewrite 规则执行完后,会对其所在的 server { … } 标签重新发起请求;
- break 标记则在本条规则匹配完成后,停止匹配,不再做后续的匹配;
- 使用 proxy_pass 指令时,则必须使用break。