nginx全解析

256 阅读11分钟

“我正在参加「掘金·启航计划」”**nginx是一个Http服务器、反向代理服务器、邮件代理服务器、和通用TCP/UDP代理服务器;**Nginx 是高性能的 HTTP 和反向代理的web服务器,处理高并发能力是十分强大的,能经受高负 载的考验,有报告表明能支持高达 50,000 个并发连接数。

其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好。

Nginx庐山真面目

nginx是一个Http服务器、反向代理服务器、邮件代理服务器、和通用TCP/UDP代理服务器;

首先Nginx是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。其是一款轻量级的web服务器反向代理服务器电子邮件服务器,实际在在设计之初Nginx的产品目的就是为了邮件服务而诞生的,特点是占有内存少、体积小、并发能力强、性能高

Nginx全能真英雄

Nginx的功能

  • 缓存静态文件(html,css,js):实现完全的前后端分离,且它处理静态文件的效率是应用服务器的几倍

  • 反向代理: 当真实服务器不能被直接访问到时,nginx可作为反向代理服务,用于中间做转发

  • web缓存: 可以对不同的文件做不同的缓存处理,配置灵活,并且支持FastCGI_Cache,主要用于对FastCGI的动态程序进行缓存。配合着第三方的ngx_cache_purge,对制定的URL缓存内容可以的进行增删管理

  • 正向代理: 

  • 负载均衡: 更大程度提高服务器的使用效率

  • 邮件代理服务器: 实现轻松扩展邮件服务器的数量、根据不同的规则选择邮件服务器,例如,根据客户的IP地址选择最近的服务器,实现邮件服务器的负载均衡

反向代理

      反向代理是Nginx使用最多的一种场景了,假如我们开发的一个服务请求量较大,一台服务器已经无法承载了,我们需要扩容使用多台服务器,那么这个时候我么就需要加一层中间件来分配用户的请求,把用户的请求下发到不同的服务器,这个时候我们就可以使用Nginx来完成,当然这只是他的一个作用,在了解反向代理之前我们再来说说正向代理,有反必然有正。

      什么是反向代理?

       反向代理服务器位于用户与目标服务器之间,但是对于用户而言,反向代理服务器就相当于目标服务器,即用户直接访问反向代理服务器就可以获得目标服务器的资源。同时,用户不需要知道目标服务器的地址,也无须在用户端作任何设定。反向代理服务器通常可用来作为Web加速,即使用反向代理作为Web服务器的前置机来降低网络和服务器的负载,提高访问效率。

      假设我们是一个用户,在上述场景中,不然增加多少台服务器,我们用户始终访问一个相同的域名,对于用户而言,其做的反向代理对用户是无感知的,这里的代理是Nginx中间件这一层把用户的请求代理到了我们的服务器上,同时他也是在服务端完成的,反向代理的过程,隐藏了真实的客户端。客户端请求的服务都被代理服务器代替来请求。

正向代理

     什么是正向代理?

      正向代理,意思是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端才能使用正向代理。

       正向代理:是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端才能使用正向代理。

       正向代理的典型用途是为在防火墙内的局域网客户端提供访问Internet的途径。正向代理还可以使用缓冲特性(由mod_cache提供)减少网络使用率。

      假设这样一个场景,在我们日常开发中应该经常会使用到vpn吧,公司的一些项目或者私有git或者一些内部的网站,我么需要登录vpn才能访问,其基本原理呢就是一个位于客户端和原始服务器之前的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并且指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端,客户端才能使用正向代理,我们登录vpn之后所有的请求将会通过vpn的这台服务器代理客户去访问某些资源或者网站,那么这台代理服务器将会是公司内部的白名单ip,这样所有的请求都统一从这里进入,就实现了一个正向代理。如此一来呢,正向代理的过程呢就隐藏了真实的客户端,客户端请求的服务都被代理服务器代替来请求。

隐藏服务端口号

       有了自己的一台服务器后,大概率你也会有自己的域名,这个时候,我们假如有多个网站,那么大概率你会去创建自己的二级域名,这个时候我们想要部署多个网站的时候,很可能变成了**192.xx.xx.xx:888[1]、 *192.xx.xx.xx:999[2]这样,假如你是一个前端,还部署了多个Node这样的项目的时候,那么你肯定会遇到这样的问题,我们知道一个服务器,正常每一个端口都是单独的,不能共享【也有特殊场景,比如socketio提供的双工通讯可以让http和ws使用同一个端口】,我们想要通过二级域名去区分不同的服务就需要将其解析到不同的二级域名中,我们知道默认打开一个网站的时候不加端口的情况下、http对应80端口https对应443端口,正常情况下云厂商也都是默认开启这两个端口的,所以我们在使用Nginx的时候,只需要监听80和443端口**,判断访问的域名地址,将其转发到不同的端口下面(具体配置最后放上),那么我们作为一个个人用户,就可以在这种场景下实现不需要加上难看的端口号了,所有的请求都会通过80、443代理到我们真实的服务端口。

       Nginx隐藏转发的端口号。

部署前端项目

       静态web服务器,部署我们前端的项目非常简单,相信很多人如果尝试自己去部署,使用Nginx是十分简单的,下载,安装,运行,指定默认目录,前端项目拖进去就能访问

 负载均衡

      负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。

负载均衡_(Load Balance)_其意思就是分摊到多个操作单元上进行执行,例如Web服务器FTP服务器企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务

       假如我们使用了三台服务器,客户端发送来请求之后我们把请求发给谁呢,总不能虽然有三台服务器,我们都转给其中一台吧,明显很不合理,为了保证我们的性能最大化,负载均衡的意思呢就是会合理的把客户端的请求分配给服务器,我们默认呢就等比例分配,可以理解为1:1:1,但是实际场景中,我们的服务器配置可能不同,可能有好有坏,所以这里有一个权重的概率,可以有我们自己配置哪台服务器多分配请求,哪一台少一点请求,这样的配置可以让服务器的性能得到最大化,合理分配请求将会使系统更为健壮稳固。

Nginx实践出真知

安装

nginx可以使用各平台的默认包来安装,本文是介绍使用源码编译安装,包括具体的编译参数信息。

正式开始前,编译环境gcc g++ 开发库之类的需要提前装好,这里默认你已经装好。

ububtu平台编译环境可以使用以下指令

apt-get install build-essential
apt-get install libtool

一般我们都需要先装pcre, zlib,前者为了重写rewrite,后者为了gzip压缩。

1.选定源码目录
可以是任何目录,本文选定的是/usr/local/src

cd /usr/local/src

2.安装PCRE库
ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/ 下载最新的 PCRE 源码包,使用下面命令下载编译和安装 PCRE 包:

cd /usr/local/src
wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.34.tar.gz 
tar -zxvf pcre-8.34.tar.gz
cd pcre-8.34
./configure
make
make install

3.安装zlib库
zlib.net/zlib-1.2.8.… 下载最新的 zlib 源码包,使用下面命令下载编译和安装 zlib包:

cd /usr/local/src

wget http://zlib.net/zlib-1.2.8.tar.gz
tar -zxvf zlib-1.2.8.tar.gz
cd zlib-1.2.8
./configure
make
make install

4.安装ssl(某些vps默认没装ssl)

cd /usr/local/src
wget http://www.openssl.org/source/openssl-1.0.1c.tar.gz
tar -zxvf openssl-1.0.1c.tar.gz

5.安装nginx

Nginx 一般有两个版本,分别是稳定版和开发版,您可以根据您的目的来选择这两个版本的其中一个,下面是把 Nginx 安装到 /usr/local/nginx 目录下的详细步骤:

cd /usr/local/src
wget http://nginx.org/download/nginx-1.4.2.tar.gz
tar -zxvf nginx-1.4.2.tar.gz
cd nginx-1.4.2

./configure --sbin-path=/usr/local/nginx/nginx \
--conf-path=/usr/local/nginx/nginx.conf \
--pid-path=/usr/local/nginx/nginx.pid \
--with-http_ssl_module \
--with-pcre=/usr/local/src/pcre-8.34 \
--with-zlib=/usr/local/src/zlib-1.2.8 \
--with-openssl=/usr/local/src/openssl-1.0.1c

make
make install

--with-pcre=/usr/src/pcre-8.34 指的是pcre-8.34 的源码路径。
--with-zlib=/usr/src/zlib-1.2.7 指的是zlib-1.2.7 的源码路径。

安装成功后 /usr/local/nginx 目录下如下

fastcgi.conf            koi-win             nginx.conf.default
fastcgi.conf.default    logs                scgi_params
fastcgi_params          mime.types          scgi_params.default
fastcgi_params.default  mime.types.default  uwsgi_params
html                    nginx               uwsgi_params.default
koi-utf                 nginx.conf          win-utf

6.启动
确保系统的 80 端口没被其他程序占用,运行/usr/local/nginx/nginx 命令来启动 Nginx,

netstat -ano|grep 80

如果查不到结果后执行,有结果则忽略此步骤(ubuntu下必须用sudo启动,不然只能在前台运行)

sudo /usr/local/nginx/nginx

打开浏览器访问此机器的 IP,如果浏览器出现 Welcome to nginx! 则表示 Nginx 已经安装并运行成功。

nginx的配置文件地址已经当前的配置文件是否合规可以使用如果你的配置文件有错误,这里也会提示你,那么我们可以cd到配置目录然后看看它的默认配置,我们可以直接open .或者cat nginx.conf都可以查看默认配置,如下,

#user  nobody;worker_processes  1;#error_log  logs/error.log;#error_log  logs/error.log  notice;#error_log  logs/error.log  info;#pid        logs/nginx.pid;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       8080;        server_name  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;        }    }    # 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;    #    }    #}    include servers/*;}

(1)、全局块: 配置影响nginx全局的指令。一般有运行nginx服务器的用户组,nginx进程pid存放路径,日志存放路径,配置文件引入,允许生成worker process数等。

(2)、events块: 配置影响nginx服务器或与用户的网络连接。有每个进程的最大连接数,选取哪种事件驱动模型处理连接请求,是否允许同时接受多个网路连接,开启多个网络连接序列化等

(3)、http块: 可以配置多个server,配置代理、缓存、日志定义等能和第三方模块的配置。如文件引入,mime-type定义,日志自定义,是否使用sendfile传输文件,连接超时时间,单连接请求数等。

(4)、server块: 配置虚拟主机的相关参数,一个http中可以有多个server。

(5)、location块: 配置请求的路由,以及各种页面的处理情况。

监听端口8080

       默认端口是8080同时呢我们刚也说了,浏览器只有80和443端口才是不需要我们拼接的,所以正常情况我们也不想要端口号,所以,我们就只需要找到8080将其替换成80即可,所以我们现在就知道了listen这个配置就是指我们要监听哪个端口号,改为80之后我们访问服务就不需要再加端口了,可以直接访问127.0.0.1即可,当然我们现在访问是不可以的。

因为Nginx修改完配置之后需要重载,我们可以停止再启动,或者更简单的nginx -s reload重载即可,具体的更多命令我们后面再说,重载完成之后我们访问就会发现是同样的效果,如果是在我们的服务器上,安装这里就不说了,去官网或者随便百度都可以找到,我们把域名解析到自己服务器,这个时候访问自己的域名不加端口就能访问到项目了,如果你还是个初学者,不太会linux的一系列命令,那么我推荐你使用xshellsftp使用可视化工具直接对文件进行拖拽操作即可晚上上述步骤,那么第一步我们的网站其实这样就可以部署完成了,如果你没有域名,那么直接输入你的服务器ip同样可以访问成功。

一台服务器部署多个网站

       多个服务只需要运行在不同端口即可,在Nginx的配置中,我们只需要根据用户访问的地址来指向不同的端口就行,那么这个怎么配置呢

server {    listen       80;    server_name   chat.jiangly.com;    location / {        proxy_pass   http://127.0.0.1:7000;    }   }

         监听80端口,当访问的域名是chat.jiangly.com的时候指向我们的7000端口,那么7000端口就是我们项目运行的真实端口,很明显呢这是一个后端node服务,这时候小伙伴有疑问了,如果我们是前端静态项目怎么办,我打了包了啊,好像没有端口了,直接访问了啊,那我哪来的这个proxy_pass呢,也很简单:

proxy_pass变成了rootroot呢指向了一个地址,那么我们就把自己项目放这个地址就行了,原来前端的项目这么简单啊,这一下,我们就可以一下部署好多网站啦,既可以访问前端这种静态网站,也可以配置node项目这种带端口的啦,这下服务器想部署多少项目不是都可以了么。如果小伙伴没有域名的话呢 server_name就需要变成127.0.0.1加上端口号或者项目地址了,比如127.0.0.1:7000127.0.0.1/project1这样来区分项目。同时需要注意的是,这里使用的是相对路径是以我们nginx -t那里的配置文件nginx.conf那一层为对比的路径

使用Https服务

Https对应的是443的端口,那我们直接监听443不就可以了么,在默认配置中,我们看见有监听443端口但是注释了,我们之间打开,配置和80完全一样没有区别,我们直接三下五初二,保存,重载,发现,报错了,原来说我们没有证书啊,没错,Https是需要证书的,这个证书呢需要收费,但是作为卑微的开发仔当然不愿意去花这个钱了呗,我个人呢是使用的腾讯云,小伙伴们可能使用的是其他厂商,但是肯定都会提供免费的证书供大家使用,去到域名管理的地方找到申请免费的Https证书腾讯云在我个人使用每次申请最多一分钟非常的快,完了之后下载会发现里面有很多的格式。我么要下载Nginx的格式,下载之后呢,打开里面会有很多文件,但我们只需要两个,crt格式的和key格式的,然后我先放一个个人的基本配置

server {
    listen 443 ssl;
    server_name chat.jiangly.com;
    ssl_certificate conf.d / chat.jiangly.com_ssl / 1 _chat.jiangly.com_bundle.crt;
    ssl_certificate_key conf.d / chat.jiangly.com_ssl / 2 _chat.jiangly.com.key;
    ssl_session_timeout 5 m;
    ssl_protocols TLSv1 TLSv1 .1 TLSv1 .2;
    ssl_ciphers ECDHE - RSA - AES128 - GCM - SHA256: HIGH: !aNULL: !MD5: !RC4: !DHE;
    ssl_prefer_server_ciphers on;
    location / {
        proxy_pass http: //127.0.0.1:7000;        root html;         index  index.html index.htm;  
    }
}

ssl_certificate_keyssl_certificate后面分别对应了两个地址,那么这个地址呢就是我们刚下载的两个文件的地址,/对应的相对地址呢和上面相同,只需要配置这两个文件,其他地方都不用改变,然后重载,这个时候就可以访问https服务了

Websocket服务

       用到websocket服务,如果还是这样的配置呢,我们会发现,请求被拦截掉了,这是为什么呢?其实是因为我们使用ws服务的时候需要告诉nginx我们需要对协议进行升级,所以当你遇到这个问题的时候只需要增加两行配置即可

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

history路由模式、跨域、缓存、反向代理

     路由通常会有两个选项,一个带**#的哈希路由一个不带,同时文档中还说了我们要使用,history就需要后端去改配置,实际这个在nginx就是简简单单的几行而已,我们只需要添加下面这几行,就可以使用history路由了**,同时还有设置一些静态格式文件的缓存,设置跨域访问等等

负载均衡

nginx的负载均衡策略有六种:

  • 轮询(默认策略,nginx自带策略):我上面的例子就是轮询的方式,它是upstream模块默认的负载均衡默认策略。会将每个请求按时间顺序分配到不同的后端服务器。

    http {
        upstream xuniji_fuzai {
            server 192.168 .30 .128: 80;
            server 192.168 .30 .135: 80;
        }
        server {
            listen 81;
            server_name www.xuniji.one.com;
            location / {
                proxy_pass http: //xuniji_fuzai;            proxy_set_header Host $proxy_host;       
            }
        }
    }
    
  • weight(权重,nginx自带策略):指定轮询的访问几率,用于后端服务器性能不均时调整访问比例。

    http {
        upstream xuniji_fuzai {
            server 192.168 .30 .128: 80 weight = 7;
            server 192.168 .30 .135: 80 weight = 2;
        }
        server {
            listen 81;
            server_name www.xuniji.one.com;
            location / {
                proxy_pass http: //xuniji_fuzai;            proxy_set_header Host $proxy_host;    
            }
        }
    }  
    
  • ip_hash(依据ip分配,nginx自带策略):指定负载均衡器按照基于客户端IP的分配方式,这个方法确保了相同的客户端的请求一直发送到相同的服务器,可以解决session不能跨服务器的问题。

    http {
        upstream xuniji_fuzai {
            ip_hash;
            server 192.168 .30 .128: 80;
            server 192.168 .30 .135: 80;
        }
        server {
            listen 81;
            server_name www.xuniji.one.com;
            location / {
                proxy_pass http: //xuniji_fuzai;            proxy_set_header Host $proxy_host;       
            }
        }
    }
    
  • least_conn(最少连接,nginx自带策略):把请求转发给连接数较少的后端服务器。

    http {
        upstream xuniji_fuzai {
            #
            把请求转发给连接数比较少的服务器 least_conn;
            server 192.168 .30 .128: 80;
            server 192.168 .30 .135: 80;
        }
        server {
            listen 81;
            server_name www.xuniji.one.com;
            location / {
                proxy_pass http: //xuniji_fuzai;           
                proxy_set_header Host $proxy_host;     
            }
        }
    }
    
  • fair(第三方):按照服务器端的响应时间来分配请求,响应时间短的优先分配。

    http {
        upstream xuniji_fuzai {
            fair;
            server 192.168 .30 .128: 80;
            server 192.168 .30 .135: 80;
        }
        server {
            listen 81;
            server_name www.xuniji.one.com;
            location / {
                proxy_pass http: //xuniji_fuzai;          
                proxy_set_header Host $proxy_host;
            }
        }
    }
    
  • url_hash(第三方):该策略按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,需要配合缓存用。

    http {
        upstream xuniji_fuzai {
            hash $request_uri;
            server 192.168 .30 .128: 80;
            server 192.168 .30 .135: 80;
        }
        server {
            listen 81;
            server_name www.xuniji.one.com;
            location / {
                proxy_pass http: //xuniji_fuzai;            proxy_set_header Host $proxy_host;       
            }
        }
    }
    

总结

参考链接:

shouce.jb51.net/nginx-doc/T…

blog.csdn.net/qq\_5974759…