Nginx

1.  安装Nginx


版本 nginx-1.14.0

# 安装C++编译器
yum -y install gcc-c++

# 下载并安装OpenSSL
openssl-fips-2.0.16.tar.gz
tar -zxf openssl-fips-2.0.16.tar.gz
cd openssl-fips-2.0.16
./config && make && make install

# 下载并安装pcre
pcre-8.42.tar.g
tar -zxf pcre-8.42.tar.g
cd pcre-8.42
./configure && make && make install

# 下载并安装zlib
zlib-1.2.11.tar.gz
tar -zxf zlib-1.2.11.tar.gz
cd zlib-1.2.11
./configure && make && make install

# 下载并安装Nginx
nginx-1.14.0.tar.gz
tar -zxf nginx-1.14.0.tar.gz
cd nginx-1.14.0
./configure && make && make install

 

 

2.  快速开始


nginx有一个master进程和多个worker进程。

master进程主要负责读取和评估配置,并维护worker进程。

worker进程负责实际的请求处理。worker进程的数量在配置文件中定义,可以指定一个固定值,也可以根据可用CPU内核的数量自动调整。

nginx及其模块的工作方式由配置文件决定。默认情况下,配置文件的名字叫nginx.conf,并且所在位置是/usr/local/nginx/conf, /etc/nginx, 或 /usr/local/etc/nginx

2.1.  启动/停止/重新加载配置

为了启动nginx,运行可执行文件nginx。一旦nginx启动以后,就可以通过 -s 参数来控制它。

用下面的语法格式:

例如,为了停止nginx进程,并且等待worker进程完成当前请求的处理,可以执行下面的命令:

nginx -s quit

(画外音:执行这个命令的用户必须与启动nginx的用户相同)

为了重新加载配置,执行下面的命令:

nginx -s reload

一旦master进程收到重新加载配置的信号以后,它检查配置文件的语法,并尝试应用配置文件中提供的配置。如果成功的话,master进程会启动一个新的worker进程并且发送消息给旧的worker进程请求它们立即shut down。否则,master进程回滚本次更改,继续用旧的配置工作。当旧的worker进程收到一个shut down的命令时,它停止接受新的连接,并继续服务当前请求,直到它收到的所有请求都处理完成。此后,旧的worker进程就退出了。

在Unix工具的帮助下(比如 kill)也可以向nginx进程发送信号。在这种情况下,信号直接被发送到给定的进程ID所代表的进程。默认情况下,nginx master进程的进程ID被写入nginx.pid文件中,该文件所在目录通常是/usr/local/nginx/logs 或 /var/run。例如,如果master进程ID是1628,那么为了发送QUIT信号给nginx,执行下面的命令:

kill -s QUIT 1628

为了获取所有正在运行的nginx进程列表,可以使用ps命令,例如:

ps -ax | grep nginx

2.2.  配置文件的结构

nginx由配置文件中的指令所控制的模块组成。指令分为简单指令和块指令。简单指令由名称和参数组成,它们之间用空格隔开,以分号(;)结束。块指令的结构与简单指令相同,但它不是以分号结尾,而是一组由大括号({ 和 })包围的附加指令。如果一个block指令可以在大括号中包含其他指令,那么它被成为上下文(例如:events, http, server 和 location)。events 和 http 指令在main上下文下,server指令在http中,location在server中。

默认的配置文件nginx.conf如下:

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    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        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    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;
    #    }
    #}

}

2.3.  服务静态内容

Web服务器其中一个重要的任务是提供文件(比如,图片和静态HTML页面)。

首先,让我们来创建/data/html目录,并在其中放一个index.html文件。同时再建一个/data/images目录用于放置图片。

接下来,打开配置文件,在默认的配置文件中server块下已经包含了一些例子,通常它们是被注释了的。

以/images/开头的请求,服务器将从/data/images目录下查找并返回文件。

例如:http://192.168.101.5/images/a.png请求,服务器将返回/data/images/a.png文件,如果这个文件不存在,则返回404。

不是以/images/开头的的请求将映射到/data/html目录。

http://192.168.101.5/

http://192.168.101.5/index.html

http://192.168.101.5/example.html

 

root指令:

 

2.4.  简单的代理服务器

首先,通过在配置文件中提那家一个或多个server块来定义代理服务器

上面的例子中定义了一个简单服务器,它监听8080端口,并且把所有请求映射到本地/data/up1目录。注意,这里root指令放在了server上下文。当一个请求不包含location它在自己的root指令中,则会使用这个server上下文中的root指令。(画外音:简单的来说,location指令中的root相当于局部变量,而server指令下的root相当于全局变量,当请求不匹配局部变量时,则使用全局变量。类比Java就是一个是自定义的方法,一个是默认实现的方法)

接下来,修改前面的配置。我们在第一个location块中放置proxy_pass指令

http://nginx.org/en/docs/http/ngx_http_proxy_module.html

参数是一个匹配所有以.gif, .jpg, 或者.png结尾的URIs的正则表达式。与之相应的,请求被映射到/ata/images目录。

location指令的参数是正则表达式

在正则表达式前面应该加上~

当nginx选择一个location块来服务一个请求时,它首先检查location指令所指定的前缀,记住最长的前缀的那个location,然后检查正则表达式。如果匹配正则表达式,则挑选这个location,否则挑选他所记住的更早的那个。

(画外音:这段话解释了nginx是如何挑选location的,我们可以这样理解,通过location指令所指定的前缀,从最长的前缀开始匹配,如果满足,则挑选这个,否则,检查第二长的,依次尝试匹配,直到找到一个匹配的location)

 

3.  常用指令


http://nginx.org/en/docs/http/ngx_http_core_module.html

3.1.  location

一个location定义可以是一个前缀字符串,也可以是一个正则表达式。正则表达式使用的时候要在前面用“~*”修饰符(用于不区分大小写匹配),或者“~”修饰符(用于区分大小写)。为了找到请求匹配的location,nginx首先检查location定义,用前缀字符串(这些location成为前缀location)。其中,最长匹配前缀的location会被选中并记住。然后,检查正则表达式,按照它们在配置文件中出现的顺序。对正则表达式的搜索在第一次匹配时终止,并使用相应的配置。如果没有找到与正则表达式的匹配,则使用前面记住的前缀位置的配置。

画外音:首先检查前缀字符串,然后检查正则表达式

1、用前缀字符串(前缀location)匹配URL,并且选中并记住最长匹配前缀的location(注意:是在匹配的里面记住最长的那个)

2、按照正则表达式在配置文件中出现的顺序依次去匹配,当匹配到第一个以后立即停止,并使用与之相应的那个location。如果没有一个正则表达式匹配,则使用之前记住的那个前缀location。

以上,我们可以得出一个结论:优先使用正则表达式,如果没有匹配的正则表达式发现,则使用匹配的最长前缀字符串location

)

例如:

 

5.  ngx_http_proxy_module模块


ngx_http_proxy_module模块允许将请求传递到另一个服务器。例如:

5.1.  proxy_pass指令

设置代理服务器的协议和地址,以及应该映射哪一个可选URI。作为协议,可以指定“http”或“https”。地址可以指定为一个域名或IP地址,以及一个可选端口:

请求URI传递给服务器:

如果proxy_pass指令带一个特定的URI,那么请求被传给给这个服务器,正常的请求URI部分被指令中指定的URI替换,例如:

如果proxy_pass指令不带URI,那么请求URI在传递给服务器的时候和原始请求是一样的,例如:

在有些情况下,请求URI部分不能决定该如何替换:

1、当location时用一个正则表达式指定的时候,或者用内部的location命中指定的时候。

那么在这种情况下,proxy_pass在指定的时候不应该带URI

2、当用rewrite指令更改location时

在这种情况下,在指令中指定的URI将被忽略

http://nginx.org/en/docs/http/ngx_http_rewrite_module.html

3、当在proxy_pass中使用变量时

在这种情况下,如果指令中指定了URI,那么将被传递给服务器,并替换原始请求URI

 

6.  ngx_http_limit_req_module模块(限流)


ngx_http_limit_req_module模块用于限制指定的key的请求处理速率,特别是来自单个IP地址的请求处理速率。这种限制使用的是“漏桶算法”。

例如:

6.1.  limit_req指令

设置共享内存区域和请求的最大突发大小。如果请求速率超过了为区域配置的速率,那么它们的处理就会延迟,这样请求就会以指定的速率进行处理。过多的请求被延迟,直到它们的数量超过最大突发大小,在这种情况下,以一个错误来终止请求。默认情况下,突发数量等于0。

平均每秒不允许超过1个请求,突发不超过5个请求。

如果不希望在请求受到限制时延迟过多的请求,则应使用参数nodelay:

可以有多个limit_req指令。例如,以下配置将限制来自单个IP地址的请求的处理速率,同时限制虚拟服务器的请求处理速率:

6.2.  limit_req_zone指令

设置共享内存区域参数。key可以包含文本、变量、以及它们的组合。

这个例子中,“one”这个区域维护的内存是10M,并且这个区域的平均请求处理速率不能超过每秒1个请求。

 

7.  控制Nginx


8.  用Nginx作为负载均衡器


8.1.  负载均衡方法

nginx支持以下负载平衡机制(或方法):

8.2.  默认的负载均衡配置

在上面的例子汇总,同一个应用运行了3个实例。默认的负载均衡策略是循环。

8.3.  最少连接的负载均衡

另一个负载平衡原则是最少连接的。在某些请求需要更长的时间才能完成的情况下,最少连接允许更公平地控制应用程序实例上的负载。

使用连接最少的负载平衡,nginx将尽量不让繁忙的应用服务器超载过多的请求,而是将新请求分发到不那么繁忙的服务器。

例如:

8.4.  Session持久化

使用循环或最少连接负载平衡,每个后续客户机的请求都可能被分发到不同的服务器。不能保证同一个客户端总是指向同一个服务器。

使用IP-hash,客户端的IP地址用作哈希key,以确定应该为客户端请求选择服务器组中的哪个服务器。此方法确保来自同一客户端的请求总是指向同一服务器,除非该服务器不可用。

例如:

8.5.  带权重的负载均衡

还可以通过使用服务器权值进一步影响nginx的负载平衡算法。

在上面的示例中,没有配置服务器权重,这意味着所有指定的服务器都被视为具有同等资格的特定负载平衡方法。

 

posted @ 2018-08-24 19:12  废物大师兄  阅读(1572)  评论(3编辑  收藏  举报