Nginx 学习篇分享

发布于 2024-11-20 12:59:18 字数 44727 浏览 0 评论 0

Nginx 是一款面向性能设计的 HTTP 服务器,能反向代理 HTTPHTTPS 和邮件相关( SMTPPOP3IMAP ) 的协议链接。并且提供了负载均衡以及 HTTP 缓存。它的设计充分使用异步事件模型,削减上下文调度的开销,提高服务器并发能力。采用了模块化设计,提供了丰富模块的第三方模块。

  • 所以关于 Nginx,有这些标签:「异步」「事件」「模块化」「高性能」「高并发」「反向代理」「负载均衡」

Nginx 配置文件在线生成: https://nginxconfig.io/

一、安装

1.1 安装依赖

prce (重定向支持) 和 openssl ( https 支持,如果不需要 https 可以不安装)

yum install -y pcre-devel 
yum -y install gcc make gcc-c++ wget
yum -y install openssl openssl-devel

CentOS 6.5 我安装的时候是选择的 基本服务器,默认这两个包都没安装全,所以这两个都运行安装即可

1.2 下载

nginx 的所有版本在这里

wget http://nginx.org/download/nginx-1.13.3.tar.gz
wget http://nginx.org/download/nginx-1.13.7.tar.gz

# 如果没有安装 wget
# 下载已编译版本
$ yum install wget

# 解压压缩包
tar zxf nginx-1.13.3.tar.gz

1.3 编译安装

然后进入目录编译安装, configure 参数说明

cd nginx-1.11.5
./configure


....
Configuration summary
  + using system PCRE library
  + OpenSSL library is not used
  + using system zlib library

  nginx path prefix: "/usr/local/nginx"
  nginx binary file: "/usr/local/nginx/sbin/nginx"
  nginx modules path: "/usr/local/nginx/modules"
  nginx configuration prefix: "/usr/local/nginx/conf"
  nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
  nginx pid file: "/usr/local/nginx/logs/nginx.pid"
  nginx error log file: "/usr/local/nginx/logs/error.log"
  nginx http access log file: "/usr/local/nginx/logs/access.log"
  nginx http client request body temporary files: "client_body_temp"
  nginx http proxy temporary files: "proxy_temp"
  nginx http fastcgi temporary files: "fastcgi_temp"
  nginx http uwsgi temporary files: "uwsgi_temp"
  nginx http scgi temporary files: "scgi_temp"

安装报错误的话比如: “C compiler cc is not found” ,这个就是缺少编译环境,安装一下就可以了 yum -y install gcc make gcc-c++ openssl-devel

如果没有 error 信息,就可以执行下边的安装了:

make
make install

1.4 nginx 测试

运行下面命令会出现两个结果,一般情况 nginx 会安装在 /usr/local/nginx 目录中

cd /usr/local/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

1.5 设置全局 nginx 命令

vi ~/.bash_profile

将下面内容添加到 ~/.bash_profile 文件中

PATH=$PATH:$HOME/bin:/usr/local/nginx/sbin/
export PATH

运行命令 source ~/.bash_profile 让配置立即生效。你就可以全局运行 nginx 命令了。

二、开机自启动

开机自启动方法一

编辑 vi /lib/systemd/system/nginx.service 文件,没有创建一个 touch nginx.service - 然后将如下内容根据具体情况进行修改后,添加到 nginx.service 文件中:

[Unit]
Description=nginx
After=network.target remote-fs.target nss-lookup.target

[Service]

Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target
[Unit]:服务的说明  
Description:描述服务  
After:描述服务类别  
[Service]服务运行参数的设置  
Type=forking 是后台运行的形式  
ExecStart 为服务的具体运行命令  
ExecReload 为重启命令  
ExecStop 为停止命令  
PrivateTmp=True 表示给服务分配独立的临时空间  
注意:[Service]的启动、重启、停止命令全部要求使用绝对路径  
[Install]运行级别下服务安装的相关设置,可设置为多用户,即系统运行级别为 3

保存退出。

设置开机启动,使配置生效:

systemctl enable nginx.service
# 输出下面内容表示成功了
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.

开机自启动方法二

vi /etc/rc.local

# 在 rc.local 文件中,添加下面这条命令
/usr/local/nginx/sbin/nginx start

如果开机后发现自启动脚本没有执行,你要去确认一下 rc.local 这个文件的访问权限是否是可执行的,因为 rc.local 默认是不可执行的。修改 rc.local 访问权限,增加可执行权限:

chmod +x /etc/rc.d/rc.local

三、运维

3.1 服务管理

# 启动
/usr/local/nginx/sbin/nginx

# 重启
/usr/local/nginx/sbin/nginx -s reload

# 关闭进程
/usr/local/nginx/sbin/nginx -s stop

# 平滑关闭 nginx
/usr/local/nginx/sbin/nginx -s quit

# 查看 nginx 的安装状态,
/usr/local/nginx/sbin/nginx -V

关闭防火墙,或者添加防火墙规则就可以测试了

service iptables stop

或者编辑配置文件:

vi /etc/sysconfig/iptables

添加这样一条开放 80 端口的规则后保存:

-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT

重启服务即可:

service iptables restart
# 命令进行查看目前 nat
iptables -t nat -L

3.2 重启服务防火墙报错解决

service iptables restart
# Redirecting to /bin/systemctl restart  iptables.service
# Failed to restart iptables.service: Unit iptables.service failed to load: No such file or directory.
  • CentOS 7RHEL 7Fedora 中防火墙由 firewalld 来管理,当然你可以还原传统的管理方式。或则使用新的命令进行管理。 假如采用传统请执行一下命令
# 传统命令
systemctl stop firewalld
systemctl mask firewalld
# 安装命令
yum install iptables-services

systemctl enable iptables 
service iptables restart

四、nginx 卸载

  • 如果通过 yum 安装,使用下面命令安装。
yum remove nginx
  • 编译安装,删除 /usr/local/nginx 目录即可
  • 如果配置了自启动脚本,也需要删除。

五、参数说明

参数说明
–prefix= <path>Nginx 安装路径。如果没有指定,默认为 /usr/local/nginx。
–sbin-path= <path>Nginx 可执行文件安装路径。只能安装时指定,如果没有指定,默认为 <prefix> /sbin/nginx。
–conf-path= <path>在没有给定-c 选项下默认的 nginx.conf 的路径。如果没有指定,默认为 <prefix> /conf/nginx.conf。
–pid-path= <path>在 nginx.conf 中没有指定 pid 指令的情况下,默认的 nginx.pid 的路径。如果没有指定,默认为 <prefix> /logs/nginx.pid。
–lock-path= <path>nginx.lock 文件的路径。
–error-log-path= <path>在 nginx.conf 中没有指定 error_log 指令的情况下,默认的错误日志的路径。如果没有指定,默认为 <prefix> /- logs/error.log。
–http-log-path= <path>在 nginx.conf 中没有指定 access_log 指令的情况下,默认的访问日志的路径。如果没有指定,默认为 <prefix> /- logs/access.log。
–user= <user>在 nginx.conf 中没有指定 user 指令的情况下,默认的 nginx 使用的用户。如果没有指定,默认为 nobody。
–group= <group>在 nginx.conf 中没有指定 user 指令的情况下,默认的 nginx 使用的组。如果没有指定,默认为 nobody。
–builddir=DIR指定编译的目录
–with-rtsig_module启用 rtsig 模块
–with-select_module –without-select_module允许或不允许开启 SELECT 模式,如果 configure 没有找到更合适的模式,比如:kqueue(sun os),epoll (linux kenel 2.6+), rtsig(- 实时信号) 或者/dev/poll(一种类似 select 的模式,底层实现与 SELECT 基本相 同,都是采用轮训方法) SELECT 模式将是默认安装模式
–with-poll_module –without-poll_moduleWhether or not to enable the poll module. This module is enabled by, default if a more suitable method such as kqueue, epoll, rtsig or /dev/poll is not discovered by configure.
–with-http_ssl_moduleEnable ngx_http_ssl_module. Enables SSL support and the ability to handle HTTPS requests. Requires OpenSSL. On Debian, this is libssl-dev. 开启 HTTP SSL 模块,使 NGINX 可以支持 HTTPS 请求。这个模块需要已经安装了 OPENSSL,在 DEBIAN 上是 libssl
–with-http_realip_module启用 ngx_http_realip_module
–with-http_addition_module启用 ngx_http_addition_module
–with-http_sub_module启用 ngx_http_sub_module
–with-http_dav_module启用 ngx_http_dav_module
–with-http_flv_module启用 ngx_http_flv_module
–with-http_stub_status_module启用 “server status” 页
–without-http_charset_module禁用 ngx_http_charset_module
–without-http_gzip_module禁用 ngx_http_gzip_module. 如果启用,需要 zlib 。
–without-http_ssi_module禁用 ngx_http_ssi_module
–without-http_userid_module禁用 ngx_http_userid_module
–without-http_access_module禁用 ngx_http_access_module
–without-http_auth_basic_module禁用 ngx_http_auth_basic_module
–without-http_autoindex_module禁用 ngx_http_autoindex_module
–without-http_geo_module禁用 ngx_http_geo_module
–without-http_map_module禁用 ngx_http_map_module
–without-http_referer_module禁用 ngx_http_referer_module
–without-http_rewrite_module禁用 ngx_http_rewrite_module. 如果启用需要 PCRE 。
–without-http_proxy_module禁用 ngx_http_proxy_module
–without-http_fastcgi_module禁用 ngx_http_fastcgi_module
–without-http_memcached_module禁用 ngx_http_memcached_module
–without-http_limit_zone_module禁用 ngx_http_limit_zone_module
–without-http_empty_gif_module禁用 ngx_http_empty_gif_module
–without-http_browser_module禁用 ngx_http_browser_module
–without-http_upstream_ip_hash_module禁用 ngx_http_upstream_ip_hash_module
–with-http_perl_module启用 ngx_http_perl_module
–with-perl_modules_path=PATH指定 perl 模块的路径
–with-perl=PATH指定 perl 执行文件的路径
–http-log-path=PATHSet path to the http access log
–http-client-body-temp-path=PATHSet path to the http client request body temporary files
–http-proxy-temp-path=PATHSet path to the http proxy temporary files
–http-fastcgi-temp-path=PATHSet path to the http fastcgi temporary files
–without-http禁用 HTTP server
–with-mail启用 IMAP4/POP3/SMTP 代理模块
–with-mail_ssl_module启用 ngx_mail_ssl_module
–with-cc=PATH指定 C 编译器的路径
–with-cpp=PATH指定 C 预处理器的路径
–with-cc-opt=OPTIONSAdditional parameters which will be added to the variable CFLAGS. With the use of the system library PCRE in FreeBSD, it is necessary to indicate –with-cc-opt=”-I /usr/local/include”. If we are using select() and it is necessary to increase the number of file descriptors, then this also can be assigned here: –with-cc-opt=”-D FD_SETSIZE=2048”.
–with-ld-opt=OPTIONSAdditional parameters passed to the linker. With the use of the system library PCRE in - FreeBSD, it is necessary to indicate –with-ld-opt=”-L /usr/local/lib”.
–with-cpu-opt=CPU为特定的 CPU 编译,有效的值包括:pentium, pentiumpro, pentium3, pentium4, athlon, opteron, amd64, sparc32, sparc64, ppc64
–without-pcre禁止 PCRE 库的使用。同时也会禁止 HTTP rewrite 模块。在 “location” 配置指令中的正则表达式也需要 PCRE 。
–with-pcre=DIR指定 PCRE 库的源代码的路径。
–with-pcre-opt=OPTIONSSet additional options for PCRE building.
–with-md5=DIRSet path to md5 library sources.
–with-md5-opt=OPTIONSSet additional options for md5 building.
–with-md5-asmUse md5 assembler sources.
–with-sha1=DIRSet path to sha1 library sources.
–with-sha1-opt=OPTIONSSet additional options for sha1 building.
–with-sha1-asmUse sha1 assembler sources.
–with-zlib=DIRSet path to zlib library sources.
–with-zlib-opt=OPTIONSSet additional options for zlib building.
–with-zlib-asm=CPUUse zlib assembler sources optimized for specified CPU, valid values are: pentium, pentiumpro
–with-openssl=DIRSet path to OpenSSL library sources
–with-openssl-opt=OPTIONSSet additional options for OpenSSL building
–with-debug启用调试日志
–add-module=PATHAdd in a third-party module found in directory PATH

六、配置

  • Centos 默认配置文件在 /usr/local/nginx-1.5.1/conf/nginx.conf 我们要在这里配置一些文件。 nginx.conf 是主配置文件,由若干个部分组成,每个大括号 {} 表示一个部分。每一行指令都由分号结束 ; ,标志着一行的结束。

6.1 常用正则

正则说明正则说明
.匹配除换行符以外的任意字符$匹配字符串的结束
?重复 0 次或 1 次{n}重复 n 次
+重复 1 次或更多次{n,}重复 n 次或更多次
*重复 0 次或更多次[c]匹配单个字符 c
\d匹配数字[a-z]匹配 a-z 小写字母的任意一个
^匹配字符串的开始--

6.2 全局变量

变量说明变量说明
$args这个变量等于请求行中的参数,同 $query_string$remote_port客户端的端口。
$content_length请求头中的 Content-length 字段。$remote_user已经经过 Auth Basic Module 验证的用户名。
$content_type请求头中的 Content-Type 字段。$request_filename当前请求的文件路径,由 rootalias 指令与 URI 请求生成。
$document_root当前请求在 root 指令中指定的值。$schemeHTTP 方法(如 httphttps )。
$host请求主机头字段,否则为服务器名称。$server_protocol请求使用的协议,通常是 HTTP/1.0HTTP/1.1
$http_user_agent客户端 agent 信息$server_addr服务器地址,在完成一次系统调用后可以确定这个值。
$http_cookie客户端 cookie 信息$server_name服务器名称。
$limit_rate这个变量可以限制连接速率。$server_port请求到达服务器的端口号。
$request_method客户端请求的动作,通常为 GETPOST$request_uri包含请求参数的原始 URI ,不包含主机名,如: /foo/bar.php?arg=baz
$remote_addr客户端的 IP 地址。$uri不带请求参数的当前 URI$uri 不包含主机名,如 /foo/bar.html
$document_uri$uri 相同。--

例如请求: http://localhost:3000/test1/test2/test.php

$host:localhost  
$server_port:3000  
$request_uri:/test1/test2/test.php  
$document_uri:/test1/test2/test.php  
$document_root:/var/www/html  
$request_filename:/var/www/html/test1/test2/test.php

6.3 符号参考

符号说明符号说明符号说明
k , K千字节m , M兆字节ms毫秒
sm分钟h小时
dwM一个月, 30
  • 例如,”8k”,”1m” 代表字节数计量。
  • 例如,”1h 30m”,”1y 6M”。代表 “1 小时 30 分”,”1 年零 6 个月”。

6.4 配置文件

  • nginx 的配置系统由一个主配置文件和其他一些辅助的配置文件构成。这些配置文件均是纯文本文件,全部位于 nginx 安装目录下的 conf 目录下。
  • 指令由 nginx 的各个模块提供,不同的模块会提供不同的指令来实现配置。 指令除了 Key-Value 的形式,还有作用域指令。
  • nginx.conf 中的配置信息,根据其逻辑上的意义,对它们进行了分类,也就是分成了多个作用域,或者称之为配置指令上下文。不同的作用域含有一个或者多个配置项。

下面的这些上下文指令是用的比较多:

DirectiveDescriptionContains Directive
mainnginx 在运行时与具体业务功能(比如 http 服务或者 email 服务代理)无关的一些参数,比如工作进程数,运行的身份等。user , worker_processes , error_log , events , http , mail
http与提供 http 服务相关的一些配置参数。例如:是否使用 keepalive 啊,是否使用 gzip 进行压缩等。server
serverhttp 服务上支持若干虚拟主机。每个虚拟主机一个对应的 server 配置项,配置项里面包含该虚拟主机相关的配置。在提供 mail 服务的代理时,也可以建立若干 server. 每个 server 通过监听的地址来区分。listen , server_name , access_log , location , protocol , proxy , smtp_auth , xclient
locationhttp 服务中,某些特定的 URL 对应的一系列配置项。index , root
mail实现 email 相关的 SMTP/IMAP/POP3 代理时,共享的一些配置项(因为可能实现多个代理,工作在多个监听地址上)。server , http , imap_capabilities
include以便增强配置文件的可读性,使得部分配置文件可以重新使用。-
valid_referers用来校验 Http 请求头 Referer 是否有效。-
try_files用在 server 部分,不过最常见的还是用在 location 部分,它会按照给定的参数顺序进行尝试,第一个被匹配到的将会被使用。-
if当在 location 块中使用 if 指令,在某些情况下它并不按照预期运行,一般来说避免使用 if 指令。-
  • 例如我们再 nginx.conf 里面引用两个配置 vhost/example.com.confvhost/gitlab.com.conf 它们都被放在一个我自己新建的目录 vhost 下面。 nginx.conf 配置如下:
worker_processes  1;
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;
        location / {
            root   html;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
    include  vhost/example.com.conf;
    include  vhost/gitlab.com.conf;
}
  • 简单的配置: example.com.conf
server {
    #侦听的 80 端口
    listen       80;
    server_name  baidu.com app.baidu.com; # 这里指定域名
    index        index.html index.htm;    # 这里指定默认入口页面
    root /home/www/app.baidu.com;         # 这里指定目录
}

6.5 内置预定义变量

  • Nginx 提供了许多预定义的变量,也可以通过使用 set 来设置变量。你可以在 if 中使用预定义变量,也可以将它们传递给代理服务器。以下是一些常见的预定义变量, 更多详见
变量名称
$args_name在请求中的 name 参数
$args `所有请求参数
$query_string$args 的别名
$content_length请求头 Content-Length 的值
$content_type请求头 Content-Type 的值
$host如果当前有 Host ,则为请求头 Host 的值;如果没有这个头,那么该值等于匹配该请求的 server_name 的值
$remote_addr客户端的 IP 地址
$request完整的请求,从客户端收到,包括 Http 请求方法、 URIHttp 协议、头、请求体
$request_uri完整请求的 URI ,从客户端来的请求,包括参数
$scheme当前请求的协议
$uri当前请求的标准化 URI

6.6 反向代理

  • 反向代理是一个 Web 服务器,它接受客户端的连接请求,然后将请求转发给上游服务器,并将从服务器得到的结果返回给连接的客户端。下面简单的反向代理的例子:
server {  
  listen       80;                                                        
  server_name  localhost;                                              
  client_max_body_size 1024M;  # 允许客户端请求的最大单文件字节数

  location / {
    proxy_pass                         http://localhost:8080;
    proxy_set_header Host              $host:$server_port;
    proxy_set_header X-Forwarded-For   $remote_addr; # HTTP 的请求端真实的 IP
    proxy_set_header X-Forwarded-Proto $scheme;      # 为了正确地识别实际用户发出的协议是 http 还是 https
  }
}
  • 复杂的配置: gitlab.com.conf
server {
    #侦听的 80 端口
    listen       80;
    server_name  git.example.cn;
    location / {
        proxy_pass   http://localhost:3000;
        #以下是一些反向代理的配置可删除
        proxy_redirect             off;
        #后端的 Web 服务器可以通过 X-Forwarded-For 获取用户真实 IP
        proxy_set_header           Host $host;
        client_max_body_size       10m; #允许客户端请求的最大单文件字节数
        client_body_buffer_size    128k; #缓冲区代理缓冲用户端请求的最大字节数
        proxy_connect_timeout      300; #nginx 跟后端服务器连接超时时间(代理连接超时)
        proxy_send_timeout         300; #后端服务器数据回传时间(代理发送超时)
        proxy_read_timeout         300; #连接成功后,后端服务器响应时间(代理接收超时)
        proxy_buffer_size          4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
        proxy_buffers              4 32k; #proxy_buffers 缓冲区,网页平均在 32k 以下的话,这样设置
        proxy_busy_buffers_size    64k; #高负荷下缓冲大小(proxy_buffers*2)
    }
}
  • 代理到上游服务器的配置中,最重要的是 proxy_pass 指令。以下是代理模块中的一些常用指令:
指令说明
proxy_connect_timeoutNginx 从接受请求至连接到上游服务器的最长等待时间
proxy_send_timeout后端服务器数据回传时间(代理发送超时)
proxy_read_timeout连接成功后,后端服务器响应时间(代理接收超时)
proxy_cookie_domain替代从上游服务器来的 Set-Cookie 头的 domain 属性
proxy_cookie_path替代从上游服务器来的 Set-Cookie 头的 path 属性
proxy_buffer_size设置代理服务器( nginx )保存用户头信息的缓冲区大小
proxy_buffersproxy_buffers 缓冲区,网页平均在多少 k 以下
proxy_set_header重写发送到上游服务器头的内容,也可以通过将某个头部的值设置为空字符串,而不发送某个头部的方法实现
proxy_ignore_headers这个指令禁止处理来自代理服务器的应答。
proxy_intercept_errors使 nginx 阻止 HTTP 应答代码为 400 或者更高的应答。

6.7 负载均衡

  • upstream 指令启用一个新的配置区段,在该区段定义一组上游服务器。这些服务器可能被设置不同的权重,也可能出于对服务器进行维护,标记为 down
upstream gitlab {
    ip_hash;
    # upstream 的负载均衡,weight 是权重,可以根据机器配置定义权重。weigth 参数表示权值,权值越高被分配到的几率越大。
    server 192.168.122.11:8081 ;
    server 127.0.0.1:82 weight=3;
    server 127.0.0.1:83 weight=3 down;
    server 127.0.0.1:84 weight=3; max_fails=3  fail_timeout=20s;
    server 127.0.0.1:85 weight=4;;
    keepalive 32;
}
server {
    #侦听的 80 端口
    listen       80;
    server_name  git.example.cn;
    location / {
        proxy_pass   http://gitlab;    #在这里设置一个代理,和 upstream 的名字一样
        #以下是一些反向代理的配置可删除
        proxy_redirect             off;
        #后端的 Web 服务器可以通过 X-Forwarded-For 获取用户真实 IP
        proxy_set_header           Host $host;
        proxy_set_header           X-Real-IP $remote_addr;
        proxy_set_header           X-Forwarded-For $proxy_add_x_forwarded_for;
        client_max_body_size       10m;  #允许客户端请求的最大单文件字节数
        client_body_buffer_size    128k; #缓冲区代理缓冲用户端请求的最大字节数
        proxy_connect_timeout      300;  #nginx 跟后端服务器连接超时时间(代理连接超时)
        proxy_send_timeout         300;  #后端服务器数据回传时间(代理发送超时)
        proxy_read_timeout         300;  #连接成功后,后端服务器响应时间(代理接收超时)
        proxy_buffer_size          4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
        proxy_buffers              4 32k;# 缓冲区,网页平均在 32k 以下的话,这样设置
        proxy_busy_buffers_size    64k; #高负荷下缓冲大小(proxy_buffers*2)
        proxy_temp_file_write_size 64k; #设定缓存文件夹大小,大于这个值,将从 upstream 服务器传
    }
}
  • 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器 down 掉,能自动剔除。

负载均衡:

  • upstream 模块能够使用 3 种负载均衡算法:轮询、IP 哈希、最少连接数。

轮询:

  • 默认情况下使用轮询算法,不需要配置指令来激活它,它是基于在队列中谁是下一个的原理确保访问均匀地分布到每个上游服务器;

IP 哈希:

  • 通过 ip_hash 指令来激活,Nginx 通过 IPv4 地址的前 3 个字节或者整个 IPv6 地址作为哈希键来实现,同一个 IP 地址总是能被映射到同一个上游服务器;

最少连接数:

  • 通过 least_conn 指令来激活,该算法通过选择一个活跃数最少的上游服务器进行连接。如果上游服务器处理能力不同,可以通过给 server 配置 weight 权重来说明,该算法将考虑到不同服务器的加权最少连接数。

6.7.1 RR

简单配置

这里我配置了 2 台服务器,当然实际上是一台,只是端口不一样而已,而 8081 的服务器是不存在的,也就是说访问不到,但是我们访问 http://localhost 的时候,也不会有问题,会默认跳转到 http://localhost:8080 具体是因为 Nginx 会自动判断服务器的状态,如果服务器处于不能访问(服务器挂了),就不会跳转到这台服务器,所以也避免了一台服务器挂了影响使用的情况,由于 Nginx 默认是 RR 策略,所以我们不需要其他更多的设置

upstream test {
    server localhost:8080;
    server localhost:8081;
}
server {
    listen       81;
    server_name  localhost;
    client_max_body_size 1024M;
 
    location / {
        proxy_pass http://test;
        proxy_set_header Host $host:$server_port;
    }
}

负载均衡的核心代码为

upstream test {
    server localhost:8080;
    server localhost:8081;
}

6.7.2 权重

  • 指定轮询几率, weight 和访问比率成正比,用于后端服务器性能不均的情况。 例如
upstream test {
    server localhost:8080 weight=9;
    server localhost:8081 weight=1;
}
  • 那么 10 次一般只会有 1 次会访问到 8081 ,而有 9 次会访问到 8080

6.7.3 ip_hash

上面的 2 种方式都有一个问题,那就是下一个请求来的时候请求可能分发到另外一个服务器,当我们的程序不是无状态的时候(采用了 session 保存数据),这时候就有一个很大的很问题了,比如把登录信息保存到了 session 中,那么跳转到另外一台服务器的时候就需要重新登录了,所以很多时候我们需要一个客户只访问一个服务器,那么就需要用 iphash 了, iphash 的每个请求按访问 iphash 结果分配,这样每个访客固定访问一个后端服务器,可以解决 session 的问题。

upstream test {
    ip_hash;
    server localhost:8080;
    server localhost:8081;
}

6.7.4 fair

  • 这是个第三方模块,按后端服务器的响应时间来分配请求,响应时间短的优先分配。
upstream backend {
    fair;
    server localhost:8080;
    server localhost:8081;
}

6.7.5 url_hash

这是个第三方模块,按访问 urlhash 结果来分配请求,使每个 url 定向到同一个后端服务器,后端服务器为缓存时比较有效。 在 upstream 中加入 hash 语句, server 语句中不能写入 weight 等其他的参数, hash_method 是使用的 hash 算法

upstream backend {
    hash $request_uri;
    hash_method crc32;
    server localhost:8080;
    server localhost:8081;
}
  • 以上 5 种负载均衡各自适用不同情况下使用,所以可以根据实际情况选择使用哪种策略模式,不过 fairurl_hash 需要安装第三方模块才能使用

server 指令可选参数:

  • weight :设置一个服务器的访问权重,数值越高,收到的请求也越多;
  • fail_timeout :在这个指定的时间内服务器必须提供响应,如果在这个时间内没有收到响应,那么服务器将会被标记为 down 状态;
  • max_fails :设置在 fail_timeout 时间之内尝试对一个服务器连接的最大次数,如果超过这个次数,那么服务器将会被标记为 down ;
  • down :标记一个服务器不再接受任何请求;
  • backup :一旦其他服务器宕机,那么有该标记的机器将会接收请求。

keepalive 指令:

  • Nginx 服务器将会为每一个 worker 进行保持同上游服务器的连接。

6.8 屏蔽 ip

  • nginx 的配置文件 nginx.conf 中加入如下配置,可以放到 http , server , location , limit_except 语句块,需要注意相对路径,本例当中 nginx.confblocksip.conf 在同一个目录中。
include blockip.conf;
  • blockip.conf 里面输入内容,如:
deny 165.91.122.67;

deny IP;   # 屏蔽单个 ip 访问
allow IP;  # 允许单个 ip 访问
deny all;  # 屏蔽所有 ip 访问
allow all; # 允许所有 ip 访问
deny 123.0.0.0/8   # 屏蔽整个段即从 123.0.0.1 到 123.255.255.254 访问的命令
deny 124.45.0.0/16 # 屏蔽 IP 段即从 123.45.0.1 到 123.45.255.254 访问的命令
deny 123.45.6.0/24 # 屏蔽 IP 段即从 123.45.6.1 到 123.45.6.254 访问的命令

# 如果你想实现这样的应用,除了几个 IP 外,其他全部拒绝
allow 1.1.1.1; 
allow 1.1.1.2;
deny all;

七、第三方模块安装方法

./configure --prefix=/你的安装目录  --add-module=/第三方模块目录

八、重定向

  • permanent 永久性重定向。请求日志中的状态码为 301
  • redirect 临时重定向。请求日志中的状态码为 302

8.1 重定向整个网站

server {
    server_name old-site.com
    return 301 $scheme://new-site.com$request_uri;
}

8.2 重定向单页

server {
    location = /oldpage.html {
        return 301 http://example.org/newpage.html;
    }
}

8.3 重定向整个子路径

location /old-site {
    rewrite ^/old-site/(.*) http://example.org/new-site/$1 permanent;
}

九、性能

9.1 内容缓存

  • 允许浏览器基本上永久地缓存静态内容。 Nginx 将为您设置 ExpiresCache-Control 头信息。
location /static {
    root /data;
    expires max;
}
  • 如果要求浏览器永远不会缓存响应(例如用于跟踪请求),请使用 -1
location = /empty.gif {
    empty_gif;
    expires -1;
}

9.2 Gzip 压缩

gzip  on;
gzip_buffers 16 8k;
gzip_comp_level 6;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_proxied any;
gzip_vary on;
gzip_types
    text/xml application/xml application/atom+xml application/rss+xml application/xhtml+xml image/svg+xml
    text/javascript application/javascript application/x-javascript
    text/x-json application/json application/x-web-app-manifest+json
    text/css text/plain text/x-component
    font/opentype application/x-font-ttf application/vnd.ms-fontobject
    image/x-icon;
gzip_disable  "msie6";

9.3 打开文件缓存

open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;

9.4 SSL 缓存

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

9.5 上游 Keepalive

upstream backend {
    server 127.0.0.1:8080;
    keepalive 32;
}
server {
    ...
    location /api/ {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

9.6 监控

使用 ngxtop 实时解析 nginx 访问日志,并且将处理结果输出到终端,功能类似于系统命令 top 。所有示例都读取 nginx 配置文件的访问日志位置和格式。如果要指定访问日志文件和/或日志格式,请使用-f 和-a 选项。

注意:在 nginx 配置中 /usr/local/nginx/conf/nginx.conf 日志文件必须是绝对路径。

# 安装 ngxtop
pip install ngxtop

# 实时状态
ngxtop
# 状态为 404 的前 10 个请求的路径:
ngxtop top request_path --filter 'status == 404'

# 发送总字节数最多的前 10 个请求
ngxtop --order-by 'avg(bytes_sent) * count'

# 排名前十位的 IP,例如,谁攻击你最多
ngxtop --group-by remote_addr

# 打印具有 4xx 或 5xx 状态的请求,以及 status 和 http referer
ngxtop -i 'status >= 400' print request status http_referer

# 由 200 个请求路径响应发送的平均正文字节以'foo'开始:
ngxtop avg bytes_sent --filter 'status == 200 and request_path.startswith("foo")'

# 使用“common”日志格式从远程机器分析 apache 访问日志
ssh remote tail -f /var/log/apache2/access.log | ngxtop -f common

十、常见使用场景

10.1 跨域问题

在工作中,有时候会遇到一些接口不支持跨域,这时候可以简单的添加 add_headers 来支持 cors 跨域。配置如下:

server {
  listen 80;
  server_name api.xxx.com;
    
  add_header 'Access-Control-Allow-Origin' '*';
  add_header 'Access-Control-Allow-Credentials' 'true';
  add_header 'Access-Control-Allow-Methods' 'GET,POST,HEAD';

  location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host  $http_host;    
  } 
}

上面更改头信息,还有一种,使用 rewrite 指令重定向 URI 来解决跨域问题。

upstream test {
  server 127.0.0.1:8080;
  server localhost:8081;
}
server {
  listen 80;
  server_name api.xxx.com;
  location / { 
    root  html;                   #去请求../html 文件夹里的文件
    index  index.html index.htm;  #首页响应地址
  }
  # 用于拦截请求,匹配任何以 /api/开头的地址,
  # 匹配符合以后,停止往下搜索正则。
  location ^~/api/{ 
    # 代表重写拦截进来的请求,并且只能对域名后边的除去传递的参数外的字符串起作用,
    # 例如 www.a.com/proxy/api/msg?meth=1&par=2 重写,只对/proxy/api/msg 重写。
    # rewrite 后面的参数是一个简单的正则 ^/api/(.*)$,
    # $1 代表正则中的第一个(),$2 代表第二个() 的值,以此类推。
    rewrite ^/api/(.*)$ /$1 break;
    
    # 把请求代理到其他主机 
    # 其中 http://www.b.com/ 写法和 http://www.b.com 写法的区别如下
    # 如果你的请求地址是他 http://server/html/test.jsp
    # 配置一: http://www.b.com/ 后面有“/” 
    #         将反向代理成 http://www.b.com/html/test.jsp 访问
    # 配置一: http://www.b.com 后面没有有“/” 
    #         将反向代理成 http://www.b.com/test.jsp 访问
    proxy_pass http://test;

    # 如果 proxy_pass  URL 是 http://a.xx.com/platform/ 这种情况
    # proxy_cookie_path 应该设置成 /platform/ / (注意两个斜杠之间有空格)。
    proxy_cookie_path /platfrom/ /;

    # http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass_header
    # 设置 Cookie 头通过
    proxy_pass_header Set-Cookie;
  } 
}

10.2 跳转到带 www 的域上面

server {
    listen 80;
    # 配置正常的带 www 的域名
    server_name www.wangchujiang.com;
    root /home/www/wabg/download;
    location / {
        try_files $uri $uri/ /index.html =404;
    }
}
server {
    # 这个要放到下面,
    # 将不带 www 的 wangchujiang.com 永久性重定向到  https://www.wangchujiang.com
    server_name wangchujiang.com;
    rewrite ^(.*) https://www.wangchujiang.com$1 permanent;
}

10.3 代理转发

upstream server-api{
    # api 代理服务地址
    server 127.0.0.1:3110;    
}
upstream server-resource{
    # 静态资源 代理服务地址
    server 127.0.0.1:3120;
}
server {
    listen       3111;
    server_name  localhost;      # 这里指定域名
    root /home/www/server-statics;
    # 匹配 api 路由的反向代理到 API 服务
    location ^~/api/ {
        rewrite ^/(.*)$ /$1 break;
        proxy_pass http://server-api;
    }
    # 假设这里验证码也在 API 服务中
    location ^~/captcha {
        rewrite ^/(.*)$ /$1 break;
        proxy_pass http://server-api;
    }
    # 假设你的图片资源全部在另外一个服务上面
    location ^~/img/ {
        rewrite ^/(.*)$ /$1 break;
        proxy_pass http://server-resource;
    }
    # 路由在前端,后端没有真实路由,在路由不存在的 404 状态的页面返回 /index.html
    # 这个方式使用场景,你在写 React 或者 Vue 项目的时候,没有真实路由
    location / {
        try_files $uri $uri/ /index.html =404;
        #                               ^ 空格很重要
    }
}

10.4 代理转发连接替换

location ^~/api/upload {
    rewrite ^/(.*)$ /wfs/v1/upload break;
    proxy_pass http://wfs-api;
}

10.5 ssl 配置

超文本传输安全协议(缩写:HTTPS,英语:Hypertext Transfer Protocol Secure)是超文本传输协议和 SSL/TLS 的组合,用以提供加密通讯及对网络服务器身份的鉴定。HTTPS 连接经常被用于万维网上的交易支付和企业信息系统中敏感信息的传输。HTTPS 不应与在 RFC 2660 中定义的安全超文本传输协议(S-HTTP)相混。HTTPS 目前已经是所有注重隐私和安全的网站的首选,随着技术的不断发展,HTTPS 网站已不再是大型网站的专利,所有普通的个人站长和博客均可以自己动手搭建一个安全的加密的网站。

创建 SSL 证书,如果你购买的证书,就可以直接下载

sudo mkdir /etc/nginx/ssl
# 创建了有效期 100 年,加密强度为 RSA2048 的 SSL 密钥 key 和 X509 证书文件。
sudo openssl req -x509 -nodes -days 36500 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt
# 上面命令,会有下面需要填写内容
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:New York
Locality Name (eg, city) []:New York City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Bouncy Castles, Inc.
Organizational Unit Name (eg, section) []:Ministry of Water Slides
Common Name (e.g. server FQDN or YOUR name) []:your_domain.com
Email Address []:admin@your_domain.com

创建自签证书

首先,创建证书和私钥的目录
# mkdir -p /etc/nginx/cert
# cd /etc/nginx/cert
创建服务器私钥,命令会让你输入一个口令:
# openssl genrsa -des3 -out nginx.key 2048
创建签名请求的证书(CSR):
# openssl req -new -key nginx.key -out nginx.csr
在加载 SSL 支持的 Nginx 并使用上述私钥时除去必须的口令:
# cp nginx.key nginx.key.org
# openssl rsa -in nginx.key.org -out nginx.key
最后标记证书使用上述私钥和 CSR:
# openssl x509 -req -days 365 -in nginx.csr -signkey nginx.key -out nginx.crt

查看目前 nginx 编译选项

sbin/nginx -V

输出下面内容

nginx version: nginx/1.7.8
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx-1.7.8 --with-http_ssl_module --with-http_spdy_module --with-http_stub_status_module --with-pcre

如果依赖的模块不存在,可以进入安装目录,输入下面命令重新编译安装。

./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module

运行完成之后还需要 make (不用 make install)

# 备份 nginx 的二进制文件
cp -rf /usr/local/nginx/sbin/nginx  /usr/local/nginx/sbin/nginx.bak
# 覆盖 nginx 的二进制文件
cp -rf objs/nginx   /usr/local/nginx/sbin/

HTTPS server

server {
    listen       443 ssl;
    server_name  localhost;

    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;
    # 禁止在 header 中出现服务器版本,防止黑客利用版本漏洞攻击
    server_tokens off;
    # 设置 ssl/tls 会话缓存的类型和大小。如果设置了这个参数一般是 shared,buildin 可能会参数内存碎片,默认是 none,和 off 差不多,停用缓存。如 shared:SSL:10m 表示我所有的 nginx 工作进程共享 ssl 会话缓存,官网介绍说 1M 可以存放约 4000 个 sessions。 
    ssl_session_cache    shared:SSL:1m; 

    # 客户端可以重用会话缓存中 ssl 参数的过期时间,内网系统默认 5 分钟太短了,可以设成 30m 即 30 分钟甚至 4h。
    ssl_session_timeout  5m; 

    # 选择加密套件,不同的浏览器所支持的套件(和顺序)可能会不同。
    # 这里指定的是 OpenSSL 库能够识别的写法,你可以通过 openssl -v cipher 'RC4:HIGH:!aNULL:!MD5'(后面是你所指定的套件加密算法) 来看所支持算法。
    ssl_ciphers  HIGH:!aNULL:!MD5;

    # 设置协商加密算法时,优先使用我们服务端的加密套件,而不是客户端浏览器的加密套件。
    ssl_prefer_server_ciphers  on;

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

10.6 强制将 http 重定向到 https

server {
    listen       80;
    server_name  example.com;
    rewrite ^ https://$http_host$request_uri? permanent;    # 强制将 http 重定向到 https
    # 在错误页面和“服务器”响应头字段中启用或禁用发射 nginx 版本。 防止黑客利用版本漏洞攻击
    server_tokens off;
}

10.7 两个虚拟主机

纯静态 -html 支持

http {
    server {
        listen          80;
        server_name     www.domain1.com;
        access_log      logs/domain1.access.log main;
        location / {
            index index.html;
            root  /var/www/domain1.com/htdocs;
        }
    }
    server {
        listen          80;
        server_name     www.domain2.com;
        access_log      logs/domain2.access.log main;
        location / {
            index index.html;
            root  /var/www/domain2.com/htdocs;
        }
    }
}

10.8 虚拟主机标准配置

http {
  server {
    listen          80 default;
    server_name     _ *;
    access_log      logs/default.access.log main;
    location / {
       index index.html;
       root  /var/www/default/htdocs;
    }
  }
}

10.9 防盗链

location ~* \.(gif|jpg|png|swf|flv)$ {
   root html
   valid_referers none blocked *.nginxcn.com;
   if ($invalid_referer) {
     rewrite ^/ www.nginx.cn
     #return 404;
   }
}

10.10 虚拟目录配置

alias 指定的目录是准确的,root 是指定目录的上级目录,并且该上级目录要含有 location 指定名称的同名目录。

location /img/ {
    alias /var/www/image/;
}
# 访问/img/目录里面的文件时,ningx 会自动去/var/www/image/目录找文件
location /img/ {
    root /var/www/image;
}
# 访问/img/目录下的文件时,nginx 会去/var/www/image/img/目录下找文件。]

10.11 防盗图配置

location ~ \/public\/(css|js|img)\/.*\.(js|css|gif|jpg|jpeg|png|bmp|swf) {
    valid_referers none blocked *.jslite.io;
    if ($invalid_referer) {
        rewrite ^/  https://www.wenjiangs.com/wp-content/uploads/2023/docimg26/1110-3aygbvld5bz.png;
    }
}

10.12 屏蔽.git 等文件

location ~ (.git|.gitattributes|.gitignore|.svn) {
    deny all;
}

域名路径加不加需要都能正常访问

http://wangchujiang.com/api/index.php?a=1&name=wcj
                                  ^ 有后缀

http://wangchujiang.com/api/index?a=1&name=wcj
                                 ^ 没有后缀

nginx rewrite 规则如下:

rewrite ^/(.*)/$ /index.php?/$1 permanent;
if (!-d $request_filename){
        set $rule_1 1$rule_1;
}
if (!-f $request_filename){
        set $rule_1 2$rule_1;
}
if ($rule_1 = "21"){
        rewrite ^/ /index.php last;
}

十一、错误问题

The plain HTTP request was sent to HTTPS port

解决办法, fastcgi_param HTTPS $https if_not_empty 添加这条规则,

server {
    listen 443 ssl; # 注意这条规则
    server_name  my.domain.com;
    
    fastcgi_param HTTPS $https if_not_empty;
    fastcgi_param HTTPS on;

    ssl_certificate /etc/ssl/certs/your.pem;
    ssl_certificate_key /etc/ssl/private/your.key;

    location / {
        # Your config here...
    }
}

十二、精品文章参考

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

[旋木]

暂无简介

0 文章
0 评论
23 人气
更多

推荐作者

有深☉意

文章 0 评论 0

硪扪都還晓

文章 0 评论 0

DS

文章 0 评论 0

我也只是我

文章 0 评论 0

TangBin

文章 0 评论 0

橪书

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文