速通Nginx基础教程
概述
nginx是开源、高性能、高可靠的Web服务器和反向代理服务器,支持热部署,几乎可以做到7+24小时不间断运行,即使运行几个月也不需要重新启动,还能在不间断服务的情况下对软件进行热更新。性能是nginx最终要的考量,其占用内存少、并发能力强,能支持高达5w个并发连接数,最终要的是nginx是免费的并可以商业化,配置使用也比较简单。
nginx特点
- 高并发、高性能
- 模块化架构使得它的扩展性能非常好
- 异步非阻塞的事件驱动模型(epoll)
- 相对于其他服务器来说它可以连续几个月甚至更长不需要重启服务器使它具有更高可靠性
- 热部署、平滑升级
- 完全开源、生态繁荣
作用
- http服务器
- 虚拟主机
- 反向代理、负载均衡
- 配置安全管理、可以使用nginx搭建API接口网关,对每个接口进行拦截
静态服务 | 代理服务 | 安全服务 | 流行架构 |
---|---|---|---|
浏览器缓存 | 协议类型 | 访问控制 | Nginx+PHP(Fastcgi_pass)LNMP |
防资源盗用 | 正向代理 | 访问限制 | Nginx+Java(Proxy_Pass)LNMT |
资源分类 | 反向代理 | 流量限制 | Nginx+Python(uwsgi_pass) |
资源压缩 | 负载均衡 | 拦截攻击 | |
资源缓存 | 代理缓存 | 拦截异常请求 | |
跨域访问 | 动静分离 | 拦截SQL 注入 |
nginx工作原理
服务搭建(基于centos7)
yum安装
yum -y install nginx
systemctl start nginx
systemctl disable --now firewalld
setenforce 0
编译安装
#编译前环境准备,后续添加模块时编译必备环境
yum -y install pcre pcre-devel zlib zlib-devel make gcc-c++ gd gd-devel perl-ExtUtils-Embed pcre pcre-devel openssl-devel libxml2 libxml2-devel xslt libxslt
wget https://nginx.org/download/nginx-1.28.0.tar.gz
tar -xf nginx-1.28.0.tar.gz
cd nginx-1.28.0
#无模块编译安装
./configure --prefix=/usr/local/nginx && make && make install
#配置nginx快捷启动
echo 'export $PATH:/usr/local/nginx/sbin' >> /etc/profile
source /etc/profile
c
#有模块编译
./configure --prefix=/usr/local/nginx --with-compat --with-debug --with-file-aio --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_degradation_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_mp4_module --with-http_perl_module=dynamic --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=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads
make && make install
目录结构
- yum安装
/etc/nginx/#配置文件目录
/var/lib/nginx/ #临时数据文件目录
/var/log/nginx/ #日志文件目录
/usr/share/nginx/html/ #用户访问页面根目录
/etc/nginx/conf.d/ #用户自定义配置文件目录
/etc/nginx/default/ #默认配置文件目录
- 编译安装
/usr/local/nginx/conf/
/usr/local/nginx/conf/conf.d/
/usr/local/nginx/conf/default.d/
/usr/local/nginx/html
/usr/local/nginx/logs
/usr/local/nginx/sbin
核心配置文件
[root@client conf]# pwd
/usr/local/nginx/conf
[root@client conf]# ls
fastcgi.conf koi-win scgi_params
fastcgi.conf.default mime.types scgi_params.default
fastcgi_params mime.types.default uwsgi_params
fastcgi_params.default nginx.conf uwsgi_params.default
koi-utf nginx.conf.default win-utf
配置文件名称 | 配置文件作用 |
---|---|
fastcgi.conf | 此文件包含了FastCGI相关的配置,用于与FastCGI进程通信 |
fastcgi.conf.default | 此文件是fastcgi.conf的备份副本 |
fastcgi_params | 此文件包含了用于FastCGI的参数配置,包括fastcgi的传输协议、请求超时时间等 |
fastcgi_params.default | 此文件是fastcgi_params的备份副本 |
koi-utf | 此文件包含了UTF-8编码与KOI8-R编码之间的字符转换规则,用于处理中文文件名等问题 |
koi-win | 此文件包含了Windows系统的字符转换规则,用于处理Windows系统的文件名问题 |
mime.types | 此文件包含了Nginx支持的MIME类型配置,用于设置相应的Content-Type头 |
mime.types.default | 此文件是mime.types的备份副本 |
nginx.conf | Nginx的主要配置文件,其中包含了所有全局配置和访问控制规则,作为Nginx服务器的入口文件 |
nginx.conf.default | 此文件是nginx.conf的备份副本 |
scgi_params | 此文件包含了用于SCGI协议的参数配置 |
scgi_params.default | 此文件是scgi_params的备份副本 |
uwsgi_params | 此文件包含了用于uWSGI协议的参数配置 |
uwsgi_params.default | 此文件是uwsgi_params的备份副本 |
win-utf | 此文件包含了Windows系统的字符转换规则,用于处理Windows系统的文件名问题 |
配置文件详解
##全局配置,对全局生效##
user nobody nobody; # 指定运行 Nginx 进程的用户为 nobody,组为nobody
pid /var/run/nginx.pid # master主进程的的pid存放在nginx.pid的文件
worker_processes 1; # 指定 Nginx 启动的 worker 子进程数量。
#worker_processes auto; # 与当前cpu物理核心数一致
worker_rlimit_nofile 20480; # 指定 worker 子进程可以打开的最大文件句柄数。
worker_rlimit_core 50M; # 指定 worker 子进程异常终止后的 core 文件,用于记录分析问题。
working_directory /opt/nginx/tmp; # 存放目录
worker_priority -10; # 指定 worker 子进程的 nice 值,以调整运行 Nginx 的优先级,通常设定为负值,以优先调用 Nginx。
#Linux 默认进程的优先级值是120,值越小越优先;nice 定范围为 -20 到 +19 。
#应用的默认优先级值是120加上 nice 值等于它最终的值,这个值越小,优先级越高。
worker_shutdown_timeout 5s; #指定 worker 子进程优雅退出时的超时时间。
timer_resolution 100ms; #worker 子进程内部使用的计时器精度,调整时间间隔越大,系统调用越少,有利于性能提升;反之,系统调用越多,性能下降。
daemon on; # 指定 Nginx 的运行方式,前台还是后台,前台用于调试,后台用于生产。默认是on,后台运行模式。
error_log logs/error.log; # 错误日志文件路径
##events:配置影响 Nginx 服务器与用户的网络连接;##
events {
use epoll; # 使用epoll的I/O模型(如果你不知道Nginx该使用哪种轮询方法,会自动选择一个最适合你操作系统的)
worker_connections 1024; # 允许的最大并发连接数
accept_mutex on; # 是否打开负载均衡互斥锁,默认是off关闭的,这里推荐打开
}
##http:配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置;##
http {
include mime.types; # 包含 MIME 类型的定义,文件扩展名与类型映射表
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; # 启用零拷贝传输,高效传输模式
tcp_nopush on; # 启用 TCP nopush 选项,减少网络报文段的数量
keepalive_timeout 0; # 禁用持久连接的超时时间
keepalive_timeout 65; # 保持存活连接的超时时间
gzip on; # 开启 Gzip 压缩
include /etc/nginx/conf.d/*.conf; # 加载自定义配置项
##upstream:配置后端服务器具体地址,负载均衡配置不可或缺的部分。##
upstream back_end_server{
server 192.168.100.33:8081 #定义后端web服务器节点
}
##server:配置虚拟主机的相关参数,一个 http 块中可以有多个 server 块;每个nginx相当于一个虚拟服务器的地位。##
server {
listen 80; # 监听端口 80
server_name localhost; # 服务器名为 localhost
charset koi8-r; # 字符集设置为 koi8-r
access_log logs/host.access.log main; # 主机访问日志文件及使用的日志格式
##location:用于配置匹配的 uri ;##
location / {
root html; # 指定静态资源目录位置,它可以写在 http 、 server 、 location 等配置中。
index index.html index.htm; # 默认的索引文件
deny 172.168.22.11; # 禁止访问的ip地址,可以为all
allow 172.168.33.44;# 允许访问的ip地址,可以为all
}
location /image {
alias /opt/nginx/static/image/;#它也是指定静态资源目录位置,使用alias末尾一定要添加 / ,只能写在 location 中。
}
#当用户访问 www.jx.com/image/1.png 时,实际在服务器找的路径是 /opt/nginx/static/image/1.png
error_page 404 /404.html; # 设置 404 错误页面的位置为 /404.html
error_page 500 502 503 504 /50x.html; # 将服务器错误页面重定向到 /50x.html
location = /50x.html {
root html;
}
location ~ \.php$ {
proxy_pass http://127.0.0.1; # 将 PHP 脚本代理到监听在 127.0.0.1:80 上的 Apache 服务器
}
location ~ \.php$ {
root html; # PHP 脚本位置
fastcgi_pass 127.0.0.1:9000; # 向 FastCGI 服务器传递 PHP 脚本
fastcgi_index index.php; # 指定 FastCGI 服务器默认的脚本文件名
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # FastCGI 参数配置
include fastcgi_params; # 包含 FastCGI 相关的参数配置
}
location ~ /\.ht {
deny all; # 阻止访问 .htaccess 文件
}
}
server {
listen 8000; # 监听端口 8000
listen somename:8080; # 监听 somename:8080
server_name somename alias another.alias; # 服务器名设置
location / {
root html; # 根目录位置为 html 文件夹
index index.html index.htm; # 默认的索引文件
}
}
server {
listen 443 ssl; # 启动在 443 端口,并开启 SSL
server_name localhost; # 服务器名为 localhost
ssl_certificate cert.pem; # SSL 证书文件
ssl_certificate_key cert.key; # SSL 证书的私钥文件
ssl_session_cache shared:SSL:1m; # 配置 SSL 会话缓存
ssl_session_timeout 5m; # SSL 会话缓存的超时时间设置为 5 分钟
ssl_ciphers HIGH:!aNULL:!MD5; # 配置 SSL 加密算法
ssl_prefer_server_ciphers on; # 优先使用服务器端的加密套件
location / {
root html; # 根目录位置为 html 文件夹
index index.html index.htm; # 默认的索引文件
}
}
}
- 配置层级结构图
核心命令
命令 | 作用 |
---|---|
systemctl enable nginx | 开机自动启动(适用于yum安装) |
systemctl disable nginx | 关闭开机自动启动(适用于yum安装) |
systemctl start nginx | 启动Nginx(适用于yum安装) |
systemctl stop nginx | 停止Nginx(适用于yum安装) |
systemctl restart nginx | 重启Nginx(适用于yum安装) |
systemctl reload nginx | 重新加载Nginx(适用于yum安装) |
systemctl status nginx | 查看 Nginx 运行状态(适用于yum安装) |
ps -elf | grep [n]ginx | 查看Nginx进程,但是不会显示grep本身的进程 |
kill -9 pid | 根据上面查看到的Nginx进程号,杀死Nginx进程,-9 表示强制结束进程 |
nginx -s reload | 向主进程发送信号,重新加载配置文件,热重启 |
nginx -s reopen | 重启 Nginx |
nginx -s stop | 快速关闭 |
nginx -s quit | 等待工作进程处理完成后关闭 |
nginx -T | 查看当前 Nginx 最终的配置 |
nginx -t | 检查配置是否有问题 |
nginx -c configfilePath | 指定配置文件启动nginx |
- nginx信号
信号名 | 含义 |
---|---|
stop | 直接停止 |
quit | 优雅的退出:有人在访问不会结束进程 |
reopen | 分割日志 |
reload | 重新加载配置文件 |
term | 快速停止nginx进程,可能会中断现有连接,与stop信号类似。 |
usr1 | 重新打开日志文件,用于日志切割或日志重定向,与reopen信号类似。 |
usr2 | 平滑地升级nginx可执行文件。 |
hup | 重新加载配置文件,优雅地应用新配置,与reload信号类似。 |
winch | 当nginx以master/worker工作模式运行时,重新生成worker进程以适应新的配置。 |
usr3 | 向worker进程发送自定义信号。 |
nginx原生模块介绍
ngx_http_proxy_module
定义允许将请求传递到另一台服务器。
#常用选项
proxy_pass
proxy_cache
proxy_connect_timeout
proxy_read_timeout
proxy_send_timeout
proxy_next_upstream
ngx_http_upstream_module
用于定义可由proxy_pass,fastcgi_pass等指令引用的服务器组。此模块下常用指令如下:
#常用选项
upstream
server
ip_hash
配置实战
- 修改配置文件后重载配置文件或者重启nginx服务 (nginx.conf文件)
虚拟主机配置
- 基于IP地址
#修改http层级下的server层级实现虚拟主机配置,重启服务前注意为服务器配置子网卡接口或新增网卡,并配置对应ip
server {
listen 192.168.115.111:80;#ip1
server_name _;
charset utf8;
access_log /var/log/nginx/access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
}
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
# another virtual host using mix of IP-, name-, and port-based configuration
server {
listen 192.168.115.114:80;#ip2
server_name _;
location / {
root /var/www/html;#配置不同网站内容地址
index index.html index.htm;
}
}
- 基于域名
server {
listen 192.168.115.111:80;
server_name www1.jx.com;#域名1
charset utf8;
access_log /var/log/nginx/access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
# another virtual host using mix of IP-, name-, and port-based configuration
server {
listen 192.168.115.114:80;
server_name www2.jx.com;#域名2
location / {
root /var/www/html;#配置不同网站内容地址
index index.html index.htm;
}
}
- 基于端口号
server {
listen 192.168.115.111:80;#端口号80
server_name www1.jx.com;
charset utf8;
access_log /var/log/nginx/access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
# another virtual host using mix of IP-, name-, and port-based configuration
server {
listen 192.168.115.114:81;#端口号81
server_name www2.jx.com;
location / {
root /var/www/html;
index index.html index.htm;
}
}
- server_name制定虚拟主机域名
- 写法
- 精确匹配: server_name www.nginx.com ;
- 左侧通配:server_name *.nginx.com ;
- 右侧通配:server_name www.nginx.* ;
- 正则匹配:server_name ~^www.nginx.*$ ;
- 优先级别:精确匹配 > 左侧通配符匹配 > 右侧通配符匹配 > 正则表达式匹配。
- 写法
HTTPS访问配置(自签名)
- HTTPS工作流程
- 客户端(浏览器)访问 https://www.baidu.com 百度网站;
- 浏览器验证 CA 证书是否为合法证书;
- 验证通过,证书合法,生成一串随机数并使用公钥(证书中提供的)进行加密;
- 发送公钥加密后的随机数给百度服务器;
- 百度服务器拿到密文,通过私钥进行解密,获取到随机数(公钥加密,私钥解密,反之也可以);
- 百度服务器把要发送给浏览器的内容,使用随机数进行加密后传输给浏览器;(对称加密)
- 此时浏览器可以使用随机数进行解密,获取到服务器的真实传输内容。
- 获取自签名证书
openssl genrsa -out rsa1024.key 1024#生成私钥文件(包含公钥和私钥)
openssl req -new -key rsa1024.key -out rsa1024.csr#生成证书请求文件
openssl x509 -req -days 365 -in rsa1024.csr -signkey rsa1024.key -out rsa1024.crt#生成证书
openssl x509 -req -days 3650 -in rsa1024.csr -signkey rsa1024.key -text #查看证书
- 配置SSL(以编译安装为例)
移动证书到指定位置防止误删除
mkdir /usr/local/nginx/conf/pki/
mv rsa1024.key /usr/local/nginx/conf/pki/
mv rsa1024.crt /usr/local/nginx/conf/pki/
修改nginx.conf
server {
listen 443 ssl;
server_name www.jx.com;
ssl_certificate pki/nginx.crt;
ssl_certificate_key pki/nginx.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
location配置
- 作用
- 配置路径
- 匹配规则
- = 精确匹配;
- ~ 正则匹配,区分大小写;
- ~* 正则匹配,不区分大小写;
- ^~ 匹配到即停止搜索;
- 优先级: = > ^~ > ~ > ~* > 不带任何字符 “/”。
server {
listen 80;
server_name www.jx.com;
# 只有当访问 www.jx.com/info.html 时才会匹配到/usr/share/nginx/html/info.html
location = /info.html { # 必须是匹配文件
root /usr/share/nginx/html;
}
# 当访问 www.jx.com/1.jpg 等路径时会去 /usr/share/nginx/images/1.jpg 找对应的资源
location ~ \.(jpeg|jpg|png|svg)$ {
root /usr/share/nginx/html/images;
}
# 当访问 www.jx.com/bbs/ 时会匹配上 /usr/share/nginx/html/bbs/index.html
location ^~ /bbs/ {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
location /test {#location 中的反斜线,代表后面的名字是一个文件夹名
...
}
##以上写法会优先查找目录,若目录不存在则查找同名文件
location /test/ {
...
}
- return
- 停止处理请求,直接返回响应码或重定向到其他 URL ;执行 return 指令后, location 中后续指令将不会被执行。
return code [text];
return code URL;
return URL;
location / {
return 404; # 直接返回状态码
}
location / {
return 404 "pages not found"; # 返回状态码 + 一段文本
}
#location / {
# return 302 /bbs ; # 返回状态码 + 重定向地址
#}
location / {
return https://www.baidu.com ; # 返回重定向地址
}
rewrite配置
- 根据指定正则表达式匹配规则,重写 URL 。应用场景: 新老域名的更替!!!
可写入字段:server、location、if
rewirte /images/(.*\.jpg)$ /pic/$1; # $1是前面括号(.*\.jpg)的反向引用
server{
listen 80;
server_name www.jx.com; # 要在本地hosts文件进行配置
root /usr/share/nginx/html;
location /search {
rewrite ^/(.*) https://www.baidu.com redirect;
}
location /images {
rewrite /images/(.*) /pics/$1;
}
location /pics {
rewrite /pics/(.*) /photos/$1;
}
location /photos {
}
}
#访问www.jx.com/images/1.png 并在/photos下配置1.png
- if指令
- if (condition) {…}
- conditon条件
- $variable 仅为变量时,值为空或以0开头字符串都会被当做 false 处理;
- = 或 != 相等或不等;
- ~ 正则匹配;
- ! ~ 非正则匹配;
- ~* 正则匹配,不区分大小写;
- -f 或 ! -f 检测文件存在或不存在;
- -d 或 ! -d 检测目录存在或不存在;
- -e 或 ! -e 检测文件、目录、符号链接等存在或不存在;
- -x 或 ! -x 检测文件可以执行或不可执行;
- 可写入字段 server、location
location / {
if ($http_user_agent ~ Chrome) {
rewrite /(.*) /Chrome/$1 break;
}
if ($http_user_agent ~ Firefox) {
rewrite /(.*) /Firefox/$1 break;
}
}
nginx常用配置变量
变量名 | 含义 |
---|---|
remote_add | 客户端IP地址 |
remote_port | 客户端端口 |
server_addr | 服务端IP地址 |
Server_port | 服务端端口 |
server_protocol | 服务端协议 |
binary_remote_addr | 二进制格式的客户端IP地址 |
connection | TCP连接的序号,递增 |
connection_request | TCP连接当前的请求数量 |
uri | 请求的URL,不包含参数 |
request ur | 请求的URL,包含参数 |
scheme | 协议名,http或https |
request metho | 请求方法 |
request_length | 全部请求的长度,包含请求行、请求头、请求体 |
args | 全部参数字符串 |
arg_参数名 | 获取特定参数值 |
is_args | URL中是否有参数,有的话返回?,否则返回空 |
query_string | 与args相同 |
host | 请求信息中的Host,如果请求中没有Host行,则在请求头中找,最后 使用nginx中设置的server_name。 |
http_user_agent | 用户访问方式 |
http_referer | 从哪些链接过来的请求 |
http_via | 每经过一层代理服务器,都会添加相应的信息 |
http_cookie | 获取用户cookie |
request time | 处理请求已消耗的时间 |
https | 是否开启了https,是则返回on,否则返回空 |
request_filename | 磁盘文件系统待访问文件的完整路径 |
document_root | 由URI和root/alias规则生成的文件夹路径 |
limit_rate | 返回响应时的速度上限值 |
状态统计(vts模块)编译安装为例,演示新增模块
- 下载地址
https://github.com/vozlt/nginx-module-vts
- 为nginx添加模块并编译安装
tar xf nginx-module-vts-master.zip
cd nginx-1.22.1/
./configure --prefix=/usr/local/nginx/ --add-module=/root/nginx-module-vts-master && make && make install
- 配置nginx.conf
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"';
sendfile on;
keepalive_timeout 65;
gzip on;
##添加如下配置###
vhost_traffic_status_zone;
server {
listen 80;
server_name localhost;
charset utf-8;
access_log logs/$server_addr.access.log main;
location / {
root html;
index index.html index.htm;
}
##添加如下配置####
location /status {
vhost_traffic_status_display;
vhost_traffic_status_display_format html;
}
error_page 404 /404.html;
location = /404.html {
root html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
- 访问通过浏览器访问http://ip/status
nginx反向代理与缓存
- 正向代理与反向代理
- 正向代理代理的是客户端
- 为在防火墙内的局域网客户端提供访问Internet的途径
- 可以使用缓冲特性减少网络使用率
- 访问受地理位置限制的网络
- 使用代理后会隐藏真实的IP地址
- 反向代理代理的是服务端
- 提供负载均衡和高可用性.
- 缓存功能:Nginx可以缓存静态文件或动态页面,减轻服务器的负载,提高响应速度。
- 动静分离:将动态生成的内容(如 PHP、Python、Node.js 等)和静态资源(如 HTML、CSS、JavaScript、图片、视频等)分别存放在不同的服务器或路径上。
- 多站点代理:Nginx可以代理多个域名或虚拟主机,将不同的请求转发到不同的后端服务器上,实现多个站点的共享端口。
- 正向代理代理的是客户端
正向代理基本格式
server {
listen 192.164.25.100:80;
server_name ....;#客户端访问的域名
location / {
proxy_pass http://目标服务器地址;
}
}
反向代理可用模块
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协议转发至指定服务器处理
官方文档:https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
反向代理常用配置参数
proxy_pass 地址:端口的方式 ;
#用来设置将客户端请求转发给的后端服务器的主机,可以是主机名(将转发至后端服务做为主机头首部)、IP
#也可以代理到预先设置的主机群组,需要模块ngx_http_upstream_module支持
proxy_pass http://10.0.0.18:8080;
#8080后面无uri,即无 / 符号,需要将location后面url 附加到proxy_pass指定的url后面,此行为类似于root
#proxy_pass指定的uri不带斜线将访问的/web,等于访问后端服务器
proxy_pass http://10.0.0.18:8080/;
#8080后面有uri,即有 / 符号,相当于置换,即访问/web时实际返回proxy_pass后面uri内容.此行为类似于alias
#proxy_pass指定的uri带斜线,等于访问后端服务器的http://10.0.0.18:8080/index.html 内容返回给客户端
#如果location定义其uri时使用了正则表达式模式(包括~,~*,但不包括^~),则proxy_pass之后必须不能使用uri; 即不能有/ ,用户请求时传递的uri将直接附加至后端服务器之后
proxy_hide_header field;
#用于nginx作为反向代理的时候,在返回给客户端http响应时,隐藏后端服务器相应头部的信息,可以设置proxy_hide_header field;
proxy_pass_header field;
#默认nginx在响应报文中不传递后端服务器的首部字段Date, Server, X-Pad, X-Accel等参数,如果要传递的话则要使用 proxy_pass_header field声明将后端服务器返回的值传递给客户端
#field 首部字段大小不敏感
#示例:透传后端服务器的Server和Date首部给客户端,同时不再响应报中显示前端服务器的Server字段
proxy_pass_header Server;
proxy_pass_header Date;
proxy_pass_request_body on | off;
#是否向后端服务器发送HTTP实体部分,可以设置在http,server或location块,默认即为开启
proxy_pass_request_headers on | off;
#是否将客户端的请求头部转发给后端服务器,可以设置在http,server或location块,默认即为开启
反向代理实战(编译安装为例)
- 代理服务器192.164.25.153
server{
listen 192.164.25.153:80;
server_name www.pc.com;
root /usr/local/nginx/html;
location / {
proxy_pass http://192.164.25.154;
}
}
- 真实服务器192.164.25.154
echo "192.164.25.154" > /usr/local/nginx/html/index.html
- 测试机
curl 192.164.25.153
动静分离实战
- 代理服务端
location /api {
proxy_pass http://192.164.25.154;
}
location /static {
proxy_pass http://192.164.65.155;
}
- 真实服务端
#192.168.25.154
echo "dynamic" > /usr/local/nginx/html/index.html
#192.168.25.155
echo "static" > /usr/local/nginx/html/index.html
- 测试
# 192.168.25.152
curl 192.168.25.153/api
curl 192.168.25.153/static
缓存功能实战
当客户端再次请求访问相同资源时,反向代理可以直接返回缓存中的响应,无需二次请求,减少对后端服务器的请求压力,并加快响应速度。
proxy_cache zone_name on | off; 默认off
#指明调用的缓存,或关闭缓存机制;Context:http, server, location
#zone_name 表示缓存的名称.需要由proxy_cache_path事先定义
proxy_cache_key string;
#缓存中用于“键”的内容,默认值:proxy_cache_key $scheme$proxy_host$request_uri;
proxy_cache_valid [code ...] time;
#定义对特定响应码的响应内容的缓存时长,定义在http{...}中
示例:
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_path;
#定义可用于proxy功能的缓存;Context:http 必须放在http语句中
proxy_cache_path path [levels=levels] [use_temp_path=on|off]
keys_zone=zone_name:size [inactive=time] [max_size=size] [manager_files=number]
[manager_sleep=time] [manager_threshold=time] [loader_files=number]
[loader_sleep=time] [loader_threshold=time] [purger=on|off]
[purger_files=number] [purger_sleep=time] [purger_threshold=time];
#示例:在http配置定义缓存信息
proxy_cache_path /var/cache/nginx/proxy_cache #定义缓存保存路径,proxy_cache会自动创建
levels=1:2:2 #定义缓存目录结构层次,1:2:2可以生成2^4x2^8x2^8=2^20=1048576个目录
keys_zone=proxycache:20m #指内存中缓存的大小,主要用于存放key和metadata(如:使用次数),一般1M可存放8000个左右的key
inactive=120s #缓存有效时间
max_size=10g; #最大磁盘占用空间,磁盘存入文件内容的缓存空间最大值
#调用缓存功能,需要定义在相应的配置段,如server{...};或者location等
proxy_cache proxycache;
proxy_cache_key $request_uri; #对指定的数据进行MD5的运算做为缓存的key
proxy_cache_valid 200 302 301 10m; #指定的状态码返回的数据缓存多长时间
proxy_cache_valid any 1m; #除指定的状态码返回的数据以外的缓存多长时间,必须设置,否则不会缓存
proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | off ; #默认是off
#在被代理的后端服务器出现哪种情况下,可直接使用过期的缓存响应客户端
#示例
proxy_cache_use_stale error http_502 http_503;
proxy_cache_methods GET | HEAD | POST ...;
#对哪些客户端请求方法对应的响应进行缓存,GET和HEAD方法总是被缓存
server {
listen 80;
proxy_cache proxycache;
proxy_cache_key $request_uri;
#proxy_cache_key $host$uri$is_args$args;
proxy_cache_valid 200 302 301 10m;
proxy_cache_valid any 5m;
server_name www.kgc.com;
root /data/nginx/pc;
location / {
root /data/nginx/pc;
}
location /api {
proxy_pass http://192.168.25.155;
}
location ~* \.(jpg|png|gif|html)$ {
proxy_pass http://192.168.25.154;
}
}
反向代理IP透传
server{
listen 192.164.25.153:80;
server_name www.pc.com;
root /apps/nginx/html/pc;
location / {
proxy_pass http://192.164.25.155;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
######
`$proxy_add_x_forwarded_for` 是一个 nginx 变量,用于获取客户端的真实 IP 地址并将其添加到请求中的 `X-Forwarded-For` 头字段中,后端服务器可以通过检查该头字段来获取请求的真实客户端 IP 地址。
负载均衡
常见配置参数
server address [parameters];
#配置一个后端web服务器,配置在upstream内,至少要有一个server服务器配置。
#server支持的parameters如下:
weight=number #设置权重,默认为1,实现类似于LVS中的WRR,WLC等
max_conns=number #给当前后端server设置最大活动链接数,默认为0表示没有限制
max_fails=number #后端服务器的下线条件,当客户端访问时,对本次调度选中的后端服务器连续进行检测多少次,如果都失败就标记为不可用,默认为1次,当客户端访问时,才会利用TCP触发对探测后端服务器健康性检查,而非周期性的探测
fail_timeout=time #后端服务器的上线条件,对已经检测到处于不可用的后端服务器,每隔此时间间隔再次进行检测是否恢复可用,如果发现可用,则将后端服务器参与调度,默认为10秒
sorry server #自己不能转自己
down #标记为down状态
resolve #当server定义的是主机名的时候,当A记录发生变化会自动应用新IP而不用重启Nginx
- 配置
backup #设置为备份服务器,当所有后端服务器不可用时,才会启用此备用服务器
#配置示例
upstream backend {
server backend1.example.com;
server backend2.example.com backup;
server backend3.example.com;
}
location / {
proxy_pass http://backend;
}
#轮询
upstream bakend {
server 192.168.25.154;
server 192.168.25.155;
}
# 轮询权值(Weighted Round Robin)
upstream bakend {
server 192.168.25.154 weight=10;
server 192.168.25.155 weight=20;
}
#ip_hash
upstream bakend {
ip_hash;
server 192.168.25.154:88;
server 192.168.25.155:80;
}
#第三方模块库
#fair
upstream backend {
server 192.168.25.154:88;
server 192.168.25.155:80;
fair;
}
#url_hash
upstream backend {
server 192.168.25.154:88;
server 192.168.25.155:80;
hash $request_uri;
hash_method crc32;
}
# least_conn(最小连接数)
upstream backend {
least_conn;
server 192.168.25.154:88;
server 192.168.25.155:80;
}
配置跨域CORS**(Cross-Origin Resource Sharing)**
同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。通常不允许不同源间的读操作。
同源的定义
如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源。
与 URL http://store.company.com/dir/page.html 的源进行对比的示例:
- http://store.company.com/dir2/other.html 同源
- https://store.company.com/secure.html 不同源,协议不同
- http://store.company.com:81/dir/etc.html 不同源,端口不同
- http://news.company.com/dir/other.html 不同源,主机不同
不同源的限制
- Web 数据层面,同源策略限制了不同源的站点读取当前站点的 Cookie 、 IndexDB 、 LocalStorage 等数据;
- DOM 层面,同源策略限制了来自不同源的 JavaScript 脚本对当前 DOM 对象读和写的操作;
- 网络层面,同源策略限制了通过 XMLHttpRequest 等方式将站点的数据发送给不同源的站点。
Nginx 解决跨域的原理
浏览器的同源策略限制了跨域请求,但当使用 Nginx 作为代理服务器时,浏览器发送的请求实际上是发送到与前端页面同源的 Nginx 服务器。然后 Nginx 将请求转发到真正的目标服务器,目标服务器返回的响应再通过 Nginx 返回给浏览器。从浏览器的角度看,它只与同源的 Nginx 服务器进行交互,从而绕过了 CORS 限制
配置实战
前端 server 的域名为:fe.server.com
后端服务的域名为:dev.server.com
现在在 fe.server.com 对 dev.server.com 发起请求一定会出现跨域。
现在我们只需要启动一个 Nginx 服务器,将 server_name 设置为 fe.server.com 然后设置相应的 location 以拦截前端需要跨域的请求,最后将请求代理回 dev.server.com 。
server {
listen 80;
server_name fe.server.com;
location / {
proxy_pass dev.server.com;
proxy_set_cookie_domain target-domain.com your-domain.com;
proxy_set_header Host target-domain.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 可选的配置,用于处理响应头
proxy_set_header Access-Control - Allow - Origin http://fe.server.com;
proxy_set_header Access-Control - Allow - Methods GET,POST,PUT,DELETE;
proxy_set_header Access-Control - Allow - Headers Content - Type,Authorization;
}
}
配置解析:
proxy_set_header
Host backend - domain.com:设置转发请求的Host头信息。这是因为后端服务器可能会根据Host头来区分不同的虚拟主机或服务,所以需要将正确的Host信息传递给后端服务器,使其能够正确处理请求。
**X-Real-IP $remote_addr和X-Forwarded-For KaTeX parse error: Double subscript at position 12: proxy_add_x_̲forwarded_for**…remote_addr是 Nginx 记录的客户端 IP 地址,$proxy_add_x_forwarded_for是一个包含了客户端 IP 以及中间代理服务器 IP(如果有的话)的变量。这样后端服务器可以获取到正确的客户端 IP 信息,用于日志记录、访问控制等目的。
Origin http://frontend - domain.com:这是关键的一个设置,用于在转发请求时,将Origin头信息设置为前端页面的域名。后端服务器在收到这个请求时,会认为请求来自于同源的http://frontend - domain.com,从而避免了 CORS 限制。这样后端服务器就可以正常处理请求并返回响应,响应会通过 Nginx 再返回给浏览器。
proxy_set_header Access-Control - Allow - Origin
这个指令用于在 Nginx 作为代理服务器返回响应时,设置Access - Control - Allow - Origin响应头。通过将其设置为前端页面的域名(http://frontend - domain.com),浏览器会认为这个响应是来自同源的服务器,从而允许前端 JavaScript 代码访问这个响应,有效地绕过了 CORS 限制。
proxy_set_header Access-Control - Allow - Methods
用于设置Access - Control - Allow - Methods响应头,指定允许的 HTTP 请求方法。在这里列举了GET、POST、PUT和DELETE,表示后端服务器允许前端通过这些方法进行跨域请求。可以根据实际的后端 API 支持的方法进行调整。
proxy_set_header Access-Control - Allow - Headers
设置Access - Control - Allow - Headers响应头,指定允许的请求头。Content - Type头通常用于指定请求或响应的内容类型,如application/json或text/plain等;Authorization头用于传递认证信息,如令牌或用户名 / 密码等。这确保了前端在跨域请求中可以发送这些必要的请求头,并且后端会认可这些请求头。
这样可以完美绕过浏览器的同源策略:fe.server.com 访问 Nginx 的 fe.server.com 属于同源访问,而 Nginx 对服务端转发的请求不会触发浏览器的同源策略。
Nginx防盗链设置
什么是盗链
- 在实际生产过程中,我们线上的图片等静态资源,经常会被其他网站盗用,他们发大财的同时,成本确实我们在买单,下面来说下,如何杜绝这种行为。
- 应该说只要是静态资源都是可以防盗链的,只需要在Server字段加上几行代码即可。众所周知网站出名了后,会有各种刁民来找茬的,最常见的就是爬你网站的东西。
- 关于防盗链这里不得不提一下网页的加载顺序是先加载HTML相关的内容,然后解析HTML的内容,那些需要加载图片,那些需要加载文件,是逐步加载的,所以可以在加载静态资源的时候做防盗链的操作,例如:在加载图片的时候直接跳转去其他链接,或者直接返回404,403等错误代码,拒绝它的请求。
如何区分哪些是不正常的用户?
- HTTP Referer是Header的一部分,当浏览器向Web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器借此可以获得一些信息用于处理,例如防止未经允许的网站盗链图片、文件等。因此HTTP Referer头信息是可以通过程序来伪装生成的,所以通过Referer信息防盗链并非100%可靠,但是,它能够限制大部分的盗链情况.
- 比如在www.google.com 里有一个 www.baidu.com 链接,那么点击这个www.baidu.com ,它的header 信息里就有:Referer=http://www.google.com
Referer解析
- HTTP 协议中有一个用来表示“页面或资源”来源的“请求头”,这个请求头叫做 Referer --> Referer是表示请求是从哪个网址发出的防盗链功能基于HTTP协议支持的 Referer 机制,通过Referer跟踪来源,对来源进行识别和判断
配置防盗链案例
为了模拟盗链,让192.168.25.155为网站服务站点,192.168.25.154访问192.168.25.155进行盗链。
修改Nginx的字符集以支持中文:
charset utf-8;
修改 192.168.25.154 Nginx 默认访问文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>产生盗链</title>
</head>
<body>
<a href='http://192.168.25.155/photos/1.png'>站点</a>
</body>
</html>
此时在浏览器输入192.168.25.154,可以正常访问192.168.25.155站点的图片资源。
如果不想被盗链,则对192.168.25.155站点服务修改Nginx配置文件,防盗链的配置可以在任意的 location 模块下设置,不能在 server 下,不想让别人盗链哪个资源就在那个资源的 location 模块下设置防盗链。
#格式
valid_referers none | blocked | server_names | strings ....;
- –none:允许没有http_refer的请求访问资源,检测 Referer 头域不存在的情况,则可以访问。
- –blocked:检测 Referer 头域的值被防火墙或者代理服务器删除或伪装的情况。这种情况该头域的值不以
“http://” 或 “https://” 开头。允许不是http://开头的,不带协议的请求访问资源。 - –server_names :只允许指定ip/域名来的请求访问资源(白名单)。可设置一个或多个 URL ,检测 Referer 头域的值是否是这些 URL 中的某一个。在生产环境中尽量使用域名,不使用ip
配置实例
server {
listen 80;
server_name localhost;
location / {
root /usr/local/nginx/html;
index index.html index.htm;
}
location ~* \.(js|img|css|png)${
valid_referers 192.168.25.1; #只允许192.168.166.9访问静态资源,其他人访问则会返回403
if ($invalid_referer){
return 403;
}
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location =/50x.html {
root html;
}
}