Nginx

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