Nginx
http 反向代理 mail反向代理
高并发连接,官方测试可支持5w并发量,实际3w左右
使用epoll和kqueue网络I/O模型
内存消耗小,开启10个Nginx进程消耗15M*10=150M内存
支持负载均衡,反向代理
Nginx请求连接的方法
select模型,阻塞I/O
epoll模型,多路复用I/O,并发量更大,速度更快
安装Nginx
源码包安装
yum -y install gcc gcc-c++ autoconf automake
yum -y install zlib zlib-devel openssl openssl-devel pcre-devel
zlib:Nginx提供gzip模块,需zli库支持
openssl:Nginx提供ssl功能
pcre:提供地址重写rewrite功能
创建nginx系统用户和组
groupadd -r nginx
useradd -s /sbin/nologin -g nginx -r nginx
自定义模块
./configure \
--prefix=/usr/local \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_flv_module \
--with-http_gzip_static_module \
--http-log-path=/var/log/nginx/access.log \
--http-client-body-temp-path=/var/tmp/nginx/client \
--http-proxy-temp-path=/var/tmp/nginx/proxy \
--http-fastcgi-temp-path=/var/tmp/nginx/fcgi \
--with-http_stub_status_module
make && make install
编译完成后可以启动nginx,不能通过systemd服务控制启动
nginx控制方法
[root@localhost ~]# /usr/sbin/nginx -c /etc/nginx/nginx.conf
从容关闭Nginx,就是给nginx发信号
[root@localhost ~]# kill -QUIT $(cat /var/run/nginx/nginx.pid)
平滑重启nginx
[root@localhost ~]# kill -HUP $(cat /var/run/nginx/nginx.pid)
快速停止
[root@localhost ~]# kill -TERM $(cat /var/run/nginx/nginx.pid)
强制结束所有的nginx进程
[root@localhost ~]# pkill -9 nginx
发送信号重新读取配置文件
[root@localhost ~]# pkill -1 nginx
检测nginx配置文件语法
[root@localhost ~]# /usr/sbin/nginx -t -c /etc/nginx/nginx.conf
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
配置文件语法
每一个server代表一个虚拟主机,每一个location代表一个目录,如果在location外面指定root目录,location定义的目录就是根据root定义的目录结构来的,定义的内容每行最后都要以;
结尾
location匹配规则
语法:location [=|~|~*|^~] /url/ {...}
默认值:no
使用字段:server下的location
这个参数根据URL的不同需求来进行配置,可以使用字符串与正则表达式匹配,如果要使用正则表达式,你必须指定下列前缀~
:区分大小写~*
:不区分大小写^~
:禁止表达式匹配=
: 精确匹配
如果有重复匹配,则匹配最精确的行
EXAMPLE:
location = / {
#只匹配/的查询
[configuration A]
}
location / {
#匹配任何以/开始的查询,但是正则表达式与一些较长的字符串将被首先匹配
[configuration B]
}
location ^~ /images/ {
#匹配任何以/images/开始的查询并且停止搜索,不检查正则表达式
[configuration C]
}
location ~* \.(gif|jgp|jpeg)${
#匹配任何以gif,jpg,或jpeg结尾的文件,但是有/images/目录的请求将在configuration C 中处理
[configuration D]
}
配置虚拟主机
每一个server都是一个虚拟主机
[root@localhost redhatb2]# cat /etc/nginx/nginx.conf | grep -v \# | grep -v ^$
#user nobody;
指定用于运行worker进程的用户和组【user nginx nginx 】编译过程中指定了user和group此处就无需再指定
#pid /PATH/TO/PID_FILE;
指定nginx进程的pid文件路径
#worker_cpu_affinity; cpu绑定
#worker_priority [-20-19]; 指定nice值,默认为0
worker_processes 1; ======>可以设置为auto自动匹配cpu个数
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name redhatb1.example.com;
root /var/www/redhatb1;
location / {
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 80 default_server;
server_name redhatb2.example.com;
root /var/www/redhatb2;
index index.html;
}
}
上面的redhatb2.example.com主机设置成为了默认主机,此时,如果有域名解析到服务器的IP地址并请求,但是nginx配置文件中没有相对应的虚拟主机条目,此时就会跳转到redhatb2这个默认的虚拟主机上。如果所有的虚拟主机都没有配置成为默认主机选项,那么默认跳转到第一条虚拟主机条目。
当默认条目附加到以下条目的时候,配置中没有响应条目的请求就会跳到以下配置上,就会返回错误信息
server {
listen 80 default_server;
server_name _;
return 444;
}
自定义日志
可以根据不同的虚拟主机定义不同的错误日志
server {
listen 80 default_server;
server_name redhatb2.example.com;
root /var/www/redhatb2;
index index.html;
access_log /var/log/nginx/redhatb2-access.log main;
error_log /var/log/nginx/redhatb2-error.log warn; =====>可以指定级别,出于调试目的,可以指定为debug级别,但是仅在编译时,使用了“--with-debug”选项时才有效
}
自定义错误页面
可以根据自己需求自定义错误页面
server {
listen 80 default_server;
server_name redhatb2.example.com;
root /var/www/redhatb2;
index index.html;
access_log /var/log/nginx/redhatb2-access.log main;
error_log /var/log/nginx/redhatb2-error.log warn;
error_page 403 404 /40x.html;
location = /40x.html {
root /var/www/error;
}
}
要在/var/www/error下面创建40x.html,里面的内容是自定义的错误页面
可以一起定义,也可以分开定义如下所示,这样403和404错误可以显示不同的内容,同时,也需要在/var/www/error下创建403.html和404.html错误页面
server {
listen 80 default_server;
server_name redhatb2.example.com;
root /var/www/redhatb2;
index index.html;
access_log /var/log/nginx/redhatb2-access.log main;
error_log /var/log/nginx/redhatb2-error.log warn;
error_page 403 /403.html;
location = /403.html {
root /var/www/error;
}
error_page 404 /404.html;
location = /404.html {
root /var/www/error;
}
}
自动索引功能
server {
listen 80 default_server;
server_name redhatb2.example.com;
root /var/www/redhatb2;
index index.html;
location /data {
autoindex on;
}
}
开启这个功能后,访问redhatb2.example.com/data时将自动把/data目录下的所有文件列出来,和Apache里的Options Indexes功能一样,当用户请求/data目录的时候,会直接列出目录里面的内容,不会报403错误,这种方式很不安全,除非作为下载站使用。
别名功能
server {
listen 80 default_server;
server_name redhatb2.example.com;
root /var/www/redhatb2;
index index.html;
access_log /var/log/nginx/redhatb2-access.log main;
error_log /var/log/nginx/redhatb2-error.log warn;
location /a {
alias /var/www/alias/test;
}
}
假如当你访问/a/top.gif的时候,实际上访问的是/var/www/alias/test/top.gif
!!注意!!当location后面定义的目录以/结尾时,下面alias定义的目录也要以/结尾,否则报错
像这样就不会报错,和上面不以/结尾时一样的,要么都加,要么都不加
location /a/ {
alias /var/www/alias/test/;
}
但是如果加上/的话,用户在浏览器中也必须以/结尾,如果只是对一条路径的其中一段做别名,可以加上/,也可以不加,所以综合来看,还是不加要方便一点
Apache里面做别名有一个Alias模块专门定义别名,而不在directory里面定义
控制站点的访问
server {
listen 80 default_server;
server_name redhatb2.example.com;
root /var/www/redhatb2;
index index.html;
access_log /var/log/nginx/redhatb2-access.log main;
error_log /var/log/nginx/redhatb2-error.log warn;
location /a {
deny 192.168.0.123;
allow 192.168.0.0/24;
allow 192.168.1.1;
deny all;
}
}
这种控制有先后顺序,和Apache不一样,nginx是从上到下依次匹配,和防火墙的匹配规则类似
目录身份验证
和Apache的目录身份验证类似,只是语法不一样
server {
listen 80 default_server;
server_name redhatb2.example.com;
root /var/www/redhatb2;
index index.html;
access_log /var/log/nginx/redhatb2-access.log main;
error_log /var/log/nginx/redhatb2-error.log warn;
location /data {
autoindex on;
auth_basic "AwstatAuth";
auth_basic_user_file /etc/nginx/htpasswd;
}
}
同时也需要使用htpasswd命令创建htpasswd文件,详细操作参考 的基于认证的网页登录笔记
nginx状态检查
server {
listen 80 default_server;
server_name redhatb2.example.com;
root /var/www/redhatb2;
index index.html;
access_log /var/log/nginx/redhatb2-access.log main;
error_log /var/log/nginx/redhatb2-error.log warn;
location /status {
stub_status on;
access_log off;
}
}
/status目录可以不存在,进入redhatb2.example.com/status
可以查看nginx的状态信息,例如
Active connections: 2 server accepts handled requests 46 46 198 Reading: 0 Writing: 1 Waiting: 1
nginx地址重写rewrite
Rewrite主要的功能就是实现URL的重写,如果需要nginx的地址重写功能,那么在编译之前,需要编译安装PCRE库(兼容perl的正则表达式)
URL:统一资源定位符,用户浏览器里面输入的是URL地址
URI:由一个通过通用资源标识符进行定位,配置文件中location定义的是URI地址
变量名可以使用“=”或“!=”运算符
“”表示区分大小写字母的匹配*”表示不区分大小写的匹配
“
“!”和“!*”与“”“!”相反
“-f”和“!-f”用来判断文件是否存在
“-d”和“!-d”用来判断目录是否存在
“-e”和“!-e”用来判断文件或目录是否存在
“-x”和“!-x”用来判断文件是否可以执行
同时支持$1到$9的位置化参数
rewrite最后一项参数为flag标记,支持以下几种
last:相当于Apache里面的【L】标记,表示完成rewrite
break:本条规则匹配完成后,终止匹配,不再匹配后面的规则
redirect:返回302临时重定向,浏览器地址会显示跳转后的URL地址
permanent:返回301永久重定向,浏览器地址栏会显示跳转后的URL地址
last和break用来实现URI重写,浏览器地址栏URL地址不变
redirect和permanent用来实现URL跳转,浏览器地址栏会显示跳转后的URL地址
一般在跟location中(即location / {……})或直接在server标签中编写rewrite规则,推荐使用last标记
在非根location中(location /data {……}),则使用break标记
if指令
规则语法
if($http_user_agent ~ MSIE){
rewrite ^(.*)$/mesi/$1 break;
}
$1代表位置化参数,引用root后面的URI路径
if(!-f $request_filename){
rewrite ^/img/(.*)$ /site/$host/imgages/$1 last;
}
return指令
规则语法
location ~ .*\.(sh|bash)?$
{
return 403;
}
将原来要访问/pub目录重写为/download
server {
listen 80;
server_name redhatb1.example.com;
root /var/www/redhatb1;
location / {
index index.html index.htm;
}
location /pub {
rewrite ^/pub/?$ /download permanent;
}
location /download {
autoindex on;
}
}
将所有请求redhatb1.example.com/pub
的链接重写到redhatb1.example.com/download
rewrite可以写在location里面,也可以写在location外面
根据不同的浏览器将得到不同的结果
server {
listen 80;
server_name redhatb1.example.com;
root /var/www/redhat1;
if ($http_user_agent ~ Firefox ){
rewrite ^/data/(.*)$ /firefox/data/$1 last;
}
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 last;
}
}
实现域名跳转
server {
listen 80;
server_name redhatb3.example.com;
root /var/www/redhatb3;
index index.html;
rewrite ^(.*)$ http://redhatb1.example.com/$1 permanent;
location /firefox/data {
index index.html;
}
}
当访问redhatb3.example.com
的时候,将自动跳转到redhatb1.example.com
TLS认证的配置
server {
listen 443 ssl;
server_name redhatb.example.com;
ssl_certificate /etc/pki/tls/certs/nginx.crt;
ssl_certificate_key /etc/pki/tls/private/nginx.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root /var/www/redhatb;
index index.html index.htm;
}
}
通过keygen命令生成证书和私钥,证书放在/etc/pki/tls/certs里面,私钥放在/etc/pki/tls/private里面,重启nginx生效
nginx日志管理
log_format指令用来设置日志的记录格式,语法如下:
log_format name format [format……]
默认的日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
- $remote_addr:客户端的IP地址
- $remote_user:用来记录远程客户端用户名称,一般不会有记录,除非用账号密码认证了的,才会记录用户名
- $time_local:用来记录访问时间及时区
- $request:用于记录请求的URL和HTTP协议
- $status:用于记录请求的状态,例如成功时状态为200,页面找不到时为404
- $bady_bytes_sent:用于记录发送给客户端的文件主体内容大小
- $http_referer:用于记录是从哪个页面链接访问过来的
- $http_user_agemt:用于记录客户端浏览器的相关信息
- $http_x_forwarded_for:用于记录远程用户真正的IP地址。一旦有了缓存,代理,后端日志记录的是缓存,代理的IP地址,而不会记录原来真正的IP地址,此字段就是用于记录真正的来源IP地址。
可以给每个server或者每个location分别定义日志,更精确
可以将日志放在缓存里面例如:
access_log /data/log/$server_name.log main buffer=32k;
buffer=32k:表示设置内存缓冲区的大小
注意:尽量不要用变量,当主机不多的时候,直接用主机名
开启日志打开缓存
对于每一条日志记录,日志文件都将先打开文件,再写入日志记录,然后马上关闭,为了提高包含变量的日志文件存放路径的性能,可以使用open_log_file_cache指令来设置,格式如下:
open_log_file_cache max=N [incative=time] [min_user=N] [valid=time] | off
该指令默认是禁止的,等同于open_log_file_cache off;
- max:设置缓存中的最大文件描述符数量
- inactive:设置一个时间,如果在设置的时间内没有使用此文件描述符,则自动删除此描述符
- min_uses:在参数inactive指定的时间范围内,如果日志文件超过被使用的次数,则将该日志文件的描述符计入缓存,默认为10秒钟
- valid:设置多长时间检查一次,看日志文件路径与文件名是否仍然存在,默认60秒
- open_log_file_cache max=1000 inactive=20s min_uses=2 valid=1m;
这条指令的意思是,设置1000个文件描述符,每1分钟检查一次,如果检查到20秒内该文件没有被使用2次,则将它从缓存中删除,如果使用了2次及2次以上,则计入缓存。
nginx日志的分割
编辑一个脚本
vim /var/log/nginx/nginx_log.sh
#!/bin/bash
#定义日志目录
log_path='/var/log/nginx'
#创建每天的目录
mkdir -p $log_path/$(date -d yesterday +%Y)/$(date -d yesterday +%m)/$(date -d yesterday +%d)/
#把日志移动到相应的目录
mv $log_path/redhatb2-access.log $log_path/$(date -d yesterday +%Y)/$(date -d yesterday +%m)/$(date -d yesterday +%d)/$(date -d yesterday +%Y-%m-%d)-redhatb2.access.log
#重启nginx生成新的日志文件
kill -HUP $(cat /var/run/nginx/nginx.pid)
创建计划任务
crontab -e
01 01 * * * /bin/bash /var/log/nginx/nginx_log.sh
每天的1点1分执行一次
上述脚本及计划任务的作用就是,把每天的日志分割出来,放到相应的目录里面去,便于管理,不至于日志文件过于庞大
nginx开启压缩功能
在http{……}中间,启用压缩
#vim /etc/nginx/nginx.conf
gzip on;
gzip_mon_length 1k ;
gzip_buffer 4 16k ;
gzip_http_version 1.1 ;
gzip_comp_level 2 ;
gzip_type text/plain application/x-javascript text/css application/xml;
gzip_vary on;
nginx的浏览器本地缓存设置
#vim /etc/nginx/nginx.conf
location ~ .*\.(gif|jpg|jpge|png|bmp|swf)$
{
expires 30d;
}
location ~ .*\.(js|css)?$
{
expires 1h;
}
设定限速
location /download {
limit_rate_after 20m;
limit_rate 256k;
autoindex on;
}
设置前20M不限速,下载完20M之后开始限速,每秒256KB
设置反向代理及缓冲,下面是整个的配置
需要在http和location字段中同时设置
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;
client_max_body_size 300m;
client_body_buffer_size 128k;
proxy_read_timeout 600;
proxy_send_timeout 600;
proxy_buffer_size 16k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_temp_path /proxy/nginx/temp;
proxy_cache_path /proxy/nginx/cache levels=1:2 keys_zone=cache_one:500m inactive=1d max_size=1g;
#上面这一段可以写到下面的location中,写在这里表示全局适用
server {
listen 80;
server_name redhatb3.example.com;
root /var/www/redhatb3;
index index.html;
location /firefox/data {
index index.html;
}
location /sms {
proxy_pass http://172.25.254.121;
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_cache_valid 200 10m;
proxy_cache_valid 304 1m;
proxy_cache_valid 301 302 1h;
proxy_cache_valid any 1m;
proxy_cache_key $host$uri$is_args$args;
}
}
}
在http段进行设置中的各个指令的意义
http {
#允许客户端请求的最大的单个文件字节数
client_max_body_size 300m;
#缓冲区代理缓冲用户端请求的最大字节数,可以理解为先保存到本地再传给用户
client_body_buffer_size 128k;
#跟后端服务器连接的超时时间,发起握手等候响应的超时时间
proxy_connent_timeout 600;
#连接成功后,等候后端服务器响应时间,其实已经进入后端的排队之中等候处理
proxy_read_timeout 600;
#后端服务器回传时间,就是在规定时间之内后端服务器必须传完所有的数据
proxy_send_timeout 600;
#代理请求缓存区,这个缓存区会保存用户的头信息以供nginx进行规则处理,一般只要能保存下头信息即可
proxy_buffer_size 16k;
#告诉nginx保存单个用的几个buffer及最大用多大空间
proxy_buffers 4 32k;
#如果系统很忙的时候可以申请更大的proxy_buffers,官方推荐*2
proxy_busy_buffers_size 64k;
#proxy缓存临时文件的大小
proxy_temp_file_write_size 64k;
proxy_temp_path /data1/proxy_temp_path;
proxy_cache_path /data1/proxy_cache_path levels=1:2 keys_zone=cache_one:500m inactive=1d max_size=1g;
}
###上面keys_zone=cache_one:500m指定的500m是存放在内存中的,不要设置的太大,cache_one是cache的名字,inactive=1d 缓存一天
在location中设置的指令的意义
location /sms {
#根据目录将请求丢到后端服务器,而本地不能有/sms目录,否则将访问本地的/sms目录
proxy_pass http://172.25.254.111; #后面可以接IP也可以接ip加端口号
#这个字段的意思是记录来源IP,而不是记录代理服务器,就是后端的日志里面记录的不是代理服务器IP,而是,真正远端客户端的IP
proxy_set_header Host $host;
#引用的cache
proxy_cache cache_one;
#记录远程IP,加入中间有代理,则没经过一次,加一个上一级代理IP,此时第一个ip为客户端原始ip
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
上面这些设置仅仅是把请求丢到后端,并没有做缓存,如果需要缓存,加上以下字段
proxy_cache_valid 200 10m;
proxy_cache_valid 304 1m;
proxy_cache_valid 301 302 1h;
proxy_cache_valid any 1m;
#以域名、URI、参数组合成Web缓存key值,nginx根据key值哈希,存储缓存内容到二级缓存目录内
proxy_cache_key $host$uri$is_args$args;
}
upstream模块实现负载均衡
upstream这个字段应该设置在http段里面
http {
......
upstream my_server_pool {
server 172.25.254.121:80 weight=1 max_fails=2 fail_timeout=30s;
server 172.25.254.123:80 weight=2 max_fails=2 fail_timeout=30s;
}
location /sms {
proxy_pass http://my_server_pool;
}
}
在上面的配置中,my_server_pool是upstream的名字,可以随便取,weight代表权重,就是丢给那个主机的次数,权重为2表示丢给它两次,再丢给下个主机,以上面的为例,121处理一次,123处理2次,再丢给121处理1次,然后再丢给123处理2次。max_fails为最大失败次数,失败两次后,丢给下一台主机,fail_timeout表示超时时间,超过30秒,丢给下一台主机
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 289211569@qq.com