nginx学习笔记

介绍

什么是nginx

nginx是一个高性能的http和反向代理web服务器
其特点是占有内存少,并发能力强

nginx是一个安装非常的简单,配置文件非常简洁(还能够支持perl语法)bug非常少的服务.nginx启动特别容易,并且几乎可以做到7*24不间断允许,即使运行数个月也不需要重新启动,你还能狗不间断服务的情况下进行软件版本的升级.

nginx代码完全用c语言从头写成,官方数据测试表明能够支持高达50000个并发连接数的响应.

nginx作用

http代理,反向代理:作为web服务器最常见的功能之一,尤其是反向代理

正向代理

反向代理

nginx提供的负载均衡策略有两种:内置策略和扩展策略.内置策略为轮询,加权轮询,ip hash. 扩展策略,就天马行空,只有你想不到的没有他做不到的.

轮询

加权轮询

iphash

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

动静分离

动静分离,在我们的软件开发中,有些请求是需要后台处理的,有些请求是不需要经过后台处理的(如:css,html,jpg,js等等文件),这些不需要经过后台处理的文件称为静态文件.让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作.提高资源响应的速度.

apache和nginx的区别

apache和nginx在处理php代码时有什么区别

  1. Nginx是通过php-fpm这个服务来处理php文件
  2. Apache是通过libphp5.so这个模块来处理php文件

Apache的libphp5.so随着apache服务器一起运行,而Nginx和php-fpm是各自独立运行,所以在运行过程中,Nginx和php-fpm都需要分别启动!

nginx相对于apache的优点:
轻量级,同样起web服务,比apache占用更少的内存及资源;高并发, nginx处理请求是异步非阻
塞的,而apache则是阻塞型的,在高并发下nginx能保持低资源低消耗高性能;高度模块化的设计,
编写模块相对简单;社区活跃,各种高性能模块出品迅速

安装环境

安装nginx所需环境

1
yum install gcc-c++  pcre pcre-devel zlib zlib-devel openssl openssl-devel
  1. gcc-c++ #nginx源码进行编译,编译依赖 gcc 环境
  2. prce #是一个Perl库,包括 perl 兼容的正则表达式库。nginx 的 http 模块使用 pcre 来解析正 则表达式,所以需要在 linux 上安装 pcre 库,
  3. pcre-devel #是使用 pcre 开发的一个二次开发库。nginx也需要此库
  4. zlib #zlib库提供了很多种压缩和解压缩的方式, nginx 使用 zlib 对 http 包的内容进行 gzip

下载编译nginx

下载

1
http://nginx.org/en/download.html

编译nginx

1
2
3
4
5
6
7
8
9
tar -zxvf nginx-1.12.0.tar.gz
cd nginx-1.12.0

创建一个nginx用户,用于后期启动nginx,比你直接使用root用户启动nginx更安全
useradd -M -s /sbin/nologin nginx
-M #指定登录shell
-s #不创建家目录

./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_gzip_static_module --with-pcre #检查编译环境

参数说明:

–prefix=/usr/local/nginx #指定安装路径

–user=nginx –group=nginx #指定运行nginx进程的用户和组

–with-http_ssl_module #支持ssl加密

–with-http_realip_module #此模块支持显示真实来源ip地址,主要用于nginx做前端负载均衡服务器使用

–with-http_gzip_static_module #这个模块指定压缩

–with-pcre #此模块支持rewrite功能

编译安装

1
2
3
make -j 4 #编译,把源代码编译成可执行的二进制文件
-j 4 #以4个进程同时编译
make install #安装

启动nginx

1
2
3
4
cd /usr/local/nginx/sbin
./nginx

访问80端口即可

nginx常用命令

1
2
3
4
5
6
./nginx #启动
./nginx -s stop #停止
./nginx -s quit #安全退出
./nginx -s reload #重新加载配置文件
./nginx -t #检查配置文件是否语法错误
ps aux |grep nginx #查看nginx进程

nginx配置文件

nginx配置文件位置

1
vim /usr/local/nginx/conf/nginx.conf

nginx配置文件组成

第一部分:全局块

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

图片删除了不必要的注释


work process指令

worker_processes:用于配置nginx生成工作进程的数量,这个是nginx服务器实现并发处理服务的关键所在.理论上来说worker process的值越大,可以支持的并发处理量也越多,但事实上这个值的设定是需要受到来自服务器的自身的限制, 建议将该值和服务器CPU的内核数保持一致

语法 默认值 位置
worker_processes num/auto; 1 全局块

worker_processes默认值是1 我们可以通过进程来看


include 指令

1、应用场景:

当存在多个域名时,如果所有配置都写在 nginx.conf 主配置文件中,难免会显得杂乱与臃肿。

为了方便配置文件的维护,所以需要进行拆分配置。

  1. 我们创建test.conf文件 内容如下:
1
2
3
4
5
6
7
8
9
10
1 server {
2 listen 81;
3 server_name localhost;
4
5 location / {
6 root html;
7 index index.html index.htm;
8 }
9
10 }
  1. 然后编辑nginx.conf文件 在http全局块写上
1
include test.conf;
  1. 重新加载配置文件并测试
1
[root@localhost nginx]# ./sbin/nginx -s reload

内容一样是因为我两个站点都是使用同一个路径


user 指令

user:用于配置运行nginx服务器的worker进程的用户和用户组.

该属性也可以在编译的时候制定,语法如下./configure –user=user –group=group, 如果这两个地方都进行了设置,最终生效的是配置文件中的配置.

  1. 指令使用步骤
1
user www;

我们从图上可以看出配置文件报错了 因为我们系统没有www这个用户 需要添加

1
useradd www

添加完用户 检查一下配置文件 正常不报错了

  1. 测试
    我们先不重启nginx 先查看nginx进程的用户是什么 可以看到是nobody 因为默认值就是这个

我们重新加载配置文件看看 我们刚刚配置的用户 有没有生效


第二部分:events块

accept_mutex

用来设置nginx网络连接序列化

语法 默认值 位置
accept_mutex on/off; accept_mutex on; events

这个配置主要可以用来解决常说的”惊群”问题. 大致意思是在某一个时刻,客户端发来一个请求连接,nginx后台是以多进程的工作模式,也就是说有多个worker进程会被同时唤醒,但是最终只会有一个进程可以获取到连接,如果每次唤醒的进程数目太多,就会影响nginx的整体性能.如果将上诉值设置成on开机状态,将会对多个nginx进程接受连接进行序列号,一个个来唤醒接受,就防止了多个进程对连接的争强


multi accept

用来设置是否允许同时接受多个网络连接

语法 默认值 位置
multi_accept on/off; multi_accept off; events

如果multi_accept被禁止了,nginx一个工作进程只能同时接受一个新的连接.否则,一个工作进程可以同时接受所有的新连接


worker_connections

语法 默认值 位置
worker_connections number; worker_connections 512; events

这里的连接数不仅仅包括和前端用户建立的连接数,而是包括所有可能的连接数.另外,number值不能大于操作系统支持打开的最大文件句柄数量


第三部分:http块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
http {
include mime.types;
default_type application/octet-stream;

server {
listen 80;
server_name localhost;

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

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}

}

}

这算是nginx服务器配置中最频繁的部分,代理,缓存和日至定义等绝大多数功能和第三方模块的配置都在这里.
需要注意的是:http块也可以包括http全局块 server块

http全局块

http全局块配置的指令包括文件引入,MIME-TYPE定义,日志自定义,连接超时时间 单链接请求数上限等.

server块

这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了节省互联网服务器硬件成本.

每个http块可以包括多个server块,而每个server块就相当于一个虚拟主机.
而每个server块也分为全局server块,以及可以同时包含多个location块

  1. 全局server块

最常见的配置是本虚拟机主机的监听配置和本虚拟主机的名称或IP配置

  1. location块

这块的主要作用是基于nginx服务器接收到的请求字符串(例如 server_name/uri-string) ,对虚拟主机名称(也可以是IP别名)之外的字符串(例如 前面的 /uri-string ) 进行匹配,对特定的请求进行处理.地址定向 数据缓存和应答控制等功能,还有许多第三方模块的配置也在这里进行


sendfile

用来设置nginx服务器是否使用sendfile()传输文件,该属性可以大大提高nginx处理静态资源的性能

建议开启

语法 默认值 位置
sendfile on/off; sendfile off; http,server,location

keepalive_timeout

用来设置长连接的超时时间

为什么要使用keepalive

我们都知道http是一种无状态协议,客户端想服务端发送一个tcp请求,服务端响应完毕后断开连接.
如果客户端向服务端发送多个请求,每个请求都需要重新创建一次连接,效率相对来说比较多,使用keepalive模式,可以告诉服务器端在处理完一个请求后保持这个tcp连接的打开状态,若接受到来自这个客户端的其他请求,服务端就会利用这个未被关闭的连接,而不需要重新创建一个新连接,提升效率,但是这个连接也不能一直保持,这样的话,连接如果过多,也会是服务器的性能下降,这个时候就需要我们进行设置其的超时时间

语法 默认值 位置
keepalive_timeout time; keepalive_timeout 75s; http,server,location

keepalive_requests

用来设置一个keep-alive连接的次数

语法 默认值 位置
keepalive_requests number; keepalive_requests 100; http,server,location

nginx配置到系统环境

我们可以将该二进制可执行文件加入到系统的环境变量,这样的花在任何目录都可以使用nginx对应的相关命令,具体实现步骤如下

  1. 修改/etc/profile文件
1
2
3
vim /etc/profile
在最后一行添加
export PATH=$PATH:/usr/local/nginx/sbin
  1. 立即生效
1
source /etc/profile
  1. 执行命令
1
nginx -v

nginx配置成系统服务

我们会发现,如果想要启动,关闭或重启加载nginx配置文件,都需要先进入到nginx的安装目录的sbin目录,然后使用nginx的二进制可执行文件来操作,相对来说操作比较繁琐,这块该如何优化?另外如果我们想把nginx设置成随这服务器启动就自动完成启动操作,又该如何来实现?

把nginx应用服务设置成为系统服务,方便对nginx服务的启动和停止等相关操作,具体实现步骤

  1. 在/usr/lib/systemd/system目录下添加nginx.service,内容如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
vim /usr/lib/systemd/system/nginx.service

[Unit]
Description=nginx web service
Documentation=http://nginx.org/en/docs/
After=network.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
PrivateTmp=true

[Install]
WantedBy=default.target
  1. 添加完成后如果权限有问题需要进行权限设置
1
chmod 755 /usr/lib/systemd/system/nginx.service
  1. 使用系统命令来操作nginx服务
1
2
3
4
5
6
启动:systemctl start nginx
停止:systemctl stop nginx
重启:systemctl restart nginx
重新加载配置文件:systemctl reload nginx
查看nginx状态:systemctl status nginx
开机启动:systemctl enable nginx

Nginx基础配置实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
需求如下:
访问:http://192.168.10.11:8081/server1/test1
访问的是:index.html
访问:http://192.168.10.11:8081/server1/test2
访问的是:index.html
访问:http://192.168.10.11:8082/server2/test1
访问的是:index.html
访问:http://192.168.10.11:8082/server2/test2
访问的是:index.html

如果访问的资源不存在
返回自定义的404页面

将/server1和/server2的配置使用不同的配置文件分割
将文件放到/home/www/conf.d目录下,然后使用include进行合并

为/server1和/server2各自创建一个访问日志文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@localhost home]# tree
.
└── www
├── conf.d
│ ├── server1.conf
│ └── server2.conf
└── web
├── 404.html
├── server1
│ ├── logs
│ │ └── access.log
│ ├── test1
│ │ └── index.html
│ └── test2
│ └── index.html
└── server2
├── logs
├── test1
│ └── index.html
└── test2
└── index.html

11 directories, 8 files
[root@localhost home]#

nginx.conf 主配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
user www;
worker_processes 1;

events {
accept_mutex on; #设置nginx网络连接序列化
multi_accept on; #设置nginx的worker进程是否可以同时接受多个请求
worker_connections 1024; #设置nginx的worker进程最大的连接数
}

http {
include mime.types;
default_type application/octet-stream;
sendfile on; #配置允许使用sendfile方式运输
keepalive_timeout 65; #配置连接超时时间

include /home/www/conf.d/*.conf;
server {
listen 80;
server_name localhost;

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

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}

server1.conf 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
server {
listen 8081;
server_name test;
access_log /home/www/web/server1/logs/access.log;
location /server1/test1{
root /home/www/web/;
index index.html;
}


location /server1/test2{
root /home/www/web/;
index index.html;

}

error_page 404 /404.html;
location /404.html {
root /home/www/web;
index 404.html;
}
}

server2.conf 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
server {
listen 8082;
server_name localhost;

location /server2/test1{
root /home/www/web/;
index index.html;

}


location /server2/test2{
root /home/www/web/;
index index.html;
}

error_page 404 /404.html;
location /404.html {
root /home/www/web;
index 404.html;
}
}

Nginx 反向代理

实例1

  1. 实现效果
    访问192.168.10.11:80 跳转到tomcat 8080端口
  2. 准备工作
1
2
3
4
5
6
7
8
9
10
安装java8
yum install -y java-1.8.0-openjdk


下载tomcat
https://tomcat.apache.org/download-80.cgi

启动tomcat 端口为8080
cd /root/apache-tomcat-8.5.73/bin
./startup.sh
  1. 配置nginx文件
1
2
3
4
vim /usr/local/nginx/conf

proxy_pass http://127.0.0.1:8080;
.sbin/nginx -s reload #重新加载配置文件

实例2

  1. 实现效果
    使用nginx反向代理,根据访问的路径跳转到不同端口的服务中

    nginx监听端口为80
    访问http://192.168.10.11:9001/web1 直接跳转到192.168.10.11:8001
    访问http://192.168.10.11:9001/web2 直接跳转到192.168.10.11:8002

  2. 准备工作

1
2
3
4
5
6
7
8
9
10
准备两个tomcat服务
vim ./tomcat2/apache-tomcat-8.5.73/conf/server.xml
修改其中一台tomcat端口为其他
防止冲突

8080端口的tomcat配置
在webapps目录下创建web1 然后在web1创建index.html 内容为8080

8081端口的tomcat配置
在webapps目录下创建web2 然后在web2创建index.html 内容为8081
  1. 配置nginx
1
2
3
4
5
6
7
8
9
10
vim /usr/local/nginx/conf/nginx.conf

52 location /web1 {
53 proxy_pass http://127.0.0.1:8080;
54 index index.html;
55 }
56 location /web2 {
57 proxy_pass http://127.0.0.1:8081;
58 index index.html;
59 }
  1. 测试

Nginx 负载均衡

介绍

  Nginx 服务器是介于客户端和服务器之间的中介,客户端发送的请求先经过 Nginx ,然后通过 Nginx 将请求根据相应的规则分发到相应的服务器。

配置负载均衡

轮询

  1. 准备工作
1
2
3
4
5
6
7
8
9
10
准备两个tomcat服务
vim ./tomcat2/apache-tomcat-8.5.73/conf/server.xml
修改其中一台tomcat端口为其他
防止冲突

8080端口的tomcat配置
在webapps目录下创建web1 然后在web1创建index.html 内容为8080

8081端口的tomcat配置
在webapps目录下创建web1 然后在web1创建index.html 内容为8081
  1. 配置nginx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
vim /usr/local/nginx/conf/nginx.conf

35 upstream test{
36 server 127.0.0.1:8080;
37 server 127.0.0.1:8081;
38 }
39
40
41 server {
42 listen 80;
43 server_name localhost;
44
45 #charset koi8-r;
46
47 #access_log logs/host.access.log main;
48
49 location / {
50 root html;
51 proxy_pass http://test;
52 index index.html index.htm;
53 }
54

前端还是使用80来监听,把请求转发到8080和8081端口。



./sbin/nginx -s reload

可以刷新多次 看到已经实现负载均衡

加权轮询

上述两台Tomcat服务器基本上是交替进行访问的。但是这里我们有个需求:

  由于Tomcat1服务器的配置更高点,我们希望该服务器接受更多的请求,而 Tomcat2 服务器配置低,希望其处理相对较少的请求。

那么这时候就用到了加权轮询机制了。

nginx.conf配置

1
2
3
4
5
6
7
8
9
10
11
12
13
upstream test {
server 127.0.0.1:8080 weight=5;
server 127.0.0.1:8081 weight=2;
}
server {
listen 80;
server_name localhost;

location / {
proxy_pass http://test;

}
}

其实对比上面不加权的轮询方式,这里在 upstream 指令中多了一个 weight 指令。该指令用于配置前面请求处理的权重,默认值为 1。

也就是说:第一种不加权的普通轮询,其实其加权值 weight 都为 1。

weight代表权重,默认为1,权重越高被分配到的客户端越多

明显 8080 端口号出现的次数更多,试验的次数越多越接近我们配置的比例。

ip_hash

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

1
2
3
4
5
upstream test{
ip_hash
server 192.168.1.1:80
server 192.168.1.2:80
}

fair

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

1
2
3
4
5
upstream test{
server 192.168.1.1:80
server 192.168.1.2:80
fair
}

gzip

1
2
3
4
5
6
7
8
9
10
11
12
写在http块全局
#开启gzip压缩功能,目的:提高传输效率,节约带宽
gzip on;

#限制最小压缩,小于1字节文件不会压缩
gzip_min_length 1;

#定义压缩的级别(压缩比,文件越大,压缩越多,但是cpu使用会越多)
gzip_comp_level 3;

#定义压缩文件的类型
gzip_types text/plain application/javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;

nginx防盗链

1
2
3
4
5
6
7
8
server全局块

#对源站点验证
valid_referers *.test.com;
#非法引入会进入下方判断
if ($invalid_referer){
return 403;
}