一.nginx概述 nginx是一款开源的http,web应用服务器,其功能模块化,高性能高可靠。
特性: 功能模块少:源代码仅保留http与核心模块代码,其余不够核心代码会作为插件来安装 代码模块化:易读,便于二次开发 优势: 适合当前主流架构趋势,微服务,云架构,中间层 统一技术栈,降低维护成本,降低技术成本更新成本
Nginx特点是占有内存 少,并发 能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好。
Nginx由内核和模块组成,其中,内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端请求映射到一个location block(location是Nginx配置中的一个指令,用于URL匹配),而在这个location中所配置的每个指令将会启动不同的模块去完成相应的工作。
Nginx相对于Apache优点:
高并发响应性能非常好,官方Nginx处理静态文件并发5w/s
反向代理性能非常强。(可用于负载均衡)
内存和cpu占用率低。(为Apache的1/5-1/10)
对后端服务有健康检查功能。
支持PHP cgi方式和fastcgi方式。
配置代码简洁且容易上手。
nginx采用epoll模型(异步非阻塞),而apache采用select模型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 select 和epoll 模型的区别 select :当用户发起一次请求,select 模型就会进行一次遍历扫描,从而导致性能低下 epoll :当用户发起请求,epoll 模型会直接进行处理,效率高效,并无连接限制。 select 和epoll 对比select 随着连接数增加,急剧下降。处理成千上万并发连接数时,性能很差。 连接数有限制,处理的最大连接数不超过1024 。如果要处理超过1024 个连接数,则需要修改FD_SETSIZE宏,并重新编译 。 线性轮询 开发复杂性低epoll 随着连接数增加,性能基本上没有下降。处理成千上万并发连接时,性能很好。 连接数无限制。 回调callback 开发复杂性中
nginx应用场景: 静态服务: 浏览器缓存,防资源盗用,资源分类,资源压缩,资源缓存,跨域访问 代理服务: 协议类型,正向代理,反向代理,负载均衡,代理缓存,动静分离 安全服务: 访问控制,访问限制,流量限制,拦截共计,拦截异常请求,拦截sql注入 流行框架 nginx+php,nginx+java ,nginx+python
二.nginx安装 http://nginx.org/en/download.html #nginx官网地址
nginx一般有两种安装方式:
源码安装和rpm安装:
rpm安装:
epel源:版本低,功能少 官方源:官方编译好的,封装成rpm包,提供yum源 版本新
yum安装 官方源: 1 sudo yum install yum-utils
To set up the yum repository, create the file named /etc/yum.repos.d/nginx.repo with the following contents:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [nginx-stable] name =nginx stable repobaseurl =http://nginx.org/packages/centos/$releasever /$basearch /gpgcheck =1 enabled =1 gpgkey =https://nginx.org/keys/nginx_signing.keymodule_hotfixes =true [nginx-mainline] name =nginx mainline repobaseurl =http://nginx.org/packages/mainline/centos/$releasever /$basearch /gpgcheck =1 enabled =0 gpgkey =https://nginx.org/keys/nginx_signing.keymodule_hotfixes =true
By default, the repository for stable nginx packages is used. If you would like to use mainline nginx packages, run the following command:
To install nginx, run the following command:
When prompted to accept the GPG key, verify that the fingerprint matches 573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62, and if so, accept it.
上面的为最新包的安装,下面的为稳定版的安装,文档内容截自官方文档,如为其他系统则参考官方文档 :http://nginx.org/en/linux_packages.html#RHEL-CentOS
epel源: 1 2 3 4 5 yum -y install epel-release.noarch ``` yum makecache yum -y install nginx 安装完成以后 nginx -V 查看nginx安装配置以及版本
源码安装: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 wget http://nginx.org/download/nginx-1.19.6.tar.gz useradd -s /sbin/nologin -M nginx tar -xvf nginx-1.19.6.tar.gz && cd nginx-1.19.6/ yum install -y gcc gcc-c++ make libtool zlib zlib-devel openssl openssl-devel pcre pcre-devel ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-http_auth_request_module --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-debug make && make install ll /usr/local/nginx/
源码安装的好处在于其所有nginx相关文件都可以放在一起,方便数据迁移。相比于yum麻烦的是:
源码安装完成以后linux环境变量没有nginx路径,需要配置(才能直接在命令行找到命令)
systemd不会自动生成nginx启动文件(无法通过systemctl直接启动关闭nginx)
所以这两个都需要手动进行生成
systemd: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 cat > /etc/ systemd/system/ nginx.service << EOF [Unit] Description=The nginx HTTP and reverse proxy server After=network.target remote-fs.target nss-lookup.target[Service] Type=forking PIDFile=/usr/ local/nginx/ logs/nginx.pid ExecStartPre=/usr/ bin/rm -f $PIDFile ExecStartPre=/usr/ local/nginx/ sbin/nginx -t ExecStart=/usr/ local/nginx/ sbin/nginx ExecReload=/bin/ kill -s HUP PIDFileExecStartPre=/usr/ local/nginx/ sbin/nginx−tExecStart=/u sr/local/ nginx/sbin/ nginxExecReload=/bin/ kill−sHUP$MAINPID KillSignal=SIGQUIT TimeoutStopSec=5 KillMode=mixed PrivateTmp=true[Install] WantedBy=multi-user.target EOF
将systemd文件写入以后可以使用systemctl start nginx测试一下
加入环境变量 1 2 3 4 5 cat > /etc/ profile.d/nginx.sh << EOF export PATH=/usr/ local/nginx/ sbin:$PATH EOF source /etc/ profile.d/nginx.sh nginx -V
三. nginx配置文件
nginx配置文件: 主配置文件: /etc/nginx /etc/nginx/nginx.conf /etc/nginx/conf.d/* cgi,fastcgi,uwcgi配置文件 /etc/nginx/fastcgi_params /etc/nginx/scgi_params /etc/nginx/uwsgi_params 编码转换映射文件 /etc/nginx/win-utf /etc/nginx/koi-utf /etc/nginx/koi-win http协议的conten-type与扩展名 /etc/nginx/mime.types systemd: /usr/lib/systemd/system/nginx.service nginx日志轮询,日志切割 /etc/logrotate.d/nginx 模块目录 /etc/nginx/modules /usr/lib64/nginx /usr/lib64/nginx/modules 默认站点目录 /usr/share/nginx /usr/share/nginx/html/*.html logs: /var/log/nginx 缓存: /var/cache/nginx
默认使用rpm包的nginx相关配置文件如上,如果是源码安装的如果没特别指定路径一般在编译安装prefix指定的nginx根目录下,也有些文件夹不会自动生成可以手动生成。比较重要的配置文件有
conf/nginx.conf:这个是nginx的根配置文件
html站点目录:这个是网站文件夹的路径(也可以不用默认的路径)
nginx.logs:nginx日志生成目录
nginx.conf nginx配置文件格式一般为: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ... events{... } http {... server{... location { .. #location定义的是虚拟主机,location 指令的功能是用来匹配不同的 URI 请求,进而对请求做不同的处理和响应。例如一个网站的/根目录会匹配到服务器主机的哪个文件目录,就是在这里定义的 } } } #一个配置段由{ 开始 } 结尾, ...表示省略的具体配置信息
完整配置文件以及常用到的一些配置: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 user www www;worker_processes 8 ;worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000 ;worker_rlimit_nofile 102400 ;error_log /usr/local/nginx/logs/error.log; pid /usr/local/nginx/nginx.pid;worker_rlimit_nofile 65535 ;events { use epoll ; worker_connections 102400 ; multi_accept on ; }http { include mime.types; default_type application/octet-stream; access_log /usr/local/nginx/log/nginx/access.log; sendfile on ; tcp_nopush on ; keepalive_timeout 60 ; tcp_nodelay on ; gzip on ; gzip_min_length 1k ; gzip_buffers 4 16k ; gzip_http_version 1 .1 ; gzip_comp_level 4 ; gzip_types text/plain application/x-javascript text/css application/xml; gzip_vary on ; client_max_body_size 10m ; client_body_buffer_size 128k ; proxy_connect_timeout 120 ; proxy_send_timeout 120 ; proxy_read_timeout 120 ; proxy_buffer_size 4k ; proxy_buffers 4 32k ; proxy_busy_buffers_size 64k ; large_client_header_buffers 4 4k ; client_header_buffer_size 4k ; open_file_cache max=102400 inactive=20s ; open_file_cache_valid 30s ; open_file_cache_min_uses 1 ; upstream tdt_wugk { server 127.0.0.1:8080 weight=1 max_fails=2 fail_timeout=30s ; server 127.0.0.1:8081 weight=1 max_fails=2 fail_timeout=30s ; } server { listen 80 ; server_name www.wuguangke.cn; access_log logs/access.log main; root /data/webapps/wugk; index index.php index.html index.htm; location ~ / { root /data/www/wugk; index index.php index.html index.htm; proxy_next_upstream http_502 http_504 error timeout invalid_header; proxy_redirect off ; 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_pass http://tdt_wugk; } location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css)$ { root /data/www/wugk; expires 30d ; } location ~ \.php$ { root /root; fastcgi_pass 127.0.0.1:9000 ; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /data/www/wugk$fastcgi_script_name; include fastcgi_params; } location /NginxStatus { stub_status on ; } } }
四.nginx常用命令 nginx -v #查看版本号
nginx -V #查看版本号以及安装时安装的模块
nginx -s reload | stop 重新载入配置文件|停止nginx
nginx -t 检查配置文件语法是否正确
nginx 直接输入命令表示启动nginx进程
五.nginx常用模块功能 1.nginx目录索引 目录索引模块:ngx_http_autoindex_module
默认:编译进内核
编译参数:--without-http_autoindex_module
1 2 3 4 5 6 7 8 9 10 autoindex on ; 加在对应location 里面即可实现目录索引浏览(autoindex也可加在http,server 里面,但一般不这么用)Syntax:autoindex on |off ;default : autoindex off ; context: http server location 常用参数 autoindex_exact_size off ; 默认为on ,显示出文件的确切大小,单位为bytesoff ,显示文件的大概大小,单位为kb or MB or GBautoindex_localtime on ; 默认为off ,显示的文件时间为GMT时间 默认为on ,显示的文件时间为文件的服务器时间charset utf-8 ,gbk; 默认中文目录乱码,添加防止乱码。
示例:
nginx -s reload #重载配置文件
访问:
2.nginx状态监控 状态监控模块:ngx_http_stub_status_module
默认:不编译进内核
编译参数:--with-http_stub_status_module
配置实例
1 2 3 4 5 location = /status { stub_status; access_log off; }
访问:
因安全缘由,建议status状态页面仅内网开放访问或限制访问ip访问认证限制。
3.nginx访问控制 基于IP的访问控制模块: http_access_module 默认:编译进内核 编译参数:--without-http_access_module
基于用户登录认证模块: http_auth_basic_module 默认:编译进内核 编译参数:--without-http_auth_basic_module
IP: 1 2 3 4 5 6 7 8 允许: syntax: allow address |CIDR |unix: |all ;Default :- context: httpx server ,location ,limit_except 拒绝: syntax: deny address |CIDR |unix: |all ; context: http, server , location , limit_exceptdefault : -
示例
本机访问(本机ip为10.10.10.214)
已被拒绝,其他同网端服务器访问没问题。
登录认证访问: 1 2 3 4 5 6 7 8 9 10 syntax: auth_basic string|off;default: auth_basic off;Context: http, server, location,limit_exceptsyntax: auth_basic_user_file file;Default: -Context: http, server, location,limit_except
yum -y install httpd-tools (安装http工具包) htpasswd -b -c /x/x/x admin 123456
前面是用户后面是密码,生产用户密码文件
示例:
4.访问限制 经常会遇到这种情况,服务器流量异常,负载过大等等。对于大流量恶意的攻击访问,会带来带宽的浪费,服务器压力,影响业务,往往考虑对同一个IP的连接数,并发数进行限制。
限制连接数:ngx_http_limit_req_module
限制请求频率:ngx_http_limit_conn_module
默认:编译进内核
编译参数:--without-http_limit_conn_module
limit_req_zone 用来限制单位时间内的请求数,即速率限制,采用的漏桶算法 “leaky bucket”
limit_conn_zone 用来限制同一时间连接数,即并发限制
limit_conn_zone: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 句法: limit_conn_zone key zone=name:size; 默认: — 内容: http Syntax: limit_conn zone number Default: — Context: http,server, location 可能有几个`limit_conn`指令。例如,以下配置将限制每个客户端IP与服务器的连接数,并同时限制与虚拟服务器的连接总数: limit_conn_zone $binary_remote_addr zone=addr:10m; server { location /download/ { limit_conn addr 1; } limit_conn_zone $binary_remote_addr zone=perip:10m; limit_conn_zone $server_name zone=perserver:10m; server { ... limit_conn perip 10; limit_conn perserver 100; }
当且仅当limit_conn
当前级别上未定义任何指令时,这些指令才从先前的配置级别继承。
1 2 3 4 句法: limit_conn_dry_run on | off ; 默认: limit_conn_dry_run off ; 内容: http,server ,location
启用空运行模式。在这种模式下,连接数不受限制,但是,在共享内存区域中,过多连接的数将照常计算。
1 2 3 4 句法: limit_conn_log_level info | notice | warn | error; 默认: limit_conn_log_level error; 内容: http,server ,location
为服务器限制连接数的情况设置所需的日志记录级别。
1 2 3 4 句法: limit_conn_status code 默认: limit_conn_status 503 内容: http,server,location
设置状态代码以响应被拒绝的请求而返回。
limit_req_zone: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 句法: limit_req_zone key zone=name:size rate=rate [sync]; 默认: — 内容: http Sntax: limit_req zone=name [burst=number] [nodelay | delay=number]; Default: — Context: http, server, location http { limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; ... server { ... location /search/ { limit_req zone=one burst=5; }
http{ //http段配置请求限制,rate限制速率,限制一秒钟最多一个IP请求 limit_req_zone $binary_remote_addr zone=req_zone:10m rate=1r/s; … server { … location / { //1r/s只接收一个请求,其余请求拒绝处理并返回错误码给客户端.. limit_req zone=req_zone; //请求超过1r/s,剩下的将被延迟处理,请求数超过burst定义的数量,多余的请求返回503 #limit_req zone=req_zone burst=3 nodelay; } }} rate=1r/s表示每秒最大一个请求,burst=3表示请求队列最大为3
1 2 3 4 句法: limit_req_dry_run on | off ; 默认: limit_req_dry_run off ; 内容: http,server ,location
启用空运行模式。在这种模式下,请求处理速率不受限制,但是,在共享内存区域中,过多请求的数量将照常计算。
1 2 3 4 句法: limit_req_log_level info | notice | warn | error; 默认: limit_req_log_level error; 内容: http,server ,location
在服务器由于速率超出而拒绝处理请求或延迟请求处理的情况下,设置所需的日志记录级别。延迟的记录级别比拒绝的记录级别少1分;例如,如果limit_req_log_level notice
指定“ ” ,则将延迟记录为该info
级别。
1 2 3 4 句法: limit_req_status code 默认: limit_req_status 503 内容: http,server,location
设置状态代码以响应被拒绝的请求而返回。
1 2 3 4 5 $server_name 表示服务器的变量$binary_remote_addr 变量长度是固定的4字节$remote_addr 变量长度是7-15字节 一个IP地址=32bit=4字节,所以一般用第一个变量即可 两个都是代表IP地址的变量,区别在于变量存储长度(也可直接换成某个IP地址,但是限制一般针对所有IP地址,而非一个ip地址,所以使用变量)
5.日志模块 日志模块:
默认:编译进内核(在官方文档的编译模块中,没有日志模块的编译或不编译进内核的选项)
1 2 3 4 5 6 7 8 9 10 Syntax: log_format name [escape=default |json|none ] string ...;Default : log_format combined "..." ; Context: http Syntax: access_log path [format [buffer=size ] [gzip[=level]] [flush =time] [if =condition]]; access_log off;Default : access_log logs/access .log combined; Context: http, server, location, if in location, limit_except
配置示例:
1 2 3 4 5 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;
log_format是定义的日志格式,access_log是存放的位置。main为日志的名称,下面通过这个main来进行调用
log_format 后面首先定义日志名称,然后’’中间代表日志显示格式,调用的是nginx变量,例如$remote_addr是客户端ip地址 , remote_user是客户端用户,下面是日志实际显示示例:
nginx常见内置变量:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 嵌入式变量 该ngx_http_core_module模块支持名称与Apache Server变量匹配的嵌入式变量。首先,这些是代表客户端请求标头字段的变量,例如$ http_user_agent,$ http_cookie等。另外还有其他变量:$arg _name name请求行中的 参数$args 请求行中的参数$binary _remote_addr 客户端地址(二进制形式),对于IPv4地址,值的长度始终为4 个字节,对于IPv6地址,值的长度始终为16 个字节$body _bytes_sent 发送给客户端的字节数,不计算响应头;此变量与 Apache模块 的“ %B”参数 兼容mod_log_config$bytes _sent 发送给客户端的字节数(1.3 .8 、1.2 .5 )$connection 连接序列号(1.3 .8 、1.2 .5 )$connection _requests 通过连接发出的当前请求数(1.3 .8 、1.2 .5 )$content _length “内容长度”请求标头字段$content _type “内容类型”请求标头字段$cookie _name 该name饼干$document _root 当前请求的根或别名指令的值$document _uri 和...一样 $ uri$host 优先顺序如下:请求行中的主机名,或“主机”请求标头字段中的主机名,或与请求匹配的服务器名$hostname 主机名$http _name 任意请求头字段;变量名称的最后一部分是字段名称,该字段名称已转换为小写,并用短划线代替了下划线$https on如果连接以SSL模式运行,则为 “ ”,否则为空字符串$is _args “ ?”(如果请求行包含参数),否则为空字符串$limit _rate 设置此变量将启用响应率限制;参见limit_rate$msec 以毫秒为单位的当前时间(以秒为单位)(1.3 .9 ,1.2 .6 )$nginx _version Nginx版本$pid 工作进程的PID$pipe “ p”如果请求被流水线.“ ”否则(1.3 .12 ,1.2 .7 )$proxy _protocol_addr 来自PROXY协议标头(1.5 .12 )的客户端地址 必须通过proxy_protocol在listen指令中设置参数来预先启用PROXY协议 。$proxy _protocol_port PROXY协议标头(1.11 .0 )中的客户端端口 必须通过proxy_protocol在listen指令中设置参数来预先启用PROXY协议 。$proxy _protocol_server_addr PROXY协议标头中的服务器地址(1.17 .6 ) 必须通过proxy_protocol在listen指令中设置参数来预先启用PROXY协议 。$proxy _protocol_server_port PROXY协议标头中的服务器端口(1.17 .6 ) 必须通过proxy_protocol在listen指令中设置参数来预先启用PROXY协议 。$query _string 和...一样 $ args$realpath _root 绝对路径名,对应于当前请求的 根或别名指令的值,所有符号链接都解析为真实路径$remote _addr 客户地址$remote _port 客户端口$remote _user 基本身份验证随附的用户名$request 完整的原始请求行$request _body 请求主体 当将请求正文读取到内存缓冲区时, 该变量的值可在proxy_pass, fastcgi_pass, uwsgi_pass和 scgi_pass指令处理的位置 使用。$request _body_file 带有请求正文的临时文件的名称 在处理结束时,需要删除文件。要始终将请求正文写入文件, 需要启用client_body_in_file_only。当在代理请求中或在对FastCGI / uwsgi / SCGI服务器的请求中传递临时文件的名称时,应分别通过 proxy_pass_request_body off, fastcgi_pass_request_body off, uwsgi_pass_request_body off或 scgi_pass_request_body off 指令来禁用传递请求正文。 。$request _completion “ OK”(如果请求已完成),否则为空字符串$request _filename 基于root或alias 指令以及请求URI 的当前请求的文件路径$request _id 从16 个随机字节生成的唯一请求标识符,以十六进制(1.11 .0 )$request _length 请求长度(包括请求行,标头和请求正文)(1.3 .12 ,1.2 .7 )$request _method 请求方法,通常是“ GET”或“ POST”$request _time 请求以毫秒为单位的处理时间(以秒为单位)(1.3 .9 、1.2 .6 );从客户端读取第一个字节以来经过的时间$request _uri 完整的原始请求URI(带有参数)$scheme 请求方案,“ http”或“ https”$sent _http_name 任意响应头字段;变量名称的最后一部分是字段名称,该字段名称已转换为小写,并用短划线代替了下划线$sent _trailer_name 在响应末尾发送的任意字段(1.13 .2 );变量名称的最后一部分是字段名称,该字段名称已转换为小写,并用短划线代替了下划线$server _addr 接受请求的服务器的地址 计算此变量的值通常需要一个系统调用。为避免系统调用,listen伪指令必须指定地址并使用bind参数。$server _name 接受请求的服务器的名称$server _port 接受请求的服务器的端口$server _protocol 请求协议,通常是“ HTTP/1.0 ”,“ HTTP/1.1 ”或“ HTTP / 2.0 ”$status 响应状态(1.3 .2 、1.2 .2 )$tcpinfo _rtt, $tcpinfo_rttvar, $tcpinfo_snd_cwnd, $tcpinfo_rcv_space 有关客户端TCP连接的信息;在支持TCP_INFO套接字选项的 系统上可用$time _iso8601 ISO 8601 标准格式(1.3 .12 ,1.2 .7 )的本地时间$time _local 通用日志格式的本地时间(1.3 .12 ,1.2 .7 )$uri 请求中的当前URI,已规范化$uri 在请求处理期间,例如在进行内部重定向或使用索引文件时, 的值可能会更改。
更多变量:https://nginx.org/en/docs/http/ngx_http_core_module.html#var_status
error_log(核心模块):
1 2 3 4 Syntax : error_log file [level]; Default: error_log logs/error .log error ; Context: main, http, mail, stream, server, location
6.虚拟站点 所属模块:ngx_http_core_module(server和location都属于该模块)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Syntax: server { ... } Default: — Context: http Syntax: server_name name ...; Default: server_name "" ; Context: server Syntax: listen address[:port] [default_server] [ssl] [http2 | spdy] [proxy_protocol] [setfib=number] [fastopen=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind ] [ipv6only=on|off] [reuseport] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]]; listen port [default_server] [ssl] [http2 | spdy] [proxy_protocol] [setfib=number] [fastopen=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind ] [ipv6only=on|off] [reuseport] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]]; listen unix:path [default_server] [ssl] [http2 | spdy] [proxy_protocol] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind ] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]]; Default: listen *:80 | *:8000; Context: server
一个server表示一个虚拟主机,一个服务器可能有多个虚拟主机(多个网站),实现虚拟主机的方式有三种:
基于IP:
每个server监听不同的IP地址,用server_name来指定(域名和IP都是通过server_name指定)
基于域名:
需要注意的是基于域名的虚拟主机首先需要通过DNS能解析到,所以要么是已经购买的域名并且配置解析到该服务器的IP上,要么是本地内部DNS配置以后整个内网可以访问到。需要基于DNS解析。但这里是测试,所以把解析放在 /etc/hosts文件即可(linux在解析主机名时会优先去查看hosts文件是否有解析条目)。域名相较于IP和端口的优点是只需要一个端口和一个ip地址即可用于多个虚拟主机,但需要多个域名以区分访问地址。
基于端口:
修改listen后的数字即可,默认是80,如果是https的话需要监听443且拥有证书。改为非80(443)端口后再浏览器访问时需主动输入端口号,不然浏览器默认会访问80端口。
7. location 1 2 3 4 Syntax: location [ = | ~ | ~* | ^~ ] uri { ... } location @name { ... } Default: — Context: server, location
location一般放置与server里面,一个server可以有多个location,location是用于匹配访问地址的uri
1 2 3 4 = 精确匹配。如果这个查询匹配,那么将停止搜索并立即处理此请求。 ~ 为区分大小写匹配(可用正则表达式) ~* 为不区分大小写匹配(可用正则表达式) ^~ 如果把这个前缀用于一个常规字符串,那么告诉nginx 如果路径匹配那么不测试正则表达式。
location匹配优先级:
1 ```(location `=` ) > (location `完整路径` ) > (location `^~` 路径) > (location `~`,`~*` 从上向下正则顺序,匹配在最后一条终止) > (location 部分起始路径) > (`/`)
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 location = / { [ configuration A ] } location / { [ configuration B ] } location /documents/ { [ configuration C ] } location ^~ /images/ { [ configuration D ] } location ~* \.(gif|jpg|jpeg)$ { [ configuration E ] } The “/” 匹配 configuration A, the “/index.html” 匹配 configuration B, the “/documents/document.html” 匹配 configuration C, the “/images/1.gif” 匹配 configuration D, and the “/documents/1.jpg” 匹配 configuration E.
locaiton定义以后还需要将其匹配到linux服务器上对应的文件,就需要用到两个配置参数,root和index
1 2 3 4 5 6 7 8 9 Syntax: root path;Default : root html; Context: http, server, location, if in locationModule ngx_http_index_module:(INDEX 非core模块,而是单独模块) Syntax: index file ...;Default :index index .html; Context: http, server, location
root是定义其的路径,如root /tmp 放在/的location里面则,当访问路径为根时,会访问到/tmp目录,但是到具体的访问文件时,是由index定义的,一般index定义为index.html或index.htm,如为.php会涉及到fastcgi协议,因为nginx本身只能处理静态html文件。
8.rewrite 所属模块:Module ngx_http_rewrite_module
默认:编译进模块 编译参数:--without-http_rewrite_module
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Syntax: rewrite regex replacement [flag]; Default: — Context: server, location, if rewrite的含义:该指令是实现URL重写的指令。 regex的含义:用于匹配URI的正则表达式。 replacement:将regex正则匹配到的内容替换成 replacement。 flag: flag标记。 flag有如下值: last: 本条规则匹配完成后,继续向下匹配新的location URI 规则。(不常用)break : 本条规则匹配完成即终止,不再匹配后面的任何规则(不常用)。 redirect: 返回302临时重定向,浏览器地址会显示跳转新的URL地址。 permanent: 返回301永久重定向。浏览器地址会显示跳转新的URL地址。
例:
1 2 3 rewrite ^(/download/ .*)/media/ (.*)\..*$ $1 /mp3/ $2 .mp3 break ; rewrite ^(/download/ .*)/audio/ (.*)\..*$ $1 /mp3/ $2 .ra break ; rewrite ^/(.*) http:/ /www.test.com/ $1 permanent;
服务器如需看rewrite日志需要做以下配置:
1.设置nginx的错误日志级别为notice error_log /var/log/nginx/error.log notice; 2.在http模块层,增加一行rewrite_log日志 http{ … rewrite_log on; … }
if: 1 2 3 Syntax: if (condition) { ... } Default: — Context: server, location
指定的condition
被评估。如果为true,则执行括号内指定的此模块伪指令,并在伪指令内为请求分配配置 if
。if
指令中的配置是从先前的配置级别继承的。
条件可以是以下任意一种:
变量名;如果变量的值为空字符串或“
”,则为false;否则为false 。
在1.0.1版之前,任何以“ 0
”开头的字符串都被视为错误值。
使用“ =
”和“ !=
”运算符将变量与字符串进行比较;
使用“ ~
”(区分大小写的匹配)和“ ~*
”(区分大小写的匹配)运算符将变量与正则表达式进行匹配。正则表达式可以包含捕获,这些捕获可用于以后在$1
..$9
变量中重用。负运算符“ !~
”和“ !~*
”也可用。如果正则表达式包含“ }
”或“ ;
”字符,则整个表达式应用单引号或双引号引起来。
使用“ -f
”和“ !-f
”运算符检查文件是否存在;
使用“ -d
”和“ !-d
”运算符检查目录是否存在;
使用“ -e
”和“ !-e
”运算符检查文件,目录或符号链接是否存在;
使用“ -x
”和“ !-x
”运算符检查可执行文件。
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 #如果UA包含"MSIE" ,rewrite请求到/msid/目录下if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /msie/$1 break ; } #如果cookie匹配正则,设置变量$id 等于正则引用部分if ($http_cookie ~* "id=([^;]+)(?:;|$)" ) { set $id $1 ; } #如果提交方法为POST ,则返回状态405(Method not allowed)。return 不能返回301,302if ($request_method = POST ) { return 405; } #限速,$slow 可以通过 set 指令设置if ($slow ) { limit_rate 10k; } #如果请求的文件名不存在,则反向代理到localhost 。这里的break 也是停止rewrite检查if (!-f $request_filename ){ break ; proxy_pass http: } #如果query string中包含"post=140" ,永久重定向到example.comif ($args ~ post =140){ rewrite ^ http: } #防盗链 location ~* \.(gif|jpg|png|swf|flv)$ { valid_referers none blocked www.jefflei.com www.leizhenfang.com; if ($invalid_referer ) { return 404; } }
if可使用的全局变量:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 变量名称 变量说明$args 这个变量等于请求行中的参数,同$query_string $content_length 请求头中的Content-length字段$content_type 请求头中的Content-Type字段$document_root 当前请求在root指令中指定的值$host 请求主机头字段,否则为服务器名称$http_user_agent 客户端agent信息$http_cookie 客户端cookie信息$limit_rate 这个变量可以限制连接速率$request_method 客户端请求的动作,通常为GET或POST$remote_addr 客户端的IP地址$remote_port 客户端的端口$remote_user 已经经过Auth Basic Module验证的用户名$request_filename 当前请求的文件路径,由root或alias 指令与URI请求生成$scheme HTTP方法(如http,https)$server_protocol 请求使用的协议,通常是HTTP/1.0或HTTP/1.1$server_addr 服务器地址,在完成一次系统调用后可以确定这个值$server_name 服务器名称$server_port 请求到达服务器的端口号$request_uri 包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”$uri 不带请求参数的当前URI,$uri 不包含主机名,如”/foo/bar.html”$document_uri 与$uri 相同
9.proxy模块 所属模块:ngx_http_proxy_module
默认:编译进模块 编译参数:--without-http_proxy_module
1 2 3 4 5 6 7 8 9 句法: proxy_pass URL; 默认: — 内容: location,if in location,limit_except Syntax: proxy_set_header field value; Default: proxy_set_header Host $proxy_host ; proxy_set_header Connection close; Context: http, server, location
proxy: proxy_pass和proxy_set_header是proxy模块中最常用到的两个功能
proxy_pass例子:
proxy_pass http:// localhost:8000 / uri /;
proxy_pass http://unix/tmp/backend.socket/uri/;
一般放在location下面,当location匹配到对应的uri之后,如果下面是proxy_pass而不是root,就会通过nginx去反向代理到proxy_pass指定的地址上面去请求访问。
反代的地址可以是ip地址,域名,sock文件地址,也可以是upstream指定的名称。
这个upstream是nginx的另一个模块叫做:ngx_http_upstream_module
ngx_http_upstream_module upstream最重要的功能是定义一组后端服务器,然后proxy_pass可以根据upstream定义好的直接调用,完成以后proxy_pass收到请求会将反向代理到upstream所定义的一组服务器上。
1 2 3 Syntax: upstream name { ... } Default: — Context: http
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 upstream backend { server backend1.example.com weight=5 ; server backend2.example.com:8080 ; server unix:/tmp/backend3; server backup1.example.com:8080 backup; server backup2.example.com:8080 backup; }server { location / { proxy_pass http://backend; } }
upstream定义了一组后端服务器后,当然也会有调度方式:
1.如不进行任何配置,默认的调度方式为轮训调度。
2.weight:设置后端服务器的权重,权重大的优先访问
server 192.168.0.15 weight=10;
3.ip_hash:每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题
upstream backend { ip_hash; server 192.168.0.14:88;}
4.fair(第三方) 按后端服务器的响应时间来分配请求,响应时间短的优先分配。
upstream backend {
fair;
server 192.168.0.14:88;}
5.url_hash(第三方) 按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
6.least_conn:
最少连接数,那个机器连接数少就分发(lc) 7.wlc: 加权最少连接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 upstream backend { server squid1:3128; server squid2:3128;hash $request_uri ; hash_method crc32; } upstream backend{ ip_hash; server 127.0.0.1:9090 down; server 127.0.0.1:8080 weight=2; server 127.0.0.1:6060; server 127.0.0.1:7070 backup; }
常用参数:down ,backup,fail_timeout=time,max_fails=number,wight,max_conns=number down: 当前的server暂时不参与负载均衡 backup: 预留的备份服务器 max_fails: 允许请求失败的次数 fail_timeout: 经过max_fails夫败后,服务暂停时间 max_conns: 限制最大的接收连接数
这几个的参数的作用是向后端转发的时候添加头信息;
1 2 3 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 ;
本文要说明nginx中的Host、X-Real-IP、X-Forwarded-For。
先看一个配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 server { listen 80; server_name 192.168.1.2; error_log /usr/local/etc/nginx/logs/test.error.log; access_log /usr/local/etc/nginx/logs/test.access.log; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; proxy_set_header Connection ""; proxy_http_version 1.1; add_header Access-Control-Allow-Origin *; proxy_pass http://127.0.0.1:8889; } location /app { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $proxy_host; proxy_set_header X-NginX-Proxy true; proxy_set_header Connection ""; proxy_http_version 1.1; proxy_pass http://192.168.1.3; } }
客户端地址(请求服务的地址):192.168.1.1
nignx服务器地址:192.168.1.2
后端服务器地址:192.168.1.3
首先说明proxy_set_header是用来设置请求头的,设置了请求头后,后端服务器就可以获取到这些变量值。
一、X-Real-IP
是指客户端的真实IP,如果设置了$remote_addr这个值,后端服务器就能获取到客户端的真实IP,也就是此例中的192.168.1.1
二、Host
host的值设置为$proxyhost, 是指proxy_pass中设置的host值,也就是192.168.1.3,也就是服务器的IP地址。
若客户端发过来的请求header中有HOST这个字段,$http_host和$host表示的就是原始请求host,比如请求的时候HOST的值是http://test.com ,那么反代后还是http://test.com 。
若客户端发过来的请求header中没有HOST这个字段,$host表示nginx代理服务器的地址,也就是此例中的192.168.1.2。
$httphost不是一个固定的变量,他其实是$http _HEADER通配后的结果,这里的HEADER是一个通配符,通配的是请求头里的header属性,例如$http_content_type
表示请求头里content-type
属性的值,同理,$http_host
指的就是请求头里的host
属性。
三、X-Forwarded-For
这个变量的值有$proxy_add_x_forwarded_for和$remote_addr,在只有一个代理服务器的转发的情况下,两者的效果貌似差不多,都可以真实的显示出客户端原始ip。
举例说明,用户A的IP是192.168.1.1,请求一个经过两次nginx转发的应用,在第一台nginx中(192.168.1.2),配置如下:
1 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
现在$proxy_add_x_forwarded_for变量的”X-Forwarded-For”部分是空的,所以只有$remote_addr,而$remote_addr的值是用户的ip,那么X-Forwarded-For变量的值就是用户的ip:192.168.1.1。
到第二台nginx,配置如下:
1 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
现在的$proxy_add_x_forwarded_for变量,X-Forwarded-For部分包含的是用户的真实ip,$remote_addr部分的值是上一台nginx的ip地址,那么X-Forwarded-For的值就变成了”用户的真实ip,第一台nginx的ip”,也就是“192.168.1.1, 192.168.1.2”
所以还是建议X-Forwarded-For的值设置成$proxy_add_x_forwarded_for。
nginx正向代理: 示例配置:
1 2 3 4 5 6 listen 80; server_name localhost; resolver 223.5.5.5; location / { proxy_pass http://$http_host$request_uri; }
其中重要的配置主要是:proxy_pass和 resolver
proxy指定其正向代理所转发的地址 $http_host为其url
$request_uri为其请求的uri
resolver后面跟的是其转发时使用的dns地址,如没指定,nginx无法正常解析dns,则无法访问域名网站。
10.四层负载均衡 proxy模块默认只支持七层代理,也就是基于http协议代理,如果想要进行四层转发的话(也就是对其他协议进行转发),可以用到stream模块:
所属模块:ngx_stream_core_module
默认:该ngx_stream_core_module
模块自1.9.0版开始可用。默认情况下未构建此模块,应使用--with-stream
配置参数启用它 。使用官方源默认会编译该模块
1 2 3 Syntax: stream { ... }Default: —Context: main
在配置文件里面,其模块位置于http同级,下面是示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 worker_processes auto;error_log /var/log/nginx/error.log info ;events { worker_connections 1024 ; }stream { upstream backend { hash $remote_addr consistent; server backend1.example.com:12345 weight=5 ; server 127.0.0.1:12345 max_fails=3 fail_timeout=30s ; server unix:/tmp/backend3; } upstream dns { server 192.168.0.1:53535 ; server dns.example.com:53 ; } server { listen 12345 ; proxy_connect_timeout 1s ; proxy_timeout 3s ; proxy_pass backend; } server { listen 127.0.0.1:53 udp reuseport; proxy_timeout 20s ; proxy_pass dns; } server { listen [::1 ]:12345 ; proxy_pass unix:/tmp/stream.socket; } }
这里于七层代理在配置文件上最大的区别就是http换成了stream
下面是我在本地做的一个实例:
效果为将一台服务器的ssh协议转发到后端两台服务器
调度器:10.10.10.105
后端服务器:10.10.10.187 ,10.10.10.243
调度服务器nginx 配置添加如下
stream { upstream backend { server 10.10.10.187:22; server 10.10.10.243:22; } server { listen 88 ; proxy_pass backend; } }
三台服务器都是虚拟机,添加好配置以后使用xshell进行测试
在弹出的对话框输入账号密码,然后测试成功!
需要注意的是经过测试,stream模块是转发请求而非代理,严格意义上来说是四层转发,其功能于lvs无异。
11.HTTPS
https在http中加入TLS/SSL层,http为明文传输,而https为密文传输,也更为安全。https默认监听端口443,需要证书进行认证,一般证书都有第三方机构或CA颁发。
所属模块:http_ssl_module
默认:不编译进内核 编译参数:–with-http_ssl_module
1 2 3 4 5 6 7 8 9 10 11 syntax: ssl on | off; Default: ssl off; context: http, server syntax : ssl_certificate file; Default: - context: http, server syntax: ssl_certificate_key file; Default: - context: http, server
nginx.conf配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 server { listen 443 ssl; server_name www.oldboy.com; ssl_certificate ssl_key/server.crt; ssl_certificate_key ssl_key/server.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; location / { root /code/https; index index.html index.htm; } }
其中ssl_certificate为证书文件,ssl_certificate_key为秘钥文件。
在公司内部使用时,也可使用私有证书(公网中无法验证证书)。
私有证书颁发步骤:
1.生成key秘钥 2.生成证书签名请求文件 csr 3.生成证书签名文件 ca
要求: 1.openssl大于1.0.2 [root@localhost ~]# openssl version OpenSSL 1.1.1g FIPS 21 Apr 2020
2.nginx必须有ssl模块 nginx -V
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 生成RSA密钥(过程需要设置一个密码,记住这个密码) openssl genrsa -des3 -out domain.key 1024 拷贝一个不需要输入密码的密钥文件 openssl rsa -in domain.key -out domain_nopass.key 生成一个证书请求 openssl req -new -key domain.key -out domain.csr 这里会提示输入国家,地区组织,email等信息.最重要的一个是"common name" ,需要与网站域名相同. Enter pass phrase for domain.key: ----- Country Name (2 letter code) [XX]:CN State or Province Name (full name) []:Jilin Locality Name (eg, city) [Default City]:Changchun Organization Name (eg, company) [Default Company Ltd]:Python Organizational Unit Name (eg, section) []:Python Common Name (eg, your name or your server's hostname) []:domain.com # 网站域名 Email Address []:123@domain.com # 邮箱 A challenge password []: # 私钥保护密码,可直接回车 An optional company name []: # 一个可选公司名称,可直接回车 输入完这些就会生成一个domain.csr文件,提交给ssl提供商的时候就是这个csr文件.当然这里并没有向任何证书提供商申请,而是自己签发证书. 使用上面的密钥和CSR对证书签名 openssl x509 -req -days 365 -in domain.csr -signkey domain.key -out domain.crt 最后将crt文件与key文件放入nginx配置文件中去