一、Nginx 简介

Nginx是一个高性能的 HTTP 和反向代理 web 服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点开发的,第一个公开版本0.1.0发布于2004年10月4日。

其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。

其特点是占有内存少,并发能力强,事实上 nginx 的并发能力确实在同类型的网页服务器中表现较好,目前已经是最主要的 web 服务器软件。

nginx 有一个主进程和几个 worker 进程。主进程的作用是读取并执行配置,并维护 worker 进程。worker 进程是实际处理请求的进程。

nginx 采用事件驱动模型和基于系统的一些机制来高效分发请求给多个 worker 进程。worker 进程的数量可以在配置文件中配置。

二、Nginx 的特点

  • 模块化设计,较好的扩展性。
  • 高可靠性。
  • 支持热部署:不停机更新配置文件,升级版本,更换日志文件。
  • 低内存消耗:10000 个 keep-alive 连接模式下的非活动连接,仅需要 2.5M 内存。

三、Nginx 能用来做什么?

  • 静态资源的web服务器。
  • FastCGI(lnmp),uWSGI(python)等协议 :web 服务器,fastcgi 配合 php-fpm 实现 php web 服务。
  • http 协议反向代理服务器。
  • pop3/imap4协议反向代理服务器。

四、Nginx与web服务相关的功能

  • 虚拟主机(server)
  • 支持 keep-alive 和管道连接
  • 访问日志(支持基于日志缓冲提高其性能)
  • url rewirte 路径别名
  • 基于 IP 及用户的访问控制
  • 支持速率限制及并发数限制
  • 重新配置和在线升级而无须中断客户的工作进程
  • SSL 支持
  • gzip 支持
  • cache 支持

五、Nginx 如何安装?

  • 包安装:apt-get,yum,用于安装系统默认支持的版本。
  • 编译安装:用于安装指定的版本。

六、Nginx 配置文件详解

nginx 配置文件是分层配置的,从外到内,main > http > server > location

nginx 配置文件

6.1 段

6.1.1 main 段

nginx 在运行时与具体业务功能无关的一些参数,比如工作进程数,运行的身份等。

woker_processes 2

在配置文件的顶级main部分,worker角色的工作进程的个数,master进程是接收并分配请求给worker处理。

这个数值简单一点可以设置为cpu的核数, 也是 auto 值,如果开启了 ssl 和 gzip 更应该设置成与逻辑 CPU 数量一样甚至为 2倍,可以减少I/O操作, 如果nginx服务器还有其它服务,可以考虑适当减少。

worker_cpu_affinity

在高并发情况下,通过设置cpu粘性来降低由于多CPU核切换造成的寄存器等现场重建带来的性能损耗。如

worker_cpu_affinity 0001 0010 0100 1000; (四核)。
worker_rlimit_nofile 10240

可以限制为操作系统最大的限制 65535。

6.1.2 events 段

worker_connections 2048

每一个 worker 进程能并发处理(发起)的最大连接数(包含与客户端或后端被代理服务器间等所有连接数)。

nginx作为反向代理服务器,计算公式最大连接数 = worker_processes * worker_connections / 4,不能超过worker_rlimit_nofile。当 nginx 作为 http 服务器时,计算公式里面是除以 2。

use epoll

在Linux操作系统下,nginx默认使用epoll事件模型,得益于此,nginx在Linux操作系统下效率相当高。同时Nginx在OpenBSD或FreeBSD操作系统上采用类似于epoll的高效事件模型kqueue。

6.1.3 http 段

与提供http服务相关的一些配置参数。例如:是否使用keepalive啊,是否使用gzip进行压缩等。

sendfile on
开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,减少用户空间到内核空间的上下文切换。对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。

keepalive_timeout 65 : 长连接超时时间,单位是秒,这个参数很敏感,涉及浏览器的种类、后端服务器的超时设置、操作系统的设置,可以另外起一片文章了。长连接请求大量小文件的时候,可以减少重建连接的开销,但假如有大文件上传,65s内没上传完成会导致失败。如果设置时间过长,用户又多,长时间保持连接会占用大量资源。

send_timeout : 用于指定响应客户端的超时时间。这个超时仅限于两个连接活动之间的时间,如果超过这个时间,客户端没有任何活动,Nginx将会关闭连接。

client_max_body_size 10m
允许客户端请求的最大单文件字节数。如果有上传较大文件,请设置它的限制值

client_body_buffer_size 128k
缓冲区代理缓冲用户端请求的最大字节数
模块http_proxy:
这个模块实现的是nginx作为反向代理服务器的功能,包括缓存功能(另见文章)

proxy_connect_timeout 60
nginx跟后端服务器连接超时时间(代理连接超时)
proxy_read_timeout 60
连接成功后,与后端服务器两个成功的响应操作之间超时时间(代理接收超时)

proxy_buffer_size 4k
设置代理服务器(nginx)从后端realserver读取并保存用户头信息的缓冲区大小,默认与proxy_buffers大小相同,其实可以将这个指令值设的小一点

proxy_buffers 4 32k
proxy_buffers缓冲区,nginx针对单个连接缓存来自后端realserver的响应,网页平均在32k以下的话,这样设置

proxy_busy_buffers_size 64k
高负荷下缓冲大小(proxy_buffers*2)

proxy_max_temp_file_size
当 proxy_buffers 放不下后端服务器的响应内容时,会将一部分保存到硬盘的临时文件中,这个值用来设置最大临时文件大小,默认1024M,它与 proxy_cache 没有关系。大于这个值,将从upstream服务器传回。设置为0禁用。

proxy_temp_file_write_size 64k
当缓存被代理的服务器响应到临时文件时,这个选项限制每次写临时文件的大小。proxy_temp_path(可以在编译的时候)指定写到哪那个目录。

proxy_pass,proxy_redirect见 location 部分。

模块http_gzip:

gzip on : 开启gzip压缩输出,减少网络传输。
gzip_min_length 1k : 设置允许压缩的页面最小字节数,页面字节数从header头得content-length中进行获取。默认值是20。建议设置成大于1k的字节数,小于1k可能会越压越大。
gzip_buffers 4 16k : 设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流。4 16k代表以16k为单位,安装原始数据大小以16k为单位的4倍申请内存。
gzip_http_version 1.0 : 用于识别 http 协议的版本,早期的浏览器不支持 Gzip 压缩,用户就会看到乱码,所以为了支持前期版本加上了这个选项,如果你用了 Nginx 的反向代理并期望也启用 Gzip 压缩的话,由于末端通信是 http/1.0,故请设置为 1.0。
gzip_comp_level 6 : gzip压缩比,1压缩比最小处理速度最快,9压缩比最大但处理速度最慢(传输快但比较消耗cpu)
gzip_types :匹配mime类型进行压缩,无论是否指定,”text/html”类型总是会被压缩的。
gzip_proxied any : Nginx作为反向代理的时候启用,决定开启或者关闭后端服务器返回的结果是否压缩,匹配的前提是后端服务器必须要返回包含”Via”的 header头。
gzip_vary on : 和http头有关系,会在响应头加个 Vary: Accept-Encoding ,可以让前端的缓存服务器缓存经过gzip压缩的页面,例如,用Squid缓存经过Nginx压缩的数据。。

6.1.4 server 段

典型的 server 段配置文件

server {
    # 监听 HTTP 协议默认的 [80] 端口。
    listen 80;
    # 绑定主机名 [example.com]。
    server_name example.com;
    # 服务器站点根目录 [/example.com/public]。
    root /example.com/public;

    # 添加几条有关安全的响应头;与 Google+ 的配置类似,详情参见文末。
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    # 站点默认页面;可指定多个,将顺序查找。
    # 例如,访问 http://example.com/ Nginx 将首先尝试「站点根目录/index.html」是否存在,不存在则继续尝试「站点根目录/index.htm」,以此类推...
    index index.html index.htm index.php;

    # 指定字符集为 UTF-8
    charset utf-8;

    # Laravel 默认重写规则;删除将导致 Laravel 路由失效且 Nginx 响应 404。
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # 关闭 [/favicon.ico] 和 [/robots.txt] 的访问日志。
    # 并且即使它们不存在,也不写入错误日志。
    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    # 将 [404] 错误交给 [/index.php] 处理,表示由 Laravel 渲染美观的错误页面。
    error_page 404 /index.php;

    # URI 符合正则表达式 [\.php$] 的请求将进入此段配置
    location ~ \.php$ {
        # 配置 FastCGI 服务地址,可以为 IP:端口,也可以为 Unix socket。
        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
        # 配置 FastCGI 的主页为 index.php。
        fastcgi_index index.php;
        # 配置 FastCGI 参数 SCRIPT_FILENAME 为 $realpath_root$fastcgi_script_name。
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        # 引用更多默认的 FastCGI 参数。
        include fastcgi_params;
    }
    # 通俗地说,以上配置将所有 URI 以 .php 结尾的请求,全部交给 PHP-FPM 处理。

    # 除符合正则表达式 [/\.(?!well-known).*] 之外的 URI,全部拒绝访问
    # 也就是说,拒绝公开以 [.] 开头的目录,[.well-known] 除外
    location ~ /\.(?!well-known).* {
        deny all;
    }
}

6.1.5 location 段

6.2 重定向

6.3 邪恶的 if

其他

  • gzip
  • http code
  • try
  • access log
  • error log
  • proxy
  • ssl
  • map

七、Nginx 高级使用

openresty

  • access control
  • 复杂的重定向
  • 缓存管理

八、测试相关

8.1 搭建一个最小的测试单元

其实,当你的 nginx 跑起来之后,你访问 127.0.0.1 就可以看到一个 nginx 的默认页面了。

你看到这个页面,说明你的 nginx 服务已经正常在运行,默认的页面是 nginx 的默认 server 段在执行,如果感兴趣的话,可以了解下默认 server 的配置文件。

搭建自己的 web 站点,你需要做以下几件事情:

8.1.1 dns 解析:

这个 dns 解析可以是真实的域名增加 A 记录,也可以是修改自己的 hosts 表,比如:

127.0.0.1 abc.test # test 域名 chrome 会识别,其他后缀的测试域名,可能会有问题。

当做好域名解析之后,你就可以在 nginx 的 vhosts 目录下增加虚拟主机了。

8.1.2 设置站点目录:

遵照习惯,我们设定 web 的根目录为 /srv/www
在这个目录下,我们建立 abc.test 目录。
在 abc.test 目录下,我们新建一个 index.html 文件,敲入如下代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p> hello, world! </p>
</body>
</html>

在 abc.test 目录下,新建 phpinfo.php, 敲入如下代码:

<?php

echo phpinfo();

?>

8.1.3 增加虚拟主机:

server {
    listen       80;
    server_name  abc.test;
    index index.html index.php;
    root  /srv/www/abc.test;

    # logs
    error_log  /var/log/nginx/abc_error.log error;
    access_log /var/log/nginx/abc_access.log;

    # rewrite
    location / {
        try_files $uri $uri/ @rewrite;
    }

    # static cache
    location ~* .(js|css|png|jpg|gif|ico)$ {
        expires 7d;
    }


    if ( $fastcgi_script_name ~ ..*/.*php ) {
        return 403;
    }

    location @rewrite {
        rewrite ^(.*)$ /index.php$1;
    }

    location ~ \.php($|/) {
        fastcgi_pass unix:/var/run/php/php5.6-fpm.sock;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include  fastcgi.conf;
    }
}

8.1.4 重启 nginx,并访问 abc.test, 以查看效果。

  • 访问 abc.test
  • 访问 abc.test/index.html
  • 访问 abc.test/phpinfo.php

如果以上访问都正常,说明 nginx 环境配置正常, php 环境配置正常。

相关

通过 curl 检测网站是否开启了 gzip 压缩

curl -H "Accept-Encoding: gzip" -I https://www.guohuawei.com

返回结果:

HTTP/2 200
date: Thu, 30 May 2019 10:22:26 GMT
content-type: text/html; charset=UTF-8
set-cookie: __cfduid=da62a867e8f6cabdd6cfc5b8c606145001559211746; expires=Fri, 29-May-20 10:22:26 GMT; path=/; domain=.guohuawei.com; HttpOnly
x-pingback: http://www.guohuawei.com/action/xmlrpc
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
server: cloudflare
cf-ray: 4deffca51a00962f-SJC
content-encoding: gzip

通过 curl 查看请求响应时间

# curl -o /dev/null -s -w %{time_namelookup}::%{time_connect}::%{time_starttransfer}::%{time_total}::%{speed_download}"\n" http://www.guohuawei.com

0.014::0.015::0.018::0.019::1516256.00

-o:把curl 返回的html、js 写到垃圾回收站[ /dev/null]
-s:去掉所有状态
-w:按照后面的格式写出rt

time_namelookup:DNS 解析域名 www.guohuawei.com 的时间
time_commect:client和server端建立TCP 连接的时间
time_starttransfer:从client发出请求;到web的server 响应第一个字节的时间
time_total:client发出请求;到web的server发送会所有的相应数据的时间
speed_download:下周速度 单位 byte/s

上面这条命令及返回结果可以这么理解:

0.014: DNS 服务器解析 www.guohuawei.com 的时间单位是s
0.015: client发出请求,到c/s 建立TCP 的时间;里面包括DNS解析的时间
0.018: client发出请求;到s响应发出第一个字节开始的时间;包括前面的2个时间
0.019: client发出请求;到s把响应的数据全部发送给client;并关闭connect的时间

1516256.00 :下载数据的速度

建立TCP连接到server返回client第一个字节的时间:0.018s - 0.015s = 0.003s
server把响应数据发送给client的时间:0.019s - 0.018 = 0.01s

在服务器上跑脚本,经常需要长时间运行,这种时候如果 shell 窗口关闭,或者遇到网络连接问题导致客户端 shell 连接问题,都会影响服务器端的脚本执行,此时就需要将进程挂起到后台执行。

nohup 是常用的命令,简单易用。

一、nohup

用途:不挂断地运行命令。

语法:nohup Command [ Arg … ] [ & ]

  无论是否将 nohup 命令的输出重定向到终端,输出都将附加到当前目录的 nohup.out 文件中。

  如果当前目录的 nohup.out 文件不可写,输出重定向到 $HOME/nohup.out 文件中。

  如果没有文件能创建或打开以用于追加,那么 Command 参数指定的命令不可调用。

退出状态:该命令返回下列出口值:
  
  126 可以查找但不能调用 Command 参数指定的命令。   
  127 nohup 命令发生错误或不能查找由 Command 参数指定的命令。   
  否则,nohup 命令的退出状态是 Command 参数指定命令的退出状态。

二、&

用途:在后台运行

一般两个一起用

nohup command &

eg:

nohup command >> /path/to/nohup.log 2>&1 &

三、查看运行的后台进程

(1)jobs -l

jobs命令只看当前终端生效的,关闭终端后,在另一个终端jobs已经无法看到后台跑得程序了,此时利用ps(进程查看命令)

(2)ps -ef

ps -aux |grep command

a:显示所有程序
u:以用户为主的格式来显示
x:显示所有程序,不以终端机来区分

注:

用 ps -def | grep查找进程很方便,最后一行总是会 grep 自己

用 grep -v 参数可以将 grep 命令排除掉

ps -aux|grep command | grep -v grep

四、用 awk 提取进程 ID 

ps -aux|grep command | grep -v grep | awk '{print $2}'

五、终止后台运行的进程

kill -9  进程号

dig 用于在 linux 下查询域名解析的信息。

一、基础命令

dig www.guohuawei.com

即查询域名的A记录,查询的 dns 服务器将采用系统配置的服务器,即/etc/resovle.conf 中的。

二、查询其他类型记录

如果要查询其他类型的记录,比如 MX,CNAME,NS,PTR 等,只需将类型加在命令后面即可。

dig www.guohuawei.com mx
dig www.guohuawei.com ns

三、查询指定 dns 服务器的解析

如果你是一个系统管理员,部署好了一台 dns 服务器之后想对它进行解析测试,就必须要显式指定待测试的 dns 服务器地址了,例如:

dig @202.106.0.20 www.guohuawei.com a

四、输出逐级查询的过程

另外一个重要的功能是 +trace 参数,使用这个参数之后将显示从根域逐级查询的过程:

dig www.guohuawei.com a +trace

比如,对域名 www.guohuawei.com A 记录的 trace 查询可以看到根域.,顶级域 .com,以及 guohuawei.com 的域名权威服务器的地址及其各自的返回结果,这样对于追踪 dns 解析中的问题有很大的帮助。

; <<>> DiG 9.10.6 <<>> guohuawei.com +trace
;; global options: +cmd
.            61341    IN    NS    m.root-servers.net.
.            61341    IN    NS    i.root-servers.net.
.            61341    IN    NS    e.root-servers.net.
.            61341    IN    NS    l.root-servers.net.
.            61341    IN    NS    d.root-servers.net.
.            61341    IN    NS    a.root-servers.net.
.            61341    IN    NS    g.root-servers.net.
.            61341    IN    NS    b.root-servers.net.
.            61341    IN    NS    f.root-servers.net.
.            61341    IN    NS    j.root-servers.net.
.            61341    IN    NS    c.root-servers.net.
.            61341    IN    NS    k.root-servers.net.
.            61341    IN    NS    h.root-servers.net.
;; Received 228 bytes from 192.168.1.1#53(192.168.1.1) in 8 ms

com.            172800    IN    NS    a.gtld-servers.net.
com.            172800    IN    NS    b.gtld-servers.net.
com.            172800    IN    NS    c.gtld-servers.net.
com.            172800    IN    NS    d.gtld-servers.net.
com.            172800    IN    NS    e.gtld-servers.net.
com.            172800    IN    NS    f.gtld-servers.net.
com.            172800    IN    NS    g.gtld-servers.net.
com.            172800    IN    NS    h.gtld-servers.net.
com.            172800    IN    NS    i.gtld-servers.net.
com.            172800    IN    NS    j.gtld-servers.net.
com.            172800    IN    NS    k.gtld-servers.net.
com.            172800    IN    NS    l.gtld-servers.net.
com.            172800    IN    NS    m.gtld-servers.net.
com.            86400    IN    DS    30909 8 2 E2D3C916F6DEEAC73294E8268FB5885044A833FC5459588F4A9184CF C41A5766
com.            86400    IN    RRSIG    DS 8 1 86400 20190611050000 20190529040000 25266 . Eigc8QOV/Nr0YjVSd8IbNk7RnAuNean6e4qpXej/V09bcPtnOGu8i7zl 4V5tuaBAqbPKed9LTxcyqhTgBqXPMAU2vBqtBj48voFsUKzhlQp5HMwN CgGqpc2vTF0UoZ/omPOYw0P+++1gjXvyLJuqAmOrnxBoMXX09QaN4lSg loX8T8NU/dbpKO/WHsUYkOpHSzLYcxm4eqSbbakcc915VjAwhwY4pSBs ohLmTNnCtma0mPfZPAE8KjoF1I52TFOfwh4BlBvKnFVJXE1LwDn4b3h6 jS681KZQOm+JjHK4lu0Oo+UarWvtdJm4EFw2kYribsRCcnJcfVKLa9uv SQIJ8g==
;; Received 1173 bytes from 199.7.91.13#53(d.root-servers.net) in 233 ms

guohuawei.com.        172800    IN    NS    dan.ns.cloudflare.com.
guohuawei.com.        172800    IN    NS    zara.ns.cloudflare.com.
CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN NSEC3 1 1 0 - CK0Q1GIN43N1ARRC9OSM6QPQR81H5M9A  NS SOA RRSIG DNSKEY NSEC3PARAM
CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN RRSIG NSEC3 8 2 86400 20190604044533 20190528033533 3800 com. YQdumHEEUmzxuBxPBgehzu4J2IUp49V8I/9jmOCeLkaXkjaIBpU6eEFg dS5HTiEjHIzJaQeCvih3VmXTdYlUj9exoNz5anezyE913cr9EAczipcN wM18pVhvJMAwNyc+vpKKquwEKb13smt8hVaezr+KRyVxG0cZSxb1IX/6 IO4=
RM7TI8631VFRPOU55KFMOFT3D91LITIP.com. 86400 IN NSEC3 1 1 0 - RM7TUTM87U3I48029OCNGJ1SF3U2LHLJ  NS DS RRSIG
RM7TI8631VFRPOU55KFMOFT3D91LITIP.com. 86400 IN RRSIG NSEC3 8 2 86400 20190603043659 20190527032659 3800 com. AiI4JLNemP1Lexi9c5fSvZCCRAKyT2v/qs703F9ToWC1NVGYvYGR/Jrg asfAFJFd/lFMHQ5zPAqY4ecUN+5GoBRnWqjc5G8j+tH0Bd+YAjasR6uB m1C6CWS5HkNeQgKCrE03Ju+nfHnSfsvtBZvYm4MZoUb9UHAWMK/Eg+z8 XAk=
;; Received 666 bytes from 192.52.178.30#53(k.gtld-servers.net) in 192 ms

guohuawei.com.        300    IN    A    104.31.79.160
guohuawei.com.        300    IN    A    104.31.78.160
;; Received 74 bytes from 173.245.59.108#53(dan.ns.cloudflare.com) in 193 ms

五、域名不存在时

比如解析 bucunzaiba.com 这个域名, 整个过程如下:

  1. 由根域名返回.com顶级域的服务器地址
  2. 由.com顶级域查到二级域名不存在,返回一条SOA记录

如:

dig bucunzaiba.com +trace

; <<>> DiG 9.10.6 <<>> bucunzaiba.com +trace
;; global options: +cmd
.            61015    IN    NS    m.root-servers.net.
.            61015    IN    NS    i.root-servers.net.
......

com.            900    IN    SOA    a.gtld-servers.net. nstld.verisign-grs.com. 1559124593 1800 900 604800 86400
com.            900    IN    RRSIG    SOA 8 1 900 20190605100953 20190529085953 3800

一、背景

Ubuntu16下,使用 apt-get 下载的 nodejs 最新版本需要升级。

二、解决方法

用 npm 安装了 Node 工具包 n ,使用该工具包将 node 升级到最新版本:

sudo npm install n -g
sudo n stable

三、n 工具包说明

n 是一个Node工具包,它提供了几个升级命令参数:

n 显示已安装的Node版本
n latest 安装最新版本Node
n stable 安装最新稳定版Node
n lts 安装最新长期维护版(lts)Node
n version 根据提供的版本号安装Node