一 初始Nginx
1 Nginx概述
Nginx是一款轻量级的Web服务器、反向代理服务器,由于它的内存占用少,启动极快,高并发能力强,在互联网项目中广泛应用。Nginx 专为性能优化而开发,使用异步非阻塞事件驱动模型。
常见服务器
- Apache
- Tomcat
举个栗子 没有Nginx的情况
有了Nginx的话
2 Nginx 四大应用场景
HTTP服务器
Nginx本身也是一个静态资源的服务器,当只有静态资源的时候, 就可以使用Nginx来做服务器,如果一个网站只是静态页面的话, 那么就可以通过这种方式来实现部署。
反向代理
反向代理应该是Nginx使用最多的功能了,反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为 一个反向代理服务器。
负载均衡
负载均衡也是Nginx常用的一个功能,负载均衡其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。
动静分离
动静分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作,这就是网站静态化处理的核心思路。
3 为什么用Nginx
背景
互联网飞速发展的今天,大用户量高并发已经成为互联网的主体. 怎样能让一个网站能够承载几万个或几十万个用户的持续访问呢?
单机架构
Tomcat 默认配置的最大请求数是150,也就是说同时支持150 个并发。具体能承载多少并发,须要看硬件的配置,线程CPU 越多性能越高,分配给JVM的内存越多性能也就越高,但也会加剧GC的负担。
引入反向代理实现负载均衡
负载均衡就是一个web服务器解决不了的问题可以通过多个 web服务器来平均分担压力来解决,并发过来的请求被平均分配到多个后台web服务器来处理,这样压力就被分解开来。
总结
- 它可以高并发连接,官方测试能够支撑5万并发连接,在实际生产环境中可以支撑2到4万并发连接。
- 内存消耗少
- 购买F5 BIG-IP ,NetScaler等硬件负载均衡交换机需要10多万甚至几十万人民币。而Nginx为 开源软件,可以免费试用,并且可用于商业用途。
- 内置的健康检查功能:如果Nginx proxy后端的某台服务器宕机了,不会影响前端访问。
- 节省带宽,支持gzip压缩。
- 稳定性高:用于反向代理(负载均衡),宕机的概率微乎其微。
- 支持热部署。在不间断服务的情况下,对软件版本升级。
二 Nginx安装部署
1 环境准备
学习环境
操作系统:Centos7.5 X64
四项确认
- 确认网络
- 确认yum可用
- 确认防火墙
- 确认SELinux
一项安装
yum -y install gcc make automake pcre-devel zlib zlib-devel openssl openssl-devel
参数:
- gcc:编译依赖gcc环境
- pcre:PCRE(Perl Compatible Regular Expressions)是一个Perl库,包括 Perl 兼容的正则表 达式库。
- zlib:zlib库提供了很多种压缩和解压缩的方式,Nginx使用zlib对http包的内容进行gzip,所 以需要在linux上安装zlib库。
- Openssl:OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥 和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用。
2 Nginx下载与安装
下载Nginx源码
官网下载Nginx软件http://Nginx.org
点击download进入下载页面
Nginx 官方提供了三个类型的版本:
Mainline Version:主线版,是最新版,但未经过过多的生产测试。
Stable Version:稳定版,生产环境使用版本。
Legacy Version:老版本。
注意: 我们需要下载的是 Stable Version。其中又分为两种版本: Linux 版与 Windows 版。开发时这两个版本我们都下载。 Linux 版用于生产环境,而 Windows 版用于开发测试,选择需要的版本进行下载。
Nginx源码编译
1.创建存放源文件的文件夹
首先在目录/opt下创建apps目录,用于存放源文件以及解压后的文件
2.上传Nginx到步骤1创建的目录下
3.解压 Nginx
[root@node1 apps]# pwd
/opt/apps
[root@node1 apps]# ls
Nginx-1.20.1.tar.gz
[root@node1 apps]# tar -zxvf nginx-1.20.1.tar.gz
[root@node1 apps]# cd nginx-1.20.1/
进入到 Nginx 解压包目录/opt/apps/nginx-1.20.1 目录中,查看 Nginx 的目录。
其中各个目录中存放的文件作用为:
auto:存放 Nginx 自动安装的相关文件
conf:存放 Nginx 服务器配置文件
configure:命令,用于对即将安装的软件的配置,完成 makefile 编译文件的生成
contrib:存放由其他机构贡献的文档材料
html:存放 Nginx 欢迎页面
man:manual,手册,存放 Nginx 帮助文档
src:存放 Nginx 源码
4.生成 makefile
在 Nginx 解压目录下运行 make 命令,用于完成编译。但此时会给出提示:没有指定目标,并且没有发现编译文件 makefile。
编译命令 make 需要根据编译文件 makefile 进行编译,所以在编译 之前需要先生成编译文件 makefile。使用 configure 命令可以生成 该文件。那么,configure 命令需要配置些什么参数呢?使用–help 可以查看到可以使用的参数说明。
configure 参数:
–prefix:Nginx 安装目录。注意,安装目录与解压目录不一样
–sbin-path:Nginx 命令文件
–modules-path:Nginx 模块存放路径
–conf-prefix:Nginx 配置文件存放路径
–pid-path:Nginx 的进程 id 文件
–error-log-path:错误日志文件
–http-log-path:http访问日志文件
安装编译参数
5.配置参数
[root@node1 Nginx-1.20.1]# mkdir -p /var/temp/nginx/client
[root@node1 Nginx-1.20.1]# pwd
/opt/apps/nginx-1.20.1
[root@node1 Nginx-1.20.1]#./configure \
--prefix=/usr/local/nginx \
--pid-path=/usr/local/nginx/logs/nginx.pid \
--error-log-path=/usr/local/nginx/logs/error.log \
--http-log-path=/usr/local/nginx/logs/access.log \
--with-http_ssl_module \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi
注意: /var/temp/nginx/client目录需要手动创建。
编译安装
make && make install
这是两个命令,make 为编译命令,make install 为安装命令, 可以分别执行。这里使用&&将两个命令连接执行,会在前面命 令执行成功的前提下才会执行第二个命令。
3 Nginx目录详解
#安装目录由--prefix=/usr/local/nginx
[root@node1 ~]# cd /usr/local/nginx/
[root@node1 Nginx]# ll
总用量 0
drwxr-xr-x 2 root root 333 8月 27 15:37 conf
drwxr-xr-x 2 root root 40 8月 27 15:37 html
drwxr-xr-x 2 root root 6 8月 27 15:37 logs
drwxr-xr-x 2 root root 19 8月 27 15:37 sbin
注意: 执行命令 tree /usr/local/nginx;如果tree命令找不到就执行 yum install tree -y安装
conf目录
Nginx所有配置文件的目录,极其重要。在该目录中包含一个 nginx.conf配置文件。
html目录
Nginx的默认站点目录。
[root@node1 Nginx]# ll html/
总用量 8
-rw-r--r-- 1 root root 494 8月 27 15:37
50x.html #错误提示页面
-rw-r--r-- 1 root root 612 8月 27 15:37
index.html #访问Nginx时的首页
logs目录
存放Nginx的日志文件。 access.log error.log
#刚安装完Nginx,从未启动过的话logs目录下什么都没有,只有启动Nginx后,才会出现以下三个文件
[root@node1 Nginx]# ll logs/
总用量 4
-rw-r--r-- 1 root root 0 8月 27 16:29
access.log #记录正常访问的日志
-rw-r--r-- 1 root root 0 8月 27 16:29
error.log #错误日志
-rw-r--r-- 1 root root 6 8月 27 16:29
Nginx.pid #Nginx进程id
[root@node1 Nginx]# cat logs/Nginx.pid
24514 #当前启动Nginx的master进程的id
sbin目录
Nginx命令的目录,如Nginx的启动命令。
[root@node1 Nginx]# ll sbin/
total 5884
-rwxr-xr-x 1 root root 6023304 Apr 20 23:53 nginx #启动关闭等操作的脚本
[root@node1 Nginx]# ./sbin/nginx #启动Nginx
[root@node1 Nginx]# ps aux|grep nginx #查看Nginx的进程
[root@localhost nginx]# ps aux|grep nginx
root 9746 0.0 0.1 46132 1956 ? Ss 03:37 0:00 nginx: master process ./nginx
nobody 9749 0.0 0.2 48648 2084 ? S 03:37 0:00 nginx: worker process
root 39706 0.0 0.0 112812 980 pts/0 R+ 04:05 0:00 grep --color=auto nginx
4 Docker安装Nginx
拉取官方的Nginx镜像
[root@localhost ~]# docker pull Nginx
以下命令使用 Nginx 默认的配置来启动一个 Nginx 容器实例:
[root@localhost ~]# docker run --rm --name Nginx-test -p 8080:80 -d Nginx
358354f206fdbc5c20199a307392c11972b1bedab306144e5af56995edbb3e4b
参数的含义如下:
–rm:容器终止运行后,自动删除容器文件。
–name Nginx-test:容器的名字叫做Nginx-test,名字自己定义.
-p: 端口进行映射,将本地 8080 端口映射到容器内部的 80 端 口
-d:容器启动后,在后台运行
Nginx 服务部署,映射本地目录到Nginx容器
创建本地目录,用于存放Nginx的相关文件信息.
mkdir -p /opt/Nginx/www /opt/Nginx/conf
参数:
www: 目录将映射为 Nginx 容器配置的虚拟目录。
conf: 目录里的配置文件将映射为 Nginx 容器的配置文件。
拷贝容器内 Nginx 默认配置文件到本地当前目录下的 conf 目录,容器ID可以查看 docker ps 命令输入中的第一列
docker cp 358354f206fd:/etc/Nginx/Nginx.conf
/opt/Nginx/conf/
部署命令
docker run --rm -d -p 8081:80 --name Nginxtest-web \
-v /opt/Nginx/www:/usr/share/Nginx/html \
-v /opt/Nginx/conf/Nginx.conf:/etc/Nginx/Nginx.conf \
Nginx
命令说明:
–rm:容器终止运行后,自动删除容器文件。
-p 8081:80: 将容器的 80 端口映射到主机的 80821端口.
–name Nginx-test-web:将容器命名为 Nginx-test-web
-v /opt/Nginx/www:/usr/share/Nginx/html:将我们自己创建的 www 目录挂载到容器的/usr/share/Nginx/html。
-v /opt/Nginx/conf/Nginx.conf:/etc/Nginx/Nginx.conf:将我们自己创建的 Nginx.conf 挂载到容器的 /etc/Nginx/Nginx.conf。
5 Nginx服务启停控制
Nginx服务的启动
在Linux 平台下,启动Nginx服务器直接运行安装目录下sbin目录中的二进制文件即可。
./nginx -h
参数:
-v : 打印版本号
-V : 打印版本号和配置
-t:测试配置正确性并退出
-q:测试配置时只显示错误
-s:向主进程发送信号
-p:指定Nginx服务器路径前缀
-c: 指定Nginx配置文件路径
-g: 指定Nginx附加配置文件路径
Nginx服务的停止
两种方式:
快速停止,快速停止是指立即停止当前Nginx服务正在处理的所有 网络请求,马上丢弃连接,停止工作。
./nginx -s stop # 快速关闭
平缓停止,平缓停止是指允许Nginx服务将当前正在处理的网络请 求处理完成,但不再接收新的请求,之后关闭连接,停止工作。
./nginx -s quit # 等待工作进程处理完成后关闭
注意: 建议使用平缓停止
Nginx服务的重启
更改Nginx服务器的配置和加入新模块后,如果希望当前的Nginx服 务应用新的配置或使新模块生效,就需要重启Nginx服务。当然我们可以先关闭Nginx服务,然后使用新的Nginx配置文件重启服务。
./nginx -s reload # 向主进程发送信号,重新加载配置文件,热重启
./nginx -s reopen # 重启 Nginx
三 Nginx指令配置
1 全局块
配置运行Nginx服务器用户(组)
用于配置运行Nginx服务器用户(组)的指令是user。
语法格式:
user user [group]
注意:
只有被设置的用户或者用户组成员才有权限启动你那个Nginx进程,如果是其他用户尝试启动Nginx进程,将报错:
Nginx: [emerg] getpwnam ("test_user") failed (2:No such file or directory )in /Nginx/conf/Nginx.conf:2
如果希望所有用户都可以启动Nginx进程,有两种办法:一是将指令注释:
# user [user] [group]
或者把用户(和用户组)设置为nobody;
user nobody nobody;
注意: 在Nginx配置文件中,每一条指令配置必须以分号结束,请不要忘记。
配置允许生成worker process数
worker process是Nginx服务器实现并发处理的关键所在。理论来 说worker_process的值越大,可以支持的并发处理也越多。
语法格式:
worker_process number | auto
- number 指定Nginx进程最多可以产生的worker_process数。
- auto ,设置此值,Nginx进程将自动检测。
在默认的配置文件中,Number=1.启动Nginx服务器后,使用以下 命令可以看出Nginx服务器除了主进程master process …/sbin/Nginx之外,还生成了一个worker_process.
ps -ef | grep nginx
注意: 此指令只能在全局快中设置。
配置Nginx进程PID存放路径
Nginx进程作为系统的守护进程运行,我们需要在某文件中保存当前运行程序的主进程号。
语法格式:
pid file;
注意:此指令只能在全局快中设置。 在指令path的时候,一定要包括文件名,如果只设置了路径,没有设置文件名,会报错。
配置错误日志的存放路径
在全局块、http块和 server 块中都可以对Nginx服务器的日志进行相关配置。这里首先介绍全局块下日志的存放配置,后两种情况的配置基本相同,只是作用域不同。
语法结构:
error_log_file | stderr[ debug|info | notice| warn |error|crit|alert]
注意:
指定的文件对于运行Nginx进程的用户具有写权限,否则在启动 Nginx进程的时候会出现以下报错信息:
Nginx:[alert] :could not open error log file :open() "/Nginx/logs/error.log failed (permission denied)"
配置文件的引入
语法结构:
include file;
其中,file是要引入的配置文件,它支持相对路径。
注意: 新引用进来的文件同样要求运行Nginx进程的用户对其具有写权限,并且符合Nginx配置文件规定的相关语法和结构。此指令可以放在配置文件的任意地方。
2 events块
事件驱动模型
Nginx服务器提供了多种事件驱动模型来处理网络消息。配置文件中为我们提供了相关的指令来强制Nginx服务器选择哪种事件驱动模型进行消息处理。
语法结构:
use method;
其中,method可选择的内容有: select、poll、kqueue、epoll、 rtsig、ldev/poll l以及 eventport。
A)标准事件模型
- Select、poll属于标准事件模型,如果当前系统不存在更有效的方法,Nginx会选择select或poll
B)高效事件模型
- Kqueue:使用于FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 和 MacOS X.使用双处理器的MacOS X系统使用kqueue可能会造成内核崩溃。
- Epoll:使用于Linux内核2.6版本及以后的系统。
- /dev/poll:使用于Solaris 7 11/99+,HP/UX 11.22+ (eventport),IRIX 6.5.15+ 和 Tru64 UNIX 5.1A+。
- Eventport:使用于Solaris 10。 为了防止出现内核崩溃的问题, 有必要安装安全补丁。
注意: 可以在编译时使用–with-select module和–withoutselect_module设置是否强制编译select模块到Nginx 内核;使 用–with-poll_module和–without-poll_module设置是否强制 编译poll模块到Nginx内核。此指令只能在events块中进行配置。
配置最大连接数
指令worker_connections主要用来设置允许每一个worker process 同时开启的最大连接数。其语法结构为:
worker_connections number;
此指令的默认设置为512。
注意: 每个工作进程的最大连接数量。根据硬件调整,和前面工作进 程配合起来用,尽量大,但是别把cpu跑到100%就行。每个进 程允许的最多连接数,理论上每台Nginx服务器的最大连接数为。worker_processes * worker_connections
3 HTTP块
定义MIME-Type
在常用的浏览器中,可以显示的内容有HTML、XML、GIF及Flash等种类繁多的文本、媒体等资源,浏览器为区分这些资源,需要使用 MIME Type。换言之,MIME Type是网络资源的媒体类型。Nginx 服务器作为Web服务器,必须能够识别前端请求的资源类型。
include mime.types;
default_type application/octet-stream;
看下mime.types片段:
自定义服务日志
记录Nginx服务器提供服务过程应答前端请求的日志,我们将其称为服务日志以示区分。
Nginx服务器支持对服务日志的格式、大小、输出等进行配置,需要使用两个指令,分别是access _log 和 log_format指令。
access_log 指令的语法结构为:
access_log path[format[buffer=size]]
- path,配置服务日志的文件存放的路径和名称。
- format,可选项,自定义服务日志的格式字符串,也可以通过“格式串的名称”使log_format指令定义好的格式。“格式串的名称”在 log_format 指令中定义。
- size,配置临时存放日志的内存缓存区大小。
和access_log联合使用的另一个指令是log_format,它专门用于定 义服务日志的格式,并且可以为格式字符串定义一个名字,以便 access_log 指令可以直接调用。其语法格式为:
log_format name string ..;
- name,格式字符串的名字,默认的名字为combined。
- string,服务日志的格式字符串。在定义过程中,可以使用Nginx 配置预设的一些变量获取相关内 容,变量的名称使用双引号括起来,string整体使用单引号括起来。在string 中可以使用的变量请 参见下文中的相关内容。
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
log_format log404 '$status [$time_local] $remote_addr $host$request_uri $sent_http_location';
日志格式设置 :
r e m o t e a d d r 与 remote_addr与 remoteaddr与http_x_forwarded_for用以记录客户端的ip 地址;
$remote_user:用来记录客户端用户名称;
$time_local: 用来记录访问时间与时区;
$request: 用来记录请求的url与http协议;
$status: 用来记录请求状态;成功是200,
$body_bytes_sent :记录发送给客户端文件主体内容大小;
$http_referer:用来记录从那个页面链接访问过来的;
$http_user_agent:记录客户浏览器的相关信息;
通常web服务器放在反向代理的后面,这样就不能获取到客户 的IP地址了,通过$remote_add拿到的IP地址是反向代理服务 器的iP地址。反向代理服务器在转发请求的http头信息中,可以增加x_forwarded_for信息,用以记录原有客户端的IP地址和原 来客户端的请求的服务器地址。
配置连接超时时间
与用户建立会话连接后,Nginx服务器可以保持这些连接打开一段时间,指令 keepalive_timeout就是用来设置此时间的。
语法结构:
keepalive_timeout timeout [header timeout];
- timeout,服务器端对连接的保持时间。默认值为75s。
- header_timeout,可选项,在应答报文头部的Keep-Alive域设 置超时时间"Keep-Alive:timeout= header_timeout”。报文中的 这个指令可以被Mozilla或者Konqueror识别。
配置示例:
keepalive_timeout 120s 100s;
其含义是,在服务器端保持连接的时间设置为120 s,发给用户 端的应答报文头部中Keep-Alive域的超时时间设置为100 s。
注意: 此指令还可以出现在server块和 location块中。
配置虚拟主机
server{} 包含在http{}内部,每一个server{}都是一个虚拟主机(站 点)
语法结构:
server{
}
配置网络监听
配置监听使用指令listen,其配置方法主要有二种。
第一种配置监听的IP地址,语法结构为:
listen address[:port]
第二种配置监听端口,语法结构为:
listen port
参数:
address,IP地址,如果是IPv6的地址,需要使用中括号“[”括起来,比如[fe80::1]等。
port,端口号,如果只定义了IP地址没有定义端口号,就使用80端口。
示例
listen 192.168.1.10:8000; #监听具体的IP和具体的端口上的连接
listen 192.168.1.10; #监听具体IP的所有端口上的连接(没用)
listen 8000; #监听具体端口上的所有IP连接
基于名称虚拟主机配置
这里的“主机”,就是指此server块对外提供的虚拟主机。设置了主机的名称并配置好 DNS,用户就可以使用这个名称向此虚拟主机发送请求了。
语法:
server_name name1 name2 name3 ...;
示例1
server_name www.baidu.com //精确匹配
示例2:
server_name *.baidu.com; //通配
示例3:
server_name www.baidu.com *baidu.com;
四种写法
server_name www.baidu.com;
server_name *.baidu.com;
server_name www.baidu.*;
server_name ~^www\.baidu\.*$;
优先级
4 location指令
配置location块
语法:
URL // http://ip:port/
location [ = | ~ | ~* | ^~] uri {
...
}
匹配规则 | 含义 | 示例 |
---|---|---|
= | 精确匹配 | location = /images/ {…} |
^~ | 匹配到即停止搜索 | location ^~ /images/ {…} |
~ | 正则匹配,区分大小写 | location ~ .(jpg |gif)$ {…} |
~* | 正则匹配,不区分大小写 | location ~* .(jpg |gif)$ {…} |
不带任何符号 | location / {…} |
示例1
没有修饰符 表示:必须以指定模式开始,如:
server {
server_name *.*;
location /abc {
……
}
}
注意如下是对的:
http://192.168.66.104/abc http://192.168.66.104/abc?p1=12312&name=w24 http://192.168.66.104/abc/ http://192.168.66.104/abcde
示例2
= 表示:必须与指定的模式精确匹配
server {
server_name *.*;
location = /abc {
……
}
}
注意:
那么,如下是对的:
http://192.168.66.104/abc http://192.168.66.104/abc?p1
如下是错的:
http://192.168.66.104/abc/ http://192.168.66.104/abcde
示例3
~ 表示:指定的正则表达式要区分大小写
server {
server_name *.*;
location ~ ^/abc$ {
……
}
}
注意:
对的
http://192.168.66.104/abc http://192.168.66.104/abc?name=wcc&password=123
错误
http://192.168.66.104/ABC http://192.168.66.104/abc/ http://192.168.66.104/abcde
示例4
~* 表示:指定的正则表达式不区分大小写
server {
server_name *.*;
location ~* ^/abc$ {
……
}
}
注意:
那么,如下是对的:
http://192.168.66.104/abc http://192.168.66.104/ABC http://192.168.66.104/abc?p1=11&p2=22
如下是错的:
http://192.168.66.104/abc/ http://192.168.66.104/abcde
优先级
示例
location = / {
# 只匹配请求 "/"
[ configuration A ]
}
location / {
# 匹配任何请求,因为所有请求都是以"/"开始
# 但是更长字符匹配或者正则表达式匹配会优先匹配
[ configuration B ]
}
location /documents/ {
# 匹配所有 /documents/ 开头的请求,在没有正则表达式匹配时选择该locaiton
[ configuration C ]
}
location ^~ /images/ {
# 匹配任何以 /images/ 开始的请求,并停止匹配其它location
[ configuration D ]
}
location ~* .(gif|jpg|jpeg)$ {
# 匹配以 gif, jpg, or jpeg结尾的请求.
# 但是所有 /images/ 目录的请求将由[Configuration D]处理.
[ configuration E ]
}
结论:
- / -> 匹配A
- /index.html -> 匹配B
- /documents/a.html -> 匹配C
- /images/1.gif -> 匹配D
- /documents/1.jpg -> 匹配E
配置请求的根目录
Web服务器接收到网络请求之后,首先要在服务器端指定目录中寻 找请求资源。在Nginx服务器中,指令root就是用来配置这个根目录的。
语法结构:
root path;
path为Nginx服务器接收到请求以后查找资源的根目录路径。
示例:
location /data/ {
root /localtion1;
}
注意: 当location块接收到“data/index.htm”的请求时,将在locationtest1/data/目录下找到index.htm响应请求。
示例:
location /lxx {
root html;
}
注意: 当location块接收到“lxx/a.htm”的请求时,将在nginx的html/lxx目录下找到a.htm响应请求。
index指令
index:设置网站的默认首页
语法 | index file …; |
---|---|
默认值 | index index.html; |
位置 | http、server、location |
index后面可以跟多个设置,如果访问的时候没有指定具体访问的资源,则会依次进行查找,找到第一个为止。
举例说明:
location / {
root /usr/local/nginx/html;
index index.html index.htm;
}
访问该location的时候,可以通过 http://ip:port/,地址后面如果不添加任何内容,则默认依次访问index.html和index.htm,找到第一个来进行返回
四 Nginx虚拟主机
1 虚拟主机的分类
概述
虚拟主机是一种特殊的软硬件技术,它可以将网络上的每一台计算机分成多个虚拟主机,每个虚拟主机可以独立对外提供 www服务,这样就可以实现一台主机对外提供多个web服务, 每个虚拟主机之间是独立的,互不影响的。
Nginx支持三种类型的虚拟主机配置
基于IP的虚拟主机
基于端口的虚拟主机
基于域名的虚拟主机
2 Nginx虚拟主机单网卡多IP配置
通过不同的IP区分不同的虚拟主机,此类虚拟主机对应的企业应用非常少见,一般不同业务需要使用多IP的常见都会在负载均衡器上进行VIP绑定,而不是在Web上通过绑定IP区分不同的虚拟机。
需求
一台Linux服务器绑定两个ip:192.168.66.100、192.168.66.101 访问不同的ip请求不同的html目录,
即:
访问http://192.168.66.100将访问“html10”目录下的html网页
访问http://192.168.66.101将访问“html101”目录下的html网页
Linux绑定多IP
Linux操作系统允许绑定多IP。是在一块物理网卡上可以绑定多个lP 地址。这样就能够在使用单一网卡的同一个服务器上运行多个基于 IP的虚拟主机。但是在绑定多IP时需要将动态的IP分配方式修改为静态的指定IP。
将动态IP修改为静态IP
[root@node1 ~]# cd /etc/sysconfig/network-scripts
[root@node1 network-scripts]# ls ifcfg-ens33
[root@node1 network-scripts]# vim ifcfgens33
BOOTPROTO="static"
IPADDR0=192.168.66.100
IPADDR1=192.168.66.101
[root@node1 network-scripts]# service network restart # centos6、7重启网卡
[root@node1 ~]# systemctl restart network #centos7重启网卡
[root@node0 network-scripts]#reboot #各种发行版都是可以的
#CentOS8重启网卡 nmcli c reload ens33
修改Nginx的配置文件完成基于IP的虚拟主机配置
Nginx的配置文件nginx.conf
如上述配置文件所示,主要由6个部分组成:
main:用于进行nginx全局信息的配置
events:用于nginx工作模式的配置
http:用于进行http协议信息的一些配置
server:用于进行服务器访问信息的配置
location:用于进行访问路由的配置
修改配置nginx.conf
[root@node1 network-scripts]# vim /usr/local/nginx/conf/nginx.conf
#一个Server就是一个虚拟主机
server {
listen 80;
#为虚拟机指定IP或者是域名
server_name 192.168.66.100;
#主要配置路由访问信息
location / {
#用于指定访问根目录时,访问虚拟主机的web目录
root html100;
#在不指定访问具体资源时,默认的展示资源的列表
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
#一个Server就是一个虚拟主机
server {
listen 80;
#为虚拟机指定IP或者是域名
server_name 192.168.66.101;
#主要配置路由访问信息
location / {
#用于指定访问根目录时,访问虚拟主机的web目录
root html101;
#在不指定访问具体资源时,默认的展示资源的列表
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
生效配置文件
./nginx -s reload
3 Nginx虚拟主机基于域名的配置
需求
两个域名指向同一个nginx服务器,用户访问不同的域名时显示不同的内容。
域名规划:
1, www.sanhao.cn => 前台
2, www.lxx.cn => 后台
修改windows的hosts文件配置域名与ip的映射
文件路径:C:\Windows\System32\drivers\etc\hosts
192.168.66.104 www.sanhao.cn www.lxx.cn
修改nginx.conf配置文件
server {
listen 80;
#为虚拟机指定IP或者是域名
server_name www.sanhao.cn;
#主要配置路由访问信息
location / {
#用于指定访问根目录时,访问虚拟主机的web目录
root sanhao;
#在不指定访问具体资源时,默认的展示资源的列表
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
#一个Server就是一个虚拟主机
server {
listen 80;
#为虚拟机指定IP或者是域名
server_name www.lxx.cn;
#主要配置路由访问信息
location / {
#用于指定访问根目录时,访问虚拟主机的web目录
root lxx;
#在不指定访问具体资源时,默认的展示资源的列表
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
准备需要的目录和html页面:
[root@node1 nginx]# mkdir sanhao
[root@node1 nginx]# mkdir lxx
[root@node1 nginx]# vim sanhao/index.html
<h1>Welcome to nginx sanhao!</h1>
<p><em>Thank you for using sanhao.</em></p>
[root@node1 nginx]# vim lxx/index.html
<h1>Welcome to lxx!</h1>
<p><em>Thank you for using lxx.</em></p>
重启Nginx服务
[root@node1 html]# ./nginx -s reload
测试访问
http://www.lxx.cn/index.html
http://www.sanhao.cn/index.html
4 Nginx虚拟主机基于多端口的配置
通过不同的端口来区分不同的虚拟主机。此类虚拟主机对应的 企业应用主要为公司内部的网站。
需求
Nginx对提供8888与9999两个端口的监听服务
请求8888端口则访问html8888目录下的index.html
请求9999端口则访问html9999目录下的index.html
还原IP地址为192.168.66.100:
上面测试单网卡多ip配置时改成了多个IP
vim /etc/sysconfig/network-scripts/ifcfgens33
#将:
IPADDR0=192.168.66.100
IPADDR1=192.168.66.101
#改为
IPADDR=192.168.66.104
#重启网络服务
systemctl restart network
修改Nginx的配置文件完成基于端口的虚拟主机配置
#一个Server就是一个虚拟主机 基于端口
server {
listen 8888;
#为虚拟机指定IP或者是域名
server_name 192.168.66.104;
#主要配置路由访问信息
location / {
#用于指定访问根目录时,访问虚拟主机的web目录
root html8888;
#在不指定访问具体资源时,默认的展示资源的列表
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
#一个Server就是一个虚拟主机 基于端口
server {
listen 9999;
#为虚拟机指定IP或者是域名
server_name 192.168.66.104;
#主要配置路由访问信息
location / {
#用于指定访问根目录时,访问虚拟主机的web目录
root html9999;
#在不指定访问具体资源时,默认的展示资源的列表
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
准备需要的目录和html页面
[root@node1 nginx]# cp -r sanhao/ html8888
[root@node1 nginx]# cp -r lxx/ html9999
[root@node1 nginx]# vim html9999/index.html
<h1>Welcome to nginx 192.168.66.104:9999!</h1>
[root@node1 nginx]# vim html8888/index.html
<h1>Welcome to nginx 192.168.66.104:8888!</h1>
重启Nginx服务
[root@node1 html]# ./nginx -s reload
测试访问
http://192.168.66.104:8888/index.html
http://192.168.66.104:9999/index.html
五 Nginx核心指令
1 root和alias指令的区别
区别
- 共同点 : root和alias两者都是用来指定URI和磁盘文件的映射关系;
- 区别: root会将定义路径与URI叠加;而alias是将定义路径与请求文件叠加;
root示例
客户端请求www.test.com/images/1.jpg,则对应磁盘映射路径/opt/nginx/html/images/images/1.jpg
location /images {
root /opt/nginx/html/images;
index index.html index.htm;
}
注意:
也就是说使用root 请求的真实路径是 rootpath + /uri ,也就是文件目录 + URI / 后面的内容。
alias示例
客户端请求www.test.com/images/1.jpg,则对应磁盘映射路径/opt/nginx/html/images/1.jpg
location /images {
alias /opt/nginx/html/images/; //最后面一定要加 "/"
index index.html index.htm;
}
注意:
使用alias uri和文件路径进行了叠加,其实就是alias + 请求的文件。
2 return指令
return功能
- 停止处理请求,直接返回响应码或重定向到其他URL;
- 执行return指令后,location中后序指令将不会被执行;
return语法结构
- return code [text]; # 如果返回2XX的,text才有意义,text会在body中;
- return code URL; #主要用于重定向;
- return URL; #须以http或者https开头的;
常用状态码:
200 请求成功
301 永久转移到其他URL
404 请求资源不存在
500 内部服务器错误
上下文
server | location | if
**示例 **
code + text
location / {
return 200 'your success';
}
请求:
➜ nginx curl website.com
your success% //响应的内容
code + URL
#302 表示临时性重定向。访问一个Url时,被重定向到另一个url上。常用于页面跳转。
location / {
return 302 /bbs;
}
location /bbs {
root html;
index index.html;
}
URL
直接重定向到了百度
location / {
return http://baidu.com;
}
3 rewrite指令
rewrite常用全局变量
rewrite指令
该指令通过正则表达式的使用来改变URI。可以同时存在一个或者多个指令,按照顺序依次对URL进行匹配和处理。
特别注意:
- URI ( Universal Resource Identifier,通用资源标识符),用于对网络中的各种资源进行标识,由存放资源的主机名、片段标志符和相对URI三部分组成。存放资源的主机名一般由传 输协议. Scheme )、 主机和资源路径三部分组成;片段标志符指向资源内容的具体元素;相对 URI表示资源在主机上的相对路径。一般格式为:
Scheme:[//][[用户名[:密码]@]主机名[:端口名]][/资源路径]
- URL (Uniform Resource Location,统一资源定位符),是用于在Internet中描述资源的字符串,是URI 的子集,主要包括传输协议(Scheme)、主机(IP、端口号或者域名)和资源具体 地址(目录和文件名)等三部分。一般格式为:
Scheme://主机名[:端口名][/资源路径]
该指令可以在server快或者location块中配置,其语法结构为:
rewrite regex replacement [flag];
关键字 正则 替代内容 flag标记
rewrite参数的标签段位置:
server,location,if
rewrite 最后一项flag参数:
标记符号 说明
last 本条规则匹配完成后继续向下匹配新的location URI规则
break 本条规则匹配完成后终止,不在匹配任何规则
redirect 返回302临时重定向
permanent 返回301永久重定向
常用正则表达式
字符 描述
\ 将后面接着的字符标记为一个特殊字符或者一个原义字符或一个向后引用
^ 匹配输入字符串的起始位置
$ 匹配输入字符串的结束位置
* 匹配前面的字符零次或者多次
+ 匹配前面字符串一次或者多次
? 匹配前面字符串的零次或者一次
. 匹配除“\n”之外的所有单个字符
(pattern) 匹配括号内的pattern
示例1
无论/search 后面跟什么内容,最后都会被永久重定向到百度页面
location /search {
rewrite ^/(.*) http://baidu.com permanent;
}
示例2
创建三个文件夹,每个文件夹下有个1.html文件;
location /images {
rewrite /images/(.*) /pics/$1; //将URL /images/1.html 重写为 /pics/1.html
}
location /pics {
rewrite /pics/(.*) /photos/$1; //将URL /pics/1.html 重写为 /photos/1.html
}
location /photos {
}
示例3
将URL /images/1.html 重写为 /pics/1.html, 并且不再匹配其他 location段
location /images {
rewrite /images/(.*) /pics/$1 break;
}
示例4
将URL /images/1.html 重写为 /pics/1.html, 重新进入server段后 匹配了/pics location段,然后又被重写。
location /images {
rewrite /images/(.*) /pics/$1 last;
}
4 实战rewrite
Nginx的rewrite功能在企业里应用非常广泛:
- 可以调整用户浏览的URL,看起来更规范,合乎开发及产品人员的需求。
- 网址换新域名后,让旧的访问跳转到新的域名上。
- 根据特殊变量、目录、客户端的信息进行URL调整等。
域名跳转
旧域名www.test.com直接跳转到新域名www.lxx.com
server {
listen 80;
server_name test.com;
rewrite ^/(.*) http://www.lxx.com/$1 permanent;
}
server {
listen 80;
server_name www.lxx.com;
location / {
root html;
index index.html index.htm;
}
}
5 if指令
该指令用来支持条件判断,并根据条件判断结果选择不同的Nginx配置,可以在server块或locatio块中配置该指令。
语法结构:
if (condition) { ... }
其中,花括号代表一个作用域,形成一个if配置块,是条件为真时的 Nginx配置。condition为判断条件( true/false ),它可以支持以下 几种设置方法:
- 变量名-如果变量的值为空字符串或者“0”开头的任意字符串,if指令认为条件为false,其他情况为 true,比如:
if ($slow) {
..... #Nginx配置
}
- 使用 “=”(等于) 和 “!=” (不等于) 比较变量和字符串是否相等,相等时if指令为条件为true,反之为 false。
if ($request_method = POST) {
return 405;
}
注意: 这里的字符串不需要加引号。
变量与正则表达式
- ~表示匹配过程对大小写敏感
- ~* 表示匹配过程对大小写不敏感
- !~ 表示匹配失败时if指令认为条件为true否则为false
if ($http_user_agent ~ MSIE) {
# $http_user_agent 的值中是否包含MSIE字符串,如果包含,为true
}
示例
判断ip地址是否为192.168.66.10如果是返回“test if ok in Url /serach”
location /search {
if ($remote_addr = "192.168.66.10"){
return 200 "test if ok in url search"
}
}
示例
不允许谷歌浏览器访问,如果时候谷歌浏览器放回500
if ($http_user_agent ~ Chrome){
return 500;
}
6 set和break指令
set指令
该指令用于设置一个新的变量。
语法结构
set variable value
- variable,为变量的名称。注意要用符号“$”作为变量的第一个字符,且变量不能与Nginx服务器预设的全局变量同名。
- value,为变量的值,可以是字符串、其他变量或变量的组合等。
break指令
该指令用于中断当前相同作用域中的其他Nginx配置。
语法结构
break;
示例
ocation / {
if ($slow){
set $id $1 ; # 处于break指令之前,配置生效
break;
limit_rate 10k; #处于break指令之后,配置无效
}
}
7 Gzip压缩指令
Nginx开启Gzip压缩功能, 可以使网站的css、js 、xml、html 文件在传输时进行压缩,提高访问速度, 进而优化Nginx性能!
Gzip压缩作用
将响应报⽂发送⾄客户端之前可以启⽤压缩功能,这能够有效地节 约带宽,并提⾼响应⾄客户端的速度。Gzip压缩可以配置 http,server和location模块下。Nginx开启Gzip压缩参数说明
指令 | 含义 |
---|---|
gzip on | 决定是否开启gzip模块,on表示开启,off表示关闭; |
gzip_min_length 1k | 设置允许压缩的页面最小字节(从header头的Content-Length中获取) ,当返回内容大于 此值时才会使用gzip进行压缩,以K为单位,当值为0时,所有页面都进行压缩。建议大于1k |
gzip_buffers 4 16k; | 设置gzip申请内存的大小,其作用是按块大小的倍数申请内存空间,param2:int(k) 后面单 位是k。这里设置以16k为单位,按照原始数据大小以16k为单位的4倍申请内存 |
gzip_http_version 1.1; | 识别http协议的版本,早起浏览器可能不支持gzip自解压,用户会看到乱码 |
gzip_comp_level 2; | 设置gzip压缩等级,等级越底压缩速度越快文件压缩比越小,反之速度越慢文件压缩比 越大;等级1-9,最小的压缩最快 但是消耗cpu |
gzip_types text/plain application/x-javascript text/css application/xml ; | 设置需要压缩的MIME类型,非设置值不进行压缩,即匹配压缩类型 |
gzip_vary on; | 启用应答头"Vary: Accept-Encoding" |
gzip_proxied off; | nginx做为反向代理时启用,off(关闭所有代理结果的数据的压缩),expired(启用压缩,如果 header头中包括 “Expires” 头信息),no-cache(启用压缩,header头中包含 “CacheControl:no-cache” ), no-store(启用压缩,header头中包含 “Cache-Control:nostore” ),private(启用压缩,header头中包含 “Cache-Control:private” ),no_last_modefied(启用压缩,header头中不包含 “LastModified” ),no_etag(启用压缩,如果header头中不包含 “Etag” 头信息),auth(启用压缩,如 果header头中包含 “Authorization” 头信息) |
gzip_disable msie6; | (IE5.5和IE6 SP1使用msie6参数来禁止 gzip 压缩 )指定哪些不需要 gzip 压缩的浏览器 (将和User-Agents进行匹配),依赖于PCRE库 |
如下是线上常使用的Gzip压缩配置
http {
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 9;
gzip_types text/plain
application/x-javascript text/css
application/xml text/javascript
application/x-httpd-php
application/javascript application/json;
gzip_disable "MSIE [1-6]\.";
gzip_vary on;
}
Nginx的Gzip压缩功能虽然好用,但是下面两类文件资源不太 建议启用此压缩功能。
- 图片类型资源 (还有视频文件)
原因:图片如jpg、png文件本身就会有压缩,所以就算开启 gzip后,压缩前和压缩后大小没有多大区别,所以开启了反而会白白的浪费资源。
- 大文件资源
原因:会消耗大量的cpu资源,且不一定有明显的效果。
六 Nginx场景实践
1 浏览器缓存
浏览器缓存
浏览器缓存是为了加速浏览,浏览器在用户磁盘上,对最近请求过的文档进行存储。当访问者再次请求这个页面时,浏览器就可以从本地磁盘显示文档,这样,就可以加速页面的阅览,缓存的方式节约了网络的资源,提高了网络的效率。
实现浏览器缓存步骤
浏览器缓存可以通过expires指令输出Header头来实现。
语法:expires[time| epoch | max |off]
默认值:expires off
作用域:http、server、location
一个HTML页面,会引用一些JavaScript文件、图片文件、而这些格 式的文件很少会被修改,则可以通过expires设置浏览器缓存。
示例
比如,对常见格式的图片、Flash文件在浏览器本地缓存30天,对 JS、CSS文件在浏览器本地缓存1小时,代码如下
location ~ .*\.(gif|jpg|png)$ {
expires 30d;
}
location ~ .*\.(js|css)?$ {
expires 1h;
}
Cache-Control
设置相对过期时间, max-age指明以秒为单位的缓存时间. 若对静态资源只缓存一次, 可以设置max-age的值为315360000000 (一万年). 比如对于提交的订单,为了防止浏览器回退重新提交,可以使用 Cache-Control之no-store绝对禁止缓存,即便浏览器回退依然请求的是服务器,进而判断订单的状态给出相应的提示信息!
Http协议的cache-control的常见取值及其组合释义:
- no-cache: 数据内容不能被缓存, 每次请求都重新访问服务器, 若有max-age, 则缓存期间不访问服务器
- no-store: 不仅不能缓存, 连暂存也不可以(即: 临时文件夹中不能暂存该资源)
- private(默认): 只能在浏览器中缓存, 只有在第一次请求的时候才访问服务器, 若有- - maxage, 则缓存期间不访问服务器
- public: 可以被任何缓存区缓存, 如: 浏览器、服务器、代理服务器等
- max-age: 相对过期时间, 即以秒为单位的缓存时间
语法结构:
# expires 1d;
add_header Cache-Control no-cache;
add_header Cache-Control private;
缓存流程
企业实战示例
下面是开发部门同事发过来的配置需求:
- 禁用html文件缓存,即cache control设置为no-cache;
- 对于js,图片,css,字体等,设置max-age=2592000. 也就是30天;
注意: 缓存控制字段cache-control的配置(add_header)要放在http, server, location区域, 或是放在location的if判断里, 例 如"add_header Cache-Control no-cache;"
配置源码
server{
listen 80;
server_name 192.168.66.100;
location ~ \.(css|js|gif|jpg|jpeg|png|bmp|swf|ttf|woff|otf|ttc|pfa)$ {
root /data/web/kevin;
expires 30d;
}
location ~ \.(html|htm)$ {
root /data/web/kevin;
add_header Cache-Control no-cache;
}
}
2 防盗链
防盗链的概念
内容不在自己的服务器上,通过技术手段将其他网站的内容(比如 一些音乐、图片、软件的下载地址)放置在自己的网站中,通过这种方法盗取其他网站的空间和流量。
防盗链技术背景
防止第三方引用链接访问我们的图片,消耗服务器资源和网络流量,我们可以在服务器上做防盗链限制。
防盗链设置思路
首要方式:区别那些请求是非正常的用户请求。
基于http_refer防盗链配置模块
HTTP Referer是header的一部分,当浏览器向web服务器发送请求 的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来 的,服务器籍此可以获得一些信息用于处理。比如从我主页上链接到一个朋友那里,他的服务器就能够从HTTP Referer中统计出每天 =有多少用户点击我主页上的链接访问他的网站。
语法结构:
valid_referers none blocked 192.168.66.104;
if ($invalid_referer) {
return 403;
}
参数:
none : 允许没有http_refer的请求访问资源;
blocked : 允许不是http://开头的,不带协议的请求访问资源;
192.168.66.104: 只允许指定ip来的请求访问资源;
3 代理服务
正向代理
正向代理,是在用户端的。比如需要访问某些国外网站,我们可能需要购买vpn。
正向代理最大的特点:
- 客户端非常明确要访问的服务器地址;
- 服务器只清楚请求来自哪个代理服务器,而不清楚来自哪个具体的客户端;
- 正向代理模式屏蔽或者隐藏了真实客户端信息。
反向代理
客户端给服务器发送的请求,nginx服务器接收到之后,按照一定的规则分发给了后端的业务处理服务器进行处理了。此时请求的来源也就是客户端是明确的,但是请求具体由哪台服务器处理的并不明确了,nginx扮演的就是一个反向代理角色。
反向代理,主要用于服务器集群分布式部署的情况下,反向代理隐藏了服务器的信息。
4 反向代理
单体架构
单体架构问题:
复杂性高:模块多,模块边界模糊,代码质量参差不齐,每次修改代码都心惊胆战
技术债务:随着时间的推移,需求变更和人员迭代,会逐渐形成应用程序的技术债务,并且越积越多
部署频率低:随着代码增多,构建和部署的时间也会增多,每次部署都要重新部署整个项目
可靠性差:某个应用有bug,可能会导致整个应用崩溃
扩展能力受限:单体应用只能作为一个整体应用进行扩展,无法根据业务模块的需要进行伸 缩
反向代理设置指令
学习Nginx服务器的反向代理服务,要涉及与后端代理服务器相关 的配置指令比较重要,是为客户端提供正常Web服务的基础,大家 应该熟练掌握尤其是proxy_pass指令,在实际应用过程中需要注意 一些配置细节,需要小心使用。
proxy_pass指令
该指令用来设置被代理服务器的地址,可以是主机名称、IP地址加 端口号等形式。
语法结构:
proxy_pass URL;
参数:
URL为要设置的被代理服务器的地址,包含传输协议、主机名称 或P地址加端口号、URI等要素。传输协议通常是"http"或 者"https://"。
示例:
server{
....
listen 80;
server_name *.*;
location / {
proxy_pass http://192.168.66.106:8080;
}
}
5 负载均衡
什么是负载均衡
负载均衡是高可用网络基础架构的关键组件,通常用于将工作负载分布到多个服务器来提高网站、应用、数据库或其他服务的性能和可靠性。
没有负载均衡的 web 架构
有负载均衡web架构:
upstream指令
upstream块不属于虚拟主机,只能在http块里配置,它定义了在反向代理时Nginx需要访问的后端服务器集群和负载均衡策略。
语法格式:
upstream back_end { # upstream需要一个名字
server 192.168.66.100:8080 max_conns=2 fail_timeout=1s;
server 192.168.66.106:8080 weight=1;
server 192.168.66.107:8080 weight=1;
}
server{
listen 80;
server_name *.*;
location / {
proxy_set_header Host $host; #转发原始请求的host头部
proxy_pass http://back_end; #转发到upstream块定义的服务器集群。
}
}
upstream参数:
- max_conns 节点的最大连接数
- slow_start 缓慢启动时间
- down 节点下线
- backup 备用节点
- max_fails 允许的最大失败数
- fail_timeout 超过最大失败数后的等待时间
6 负载均衡算法
轮询(默认)
轮询方式,依次将请求分配到各个后台服务器中,默认的负载均衡方式。
适用于后台机器性能一致的情况。
挂掉的机器可以自动从服务列表中剔除。
upstream bakend {
server 192.168.0.14:8080;
server 192.168.0.15:8080;
}
轮询加权重
根据权重来分发请求到不同的机器中,指定轮询几率,weight和访 问比率成正比,用于后端服务器性能不均的情况。
upstream bakend {
server 192.168.0.14:8080 weight=10;
server 192.168.0.15:8080 weight=10;
}
IP_hash
每个请求按访问IP的哈希结果分配,使来自同一个IP的访客固定访问一台后端服务器,并且可以有效解决动态网页存在的session共享问题。俗称IP绑定。
upstream backServer{
server 127.0.0.1:8080 ;
server 127.0.0.1:8081 ;
ip_hash;
}
server {
listen 80;
server_name www.itmayiedu.com;
location / {
### 指定上游服务器负载均衡服务器
proxy_pass http://backServer;
index index.html index.htm;
}
}
url_hash
按访问的URL的哈希结果来分配请求,使每个URL定向到一台后端 服务器,可以进一步提高后端缓存服务器的效率。Nginx本身不支 持url_hash,如果需要这种调度算法,则必须安装Nginx的hash软件包。
fair
比 weight、ip_hash更加智能的负载均衡算法,fair算法可以根据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx本身不支持fair,如果需要这种调度算法,则必须安装upstream_fair模块。
7 fair模块安装
模块介绍
fair采用的不是内建负载均衡使用的轮换的均衡算法,而是可以根据页面大小、加载时间长短智能的进行负载均衡。
模块安装
xftp上传fair模块安装包到/opt/apps下,并解压
unzip nginx-upstream-fair-master.zip
切换到nginx目录执行一下操作
[root@localhost nginx-1.20.1]# pwd
/opt/apps/nginx-1.20.1
[root@localhost nginx-1.20.1]# ./configure --prefix=/usr/local/nginx --add-module=/opt/apps/nginx-upstream-fair-master
编译
make
备份原来的nginx命令
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx-bak
替换原来的 nginx 命令
cp /opt/apps/nginx-1.20.1/objs/nginx /usr/local/nginx/sbin/nginx
配置实现
upstream backserver {
fair;
server 192.168.0.14:8080;
server 192.168.0.15:8080;
}
注意: 已安装Nginx,配置第三方模块时,只需要–add-module=/第 三方模块目录,然后make编译一下就可以,不要 make install 安装。编译后复制objs下面的nginx到指定目录下。
8 Nginx配置故障转移
当上游服务器(真实访问服务器),一旦出现故障或者是没有及时相应的话,应该直接轮训到下一台服务器,保证服务器的高可用。
Nginx配置代码
server {
listen 80;
server_name *.*;
location / {
### 指定上游服务器负载均衡服务器
proxy_pass http://backServer;
#故障转移的条件:如果后端的服务器返回502、504、执行超时等错误,
#自动将请求转发到upstream负载均衡池中的另一台服务器,实现故障转移。
proxy_next_upstream http_502 http_504 error timeout invalid_header;
###nginx与上游服务器(真实访问的服务器)超时时间
###后端服务器连接的超时时间_发起握手等候响应超时时间
proxy_connect_timeout 1s;
###nginx发送给上游服务器(真实访问的服务器)超时时间
proxy_send_timeout 1s;
### nginx接受上游服务器(真实访问的服务器)超时时间
proxy_read_timeout 1s;
index index.html index.htm;
}
}
9 跨域问题
为什么会出现跨域问题
出于浏览器的同源策略限制。同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之 的,浏览器只是针对同源策略的一种实现。
什么是跨域
当一个请求URL的协议、域名、端口三者之间任意一个与当前页面 url不同即为跨域。
跨域问题演示示例
前端页面 通过localhost:8080的tomcat部署
<html>
<body>
<button onclick="test()">发送</button>
</body>
<script
src="http://libs.baidu.com/jquery/2.0.0/jque
ry.min.js"></script>
<script>
function test (){
$.get("http://192.168.66.100:90/abc", function(result){
alert(result);
});
}
</script>
</html>
如下报错
index.html:1 Access to XMLHttpRequest at 'http://192.168.66.100:90/abc' from origin
'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is
present on the requested resource.
jquery.min.js:6 GET http://192.168.66.100:90/abc net::ERR_FAILED 200
10 跨域问题解决
解决方案
只需要在Nginx的配置文件中配置以下参数:
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,XRequested-With,If-Modified-Since,CacheControl,Content-Type,Authorization';
if ($request_method = 'OPTIONS') {
return 204;
}
}
参数:
- Access-Control-Allow-Origin 表示服务器可以接受所有的请求源(Origin),即接受所有跨域的请求。
- Access-Control-Allow-Methods 明确了客户端所要访问的资源允许使用的方法或方法列表。
- Access-Control-Allow-Headers 设置预检请求。
11 动静分离
Nginx动静分离简单来说就是把动态和静态请求分开,不能理解成只是单纯的把动态页面和静态页面物理分离。严格意义上说应该是动态请求和静态请求分开,可以理解成使用Nginx处理静态请求, Tomcat处理动态请求。
什么是动静分离
动:必须依赖服务器生存的文件 比如jsp。
静:不需要依赖容器的比如css/js或者图片等文件
动静分离的好处
- Nginx本身就是一个高性能的静态web服务器
- 其实静态文件有一个特点就是基本上变化不大,所以动静分离以后我们可以对静态文件进行缓存、 或者压缩提高网站性能
静态资源的类型
在Nginx的conf目录下,有一个mime.types文件里边列出了静态资源的类型,如下:
当用户访问一个网站,然后从服务器端获取相应的资源,通过浏览器进行解析渲染最后展示给用户,服务端可以返回各种类型的内容,比如xml、jpg、png、gif、flash、MP4、html、 css等等,浏览器就是根据mime-type来决定用什么形式来解析和展示的。服务器返回的资源给到浏览器时,会把媒体类型告 知浏览器,这个告知的标识就是Content-Type,比如ContentType:text/html。
12 动静分离实战
静态资源的准备
在服务器中准备文件夹放置图片、css、js。
mkdir -p /usr/local/nginx/static
通过请求分离
upstream webservers {
server 192.168.66.106:8080 weight=5;
server 192.168.66.107:8080 weight=5;
}
server {
listen 80;
server_name *.*;
location / {
root html;
index index.html index.htm;
proxy_set_header Host $host;
proxy_pass http://webservers;
}
location /image/ {
root static;
}
location /web/ {
proxy_set_header Host $host;
proxy_pass http://webservers;
}
}
根据扩展名分离
upstream webservers {
server 192.168.66.106:8080 weight=5;
server 192.168.66.107:8080 weight=5;
}
server {
listen 80;
server_name *.*;
location / {
root html;
index index.html index.htm;
proxy_set_header Host $host;
proxy_pass http://webservers;
}
location ~ .*.(jpg|png|gif|css|js)$ {
root static;
}
}
13 缓存机制
核心:
响应速度历来是衡量WEB应用和服务性能优劣的重要指标之 一,尤其动态网站在网络上泛滥的今天。除了优化发布内容以外,另外一个主要的办法就是把不需要实时更新的动态页面输出结果转为静态网页形式缓存,进而按照静态网页来访问。
proxy Cache缓存机制
配置proxy_cache模块
语法结构
在nginx.conf文件中添加如下代码:
http{
......
proxy_cache_path /data/nginx/tmp-test levels=1:2 keys_zone=tmp-test:100m inactive=7d max_size=1000g;
}
参数说明:
- proxy_cache_path 缓存文件路径
- levels 设置缓存文件目录层次;levels=1:2 表示两级目录
- keys_zone 设置缓存名字和共享内存大小
- inactive 在指定时间内没人访问则被删除
- max_size 最大缓存空间,如果缓存空间满,默认覆盖掉缓存时间最长的资源。
当配置好之后,重启nginx,如果不报错,则配置的 proxy_cache会生效
查看 proxy_cache_path / data/ nginx / 目录, 会发现生成了 tmp -test 文件夹。
如何使用proxy_cache
语法配置
location /tmp-test/ {
proxy_cache tmp-test;
proxy_cache_valid 200 206 304 301 302 10d;
proxy_cache_key $uri;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8081/media_store.php/tmptest/;
}
参数:
- proxy_cache tmp -test 使用名为 tmp -test 的对应缓存配置
- proxy_cache_valid 200 206 304 301 302 10d; 对httpcode为200…的缓存10天
- proxy_cache_key $uri 定义缓存唯一key,通过唯一key来进行hash存取
- proxy_set_header 自定义http header头,用于发送给后端真实服务器。
- proxy_pass 指代理后转发的路径,注意是否需要最后的 /
提出问题
到此,就完成了最基本的proxy_cache配置和访问过程介绍,但是 最基本的配置,往往无法满足我们的业务需求,我们往往会提出以下疑问和需求:
需要主动清理缓存文件
解决问题
location /tmp-test/ {
allow 127.0.0.1; //只允许本机访问
deny all; //禁止其他所有ip
proxy_cache_purge tmp-test $uri; //清理缓存
}
14 什么是限流
生活中的限流
春运,一项全人类历史上最大规模的迁移活动,抢火车票一直是每 年跨年以后的热点话题。
为什么需要限流
系统设计时一般会预估负载,当系统暴露在公网中时,恶意攻击或正常突发流量等都可能导致系统被压垮,而限流就是保护措施之一。
Nginx 的二种限流设置:
控制速率。
控制并发连接数。
15 限流算法
漏桶算法
原理: 漏桶算法思路很简单,水(请求)先进入到漏桶里,漏桶以一 定的速度出水,当水流入速度过大会直接溢出,可以看出漏桶算法能强行限制数据的传输速率。
令牌桶算法
原理: 令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌, 当桶里没有令牌可取时,则拒绝服务。
漏桶 vs 令牌桶的区别
漏桶的天然特性决定了它不会发生突发流量,就算每秒1000个请求到来,那么它对后台服务输出的访问速率永远恒定。而令牌桶则不同,其特性可以“预存”一定量的令牌,因此在应对突发流量的时候可以在短时间消耗所有令牌,其突发流量处理效率会比漏桶高,但是导向后台系统的压力也会相应增多。
16 限流实战
根据nginx官网提供的说法,有两种算法,一种是漏桶算法,一种是令牌桶算法
- limit_req_zone 用来限制单位时间内的请求数目,以及速度限制。
- limit_req_conn 用来限制同一时间连接数,即并发限制。
Nginx限速配置指令
语法结构
放在http{} 内
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;
参数解析:
第一个参数:$binary_remote_addr 限制同一客户端ip地址。
第二个参数:zone=mylimit:10m 用来存储访问的频次信息。
第三个参数:rate=1r/s表示允许相同标识的客户端的访问频次,这里限制的是每秒1次,还 可以有比如30r/m的。
limit_req zone=mylimit burst=5 nodelay;
放在server{}内
参数:
第一个参数:zone=mylimit 设置使用哪个配置区域来做限制,与上面limit_req_zone 里的name 对应。
第二个参数:burst=5,重点说明一下这个配置,burst爆发的意思,这个配置的意思是设置 一个大小为5的缓冲区当有大量请求(爆发)过来时,超过了访问频次限制的请求可以先放到 这个缓冲区内。
第三个参数:nodelay,如果设置,超过访问频次而且缓冲区也满了的时候就会直接返回 503,如果没有设置,则所有请求会等待排队。
Nginx并发限制配置指令
ngx_http_limit_conn_module 提供了限制连接数的能力,利用 limit_conn_zone 和 limit_conn 两个指令即可。
语法结构
http{
#ip limit
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
}
在需要 限制并发数 和 下载带宽 的网站配置 server {}里加上如下代码:
server {
limit_conn perip 10;
limit_conn perserver 100;
}
参数说明: 补充说明下参数:
- limit_conn perip 10 作用的key 是 $binary_remote_addr,表示限制单个IP同时最多能持有 10个连接。
- limit_conn perserver 100 作用的key是 $server_name,表示虚拟主机(server) 同时能处理并发连接的总数。
设置白名单
限流主要针对外部访问,内网访问相对安全,可以不做限流,通过 设置白名单即可。利用 Nginx ngx_http_geo_module 和 ngx_http_map_module 两个工具模块即可搞定。
查看是否具有该功能
./configure --help |grep http_limit_req_module
./configure --help |grep http_geo_module
./configure --help |grep http_map_module
在 nginx.conf 的 http 部分中配置白名单:
geo $limit {
default 1;
39.100.243.125 0;
192.168.0.0/24 0;
172.20.0.35 0;
}
map limit limit_key {
0 "";
1 $binary_remote_addr;
}
limit_req_zone $limit_key zone=myRateLimit:10m rate=10r/s;
参数:
geo 对于白名单(子网或IP都可以) 将返回0,其他IP将返回1。
map 将limit转换为 limit_key,如果是 $limit 是0(白名单),则返回空字符串;如果是1,则返回客户端实际IP。
limit_req_zone 限流的key不再使用 binary_remote_addr,而是limit_key 来动态获取值。 如果是白名单,limit_req_zone 的限流key则为空字符串,将不会限流;若不是白名单,将会 对客户端真实IP进行限流。
17 Nginx高可用
什么是高可用?
高可用HA(High Availability)是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间。如果一个系统能够一直提供服务,那么这个可用性则是百分之百,但是天有不测风云。所以我们只能尽可能的去减少服务的故障。
解决的问题 在生产环境上很多时候是以 Nginx 做反向代理对外提供服务,但是一天Nginx难免遇见故障,如:服务器宕机。当 Nginx 宕机那么所有对外提供的接口都将导致无法访问。虽然我们无法保证服务器百分之百可用,但是也得想办法避免这种悲剧,今天我们 使用 keepalived 来实现 Nginx 的高可用。
双机热备方案
这种方案是国内企业中最为普遍的一种高可用方案,双机热备其实就是指一台服务器在提供服务,另一台为某服务的备用状态,当一 台服务器不可用另外一台就会顶替上去。
18 LVS负载均衡
LVS是一个开源的软件,可以实现传输层四层负载均衡。LVS是 Linux Virtual Server的缩写,意思是Linux虚拟服务器。
目标: 通过 LVS 达到的负载均衡技术和 Linux 操作系统实现一个高性能高可用的 Linux 服务器集群,它具有良好的可靠性、可扩展性和可操作性。从而以低廉的成本实现最优的性能。
LVS的八种调度算法
- 轮叫调度 rr
- 加权轮叫 wrr
- 最少链接 lc
- 加权最少链接 wlc
- 基于局部性的最少连接调度算法 lblc
- 复杂的基于局部性最少的连接算法 lblcr
- 目标地址散列调度算法 dh
- 源地址散列调度算法 sh
19 keepalived健康监测
LVS可以实现负载均衡,但是不能够进行健康检查,比如一个rs出现故障,LVS 仍然会把请求转发给故障的rs服务器,这样就会导致请求的无效性。keepalive 软件可以进行健康检查,而且能同时实现 LVS 的高可用性,解决 LVS 单点故障的问题,其实 keepalive 就是 为 LVS 而生的。
keepalived工作原理
keepalived是基于VRRP协议实现的保证集群高可用的一个服务软件,主要功能是实现真机的故障隔离和负载均衡器间的失败切换, 防止单点故障。
VRRP协议
VRRP是一种容错协议,它保证当主机的下一跳路由器出现故障时, 由另一台路由器来代替出现故障的路由器进行工作,从而保持网络 通信的连续性和可靠性。
主要作用: VRRP可以将两台或者多台物理路由器设备虚拟成一个虚拟路由,这个虚拟路由器通过虚拟IP(一个或者多个)对外提供服 务。
20 企业双机热备方案
环境服务配置
两台Nginx服务器
Nginx 主服务器 192.168.66.104
Nginx 备服务器 192.168.66.105
Lvs 虚拟VIP 192.168.66.99
环境搭建
yum install -y keepalived
keepalived 常用命令
service keepalived start
service keepalived stop
启动报错:
Starting keepalived (via systemctl): Job for keepalived.service failed. See ‘systemctl status keepalived.service’ and ‘journalctl -xn’ for details.
解决办法
[root@edu-proxy-01 sbin]# cd /usr/sbin/
[root@edu-proxy-01 sbin]# rm -f keepalived
[root@edu-proxy-01 sbin]# cp /usr/local/keepalived/sbin/keepalived /usr/sbin/
使用keepalived虚拟VIP
修改主keepalived信息
修改主Nginx服务器keepalived文件,
/etc/keepalived/keepalived.conf
State 为MASTER
! Configuration File for keepalived
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh"
#运行脚本,脚本内容下面有,就是起到一个nginx宕机以后,自动开启服务
interval 2 #检测时间间隔
weight -20 #如果条件成立的话,则权重 -20
}
# 定义虚拟路由,VI_1 为虚拟路由的标示符,自己定义名称
vrrp_instance VI_1 {
state MASTER #来决定主从
interface ens33 # 绑定虚拟 IP 的网络接口,根据自己的机器填写
virtual_router_id 121 # 虚拟路由的 ID 号,两个节点设置必须一样
mcast_src_ip 192.168.66.104 #填写本机ip
priority 100 # 节点优先级,主要比从节点优先级高
nopreempt # 优先级高的设置 nopreempt 解决异常恢复后再次抢占的问题
advert_int 1 # 组播信息发送间隔,两个节点设置必须一样,默认 1s
authentication {
auth_type PASS
auth_pass 1111
}
# 将 track_script 块加入 instance 配置块
track_script {
chk_nginx #执行 Nginx 监控的服务
}
virtual_ipaddress {
192.168.66.99 # 虚拟ip,也就是解决写死程序的ip怎么能切换的ip,也可扩展,用途广泛。可配置多个。
}
}
修改从keepalived信息
修改从Nginx服务器keepalived文件,
/etc/keepalived/keepalived.conf
State 为BACKUP
! Configuration File for keepalived
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh"
#运行脚本,脚本内容下面有,就是起到一个nginx宕机以后,自动开启服务
interval 2 #检测时间间隔
weight -20 #如果条件成立的话,则权重 -20
}
# 定义虚拟路由,VI_1 为虚拟路由的标示符,自己定义名称
vrrp_instance VI_1 {
state BACKUP #来决定主从
interface ens33 # 绑定虚拟 IP 的网络接口,根据自己的机器填写
virtual_router_id 121 # 虚拟路由的 ID 号,两个节点设置必须一样
mcast_src_ip 192.168.66.105 #填写本机ip
priority 100 # 节点优先级,主要比从节点优先级高
nopreempt # 优先级高的设置 nopreempt 解决异常恢复后再次抢占的问题
advert_int 1 # 组播信息发送间隔,两个节点设置必须一样,默认 1s
authentication {
auth_type PASS
auth_pass 1111
}
# 将 track_script 块加入 instance 配置块
track_script {
chk_nginx #执行 Nginx 监控的服务
}
virtual_ipaddress {
192.168.66.99 # 虚拟ip,也就是解决写死程序的ip怎么能切换的ip,也可扩展,用途广泛。可配置多
个。
}
}
Nginx+keepalived实现高可用
写入nginx_check.sh脚本 /etc/keepalived/nginx_check.sh
#!/bin/bash
A=`ps -C nginx –no-header |wc -l`
if [ $A -eq 0 ];then
/usr/local/nginx/sbin/nginx
sleep 2
if [ `ps -C nginx --no-header |wc -l` -eq
0 ];then
killall keepalived
fi
fi
注意: 该脚本一定要授权。
chmod 777 nginx_check.sh