一篇文章解决Nginx基础操作

本文基于Debian操作系统演示。(不要问我服务器为啥不用CentOS,问就是它无了

【恶 灵 退 散】前方灵魂画手出没

啥是Nginx

比如你写了个HTML丢在服务器上,你输入这个服务器的域名去访问,服务器不知道要拿什么给你,也就不能访问到页面。Nginx就跟Apache一样,会监听服务器的80端口(就是http协议浏览器默认端口),有人发请求,它就把它一个特殊文件夹里的网页文件返回回去。也就是说,它是一个Web服务器应用。

Nginx的并发量非常大,能达到50000左右,是Tomcat的很多倍,在部署JavaWeb服务的时候,一个Tomcat处理的并发量有限,如果想要同时处理更多的请求,就需要有一个中间的服务器作为转发。Nginx很强(它是老毛子写的),它有两个很重要的功能,就是负载均衡反向代理。这俩后面再说。

怎么安装

我用的Debian。(CentOS变成Red Hat的上游版了,不可能再用了的~)

这次咱从源代码手动编译出Nginx,相对于直接下载得到的Nginx,自己编译的不容易有依赖问题。

你需要系统里先有C语言编译器,比如Debian类Linux可以这样:

apt install build-essential # 需要权限,这玩意里面包括了编译要用的一堆东西

先去 http://nginx.org/en/download.html 下载Nginx,是个tar.gz包,然后解压:

tar -xzvf nginx-xxx.tar.gz

解压完进入文件夹:

cd nginx-xxx
# 目录结构如下
drwxr-xr-x 6 1001 1001   4096 Mar  8 16:21 auto
-rw-r--r-- 1 1001 1001 302863 Apr 21  2020 CHANGES
-rw-r--r-- 1 1001 1001 462213 Apr 21  2020 CHANGES.ru
drwxr-xr-x 2 1001 1001   4096 Mar  8 16:21 conf
-rwxr-xr-x 1 1001 1001   2502 Apr 21  2020 configure
drwxr-xr-x 4 1001 1001   4096 Mar  8 16:21 contrib
drwxr-xr-x 2 1001 1001   4096 Mar  8 16:21 html
-rw-r--r-- 1 1001 1001   1397 Apr 21  2020 LICENSE
drwxr-xr-x 2 1001 1001   4096 Mar  8 16:21 man
-rw-r--r-- 1 1001 1001     49 Apr 21  2020 README
drwxr-xr-x 9 1001 1001   4096 Mar  8 16:21 src

执行目录下的configure文件来配置make与依赖,然后使用make来编译、安装:

./configure
make
make install

# 注意:以下是可能会需要的依赖,make不成功就把下面的也装了(yum包管理器用户自己找去)
apt install libpcre3 libpcre3-dev
apt install openssl libssl-dev
apt install zlib1g
apt install zlib1g.dev

然后查找Nginx在哪:

whereis nginx
# 得到 nginx: /usr/local/nginx

这样就装完了Nginx。

Nginx文件结构

我们可以得到以下文件树:

.
├── conf # 配置文件目录
│   ├── fastcgi.conf
│   ├── fastcgi.conf.default
│   ├── fastcgi_params
│   ├── fastcgi_params.default
│   ├── koi-utf
│   ├── koi-win
│   ├── mime.types
│   ├── mime.types.default
│   ├── nginx.conf
│   ├── nginx.conf.default
│   ├── scgi_params
│   ├── scgi_params.default
│   ├── uwsgi_params
│   ├── uwsgi_params.default
│   └── win-utf
├── html # 网页文件存放目录
│   ├── 50x.html
│   └── index.html
├── logs # 日志文件存放目录
└── sbin # 编译所得的nginx二进制文件存放目录
    └── nginx

以下介绍一下四大文件夹

conf 配置文件目录

主要有一个文件:nginx.conf,已经去除了所有的注释以及一些非必须的内容。

worker_processes  1; #工作进程的数量

events {
    worker_connections  1024; # 每个工作进程的最大连接数
}

# 代表此处配置的是http规则
http { 
    include       mime.types; # 定义mine类型
    default_type  application/octet-stream;

    sendfile        on; 
    # 是否使用sendfile函数来实现文件输出,一般网页建议为on,下载服务器,可以设置为off来降低系统压力

    keepalive_timeout  65; # 响应超时时间

    server {
        listen       80; # http协议监听端口为80
        server_name  localhost; # 配置访问域名

        location / { # 访问 / 路径时展示
            root   html; # 网站的网页存放路径,可以改到别处
            index  index.html index.htm; # 默认主页文件
        }

        error_page   500 502 503 504  /50x.html; # 错误网页,包含50x的错误
        location = /50x.html { # 50x错误时返回的网页的路径
            root   html;
        }

    }

}

html 网页文件目录

此目录存放了该服务器受到http请求时返回给浏览器的网页文件,你可以在这边放html、css、js甚至php等网页文件(如果你的系统支持的话),以及服务器报错时显示的文件(比如50x、404等)。

logs 日志文件目录

这边会有几个日志文件。

access.log会记录Nginx每次被访问的信息,包括访问地址,时间、设备、内容等信息。

error.log会记录Nginx每次出错的时间,内容等信息。

nginx.pid会记录Nginx在系统中的进程ID(即PID)。

sbin 二进制文件目录

这边只有一个文件,执行它,没有任何反应,就代表你启动了Nginx。

sudo ./nginx

然后你去用域名或者ip地址什么的访问你的服务器的80端口,就可以看到这个:

Welcome to nginx!

看到这个就说明你成功打开Nginx了。

关于nginx有一些命令行操作:

nginx -s stop # 立即停止Nginx
nginx -s quit # 关闭Nginx的所有服务再关闭Nginx
nginx -s reload #改变Nginx的配置文件后重新加载配置文件,无需重启Nginx,用户无感操作
ps aux|grep nginx # 查看Nginx的进程

Nginx可以做什么

直接拿Nginx做PHP应用服务器

你可以直接在web服务器上安装PHP解释器与MySQL数据库,然后你可以在html内放入你写好的Web程序(包括html、css、js与php文件等)。默认访问这个服务器时,它会自动打开文件里的index.html。若要自动打开PHP文件,你需要在Nginx的配置文件中改动一处:

location / { # 访问 / 路径时展示
            root   html; 
            index  index.html index.htm index.php; # 默认主页文件,在此处添加index.php
}

反向代理(Reverse Proxy)

Proxy

这是正向代理的示意图,客户端无法直接访问到目标服务器的时候,可以使用一个可以访问到目标服务器的中间服务器作为代理,来为客户端提供流量转发的服务。

那反向代理是怎么回事呢?

比如我们有3台服务器运行着我们的网站的服务,每个服务器都有着各自不同的ip地址。让我们假设每台服务器最多让100人同时访问。那么,当我们有200人同时访问这个网站时,用户要如何才能知道哪台服务器是有余力处理的,而又有哪台是被挤满了即将宕机的?用户当然没法知道,因为大家访问网站都是用同一个域名,比如百度,大家都只知道baidu.com,可是它实际上有很多很多的服务器架设在各地,每次访问我们都用的是同一个域名,没有人专门去访问百度1号,百度2号等服务器,这就是反向代理的作用。反向代理服务器把客户端的请求分给多个服务器,再由这个代理服务器将应用服务器上的返回包返回给客户。这样,客户只访问了一个域名,却不会导致大家都访问了一个服务器从而把服务器搞炸。示意图如下:

Reverse Proxy

这就是反向代理的作用,使用反向代理可以很方便的构建服务器集群,而这对于用户来说是无感的。

负载均衡

负载均衡就是Nginx反向代理时为后台的Web服务器分配请求的策略。

Nginx有很多种策略来进行负载均衡,以下简单介绍几种。

轮询

轮询适用于在后端的Web服务器的性能都差不多的时候,Nginx会把反向代理的流量均匀分配给后台每一个服务器。像上面反向代理的图片一样,服务器1,2,3号收到的代理的数量大致一样。这样可以确保大量访问到来的时候各个服务器的负载压力都相近,不至于使某个服务器压力过大。

加权轮询

理解了上面那个轮询之后,加权轮询就比较好理解了。不同于上面那一个,加权轮询更适用于后端Web服务器的性能有差异的情况下。Nginx会跟据配置文件中设置好的权重比例分配代理流量到不同的服务器上去,以实现不同性能的服务器各司其职都能最大化性能利用的功能。比如上图的1,2,3号服务器,分别最多能负载的请求数为1:2:3,那么在Nginx中配置好后,Nginx会把大约50%的流量转发到服务器3上,大约33%的流量转发到服务器2上,约17%的流量则会被转发到服务器1上。使用加权轮询策略可以尽量使服务器集群的性能最大化。(能力越大,责任越大)

IP Hash

轮询与流量转发带来的一个很重要的问题就是一个用户两次访问这个网站,他的流量可能会被转发到不同的服务器上,之前在那个服务器上进行过的操作、存留的Session在这个新服务器上并没有,而要实现服务器集群的Session共享又十分麻烦。一个好方法是使用Redis,但是Nginx的内置IP Hash策略其实可以帮我们完美解决一个问题。当第一次你从一个IP地址访问这个网站时,Nginx会算你的IP的Hash值,然后跟据留存的Hash结果,每次来自同一IP的请求,均交给同一个服务器来执行,就可以解决Session不共享的问题了。

URL重写(rewrite)

该指令通过正则表达式的使用来改变URL。可以同时存在一个或者多个指令,按照顺序一次对URL进行匹配和处理。该指令可以在server块后者location块中使用rewrite关键字配置。

  语法:rewrite regex replacement [flag];

定义如下

  • rewrite:指令关键字。  
  • regex:用来匹配URI的正则表达式。
  • replacement:匹配成功后用来替换URI中被截取内容的字符串,默认情况如果该字符串包含“http://”、”https://“开头,则不会继续向下对URI进行其他处理,直接返回重写的URI给客户端。
  • flag:用来设置rewrite对URI的处理行为,包含如下数据:
    • last:终止在本location块中处理接收到的URI,并将此处重写的URI作为新的URI使用其他location进行处理(只是终止当前location的处理)。
    • break:将此处重写的URI作为一个新的URI在当前location中继续执行,并不会将新的URI转向其他location。
    • redirect:将重写后的URI返回个客户端,状态码是302,表明临时重定向,主要用在replacement字符串不以“http://”,“ https://”或“ $scheme” 开头。
    • permanent 将重写的URI返回客户端,状态码为301,指明是永久重定向。

反向代理与负载均衡的实现

这边只实现一个最简单的http协议下80端口的反向代理与转发。

此处假设的情况是于127.0.0.1:8080127.0.0.1:8081上均运行着同一个WebApp,需要把从80端口入口的流量以1:2的权重转发给这两个服务。

nginx.conf文件下进行配置即可。(配置的部分参见上面以及下文代码的注释)

http { 
    server {
        listen       80; 
        server_name  localhost; 

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

这个代码块我省去了外围的全局配置,只留下了http那一块(实际上被我省去的不能删)

负载均衡的实现

反向代理的实现需要先实现负载均衡。负载均衡的配置需要在http协议的配置区域内配置,使用关键字upstream:

http { 
    # 此处使用upstram关键字配置负载均衡,balance1为负载均衡的自定义策略名,可任意指定
    upstrean balance1{
        server 127.0.0.1:8080 weight=1; # 每台服务器均使用server关键词声明
        server 127.0.0.1:8081 weight=1; # 使用weight来声明每个服务器的权值,这边实现了轮询
    }
    # 这边实现了加权轮询的负载均衡策略,两台服务器收到的请求数大致为1:2
    upstrean balance2{
        server 127.0.0.1:8080 weight=1;
        server 127.0.0.1:8081 weight=2;
    }
    
    server {
        # 节省篇幅,这边省去
    }
}

反向代理实现

反向代理需要在http协议的配置区域的location域内配置,使用关键字proxy pass

location / { 
            root   html;
            index  index.html index.htm; 
            
            # 此处使用proxy pass关键字进行反向代理,使用上文声明的balance2策略
            proxy pass http://balance2; # 以此方法实现Nginx对80端口的访问 / 目录的流量的反向代理
}

URL重写的实现(以http请求转https为例)

http { 
    server {
        listen       80; 
        server_name  localhost; 
        
        rewrite ^(.*)$ https://$host$1 permanent; # 把所有的请求,转发到https的同域名下
        # 或者有另一种写法,使用return实现
        return 301 https://127.0.0.1$request_uri; # 发送301 再转新的地址
    }
}

Final

Nginx是个配置坑。可以配置的地方真的是,太太太太多了,性能调优也有很多骚操作。本文只是帮助你快速理解Nginx的一些工作的原理以及如何用它最主要的功能。很多其他的功能,例如动静分离(提供静态文件服务器)等操作在本文中还没有涉及,希望后面能再自己学学。