Nginx

Nginx

标签 : nginx


Nginx

    nginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server, originally written by Igor Sysoev. For a long time, it has been running on many heavily loaded Russian sites including Yandex, Mail.Ru, VK, and Rambler. According to Netcraft, nginx served or proxied 25.64% busiest sites in April 2016. Here are some of the success stories: Netflix, Wordpress.com, FastMail.FM.
    The sources and documentation are distributed under the 2-clause BSD-like license.
    Commercial support is available from Nginx, Inc.

Nginx是一款轻量级的Web服务器/反向代理服务器电子邮件(IMAP/POP3)代理服务器,由俄罗斯工程师Igor Sysoev开发,供俄国大型入口网站及搜索引擎Rambler使用.其源代码以BSD-like协议发布. 其特点是内存占用少,并发能力强, 因此被国内很多大型网站(如京东/淘宝)采用.
(主页/介绍/文档).


编译安装

  • wget http://nginx.org/download/nginx-1.10.0.tar.gz
  • tar -zxvf nginx-1.10.0.tar.gz
  • ./configure --prefix=/usr/local/nginx

    configure阶段可能会遇到缺少依赖库的提示(如pcre/zlib),此时需要安装这些依赖才能继续:

    • yum install pcre pcre-devel
    • yum install zlib zlib-devel
  • make && make install
    安装完成后可在/usr/local/nginx/目录下生成如下文件夹:

目录 描述
conf nginx配置文件
html 网页文件
logs nginx日志文件
sbin nginx可执行文件
  • /usr/local/nginx/sbin/nginx
    启动, Nginx默认占用80端口,可在nginx.conf中更改.

Nginx信号

关于Linux信号相关知识, 可参考系列博客Linux信号实践, 在此, 我们仅介绍Nginx捕获的几个信号.

nginx can be controlled with signals.

  • Kill -信号名 PID
信号名 作用
TERM/INT fast shutdown
QUIT graceful shutdown
HUP changing configuration, keeping up with a changed time zone , starting new worker processes with a new configuration, graceful shutdown of old worker processes
USR1 re-opening log files
USR2 upgrading an executable file
WINCH graceful shutdown of worker processes

以上信号作用亦可通过编译出的nginx二进制文件实现:

To start nginx, run the executable file. Once nginx is started, it can be controlled by invoking the executable with the -s parameter. Use the following syntax:
nginx -s signal


配置

  • nginx.config
#运行服务的用户及用户组 
#user  nobody;

#工作进程数(一般设置为CPU数*核心数)
worker_processes  1;

#全局错误日志(位置/级别) 
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#PID文件
#pid        logs/nginx.pid;

#工作模式及连接数上限
events {

    # 采用epoll进行IO复用
    # use epoll;

    # 单进程所允许的最大连接数
    worker_connections  1024;
}


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"';

    #access_log  logs/access.log  main;

    #是否激活sendfile()函数
    sendfile        on;
    #将HTTP响应头压缩到一个包中发送,仅在sendfile开启时才能使用
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #开启gzip模块
    #gzip  on;

    #设定虚拟主机,默认监听80端口,可配置多个
    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        # 页面存放位置
        location / {
            # 页面存放根目录
            root   html;
            # 默认页面
            index  index.html index.htm;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ .php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ .php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.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;
    #    }
    #}
}

Server

在Nginx内可配置虚拟主机, 只需在nginx.conf中添加一个server元素:

server {
    listen 801;
    server_name www.feiqing.me;
    location / {
        root   /www.feiqing.me/;
        index  index.html index.htm;
    }
}

Log

  • 自定义log_format
log_format  fq_log_format   '$remote_addr - $remote_user [$time_local] "$request" '
        '$status $body_bytes_sent "$http_referer" '
        '"$http_user_agent" "$http_x_forwarded_for"';
  • servlet内引用
access_log logs/www.feiqing.me.access.log fq_log_format;
   启用log       log位置                     log格式
  • 示例
    www.feiqing.me server单独配置一个log:
server {
    listen 801;
    access_log logs/www.feiqing.me.access.log main;
    server_name www.feiqing.me;
    location / {
        root   /www.feiqing.me/;
        index  index.html index.htm;
    }
}

Location

Syntax:     location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
Default:    —
Context:    server, location

Sets configuration depending on a request URI.
Nginx允许自定义location块,通过指定的模式客户端请求的URI相匹配,Nginx可将网站根据URI进行划分,将网站的不同部分定位到不同的处理方式上:

server {
    server_name     www.feiqing.me;
    location /admin/ {
        # The configuration you place here only applies to http://www.feiqing.me/admin/
    }
}
  • location修饰符
    location第一个可选参数是一个符号,用来定义Nginx的匹配模式:
修饰符 描述
@ 指定一个命名的location,一般只用于内部重定向请求
= 精确匹配模式: URI的定位必须与指定的模式精确匹配
(无) 一般匹配模式: URI的定位必须以指定模式开始, 不可以使用正则表达式
~ 区分大小写的正则匹配模式: 客户端请求URI与指定正则表达式匹配必须区分大小写
~* 不区分大小写的正则匹配模式
^~ 类似于(无)模式的行为, URI的定位必须以指定模式开始, 不同的是, 如果模式匹配, 那么Nginx就停止搜索其他模式
!~/!~* 分别为区分大小写不匹配和不区分大小写不匹配的正则
/ 通用匹配, 任何请求都会匹配到
  • 有多个location配置情况下的匹配顺序:

    1. 带有=修饰符的location: 如果指定pattern与URI 精确匹配, 则Nginx使用该location设置.
    2. 没有修饰符的location: 如果指定pattern与URI 精确匹配,则使用之.
    3. 带有^~修饰符的location: 如果指定pattern与URI 开始匹配, 则使用之.
    4. 带有~/~*修饰符的location: 如果指定pattern与URI 匹配, 则使用之.
    5. 没有修饰符的location: 如果指定pattern与URI 开始匹配, 则使用之.
    6. 通用匹配/.
  • 示例:

location ~* ^/w*adminw*/ {
    root   /var/www/regexp/;
    index  index.html;
}

关于location详细内容可参考Nginx-ngx_http_core_module模块文档.


Rewrite

Rewrite用于实现URI重写, URI重写可以让我们在改变网站结构时,无需修改原先暴露出去的URL, 并且在一定程度上提高网站安全性;

The ngx_http_rewrite_module module is used to change request URI using regular expressions, return redirects, and conditionally select configurations.

Nginx的Rewrite的实现依赖于PCRE(Perl Compatible Regular Expressions:Perl兼容正则表达式)库, 因此在编译Nginx前, 需要确保系统中已经包含该依赖.

注意: 正则表达式的元字符{}会与nginx.conf中block定界符{ ... }有冲突, 如果需要在nginx.conf内写一个包含花括号的正则表达式,需要将表达式放在单引号/双引号之间.

  • Rewrite指令执行顺序:
    • 执行serverrewrite指令;
    • 执行location匹配;
    • 执行选定location中的rewrite指令;

如果其中某步URI被重写,则重新循环执行1-3步,直到找到真实存在的文件. 但循环次数不能超过10次, 否则Nginx返回500-Internal Server Error.


指令

if 指令

Syntax:     if (condition) { ... }
Default:    —
Context:    server, location
  • The specified condition is evaluated. If true, this module directives specified inside the braces are executed, and the request is assigned the configuration inside the if directive. Configurations inside the if directives are inherited from the previous configuration level.

if条件可以是如下内容:

condition 描述
一个变量名 只有该变量是空字符串或者以0开始的字符串, 才为false
使用=/!= 比较一个变量和字符串
使用~/~* 变量与正则表达式进行匹配的变量
使用-f/!-f 检查一个文件是否存在
使用-d/!-d 检查一个目录是否存在
使用-e/!-e 检查一个文件、目录、符号链接是否存在
使用-x/!-x 检查一个文件是否可执行
  • 示例
location ~* ^/w*adminw*/ {
    if ($request_method = GET) {
        return 405;
    }

    root   /var/www/regexp/;
    index  index.html;
}
  • 其他
if ($http_user_agent ~ MSIE) {
    rewrite ^(.*)$ /msie/$1 break;
}

if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
    set $id $1;
}

if ($request_method = POST) {
    return 405;
}

if ($slow) {
    limit_rate 10k;
}

if ($invalid_referer) {
    return 403;
}

break 指令

Syntax:     break;
Default: 
Context:    server, location, if
  • Stops processing the current set of ngx_http_rewrite_module directives(停止执行当前虚拟主机的后续rewrite指令).

return 指令

Syntax: return code [text];
        return code URL;
        return URL;
Default:    —
Context:    server, location, if
  • Stops processing and returns the specified code to a client. The non-standard code 444 closes a connection without sending a response header(停止处理并返回指定状态码给客户端,非标准状态码444表示关闭连接且不给客户端发送响应头).

该指令用于直接向客户端返回响应状态码,从0.8.42版本起,return支持响应URL重定向(对于301/302/303/307),或者文本响应(对于其他状态码).

注意: 对于302/307, 返回的URL中应包含"http://"/"https://".对于文本或者URL重定向可以包含变量.

if ($http_user_agent ~ Chrome) {
    return 302 http://www.baidu.com;
}

set 指令

Syntax:     set $variable value;
Default: 
Context:    server, location, if
  • Sets a value for the specified variable. The value can contain text, variables, and their combination.

rewrite 指令

Syntax:     rewrite regex replacement [flag];
Default: 
Context:    server, location, if
  • If the specified regular expression matches a request URI, URI is changed as specified in the replacement string(如果一个URI匹配指定的正则表达式, URI就按照replacement形式重写). The rewrite directives are executed sequentially in order of their appearance in the configuration file. It is possible to terminate further processing of the directives using flags(rewrite按配置文件中出现的顺序执行, 但flags标志可以停止继续处理). If a replacement string starts with “http://” or “https://”, the processing stops and the redirect is returned to a client.

注意: 接收到的URI不包含host地址(如example.com), 也不包含URL中的请求参数(如?arg1=value1&arg2=value).


实例-伪静态化

使用Rewrite功能将JavaWeb中的动态URL(xx.do?arg1=xx&arg2=xx)以静态URL替换(xx-xx-xx.html).

server {
        listen       800;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
        }

        location ~* (/javis/teacher/).*(.html)$ {
        rewrite /javis/teacher/(w+)-(w+)-(w+).html /javis/teacher/$1.do?name=$2&password=$3;
        }

        location ~* .(do|jsp|jspx)?$ {
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_pass http://10.45.156.170:80;
        }

    }

location ~* (/javis/teacher/).*(.html)$ { ... }会拦截所有/javis/teacher/ 目录下以.html结尾的静态URL,将其重写为.do结尾的动态URL(/javis/teacher/login-new_name-password.html -> /javis/teacher/login.do?name=new_name&password=password ), 然后location ~* .(do|jsp|jspx)?$ { ... }提供反向代理功能,将所有以.do结尾的URL转发到http://10.45.156.170:80地址, 由Java的后端Server提供真正的服务(反向代理相关知识可参考我的下一篇Nginx博客).


Gzip

Gzip(GNU-ZIP)是一种压缩技术,经压缩后的页面可能只有原大小的30%,大大减小了网络传输开销,浏览器加载网页的速度也会提升不少,但这项技术需要浏览器的配合(在服务端对网页进行压缩, 在浏览器对其解压并解析),由于现代浏览都支持很多种解压缩的方式(如Chrome: Accept-Encoding:gzip, deflate, sdch), 因此浏览器方面不需要我们担心.
Nginx的gzip模块是内置的, 由ngx_http_gzip_module 模块实现, 可在nginx.conf中配置使用:

The ngx_http_gzip_module module is a filter that compresses responses using the “gzip” method. This often helps to reduce the size of transmitted data by half or even more.


指令

Context: http, server, location, Gzip一共有9个指令可以设置:

指令 描述
gzip on | off; Enables or disables gzipping of responses.
gzip_buffers number size; Sets the number and size of buffers used to compress a response. By default, the buffer size is equal to one memory page. This is either 4K or 8K, depending on a platform.
gzip_comp_level level; Sets a gzip compression level of a response. Acceptable values are in the range from 1 to 9(推荐压缩级别为6).
gzip_disable regex ...; Disables gzipping of responses for requests with “User-Agent” header fields matching any of the specified regular expressions.
gzip_min_length length; Sets the minimum length of a response that will be gzipped. The length is determined only from the “Content-Length” response header field.
gzip_http_version 1.0 | 1.1; Sets the minimum HTTP version of a request required to compress a response(default 1.1).
gzip_types mime-type ...; Enables gzipping of responses for the specified MIME types in addition to “text/html”. The special value “*” matches any MIME type (0.8.29). Responses with the “text/html” type are always compressed.
gzip_vary on | off; Enables or disables inserting the “Vary: Accept-Encoding” response header field if the directives gzip, gzip_static, or gunzip are active.
gzip_proxied [flag]; Enables or disables gzipping of responses for proxied requests depending on the request and response. The fact that the request is proxied is determined by the presence of the “Via” request header field. The directive accepts multiple parameters -> details

实例-常用Gzip配置

http {
    ## ...

    gzip  on;
    gzip_min_length 1024;
    gzip_buffers 4 16k;
    gzip_comp_level 6;
    gzip_types text/plain application/x-javascript application/javascript application/xml text/css ;
    gzip_vary on;

    ## ...
}

为了使Nginx能够在全局范围内使用gzip,故将其放在http全局模块中.如果需要对各个虚拟主机区别对待,可在对应的server块中添加自己的gzip指令.

通过以上Nginx服务器访问一个网页(前提: Content-Length > 1024), 会看到静态资源文件的Response中新增了如下三个响应头:

Content-Encoding:gzip
Transfer-Encoding:chunked
Vary:Accept-Encoding

注意:
1. 由于图片/视频/音频之类文件压缩比率很小, 且压缩过程非常耗费CPU资源, 因此这类资源推荐不对其压缩.
2. 较小的文件压缩后很有可能会比原文件还大, 因此这类资源也推荐不对其压缩.


Expires

对于网站图片,尤其是新闻网站,图片一旦发布,改动的可能非常小.因此我们希望用户在第一访问之后,图片直接缓存在浏览器,而不再向服务端发送请求(不同于HTTP-304-Not Modified), 且能够自定义缓存配置.这就用到了Nginx的expires功能.

Syntax: expires [modified] time;
expires epoch | max | off;
Default:    
expires off;
Context:    http, server, location, if in location
  • Enables or disables adding or modifying the “Expires” and “Cache-Control” response header fields provided that the response code equals 200, 201, 204, 206, 301, 302, 303, 304, or 307. A parameter can be a positive or negative time.
    注意: 要确保服务器时间准确,如果服务器时间落后于实际时间,可导致缓存失效.

实例-图片缓存

  • 配置图片缓存时间为一天:
location ~* (jpg|png|jpeg|gif)$ {
    expires 1d;
}

通过以上Nginx服务器访问一个图片(如nginx.png),会看到图片的Response中添加了如下两个响应头:

Cache-Control:max-age=86400 
Expires:Fri, 20 May 2016 12:26:11 GMT

再次刷新该URL, 在浏览器(如Chrome)中会看到这张图片来自本地缓存:


原文地址:https://www.cnblogs.com/itrena/p/5926893.html