nginx安装配置 - yiyixiaozhi/readingNotes GitHub Wiki


title: nginx安装配置 date: 2019-01-24 description: nginx安装配置 categories:

  • 工具 tags:

CentOS版本

nginx安装

nginx安装:
yum -y install openssl
yum -y install zlib
yum -y install pcre
rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
yum install nginx
service nginx start

NginX - 响应时间计算与日志输出格式修改

参考:https://www.cnblogs.com/JustBeZero/p/9441413.html

  • 日志输出配置

    • 默认调用 combined 格式:

      log_format combined '$remote_addr - $remote_user [$time_local] '
                          '"$request" $status $body_bytes_sent '
                          '"$http_referer" "$http_user_agent" ';
      
    • Nginx 也允许自定义日志格式,例如:

      log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" '
                      '"$request_time"';
      

      输出日志时,还需明确指定调用自定义格式名(示例中为 main):

      access_log logs/access.log main;
      

时间计算属性

主要涉及以下两个属性值,可根据需要应用计算:

  • request_time

    • 官网描述

      request processing time in seconds with a milliseconds resolution; time elapsed between the first bytes were read from the client and the log write after the last bytes were sent to the client.

    • 应用释义

      该属性计算的是从接收到用户发送请求中的第一个字节发送完完整响应数据的时间;

      可粗略理解为:request_time = 接收请求数据时间 + 后端服务响应时间 + 输出响应数据时间

  • upstream_response_time

    • 官网描述

      keeps times of responses obtained from upstream servers; times are kept in seconds with a milliseconds resolution. Several response times are separated by commas and colons like addresses in the $upstream_addr variable.

    • 应用释义

      该属性计算的是从 Nginx与后端服务建立连接接收完数据关闭连接的时间;

      可粗略理解为: 后端服务响应时间(略去 Nginx 与后端服务之间的数据传输时间)

  • time_local

    日志输出时间

重定向URI

location指令语法

location [=||*|^~|@] /uri/ { … } 或 location @name { … }

Nginx路径匹配符号

= 表示精确匹配 ^~ 表示uri以某个常规字符串开头,大多情况下用来匹配url路径,nginx不对url做编码,因此请求为/static/20%/aa,可以被规则^~ /static/ /aa匹配到(注意是空格)。 ~ 正则匹配(区分大小写) ~* 正则匹配(不区分大小写) !和!*分别为区分大小写不匹配及不区分大小写不匹配的正则 / 任何请求都会匹配

符号的优先级

首先匹配 =,其次匹配^~, 其次是按文件中顺序的正则匹配,最后是交给 / 通用匹配。当有匹配成功时候,停止匹配,按当前匹配规则处理请求。

URI匹配模式

location指令分为两种匹配模式:

  1. 普通字符串匹配:以=开头或开头无引导字符(~)的规则
  2. 正则匹配:以~或~*开头表示正则匹配,~*表示正则不区分大小写

location URI匹配规则

当nginx收到一个请求后,会截取请求的URI部份,去搜索所有location指令中定义的URI匹配模式。在server模块中可以定义多个location指令来匹配不同的url请求,多个不同location配置的URI匹配模式,总体的匹配原则是:先匹配普通字符串模式,再匹配正则模式。只识别URI部份。

一个请求过来后,Nginx匹配这个请求的流程如下:

  1. 先查找是否有=开头的精确匹配,如:location = /test/abc/user.do { … }

  2. 再查找普通匹配,以 最大前缀 为原则,如有以下两个location,则会匹配后一项

    location /test/ { … } location /test/abc { … }

  3. 匹配到一个普通格式后,搜索并未结束,而是暂存当前匹配的结果,并继续搜索正则匹配模式

  4. 所有正则匹配模式location中找到第一个匹配项后,就以此项为最终匹配结果。所以正则匹配项匹配规则,受定义的前后顺序影响,但普通匹配模式不会。

  5. 如果未找到正则匹配项,则以3中缓存的结果为最终匹配结果。

  6. 如果一个匹配都没搜索到,则返回404。

精确匹配与模糊匹配差别

location =/ { … } 与 location / { … } 的差别:

前一个是精确匹配,只响应/请求,所有/xxx或/xxx/xxxx类的请求都不会以前缀的形式匹配到它。

后一个是只要以 / 为前缀的请求都会被匹配到。如:/abc , /test/abc, /test/abc/aaaa

正则与非正则匹配

  1. location ~ /test/.+.jsp$ { … } :正则匹配,支持标准的正则表达式语法。
  2. location ^~ / { … } : ^~意思是关闭正则匹配,当搜索到这个普通匹配模式后,将不再继续搜索正则匹配模式。

Rewrite用法

rewrite regex replacement [flag];

如果相对域名或参数字符串起作用,可以使用全局变量匹配,也可以使用proxy_pass反向代理。 从上表明看rewrite和location功能有点像,都能实现跳转。主要区别在于rewrite是在同一域名内更改获取资源的路径,而location是对一类路径做控制访问或反向代理,可以proxy_pass到其他机器。

很多情况下rewrite也会写在location里,它们的执行顺序是:

  1. 执行server块的rewrite指令
  2. 执行location匹配
  3. 执行选定的location中的rewrite指令

如果其中某步URI被重写,则重新循环执行1-3,直到找到真实存在的文件;循环超过10次,则返回500 Internal Server Error错误。

rewrite语法格式

rewrite        <regex>        <replacement>        <flag>;
 关键字        正则表达式         代替的内容         重写类型

Rewrite:一般都是rewrite
Regex:可以是字符串或者正则来表示想要匹配的目标URL
Replacement:将正则匹配的内容替换成replacement

Flag:flag标示,重写类型:
  - last:本条规则匹配完成后,继续向下匹配新的location URI规则;相当于Apache里德(L)标记,表示完成rewrite,浏览器地址栏URL地址不变;一般写在server和if中;
  - break:停止执行当前虚拟主机的后续rewrite指令集。本条规则匹配完成后,终止匹配,不再匹配后面的规则,浏览器地址栏URL地址不变;一般使用在location中;
  - redirect:返回302临时重定向,浏览器地址会显示跳转后的URL地址;
  - permanent:返回301永久重定向,浏览器地址栏会显示跳转后的URL地址;

因为301和302不能简单的只返回状态码,还必须有重定向的URL,这就是return指令无法返回301,302的原因了。

这里 last 和 break 区别有点难以理解:

  1. last一般写在server和if中,而break一般使用在location中
  2. last不终止重写后的url匹配,即新的url会再从server走一遍匹配流程,而break终止重写后的匹配
  3. break和last都能组织继续执行后面的rewrite指令
server {
  # 访问 /last.html 的时候,页面内容重写到 /index.html 中,并继续后面的匹配,浏览器地址栏URL地址不变
  rewrite /last.html /index.html last;

  # 访问 /break.html 的时候,页面内容重写到 /index.html 中,并停止后续的匹配,浏览器地址栏URL地址不变;
  rewrite /break.html /index.html break;

  # 访问 /redirect.html 的时候,页面直接302定向到 /index.html中,浏览器地址URL跳为index.html
  rewrite /redirect.html /index.html redirect;

  # 访问 /permanent.html 的时候,页面直接301定向到 /index.html中,浏览器地址URL跳为index.html
  rewrite /permanent.html /index.html permanent;

  # 把 /html/*.html => /post/*.html ,301定向
  rewrite ^/html/(.+?).html$ /post/$1.html permanent;

  # 把 /search/key => /search.html?keyword=key
  rewrite ^/search\/([^\/]+?)(\/|$) /search.html?keyword=$1 permanent;
  
  # 把当前域名的请求,跳转到新域名上,域名变化但路径不变
  rewrite ^/(.*) http://www.jd.com/$1 permanent;
  }

IF判断

if (表达式) {
}
对给定的条件condition进行判断。如果为真,大括号内的rewrite指令将被执行,if条件(conditon)可以是如下任何内容:
当表达式只是一个变量时,如果值为空或任何以0开头的字符串都会当做false
直接比较变量和内容时,使用=或!=
~  正则表达式匹配
~* 不区分大小写的匹配
!~  区分大小写的不匹配
-f和!-f  用来判断是否存在文件
-d和!-d  用来判断是否存在目录
-e和!-e  用来判断是否存在文件或目录
-x和!-x  用来判断文件是否可执行

#当表达式只是一个变量时,如果值为空或任何以0开头的字符串都会当做false直接比较变量和内容时,使用=或!=~正则表达式匹配,~*不区分大小写的匹配,!~区分大小写的不匹配

#判断访问地址
if  ($remote_addr = 192.168.1.100) { 
  return 403;
}

#判断访问的是否ie;
if ($http_user_agent ~ MSIE) {
  rewrite ^.*$ /ie.htm;
  break; #不break会循环重定向(是ie重写到ie.htm,然后又发现是ie,又重写到ie.htm...)
}

如果用户设备为IE浏览器的时候,重定向
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
} //如果UA包含"MSIE",rewrite请求到/msid/目录下
 
if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
set $id $1;
} //如果cookie匹配正则,设置变量$id等于正则引用部分
 
if ($request_method = POST) {
return 405;
} //如果提交方法为POST,则返回状态405(Method not allowed)。return不能返回301,302
 
if ($slow) {
limit_rate 10k;
} //限速,$slow可以通过 set 指令设置
 
if (!-f $request_filename){
break;
proxy_pass http://127.0.0.1;
} //如果请求的文件名不存在,则反向代理到localhost 。这里的break也是停止rewrite检查
 
if ($args ~ post=140){
rewrite ^ http://example.com/ permanent;
} //如果query string中包含"post=140",永久重定向到example.com
 
location ~* \.(gif|jpg|png|swf|flv)$ {
valid_referers none blocked www.jefflei.comwww.leizhenfang.com;
if ($invalid_referer) {
return 404;
} //防盗链
}

# 示例1:不存在的文件跳到404.html
#跳转到404
if (!-e $document_root$fastcgi_script_name) {
  rewrite ^.*$ /404.html;
  break;
} 
/*
要加break,以 xx.com/dsafsd.html这个不存在页面为例,我们观察访问日志, 日志中显示的访问路径,依然是GET /dsafsd.html HTTP/1.1

提示: 服务器内部的rewrite和302跳转不一样.302跳转url会改变,变成重新http请求404.html, 而内部rewrite, 上下文没变,
就是说 fastcgi_script_name 仍然是 dsafsd.html,因此会循环重定向.
*/

# 示例2:在不使用break的情况下,对ie访问进行重写
if ($http_user_agent ~* msie) { //如果是ie访问的话设变量为1;
  set $isie 1;
}

if ($fastcgi_script_name = ie.html) { //如果访问的脚本为ie.html,变量为0;
  set $isie 0;
}

if ($isie 1) { //综合起来,如果ie访问的是ie.html这个脚本就不重写;
  rewrite ^.*$ ie.html;
}

# 示例3:目录自动加/
if (-d $request_filename){
    rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;
}
用(1)匹配最后一个非'/'的字符,然后自己强行再添加一个'/'($2变量后的那个)

# 示例4:Nginx防盗链
location ~* ^.+\.(jpg|jpeg|gif|png|swf|rar|zip|css|js)$ {
    valid_referers none blocked *.nixi8.com nixi8.com localhost 192.168.42.188; #定义none(空,直接访问),blocked(被防火墙标记过的来路),nixi8.com的二级域名和一级域名,localhost,192.168.42.188
    
    if ($invalid_referer) { # 如果不是上面定义的其中一个
        rewrite ^/ http://www.nixi8.com/none.gif;  # 就重写到一张gif图片上;
        return 412;
        break;
    }
    
    access_log   off;  # 关闭日志,降低服务器的损耗
    root /opt/lampp/htdocs/web; 
    expires 3d; 
    break;
}

# 示例5:隐藏index.php
apache下只要在全局配置文件中设置了缺省首页index.php就能实现直接到达index.php,但是nginx目前默认情况下只能到达index.html而不能访问到index.php,所以只好rewrite重写使其支持
if (-f $request_filename) { //使其不隐藏index.php的时候也能访问到
    expires max;
    break;
}
if (!-e $request_filename) {
    rewrite ^/(.*)$ /index.php/$1 last;
}

内置全局环境变量

$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相同。
 
例子:
URL:http://localhost:81/download/stat.php?id=1585378&web_id=1585378
Server_Dir:/var/www/html
$host:localhost
$server_port:81
$request_uri:/download/stat.php?id=1585378&web_id=1585378
$document_uri:/download/stat.php
$document_root:/var/www/html
$request_filename:/var/www/html/download/stat.php

# 如果文件不存在则返回400
if (!-f $request_filename) {
    return 400;
}

# 如果host是www.360buy.com,则301到www.jd.com中
if ( $host != "www.jd.com" ){
    rewrite ^/(.*)$ https://www.jd.com/$1 permanent;
}

# 如果请求类型是POST则返回405,return不能返回301,302
if ($request_method = POST) {
    return 405;
}

# 如果参数中有 a=1 则301到指定域名
if ($args ~ a=1) {
    rewrite ^ http://example.com/ permanent;
}
- 文件名及参数重写
 location = /index.html {
 # 修改默认值为
 set $name test;

 # 如果参数中有 name=xx 则使用该值
 if ($args ~* name=(\w+?)(&|$)) {
     set $name $1;
 }

 # permanent 301重定向
 rewrite ^ /$name.html permanent;
}
- 隐藏真实目录
server {
  root /var/www/html;
  # 用 /html_test 来掩饰 html
  location / {
      # 使用break拿一旦匹配成功则忽略后续location
      rewrite /html_test /html break;
  }

  # 访问真实地址直接报没权限
  location /html {
      return 403;
  }
}
- 禁止指定IP访问
 location / {
        if ($remote_addr = 192.168.1.253) {
                return 403;
        }
 }
- 如果请求的文件不存在,则反向代理到localhost 。这里的break也是停止继续rewrite
if (!-f $request_filename){
    break;
    proxy_pass http://127.0.0.1;
}
- /images/bla_500x400.jpg文件请求,重写到/resizer/bla.jpg?width=500&height=400地址,并会继续尝试匹配location。
rewrite ^/images/(.*)_(\d+)x(\d+)\.(png|jpg|gif)$ /resizer/$1.$4?width=$2&height=$3? last;

反向代理Proxy_Pass

Proxy_pass反向代理,用的是nginx的Proxy模块。

第一种:
location /proxy/ {
    proxy_pass http://127.0.0.1/;
}
代理到URL:http://127.0.0.1/test.html


第二种:
location /proxy/ {
    proxy_pass http://127.0.0.1;  #少/
}
代理到URL:http://127.0.0.1/proxy/test.html


第三种:
location /proxy/ {
    proxy_pass http://127.0.0.1/aaa/;
}
代理到URL:http://127.0.0.1/aaa/test.html


第四种(相对于第三种,最后少一个 / )
location /proxy/ {
    proxy_pass http://127.0.0.1/aaa;
}
代理到URL:http://127.0.0.1/aaatest.html
- proxy_set_header  Host  $host;  作用web服务器上有多个站点时,用该参数header来区分反向代理哪个域名。比如下边的代码举例。
- proxy_set_header X-Forwarded-For  $remote_addr; 作用是后端服务器上的程序获取访客真实IP,从该header头获取。部分程序需要该功能。
  • Proxy_pass配合upstream实现负载均衡
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
 
    upstream core_tomcat {
      server 192.168.1.253:80      weight=5  max_fails=3 fail_timeout=30;
      server 192.168.1.252:80      weight=1  max_fails=3 fail_timeout=30;
      server 192.168.1.251:80      backup;
    }

    server {
        listen       80;
        server_name  www.jd.com;
        location /web {
            proxy_pass http://core_tomcat;
            proxy_set_header  Host  $host;
        }
    }
 }

Nginx负载均衡的几种模式

  • 轮询:每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,就不在分配;
upstream core_tomcat {
    server 192.168.1.253:80      max_fails=3 fail_timeout=30;
    server 192.168.1.252:80      max_fails=3 fail_timeout=30;
 }
  • 权重轮询:根据后端服务器性能不通配置轮询的权重比,权重越高访问的比重越高;
upstream core_tomcat {
    server 192.168.1.253:80      weight=2  max_fails=3 fail_timeout=30;
    server 192.168.1.252:80      weight=8  max_fails=3 fail_timeout=30;
}
#假如有十个请求,八个会指向第二台服务器,两个指向第一台;
  • IP_Hash:根据请求的ip地址hash结果进行分配,第一次分配到A服务器,后面再请求默认还是分配到A服务器;可以解决Session失效重新登录问题;
upstream core_tomcat {
  ip_hash;
  server 192.168.1.253:80      max_fails=3 fail_timeout=30;
  server 192.168.1.252:80      max_fails=3 fail_timeout=30;
}
  • Fair:按后端服务器的响应时间来分配请求,响应时间短的优先分配;
upstream core_tomcat {
  fair;
  server 192.168.1.253:80      max_fails=3 fail_timeout=30;
  server 192.168.1.252:80      max_fails=3 fail_timeout=30;
}
  • Url_hash:按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效;
upstream core_tomcat {
  hash  $request_uri;
  server 192.168.1.253:80      max_fails=3 fail_timeout=30;
  server 192.168.1.252:80      max_fails=3 fail_timeout=30;
}

配置访问静态资源

[root@localhost conf.d]# cat /etc/nginx/nginx.conf 
#user  nginx;
user root; ## 修改用户为root,访问没有访问权限

[root@localhost conf.d]# cat /etc/nginx/conf.d/yyxz.conf 
server {
    listen       82;
    server_name  localhost;
    #charset koi8-r;
    access_log  /var/log/nginx/host.access.log  main;

    # 静态资源访问统一重定向到本机路径(所有http://**/api/**.jpg都会访问到/home/yyxz/yyxz/static/test/**.jpg)
    location ~ /api/.*\.(jpg|png|xlsx)$ {
        rewrite "^/api/(.*\.(jpg|png|xlsx))$" /$1 break;
        root /home/yyxz/yyxz/static/test/;
    }
    # 指定静态资源访问
    location /bianxh/ {
        alias /home/yyxz/yyxz/static/test/;
        #autoindex on; ## 是否开启路径访问
    }
}

报错:

nginx -s reload

nginx: [error] invalid PID number "" in "/var/run/nginx.pid"

发生这个错误的原因是,nginx读取配置文件时出错,需要指定一个特定的nginx配置文件,所以解决这个问题需要先执行 sudo nginx -c etc/nginx/nginx.conf

参考

⚠️ **GitHub.com Fallback** ⚠️