nginx学习记录

注:本文内容来源于网络

1. nginx 基本介绍

 nginx使用可扩展事件驱动架构,相对传统的过程驱动框架,需要的内存更少,并且在并发连接增多时,使内存使用更加可预测。传统WEB体系中,每个客户端连接都作为一个单独的进程或线程处理,随着网站的流行度增加,并发连接数量增加,Web服务器将减慢,对客户端的响应也会大大变慢,在线程/进程切换时运行新的上下文时,将会消耗额外的内存和时间,影响性能。nginx为了实现10倍以上的性能,优化服务器资源使用,同时也能扩展和支持网站的动态增长,nginx是最知名的模块化、事件驱动、异步、单线程WEB服务器和WEB代理之一。

 作为高性能Web和反向代理服务器,有如下特性:

  • 可以作为WEB服务器:相比 Apache,Nginx 使用更少的资源,支持更多的并发连接,体现更高的效率,能够支持高达 50,000 个并发连接数的响应;
  • 可以作为负载均衡(多个服务器对外提供单一的网络服务)服务器:Nginx 既可以在内部直接支持 Rails 和 PHP,也可以支持作为 HTTP代理服务器 对外进行服务,Nginx 用 C 编写, 不论是系统资源开销还是 CPU 使用效率都比 Perlbal 要好的多;
  • 可以作为邮件代理服务器:Nginx 同时也是一个非常优秀的邮件代理服务器(最早开发的目的之一);

 Nginx 安装简单,配置文件简洁(还能够支持perl语法),Bugs少,启动也容易,并且几乎可以做到7*24不间断运行,即使运行数个月也无须重启,而且可以在不间断服务的情况下进行软件版本的升级。

 处理并发连接方面,传统的基于进程或线程的模型涉及使用单独进程或线程处理每个连接,并阻止网络或输入/输出操作。 根据应用,在内存和CPU消耗方面可能效率会比较低。产生一个单独的进程或线程需要准备一个新的运行时环境,包括分配堆和堆栈内存,以及创建新的执行上下文,额外的CPU时间也用于创建这些项目,这可能会导致由于线程需要在过多的上下文切换上的转机而导致性能下降,所有这些并发症都表现在较老的Web服务器架构(如Apache)中。从一开始nginx就是一个专门工具,可以实现更高性能、更密集和经济地使用服务器资源,同时实现网站的动态发展,还采用了不同的模式。 它实际上受到各种操作系统中高级事件机制的不断发展的启发,演变成了一个模块化、事件驱动、异步、单线程的非阻塞架构的nginx代码基础。nginx大量使用复用和事件通知,并有专门用于分离进程的特定任务。 连接在有限数量的单线程进程称为工人(worker)的高效运行循环中处理。在每个工作(worker)中,nginx可以处理每秒数千个并发连接和请求。

【注意】

 一般情况都是在Linux中部署nginx,nginx的Windows版本不是一个功能完整的端口,nginx和Windows内核架构有一些不能很好地交互的局限性,在Windows版本的nginx已知问题包括并发连接数量低得多,性能下降,无缓存,无带宽监管,可能将来的版本会不断完善。

2. 安装

 nginx有多个版本,最简单的就是win版本直接解压运行即可,最复杂的是从源码构建,如果需要一些特殊的功能,在包和端口不可用的情况下,也可以从源代码编译来安装,源码构建的安装方式虽然复杂,但很灵活。通常直接如下安装即可:
1.更新系统和依赖包安装

 我本地是CentOS 7版本,首先进行系统升级:

yum update

关于升级命令,作一个区分:

# 升级所有包,改变软件设置和系统设置,系统版本内核都升级
yum -y update

# 升级所有包,不改变软件设置和系统设置,系统版本升级,内核不改变
yum -y upgrade

然后安装依赖包:

yum -y install gcc gcc-c++ autoconf automake libtoll make cmake
yum -y install zlib zlib-devel openssl openssl-devel pcre-devel

2.下载nginx包

 可以到官网先下载在上传,或者直接通过wget直接获取,这里是已最新的stable版本1.14.0版本为例进行下载编译:

# 目录可以随意指定
cd /usr/local/src/
# 下载nginx
wget -c http://nginx.org/download/nginx-1.14.0.tar.gz
# 解压
tar zxvf nginx-1.14.0.tar.gz

3.创建nginx用户及用户组

 切换至root用户创建用户和用户组:

# 创建一个名字为`nginx`的用户组
groupadd nginx

# 创建一个用户,名字为nginx(第一个表示组名,第二个表示创建的用户名),-M参数用户不为创建的新用户创建新的用户目录,将用户nginx拉到用户组nginx中
useradd -g nginx -M nginx

修改bash登录信息:

vim /etc/passwd

# 将nginx的信息修改为下面的,新添加的用户一般在该文件的最后一行
nginx:x:1003:1003::/home/nginx:/sbin/nologin

4.编译配置安装

 进入刚刚解压后的源码目录:

[root@10 nginx-1.14.0]# pwd
/usr/local/src/nginx-1.14.0

# 下面命令中的反斜杠表示继续换行,linux不会直接执行未完成的命令
[root@10 nginx-1.14.0]# ./configure --prefix=/usr/local/nginx \
> --pid-path=/usr/local/nginx/run/nginx.pid \
> --with-http_ssl_module \
> --user=nginx \
>  --group=nginx \
> --with-pcre \
> --without-mail_pop3_module \
> --without-mail_imap_module \
> --without-mail_smtp_module

其中--prefix=/usr/local/nginx表示将nignx内容安装到指定目录下,这里指定的是/usr/local/nginx目录,下面进行编译安装:

[root@10 nginx-1.14.0]# make
[root@10 nginx-1.14.0]# make install

这样以后,nginx就被安装在了/usr/local/nginx这个目录中,验证一下编译安装的nginx信息:

[root@10 nginx-1.14.0]# /usr/local/nginx/sbin/nginx -v

# 得到如下信息
nginx version: nginx/1.14.0

3. 配置nginx

 nginx默认是监听的是浏览器的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;
        }
    }

在修改后nginx也提供了验证配置文件是否合法的命令:

# 进入nginx的sbin目录,验证配置文件
./nginx -t

# 验证成功的结果
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

# 验证失败的结果,改了一个不存在的端口号
nginx: [emerg] invalid port in "80123456" of the "listen" directive in /usr/local/nginx/conf/nginx.conf:36
nginx: configuration file /usr/local/nginx/conf/nginx.conf test failed

验证配置文件成功后,启动nginx:

# 前提:进入nginx的sbin文件目录下启动
./nginx

# 查看nginx是否启动成功,直接查看nginx相关的端口
ps -ef | grep nginx
# 结果如下,说明启动成功了
root      80298      1  0 16:30 ?        00:00:00 nginx: master process ./nginx
nginx     80299  80298  0 16:30 ?        00:00:00 nginx: worker process
root      80322  73145  0 16:30 pts/1    00:00:00 grep --color=auto nginx

nginx的常用命令,前提都是先进入nginx的sbin目录下:

# 1. 启动
./nginx
# 2. 有序停止nginx,直接用上述中的主进程号(即master process),上面是80298
kill -QUIT 80298
# 3. 快速停止nginx
kill -TERM 80298
# 4. 强制停止Nginx
pkill -9 nginx
# 5. 重启nginx,会重新载入配置文件
./nginx -s reload

除了通过上述查看进程的运行情况外,最直观的方式是直接用curl或者打开浏览器,输入本机IP查看,由于默认监听80端口,所以会有如下的结果:

[root@10 sbin]# curl -X GET localhost

# 结果如下
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
   
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

上述都是针对Linux环境下的运行,对于windows版本的Nginx基本操作更加简单,如下:

  1. nginx 启动会一闪而过: start nginx 或者直接双击nginx.exe;
  2. 验证配置文件是否正确:nginx -t
  3. 改动配置文件后需要重新加载配置文件:nginx -s reload
  4. 查看nginx是否启动成功:tasklist /fi "imagename eq nginx.exe"
  5. 关闭nginx服务同样一闪而过: nginx -s stop(快速停止) 或 nginx -s quit(完全有序的停止)。

4. Nginx基本点

 nginx有一个主进程和多个worker进行工作,主进程的目的是读取和评估配置,并维护woker进程,worker进程对请求进行实际处理,nginx采用基于事件的模型和依赖于操作系统的机制来有效地在worker进程之间分配请求,具体worker进程的数量可在配置文件中定义,并且可以针对给定的配置进行修改,或者自动调整到可用CPU内核的数量。nginx的配置文件为根目录下的conf/nginx.conf

 在nginx启动后,可以通过-s参数调用可执行文件来控制它,语法如下:

./nginx -s signal

其中signal可以为:

  • stop:快速关闭服务;
  • quit:正常关闭服务(会等待工作进程服务完成当前请求再停止nginx进程);
  • reload:重新加载配置文件;
  • reopen:重新打开日志文件;

其中reload基本在配置改动后会使用该命令进行会让nginx重新加载配置:当主进程收到要重新加载配置的信号,它将检查新配置文件的语法有效性,并尝试应用其中提供的配置。如果新配置是成功的,主进程将启动新的工作进程,并向旧的工作进程发送消息,请求它们关闭,旧的worker进程接收关闭命令,停止接受新连接;否则,主进程回滚更改,并继续使用旧配置,并继续维护当前请求,直到所有这些请求得到维护。

4.1 利用nginx提供静态内容服务

 如果一个网站需要提供静态文件,这些静态文件由本地不同的目录提供,比如/data/html/data/images,那就需要在配置文件中进行指定,使用2个位置块在http块内设置服务器块,在/data/html下放一个html文件index.html,在data/images中放一个图片文件,下面直接干这样一个事儿:

# 创建 2 个目录
[root@localhost ~]# mkdir -p /data/html
[root@localhost ~]# mkdir -p /data/images

# 进入images目录下载一个百度一下的图片
cd /data/images
wget https://www.baidu.com/img/bd_logo1.png

# 在html目录中创建一个html文件,内部写一个 <h2> New Static WebSite Demo </h2>
vim ../html/index.html

# 进入nginx的conf目录,复制一份nginx的配置文件然后更改
cp -p nginx.conf nginx.conf.back

vim nginx.conf

然后将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 {
  server {
    location / {
      root /data/html;
    }
    location /images/ {
      root /data;
    }
  }
}

最后启动nginx验证:

./nginx

curl -X GET localhost

# 结果如下:
<h2>New Static WebSite Demo.</h2>

# 查看图片,会出现一片二进制流乱码,可以用浏览器打开
curl -X GET localhost/images/bd_logo1.png

【注意】上述访问index.html直接使用的是curl -X GET localhost是因为html的文件名为index.html,nginx可以自动找到,但是如果是其他的名字需要显式的写出来,否则是找不到的,比如后面查看图片时就必须指出文件名,否则是找不到路径的。

上述配置中,http块中包含了两个服务块:

http {
   
  server {
   
    location / {
   
      root /data/html;
    }
    location /images/ {
   
      root /data;
    }
  }
}

对于上述http块中的server块中的location基本语法为alias file-path\directory-path(即别名 文件路径),location指令指定了用于指示位置的路径,它可能看起来类似于root这样的形式,但文档根目录不会更改,只是用于请求的文件系统路径(说的简单点就是文件本身路径不会变,只是请求的路径变了),比如:

location  /i/ {
   
 alias   /spool/w3/images/;
}

那么当请求/i/top.gif时,实际请求的是/spool/w3/images/top.gif这个文件,注意,这里是可以在替换的路径中使用变量的。alias指令不能在指定的正则表达式的location内部使用,如果想使用就必须使用rewriteroot的组合。

配置文件一般可以包括服务器监听的端口和服务器名称区分不同的server块,当nginx决定哪个服务器处理请求后,它会根据服务器块内部定义的location指定的参数测试请求头中指定的URI,该location块指定与请求中的URI相比较的/前缀,对于匹配请求,URI将被添加到root指定的路径(即/data/html),以形成本地文件系统上所请求文件的路径,如果有几个匹配的location块,nginx将选择具有最长前缀来匹配location块,上面的location块提供最短的前缀长度为1,因此只有当所有其他location块不能提供匹配时,才会使用该块。

注意】关于aliasroot

对于上述location中配置的aliasroot做一个简单的说明,其实看命名就可以看出来,alias是别名,用来替换URI的,比如上述的配置

location  /i/ {
   
 alias   /spool/w3/images/;
}

那么此时请求/i/top.gif时,直接用/spool/w3/images/代替/i/,所以实际请求的是/spool/w3/images/top.gif这个文件;

root是指定根目录,location出现的URI是追加其后面的,如上述配置改为:

location  /i/ {
   
 root   /spool/w3/images/;
}

再去请求/i/top.gif时,那么实际请求的文件是/spool/w3/images/i/top.gif,简单点说就是alias是替换,而root是追加。

最后还有一个坑,alias指令指定的路径后面一定要加/,不然基本就废了,请求该路径时Nginx给的状态码是403,而不是404,很难排查(会疯掉……),记录一下(我踩了多次,找不到原因,偶然翻到文档才解决◑﹏◐)

4.2 利用Nginx设置简单的代理服务器

 将nginx设置为代理服务器是一种较为常见的用途,它可以作为一个接收请求的服务器,将其传递给代理服务器,从代理服务器中检索响应,并将其发送给客户端,和上面的一样在/data目录下创建一个up1/index.html文件,里面随便放点东西,比如<h1>Hello Proxy</h1>,然后在nginx的配置文件中已有的http块中加上如下的server块:

server {
   
    # nginx默认使用的80端口,上面没有配置访问时无需指定端口号即可访问,这里指定8080端口
    listen 8080;
    root /data/up1;

    location / {
   
    }
}

在访问时直接curl -X GET localhost:8080这里必须指定端口号,否则会被映射到原来上一个静态内容服务的Demo,但是现在需要将nginx搞成一个代理服务器,直接修改静态内容服务Demo中配置的第一个server块,将location内部的root /data/html修改为proxy_pass http://localhost:8080;,此时重新载入nginx配置文件后,再次访问localhost将不再是New Static WebSite Demo,而是Test proxy!,因为在80端口原来的/被代理到了8080端口,而8080端口的/是映射到Test proxy的html文件的。然后将之前映射的图片的location块内容修改为:

location ~ \.(gif|jpg|png)$ {
   
    root /data/images;
}

上述的location配置的时候使用了正则表达式,此时nginx将过滤以.gif.jpg以及.png结尾的URI(其他的结尾字符的路径将不会过滤出来,直接会404),其中~表示正则表达式的开始标识符(它没有实际意义),而$则表示正则表达式结尾的标识符,也没有实际意义。

注意proxy_pass语法

主要是通过该参数指定的路径一定要完整(包含所有URI完整字符串,包括\字符),比如上述的配置,如果指定为proxy_pass http://localhost:8080,那么是无法访问到Test proxy页面,直接404,这玩意儿也很细致。

4.3 利用Nginx设置Fast CGI代理

 nginx可用于将请求路由到使用各种框架和PHP等编程语言构建的应用程序的FastCGI服务器,这里最基本的配置是直接用fastcgi_param代替上述基本代理配置中的proxy_pass参数即可,在PHP中使用SCRIPT_FILENAME参数用于确定脚本名称,QUERY_STRING用于传递请求参数。

5. Nginx的进程和运行时控制

 NGINX有一个主进程和一个或多个worker进程。 如果启用缓存,缓存加载程序和缓存管理器进程也将在启动时运行。主程序的主要目的是读取和评估配置文件以及维护wroker进程。worker进程执行请求的实际处理,NGINX依赖于操作系统的机制来有效地在worker进程之间分配请求,工作进程的数量可在nginx.conf配置文件中定义,可以针对给定的配置进行修复,或者自动调整为可用CPU内核数。

 要重新加载配置文件,可以停止或重新启动NGINX,或者发送信号到主进程。 可以使用-s参数运行nginx命令(调用NGINX可执行文件)来发送信号,这点在第4章节中已有涉及,语法:
./nginx -s signal
其中signal可以为:

  • stop:快速关闭服务;
  • quit:正常关闭服务(会等待工作进程服务完成当前请求再停止nginx进程);
  • reload:重新加载配置文件;
  • reopen:重新打开日志文件;

当然杀死程序也可使用,默认情况下,主进程的进程ID写入到nginx/logs/nginx.pid或者/var/run/nginx.pid文件中(但是我并没有发现),该文件的名称可以在配置文件中使用pid指令进行更改(我更改后直接报错)。nginx可以使用信号控制,主程序支持以下信号:

  • TERMINT - 快速关闭
  • QUIT - 正常关闭
  • HUP - 改变配置,跟上改变的时区(仅适用于FreeBSD和Linux),使用新配置启动新的工作进程,正常关闭旧的工作进程
  • USR1 - 重新打开日志文件
  • USR2 - 升级可执行文件
  • WINCH - 正常关闭工作进程

个别worker进程可以使用信号控制(尽管这不是必需的),支持的信号有:

  • TERMINT - 快速关闭
  • QUIT - 正常关闭
  • USR1 - 重新打开日志文件
  • WINCH - 调试异常终止(需要启用debug_points)

【注】关于nginx.pid文件的位置以及配置

1.上述网络上所说的两个位置上我并没有找到nginx.pid文件,最后发现我本地的文件位置为/usr/local/nginx/run/nginx.pid,如果是在找不到,可以直接locate nginx.pid搜一下,如果还找到,先更新一下库update db,然后再locate nginx.pid搜索。

2.关于在main环境中使用pid指令配置nginx.pid文件的位置和名字时,使用./nginx -s reload指令重载配置文件时会出现nginx: [error] open() "/data/nginx.pid" failed (2: No such file or directory)错误,是因为nginx被停止时,原先的nginx.pid被删除,而reopenreload命令需要通过nginx.pid文件获取主进程号,如果不存在,就报错了。所以如果需要自定义配置nginx.pid文件信息,正确的做法是先停止nginx服务,然后再改配置文件,最后启动,下面是简单配置示例:

# 先停止nginx服务
./nginx -s stop

# 在nginx.conf中添加配置
pid /data/nginx.pid;

# 启动nginx
./nginx

通过ps -ef | grep nginx指令查看nginx的主进程的id,然后通过查看配置的nginx.pid文件,可以发现两者是一致的。

更改配置文件

 为了使nginx重新读取配置文件,应将HUP信号发送到主进程,因为主进程是负责维护配置文件的,它会首先检查语法的有效性,然后尝试应用新的配置,即打开日志文件和新的监听套接字,如果失败则回滚并继续使用旧配置;如果操作失败,它将启动新的worker进程,并向旧的worker进程发送消息,请求它们正常关闭。旧的worker进程模切监听套接字,并继续监听旧客户端服务,在所有的客户端被服务后,旧的worker进程将会被关闭。

循环日志文件

 要循环日志文件,首先需要重命名,之后USER1信号发送到主进程,然后主进程将重新打开所有当前打开的日志文件,并将其分配给正在运行的工作进程的非特权用户作为所有者。成功重新打开后,主程序关闭所有打开的文件,并将消息发送到工作进程,要求他们重新打开文件。工作进程也会打开新文件并立即关闭旧文件。因此,旧文件几乎立即可用于后处理,如压缩。

6. Nginx的配置文件

 上面已有涉及部分nginx的配置文件,位置为nginx/conf/nginx.conf,进入nginx的安装目录(而非源码目录)/usr/local/nginx,查看nginx的配置文件:

# 查看nginx的配置文件
vim conf/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;
    #    }
    #}

}

网络上有人对nginx的配置文件做了区域划分的很清晰,如下:

nginx配置文件

nginx的配置文件是由指令及其参数组成,简单(单行)指令各自以分号结尾;其他指令作为“容器”,将相关指令组合在一起,将其包围在花括号{xxx}中。官方一点就是配置文件由指令控制模块组成,指令控制模块分为简单指令和块指令:

  • 简单指令:由空格分隔的名称和参数组成,并以分号;结尾,比如:error_log logs/error.log info;
  • 块指令:具有与简单指令相同的结构,但不是以分号结尾,而是以大括号{ }包围的一组附加指令结束;
  • 上下文:如果块指令在大
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值