Nginx 运维入门

2,471 阅读8分钟

一、Nginx 概述

Nginx 专为 性能优化而开发,其最知名的优点是它的稳定性和低系统资源消耗,以及对并发连接的高处理能力(单台物理服务器可支持 30000-50000 个并发连接,tomcat 通常是几百,不超过 1000 个), 是一个高性能的 HTTP 和反向代理服务器,也是一个IMAP/POP3/SMTP 代理服务器。

集群的架构通常可以解决几万的连接。

注意:c10k问题,是指10000个客户端(client)同时访问服务器,即高并发连接服务器的问题。

关于Nginx服务器,除了其高效性和稳定性的优点之外,我们最常使用的主要是 其反向代理和负载均衡,以及动静分离功能。

二、Nginx功能

2.1 Nginx 正向代理

通常,我们可以通过 ip 地址来直接访问网络中的某台确定的主机(更确切的说应该是通过 socket 套接字来访问确定中的某个确定的进程)。正向代理的代理服务器,是用户主动设置的,在我们的浏览器里面配置代理服务器,通过代理服务器进行互联网的访问。

img

img

假设服务器B,能够将客户端的请求转发给服务器A,同时服务器B又能够将服务器A的响应转发给客户端,那么显而易见,我们就可以通过访问服务器B,从而达到访问服务器A的目的。

类似于 等保里面的堡垒机,提供堡垒机访问其他服务器。

如下图,客户端访问服务器 A 的过程,客户端通过服务器 B 同样达到了 访问服务器 A 的目的,但是,请注意此时:服务器 B 似乎是作为客户端访问服务器 A 的一个媒介。

img

正向代理的用途:

  • 访问原来无法访问的资源,如 google
  • 可以做缓存,加速访问资源
  • 对客户端访问授权,上网进行认证
  • 代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息

2.2 Nginx 反向代理

与正向代理服务器不同,反向代理服务器的作用,不仅仅是充当能够访问到目标服务器的 “媒介”。反向代理服务器,是服务器端设置的,不是用户,客户端对是否代理是没有感知的,由反向代理选择目标服务器

反向代理是在服务器端(如Web 服务器)作为代理使用,而不是客户端。客户端通过正向代理可以访问不同的资源,而反向代理是很多客户端都通过它访问不同后端服务器上的资源,而不需要知道这些后端服务器的存在,而以为所有资源都来自这个反向代理服务器。

也就是说,用户请求目标服务器,由代理服务器决定访问哪个 IP ,这个时候是代理服务器去决定访问那个节点。

img

Nginx可以承担 “反向代理”的功能,服务器A和B可以是两个Tocmat服务器。

反向代理的作用:

  • 1、保证内网的安全,阻止 web 攻击,大型网站,通常将反向代理作为公网访问地址,web 服务器是内网。
  • 2、负载均衡,通过反向代理服务器来优化网站的负载。

2.3 负载均衡

在上图中,我们可以看到,服务器 A、B 之间的功能完全相同,可以相互替代,通过将原本由一个服务器负责处理的任务,分担给多台服务器的并发压力,同时扩展了服务器的带宽,从而提高了吞吐量----这就是负载均衡。

Nginx 提供的负载均衡有 2种:内置策略 和扩展策略。

内置策略为轮询,加权轮询,IP Hash 。扩展策略,自定义负载均衡策略。

轮询

img

权重轮询:

img

ip Hash

ip hash 对 客户端请求的 IP 进行 hash 操作,然后根据 hash 结果将同一个客户端 ip 的请求分发给同一台服务器进行处理,可以解决 session 不共享的问题。

img

2.4 动静分离

对于一些基本很少发生变化的静态资源,可以直接放在 Nginx 服务器上,当客户端访问这些静态资源时,Nginx 就可以直接访问给客户端,而不用再访问服务器集群,从而节省了部分请求和响应的时间。

这样一来,当客户端访问Nginx服务器时,当客户端访问静态资源时,Nginx就将静态资源直接返回给客户端,当客户端访问的是动态资源的时候,Nginx才会访问集群,就实现了动态资源和静态资源的分离,从而提高了系统的吞吐量。

CDN

Content Delivery Network,即内容分发网络。

CDN是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术。

三、Nginx 原理

具体的安装可以查看我之前的文章。

3.1 nginx 进程模型

image-20210827202552036

在启动 nginx 之后,可以 发现发现有两个进程,一个 master ,一个 work。

这两个进程分别起着怎样的作用呢?

  • master 进程:它是主进程,相当于一个领导者,它不干活,只分发任务。
  • worker 进程:工作进程,相当于 一个工作人,它是替 master 进程去服务i的。

master 进程有且只有一个,而 worker 进程,默认下也只有一个,但是可以在配置文件中去配置 worker 的进程数量。当然,这个值 在nginx.conf 中可以配置,一般配置为 cpu-1 。

#user  nobody;
worker_processes  1;
events {
    worker_connections  1024; // 每个 worker 线程的最大处理线程数。总共打开数 小于 linux的最大打开数量 65535. 
}

总结:

  • master 会把所有的请求信号,分配给 worker 进程去处理。相当于老板在外面接了很多的任务,然后分派给小伙伴去完成。
  • master 会监控 worker,是否正常还是发生了一次退出了,这个时候 master 会重启一个新的 worker 去重新执行任务

image-20210827203604012

3.2 Nginx 的 worker 抢占机制

1、通过配置文件,修改 worker 进程的数量,假设是 3 个。

2、其原理是:master 通过主进程 fork 了三个工作worker进程。这个时候如果有客户端有请求进入 nginx 服务器,三个 worker 进程会通过 accept_mutex 锁,来处理某个客户端的请求,谁占有锁,谁就去处理这个客户端请求。

img

需要注意Nginx 所有worker进程协同工作的关键(共享内存).

3.3 Nginx 的事件处理机制

1、底层的 worker 工作进程,采用的是 Linux 底层操作系统的 io 模式 epoll 来完成处理的。

2、epoll 的io 线程处理模型,采用的是 异步非阻塞的机制来完成线程的处理,所以上面的 client1 如果发生了阻塞,并不会影响 client2 和 client3 的执行。在一般的情况下:nginx 的每个 worker 可以处理 6-8 w的线程处理,所以并发很高。

image-20210827210437573

3.4 nginx.conf 讲解

image-20210827211258018

#user  nobody; // worker 进程工作数
worker_processes  1;
​
​
events {
    // linux 默认使用epoll
    worker_connections  1024; //每个 worker 进程允许最大打开的文件数
}
​
// 针对 http 网络的配置
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;  // 和 sendfile 一起使用,当请求的数据包累计到了一定大小的时候再发送
​
    #keepalive_timeout  0;
    keepalive_timeout  65; // 客户端连接服务器的超时时间,默认65 秒,0 代表不保持连接。
​
    #gzip  on;              // 一定打开,利于文件和请求数据的传输,同时消耗时间。
​
    // 服务虚拟主机配置
    server {
        listen       80; // 监听端口
        server_name  localhost; // 监听服务器 ip、域名、或者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;
    #    }
    #}
​
}

3.5 负载均衡演示

1、轮询(weight=1)

默认选项,当weight不指定时,各服务器weight相同,

每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。

upstream bakend {
    server 192.168.1.10;
    server 192.168.1.11;
}

2、weight 权重

指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。

如果后端服务器down掉,能自动剔除。

比如以下配置,则1.11服务器的访问量为1.10服务器的两倍。

upstream bakend {
server 192.168.1.10 weight=1;
server 192.168.1.11 weight=2;
}

3、ip_hash 哈希

每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session不能跨服务器的问题。

如果后端服务器down掉,要手工down掉。

upstream resinserver{
    ip_hash;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

4、fair(第三方插件)

按后端服务器的响应时间来分配请求,响应时间短的优先分配。

upstream resinserver{
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    fair;
}

5、url_hash(第三方插件)

按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存服务器时比较有效。

在upstream中加入hash语句,hash_method是使用的hash算法。

upstream resinserver{
​
    server 192.168.1.10:8080 ;
    server 192.168.1.11:8080;
    hash $request_uri;
    hash_method crc32;
}