Featured image of post Nginx初识与实战

Nginx初识与实战

简单叙述下nginx功能,并以我日常开发接触到的使用为例进行讲解

什么是Nginx

Nginx最初被创建为一个用于解决C10k问题的Web服务器。作为一个Web服务器,它可以以极快的速度提供数据。但是,Nginx远不止于一个Web服务器。可以将其用作反向代理,与较慢的上游服务器(如Unicorn或Puma)轻松集成。您可以适当地分发流量(负载均衡),流式传输媒体,实时调整图像大小,缓存内容等等。

作为Web服务器

因为这部分不是今天的重点,所以只会简略的介绍一下,反向代理才是本文章的重点

提供静态资源的服务

web服务器很重要的一点就是提供静态资源的服务(比如图片或html文件),Nginx当然也提供了这项功能。通过配置Nginx,我们可以指定要提供的静态文件的位置,并定义对这些文件的访问权限。Nginx具有出色的并发处理能力,能够同时处理大量的并发请求。这使得它成为处理高负载和大流量的理想选择。

Nginx的静态资源服务不仅仅是简单地传输文件。它还支持内容压缩和范围请求,以提高传输效率和节省带宽。此外,Nginx可以实现静态文件的缓存,减轻后端服务器的负担,并提供更快的响应时间。

提供动态资源的服务(Todo)

作为动态资源服务器,Nginx能够处理和传输动态生成的内容,如动态网页、API响应和数据库查询结果等。

通过与后端应用服务器(如Unicorn、Puma或Node.js)的集成,Nginx可以作为反向代理服务器,将请求转发到后端应用服务器进行处理。这种架构可以提高应用程序的性能和可靠性,同时减轻后端服务器的负载。

Nginx具有出色的并发处理能力和高性能,能够同时处理大量的并发请求。它采用事件驱动的异步处理模型,有效地减少了资源消耗并提高了吞吐量。

作为反向代理

Nginx反向代理的使用 反向代理是一种网络架构模式,通过代理服务器接收客户端请求,并将请求转发到后端服务器进行处理,然后将响应返回给客户端。 Nginx的反向代理功能具有以下优点:

  • 隐藏后端服务器细节:Nginx作为反向代理服务器,客户端只与Nginx进行通信,而不直接与后端服务器交互。这样可以隐藏后端服务器的细节和拓扑结构,提高系统的安全性和隐私保护。

  • 负载均衡:Nginx可以将客户端请求平均分配到多个后端服务器上,实现负载均衡。通过合理分配请求,Nginx可以避免某个服务器过载,确保每个服务器的负载相对均衡,提高系统的可用性和性能。

  • 高可靠性和容错性:当某个后端服务器发生故障或不可用时,Nginx可以自动将请求转发到其他可用的服务器,实现故障转移和容错。这样可以保证系统的稳定性和可靠性,避免单点故障对整个系统的影响。

  • 缓存功能:Nginx可以缓存后端服务器的响应,将其存储在内存中或磁盘上,以便在后续相同的请求中快速返回响应。这可以减轻后端服务器的负载,并提高系统的响应速度和吞吐量。

  • SSL终端:Nginx可以作为SSL终端,负责处理客户端与服务器之间的安全连接。它可以处理SSL/TLS握手、证书验证和安全加密,提供安全的通信通道

为什么要用Nginx

在传统的Web项目中,并发量小,用户使用的少。 所以在低并发的情况下,用户可以直接访问tomcat服务器,然后tomcat服务器返回消息给用户。 用户访问<-->Tomcat服务器 而在互联网项目下,因单个tomcat默认并发量有限制。如果请求量过大,会产生如下问题:

  • Tomcat的默认配置的最大请求数为150,也就是说同一时间超过150个请求进行访问就会导致部分请求无法获取到数据

而Nginx由于出色的并发连接处理能力,静态资源的缓存机制以及具有负载均衡的功能,可以改善Tomcat并发限制带来的问题,提高系统的可用性和性能,同时减轻Tomcat的负载压力。这样可以更好地应对高并发的请求量,确保项目的顺利运行。

如何使用Nginx

配置文件的整体架构与解释

下图是debian官网下给出的nginx配置的目录文件 debian官网下给出的nginx配置的目录文件 由于今天我们主要讲解Nginx作为反向代理的使用,所以此处我们只需要关注./conf.d/*.conf ./nginx.conf ./sites-available/* ./sites-enabled/*即可


/etc/nginx/nginx.conf

该文件是由Nginx的维护者管理的,所以应该尽量避免在该文件里进行修改


/etc/nginx/conf.d/.conf*

默认的nginx.conf文件在http块(稍后会介绍)里会有数行专门用来引入其他的配置文件,类似于这样

http {
     include /etc/nginx/conf.d/*.conf;
}

./sites-available/ & ./sites-enabled/*

一般来说如果我们在服务器上想运行一个被nginx管理的网站,我们就会在./sites-available/该目录下建一个mywebsite这样的配置文件,并通过在nginx.conf里添加一行

include /etc/nginx/./sites-available/mywebsite

来使其生效

至于后者(sites-enabled)之所以存在是因为Apache 的一般配置约定。在 Apache 中,常见的配置约定是将潜在的网站配置文件存放在 /sites-available 目录中,而启用的网站则通过在 /sites-enabled 目录中创建符号链接指向 sites-available 目录中的配置文件来实现。如此一来Nginx只会读取显示的创建过链接的sites-available目录下的配置文件,但该约定过于繁琐,且对于大多数个人开发者并无必要,所以不推荐

单个配置文件的构造与解释

nginx 由配置文件中指定的指令控制的模块组成。

指令的类型

指令分为简单指令和块指令。


简单指令由名称和参数组成,名称和参数之间用空格分隔,并以分号结尾。

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;

块指令的结构与简单指令,但它不是以分号结尾,而是以一组由大括号({和})包围的附加指令结尾。如果块指令可以在大括号内包含其他指令,则称为上下文(例如:events、http、server 和 location) 。

http {              # http context
    gzip on;        # directive in http context

  server {          # server context
    listen 80;      # directive in server context
  }
}

简单指令的类型

  • Normal -> 每个上下文都有一个值。而且,它只能在上下文中定义一次。子上下文可以覆盖父指令,但此覆盖仅在给定的子上下文中有效。
gzip on;
gzip off; # illegal to have 2 normal directives in same context

server {
  location /downloads {
    gzip off;
  }
}
  • Array -> 在同一上下文中添加多个指令将添加值,而不是完全覆盖它们。在子上下文中定义指令将覆盖给定子上下文中的所有父值。
error_log /var/log/nginx/error.log;
error_log /var/log/nginx/error_notive.log notice;
error_log /var/log/nginx/error_debug.log debug;

server {
  location /downloads {
    # this will override all the parent directives
    error_log /var/log/nginx/error_downloads.log;
  }
}
  • Action directive - > Actions are directives that change things. Their inheritance behaviour will depend on the module.
server {
  rewrite ^ /foobar; # This line will rewrite the request to start
                     # with `/foobar` and then match the location below

  location /foobar {
  }
}

常见上下文(context)的作用

  • events

该部分是用来设置Nginx对于请求的总体的处理方式,作用范围是全局,因此一个配置文件只能有一个events 上下文(多个文件也只能有一个)

  • http

就像这个名字一样,http 上下文是关于服务器如何处理http(s)的请求。 也是一个配置文件只能有一个http上下文

  • server

server上下文一般是嵌套在http上下文中,用来配置单个主机内的特定虚拟服务器。嵌套在 http 上下文中的有效配置文件中可以有多个server上下文。每个server上下文都被视为一个虚拟主机。

注:上面提到的虚拟服务器是对一个服务器内部运行的占用某个特定接口的服务的抽象 举个例子,你可能会在服务器上有一个py的服务,一个java的服务,他们肯定位于服务器内部不同的位置,但对于他们的访问都要从服务器入口通过。因此有了这层抽象就可以认为服务器提供了两个虚拟服务器。(更进一步的知识可以去学下计算机网络)

nginx.conf的默认设置

以下是nginx安装后nginx.conf的默认配置

events {
        worker_connections 768;
        # multi_accept on;
}

http {

        ##
        # Basic Settings
        ##

        sendfile on;
        tcp_nopush on;
        types_hash_max_size 2048;
        # server_tokens off;

        # server_names_hash_bucket_size 64;
        # server_name_in_redirect off;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # SSL Settings
        ##

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        ##
        # Gzip Settings
        ##

        gzip on;

        # gzip_vary on;
        # gzip_proxied any;
        # gzip_comp_level 6;
        # gzip_buffers 16 8k;
        # gzip_http_version 1.1;
        # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

        ##
        # Virtual Host Configs
        ##

        include /etc/nginx/conf.d/*.conf;
}

可以看到该文件定义了 Nginx 的基本设置,包括文件传输、TCP 优化、SSL/TLS 设置、日志记录、压缩等功能。还通过 include 指令引入其他配置文件。

这些都是些较为底层的设置,如果我们想通过nginx来进行负载均衡反向代理还需要我们自己在其他地方配置,比如conf.d目录。

以nginx提供的default配置学习下反向代理

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        # SSL configuration
        #
        # listen 443 ssl default_server;
        # listen [::]:443 ssl default_server;
        #
        # Note: You should disable gzip for SSL traffic.
        # See: https://bugs.debian.org/773332
        #
        # Read up on ssl_ciphers to ensure a secure configuration.
        # See: https://bugs.debian.org/765782
        #
        # Self signed certs generated by the ssl-cert package
        # Don't use them in a production server!
        #
        # include snippets/snakeoil.conf;

        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        server_name _;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }

        # pass PHP scripts to FastCGI server
        #
        #location ~ \.php$ {
        #       include snippets/fastcgi-php.conf;
        #
        #       # With php-fpm (or other unix sockets):
        #       fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        #       # With php-cgi (or other tcp sockets):
        #       fastcgi_pass 127.0.0.1:9000;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #       deny all;
        #}
}

# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
#       listen 80;
#       listen [::]:80;
#
#       server_name example.com;
#
#       root /var/www/example.com;
#       index index.html;
#
#       location / {
#               try_files $uri $uri/ =404;
#       }
#}

注意,一个server context有以下组成部分

  • listen 这个表示该虚拟服务器的服务来源是正在监听的这个端口
  • server_name 可以简单的把这个当作域名,nginx会将请求中含有该name的转发到这个虚拟服务器
  • root 将进来的请求的根目录设为指定的目录,方便后续根据路径来查找/匹配资源
  • location location 指令根据请求的 URI来进行匹配,从而完成进一步的配置
  • try-files 查找该指令的参数是否存在,如果存在则返回

以default配置文件的第二个server context为例

首先创建了一个服务来源是80端口的虚拟服务器,会对域名为example.com的请求进行接受,其根目录为服务器的/var/www/example.com路径,如果请求中只包含协议和域名,则会返回index.html。如果请求中还有进一步的参数,则会进入到Loation块进行匹配,此处的匹配是匹配所有的请求,具体是尝试根据uri去寻找服务器相应路径下的资源,如果找不到则返回404

Nginx实战

Built with Hugo
Theme Stack designed by Jimmy