Nginx | 万字文章助你从入门到实践!

Posted 青年之学

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nginx | 万字文章助你从入门到实践!相关的知识,希望对你有一定的参考价值。

前言

最近在学习Web项目部署的相关内容,前不久基于Ubuntu+Flask+uWSGI+nginx部署了一个使用Python的Flask框架实现的API接口,由于只是返回一个简单的Json数据,没有涉及前端页面等静态资源部署,所以对于Nginx的使用并没有体现出来,在这里就简单介绍下有关Nginx的相关内容。文章篇幅较长,请耐心看完!

文章目录

1.什么是Nginx
2.为什么使用Nginx
3.正向代理和反向代理
4.负载均衡
5.动静分离
6.安装Nginx
7.Nginx常用命令
8.Nginx配置文件
9.配置反向代理
10.配置负载均衡
11.配置动静分离
12.常用技巧配置
13.使用规范建议
14.写在最后
15.参考文档

一、什么是Nginx

Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,最初目的之一也是作为邮件代理服务器,Nginx代码完全用C语言从头写成,其特点是占有内存少,并发能力强。

二、为什么使用Nginx

在传统的Web服务器,每个客户端连接作为一个单独的进程或线程处理,需在切换任务时将CPU切换到新的任务并创建一个新的运行时上下文,消耗额外的内存和CPU时间,当并发请求增加时,服务器响应变慢,从而对性能产生负面影响。

Nginx是开源、高性能、高可靠的 Web 和反向代理服务器

  • 在性能上,Nginx以 事件驱动的方式编写,所以有非常好的性能,其 占用内存少、并发能力强、能支持高达 5w 个并发连接数。
  • 在功能上,Nginx是优秀的 代理服务器和 负载均衡服务器。
  • 在安装配置上,Nginx 安装简单、配置灵活。
  • Nginx 支持热部署, 启动速度特别快,还可以在不间断服务的情况下对软件版本或配置进行升级,即使运行数月也无需重新启动。
  • 最后,Nginx 是 免费的并可以商业化。

Nginx并不可以直接处理php、java,对于大多数使用者来说,Nginx只是一个静态文件服务器或者http请求转发器,它可以把静态文件的请求直接返回静态文件资源,把动态文件的请求转发给后台的处理程序。后台服务,即使没有nginx的情况下也是可以直接访问的。

三、正向代理和反向代理

一般情况下,Web访问过程是由客户端直接发送请求至目标服务器,目标服务器收到请求经处理后返回数据信息。

正向代理

在使用正向代理后,客户端发送请求至代理服务器(需指定代理服务器),然后由代理服务器向目标服务器进行通信并发送请求,经目标服务器处理请求后返回数据信息至代理服务器,再由代理服务器返回至客户端。

Nginx | 万字文章助你从入门到实践!
Nginx正向代理

反向代理

客户端只需要将请求发送到反向代理服务器,由反向代理服务器去选择目标服务器(不需要指定目标服务器),获取数据信息后再返回给客户端。反向代理隐藏了真实的服务器,为服务器收发请求,使真实服务器对客户端不可见。一般在处理跨域请求的时候比较常用。

Nginx | 万字文章助你从入门到实践!
Nginx反向代理

通常,代理对象为客户端的是正向代理,代理对象为服务器的是反向代理。
无论正向代理还是反向代理,都能加快客户端的访问速度,因为nginx服务器是一个高性能的http web服务器,其能够对代理中的数据作缓冲。

四、负载均衡

当网站信息数量不断增加,访问(并发)量非常大,以及系统业务复杂度持续增加,导致网站运行越来越慢,造成的服务器性能低下,在这种情况下导致一台服务器不能满足用户需求,于是就出现了服务器集群现象。

服务器集群也就是增加服务器数量,然后将原先请求单个服务器的情况改为将请求分发到多个服务器上。

在使用服务器集群后,将请求分发到各个服务器上,将负载分发到不同的服务器,也就是负载均衡

Nginx | 万字文章助你从入门到实践!
负载均衡

Nginx 实现负载均衡,一般来说指的是将请求转发给服务器集群

实质就是将同一个应用部署在多台服务器上,将大量用户的请求分配给多台机器处理。减少单服务器的运行压力,同时可以提高运行稳定性,一台服务器宕机,只要还有其他服务器正常运行,就不会影响用户使用。

Nginx可以通过反向代理来实现负载均衡。

五、动静分离

所谓动静分离就是将网站动态页面和静态页面分布到不同的服务器来解析,减少服务器压力,主要目的就是加快解析速度。

由于Nginx的高并发和静态资源缓存等特性,经常将静态资源部署在Nginx上。如果请求的是静态资源,直接到静态资源目录获取资源,如果是动态资源的请求,则利用反向代理的原理,把请求转发给对应后台应用去处理,从而实现动静分离。

Nginx | 万字文章助你从入门到实践!
动静分离

六、安装Nginx

Nginx可以使用各平台的默认包来安装:

  • Centos
yum install nginx
  • Ubuntu
sudo apt install nginx

也可以使用源码编译安装,具体安装步骤在这里不再赘述。安装 Nginx后,在命令行中nginx -v 就可以看到具体的 Nginx 版本信息代表安装成功。

七、Nginx常用命令

Nginx 仅有几个命令行参数,其使用完全通过配置文件来配置,Nginx 的命令在控制台中输入nginx -h就可以看到完整的命令,这里列举几个常用的命令:

查看启动进程:ps -ef | grep nginx
# 启动Nginx
sudo /usr/local/nginx/nginx     # (nginx二进制文件绝对路径,可以根据自己安装路径实际决定)
# nginx从容停止命令,等所有请求结束后关闭服务
ps -ef |grep nginx
kill -QUIT  nginx主进程号
# nginx 快速停止命令,立刻关闭nginx进程
ps -ef |grep nginx
kill -TERM nginx主进程号 
# 如果以上命令不管用,可以强制停止
kill -9 nginx主进程号

nginx -s reload  #重新加载nginx配置
nginx -s reopen  #重启nginx
nginx -s stop    #停止nginx
nginx -s quit    #退出nginx
nginx -?,-h           # 打开帮助信息
nginx -v              # 显示版本信息并退出
nginx -V              # 显示版本和配置选项信息,然后退出
nginx -t              # 检测配置文件是否有语法错误,然后退出
nginx -q              # 在检测配置文件期间屏蔽非错误信息
nginx -p prefix       # 设置前缀路径(默认是:/usr/local/Cellar/nginx/1.2.6/)

nginx -c filename     # 设置配置文件(默认是:/usr/local/etc/nginx/nginx.conf)

nginx -g directives   # 设置配置文件外的全局指令

systemctl 是 Linux 系统应用管理工具 systemd 的主命令,用于管理系统,我们也可以用它来对 Nginx 进行管理,相关命令如下:

systemctl start nginx   # 启动Nginx
systemctl stop nginx   # 停止Nginx
systemctl restart nginx   # 重启Nginx
systemctl reload nginx   #重新加载Nginx,用于修改配置后
systemctl enable nginx   #设置开机启动Nginx
systemctl disable nginx   #禁止开机启动Nginx
systemctl status nginx  #查看Nginx运行状态

八、Nginx配置文件

正如前面所说,Nginx的使用完全通过配置文件来配置,所以掌握其配置文件就显得尤为重要。
在详细介绍配置文件之前,首先了解一下配置文件的语法规则:

  • 每条指令以 ; 分号结尾,指令与参数间以 空格符号分隔;
  • 指令块以 {} 大括号将多条指令组织在一起;
  • include 语句允许组合多个配置文件以提升可维护性;
  • 使用 # 符号添加注释,提高可读性;
  • 使用 $ 符号使用变量;
  • 部分指令的参数支持正则表达式;

Nginx 配置文件有三部分组成,即全局块,events块,http块。

Nginx | 万字文章助你从入门到实践!
配置文件结构

全局块

从配置文件开始到events块之间的内容,主要会设置一些影响nginx服务器整体运行的配置指令,主要包括配置运行Nginx服务器的用户(组)、允许生成的 worker process 数,进程 PID 存放路径、日志存放路径和类型以及配置文件的引入等。

events块

这里主要影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多work process下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个work process可以同时支持的最大连接数等。

http块

Nginx服务器配置中最频繁的部分,代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里。http 块也可以包括http全局块、server块,且可以包括多个server块,而每个server块就相当于一个虚拟主机。

  • http全局块
    http全局块配置的指令包括文件引入、MIME-TYPE 定义、日志自定义、连接超时时间、单链接请求数上限等。
  • server 块
    这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了 节省互联网服务器硬件成本。

每个 server 块也分为全局 server 块,以及可以同时包含多个 locaton 块。

  • 全局 server 块 最常见的配置是本虚拟机主机的监听配置和本虚拟主机的名称或IP配置。
  • location 块 location有两种格式:匹配uri类型,有四种参数可选,当然也可以不带参数。命名location,用@来标识,类似于定义goto语句块。
location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }

location指令后面符号含义:

  • = 精确匹配路径,用于不含正则表达式的 uri 前,如果匹配成功,不再进行后续的查找;
  • ^~ 用于不含正则表达式的 uri 前,表示如果该符号后面的字符是最佳匹配,采用该规则,不再进行后续的查找;
  • ~ 表示用该符号后面的正则去匹配路径,区分大小写;
  • ~* 表示用该符号后面的正则去匹配路径,不区分大小写。

如果 uri 包含正则表达式,则必须有 ~ 或 ~* 标志。

location匹配顺序

= > ~^ > ~ = ~* >最长前缀匹配 > /

location URI结尾带不带/

一般的处理逻辑是带/表示访问目录,不带/表示访问文件,如果文件不存在也会去匹配目录。

命名location

带有"@"的location是用来定义一个命名的location,这种location不参与请求匹配,一般用在内部定向。例如用在error_page, try_files命令中。它的功能类似于编程中的goto。

Nginx 有一些常用的全局变量,你可以在配置的任何位置使用它们,如下:

Nginx | 万字文章助你从入门到实践!
全局变量

Nginx基本配置:

user  nginx;                        # 运行用户,可以不进行设置
worker_processes  1;                # Nginx 进程数,一般设置为和CPU核数一样
error_log  /var/log/nginx/error.log warn;   # Nginx 的错误日志存放目录
pid        /var/run/nginx.pid;      # Nginx 服务启动时的 pid 存放位置
#全局错误日志及PID文件
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#工作模式及连接数上限
events {
  #epoll是多路复用IO(I/O Multiplexing)中的一种方式,
  #仅用于linux2.6以上内核,可以大大提高nginx的性能
   use epoll;
   worker_connections 1024;   # 每个进程允许最大并发数
   # 并发总数是 worker_processes 和 worker_connections 的乘积
   # 即 max_clients = worker_processes * worker_connections
   # 在设置了反向代理的情况下,max_clients = worker_processes * worker_connections / 4
}

http {   # 配置使用最频繁的部分,代理、缓存、日志定义等绝大多数功能和第三方模块的配置都在这里设置
   # 设置日志模式
   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  /var/log/nginx/access.log  main;   # Nginx访问日志存放位置

   sendfile            on;   # 开启高效传输模式
   tcp_nopush          on;   # 减少网络报文段的数量
   tcp_nodelay         on;
   keepalive_timeout   65;   # 保持连接的时间,也叫超时时间,单位秒
   types_hash_max_size 2048;

   include             /etc/nginx/mime.types;      # 文件扩展名与类型映射表
   default_type        application/octet-stream;   # 默认文件类型

   include /etc/nginx/conf.d/*.conf;   # 加载子配置项
   
   server {
    listen       80;       # 配置监听的端口
    server_name  localhost;    # 配置的域名
    
    location / {
    root   /usr/share/nginx/html;  # 网站根目录
    index  index.html index.htm;   # 默认首页文件
    deny 192.168.17.11;   # 禁止访问的ip地址,可以为all
    allow 192.168.23.44;# 允许访问的ip地址,可以为all
    }
    
    error_page 500 502 503 504 /50x.html;  # 默认50x对应的访问页面
    error_page 400 404 error.html;   # 默认40x对应的访问页面
      #静态文件,nginx自己处理
        location ~ ^/(images|javascript|js|css|flash|media|static)/ {
            
            #过期30天,静态文件不怎么更新,过期可以设大一点,
            #如果频繁更新,则可以设置得小一点。
            expires 30d;
        }
 
        #PHP 脚本请求全部转发到 FastCGI处理. 使用FastCGI默认配置.
        location ~ .php$ {
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include fastcgi_params;
        }
 
        #禁止访问 .htxxx 文件
            location ~ /.ht {
            deny all;
        }
   }
}

九、配置反向代理

nginx反向代理不需要编译额外的模块,默认自带proxy_pass和fastcgi_pass指令,通过在location配置块中增加指令就可以实现反向代理功能。

server {
    listen 80;
    server_name www.nginx.cn nginx.cn; # 你的网站IP

    location /app {
       proxy_pass http://127.0.0.1:8080;
    }
}

fastcgi_pass是用来反向代理fastcgi协议,proxy_pass可以代理包括fastcgi协议在内的其它协议。

反向代理还有一些其他的指令,可以了解一下:

            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;
 
            #nginx跟后端服务器连接超时时间(代理连接超时)
            proxy_connect_timeout 90;
 
            #连接成功后,后端服务器响应时间(代理接收超时)
            proxy_read_timeout 90;
 
            #设置代理服务器(nginx)保存用户头信息的缓冲区大小
            proxy_buffer_size 4k;
 
            #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
            proxy_buffers 4 32k;
 
            #高负荷下缓冲大小(proxy_buffers*2)
            proxy_busy_buffers_size 64k; 
 
            #设定缓存文件夹大小,大于这个值,将从upstream服务器传
            proxy_temp_file_write_size 64k;

十、配置负载均衡

负载均衡主要思想就是把负载均匀合理地分发到多个服务器上,实现压力分流的目的。

#设定http服务器,利用它的反向代理功能提供负载均衡支持
http {

    #设定mime类型,类型由mime.type文件定义
    include             /etc/nginx/mime.types;
    default_type    application/octet-stream;

    #设定日志格式
    access_log        /var/log/nginx/access.log;

    #省略上文有的一些配置节点
    #。。。。。。。。。。

    #设定负载均衡的服务器列表
    upstream mysvr {
        #weigth参数表示权值,权值越高被分配到的几率越大
        server 192.168.8.1x:3128 weight=5;
        #本机上的Squid开启3128端口,不是必须要squid
        server 192.168.8.2x:80    weight=1;
        server 192.168.8.3x:80    weight=6;
    }
        
    upstream mysvr2 {
        #weigth参数表示权值,权值越高被分配到的几率越大
        server 192.168.8.x:80    weight=1;
        server 192.168.8.x:80    weight=6;
    }

    #第一个虚拟服务器
    server {
        #侦听192.168.8.x的80端口
        listen             80;
        server_name    192.168.8.x;

        #对aspx后缀的进行负载均衡请求
        location ~ .*.aspx$ {
            #定义服务器的默认网站根目录位置
            root     /root; 
            #定义首页索引文件的名称
            index index.php index.html index.htm;
            
            #请求转向mysvr 定义的服务器列表
            proxy_pass    http://mysvr ;   

        }
    }
}

Nginx 提供了好几种分配方式,默认为轮询。有以下几种分配方式:

  • 轮询,默认方式,每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务挂了,能自动剔除;

  • weight,权重分配,指定轮询几率,权重越高,在被访问的概率越大,用于后端服务器性能不均的情况;

  • ip_hash,每个请求按访问 IP 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决动态网页 session 共享问题。负载均衡每次请求都会重新定位到服务器集群中的某一个,那么已经登录某一个服务器的用户再重新定位到另一个服务器,其登录信息将会丢失,这样显然是不妥的;

  • fair(第三方),按后端服务器的响应时间分配,响应时间短的优先分配,依赖第三方插件 nginx-upstream-fair,需要先安装;

十一、配置动静分离

实现动静分离方式主要有两种,一种是纯粹把静态文件独立成单独的域名,放在独立的服务器上。另外一种方法就是动态跟静态文件混合在一起发布,通过 Nginx 配置来分开。

server {
        listen       80;
        server_name  https://yjs0612.gitee.io/;
        location / {
            root   html;
            index  index.html index.htm;
            proxy_set_header Host $host;
            proxy_pass https://yjs0612.gitee.io/;
        }
        location /image/ {
            proxy_set_header Host $host;
        proxy_pass https://****/;
        }
        location /dynamic/ {
            proxy_set_header Host $host;
        proxy_pass https://****/;
        }
    }

十二、常用技巧配置

静态服务

server {
 listen       80;
 server_name  static.sherlocked93.club;
 charset utf-8;    # 防止中文文件名乱码

 location /download {
   alias          /usr/share/nginx/html/static;  # 静态资源目录
   
   autoindex               on;    # 开启静态资源列目录
   autoindex_exact_size    off;   # on(默认)显示文件的确切大小,单位是byte;off显示文件大概大小,单位KB、MB、GB
   autoindex_localtime     off;   # off(默认)时显示的文件时间为GMT时间;on显示的文件时间为服务器时间
 }
}

图片防盗链

server {
 listen       80;
 server_name  *.sherlocked93.club;
 
 # 图片防盗链
 location ~* \.(gif|jpg|jpeg|png|bmp|swf)$ {
   valid_referers none blocked 192.168.0.2;  # 只允许本机 IP 外链引用
   if ($invalid_referer){
     return 403;
   }
 }
}

请求过滤

# 非指定请求全返回 403
if ( $request_method !~ ^(GET|POST|HEAD)$ ) {
 return 403;
}

location / {
 # IP访问限制(只允许IP是 192.168.0.2 机器访问)
 allow 192.168.0.2;
 deny all;
 
 root   html;
 index  index.html index.htm;
}

配置图片等静态文件缓存

由于图片、字体、音频、视频等静态文件在打包的时候通常会增加了 hash,所以缓存可以设置的长一点,先设置强制缓存,再设置协商缓存;如果存在没有 hash 值的静态文件,建议不设置强制缓存,仅通过协商缓存判断是否需要使用缓存。

# 图片缓存时间设置
location ~ .*\.(css|js|jpg|png|gif|swf|woff|woff2|eot|svg|ttf|otf|mp3|m4a|aac|txt)$ {
expires 10d;
}

# 如果不希望缓存
expires -1;

十三、使用规范建议

  • 为了使 Nginx 配置更易于维护,建议为每个服务创建一个单独的配置文件,存储在 /etc/nginx/conf.d 目录,根据需求可以创建任意多个独立的配置文件。
  • 独立的配置文件,建议遵循以下命名约定 <服务>.conf,比如域名是 imyjs.xyz,那么你的配置文件的应该是这样的 /etc/nginx/conf.d/imyjs.xyz.conf,如果部署多个服务,也可以在文件名中加上Nginx转发的端口号
  • 常用的、复用频率比较高的配置可以放到 /etc/nginx/snippets 文件夹,在 Nginx 的配置文件中需要用到的位置 include 进去,以功能来命名,并在每个 snippet 配置文件的开头注释标明主要功能和引入位置,方便管理。

十四、写在最后

首先感谢你的阅读,,希望这篇文章对你有所帮助!
由于自己最近在做一些WEB项目的开发部署练习与学习,在实践过程中,很难避免与Nginx打交道,于是就简单的学习了一下Nginx的基础相关知识,在网上此类文章较多,学习起来较为杂乱,于是自己就在学习的过程中,记录了一下相关内容。对于文章内容为Nginx较为常用、简单的技术手段,文章内容大多为个人学习参考相关文档得出的个人见解,若有疑问或错误,欢迎指正提出。

了解掌握更多Nginx相关技术,可以移步Nginx中文文档、Nginx中文手册。

文章整理不易,转载请注明来源:微信公众平台青年之学

推荐关注:青年之学
我的博客:https://yjs0612.gitee.io/
我的站点:http://dh.imyjs.xyz/

十五、参考文档

1.Nginx中文文档
2.Nginx中文手册
3.妙味课堂 Nginx 从入门到实践

Nginx | 万字文章助你从入门到实践!

  掌握更多技术,请扫码关注我~
点击下方“在看”,给我鼓励

以上是关于Nginx | 万字文章助你从入门到实践!的主要内容,如果未能解决你的问题,请参考以下文章

万字长文助你上手软件领域驱动设计 DDD

还不会Git吗?近万字总结,让你从入门到精通!

五本书籍助你从零基础学习java编程到精通之路

深度2万字好文:图像处理-基于 PyTorch 的 YOLO v5 表情识别(附源代码)

万字长文:SpringCloud gateway入门学习&实践

MySQL 从入门到实践,万字详解!