分布式调用与高并发处理 Nginx

 一、初识Nginx

分布式调用与高并发处理 Nginx_第1张图片

 1.1 Nginx概述

Nginx是一款轻量级的Web服务器、反向代理服务器,由于它的内存占用少,启动极快,高并发能力强,在互联网项目中广泛应用。Nginx 专为性能优化而开发,使用异步非阻塞事件驱动模型

常见服务器

  • Apache
  • Tomcat

分布式调用与高并发处理 Nginx_第2张图片

 没有Nginx的情况

分布式调用与高并发处理 Nginx_第3张图片

 有了Nginx的话

分布式调用与高并发处理 Nginx_第4张图片

 1.2 Nginx 四大应用场景

分布式调用与高并发处理 Nginx_第5张图片

 HTTP服务器

Nginx本身也是一个静态资源的服务器,当只有静态资源的时候,就可以使用Nginx来做服务器,如果一个网站只是静态页面的话,那么就可以通过这种方式来实现部署。

反向代理

反向代理应该是Nginx使用最多的功能了,反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。增强安全性。

分布式调用与高并发处理 Nginx_第6张图片

负载均衡 

负载均衡也是Nginx常用的一个功能,负载均衡其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。

分布式调用与高并发处理 Nginx_第7张图片

 动静分离

动静分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作,这就是网站静态化处理的核心思路。

分布式调用与高并发处理 Nginx_第8张图片

 1.3 为什么要使用Nginx

分布式调用与高并发处理 Nginx_第9张图片

 背景

互联网飞速发展的今天,大用户量高并发已经成为互联网的主体.怎样能让一个网站能够承载几万个或几十万个用户的持续访问呢?

单机架构

分布式调用与高并发处理 Nginx_第10张图片

 Tomcat 默认配置的最大请求数是150,也就是说同时支持150个并发。具体能承载多少并发,须要看硬件的配置,线程CPU 越多性能越高,分配给JVM的内存越多性能也就越高,但也会加剧GC的负担。

引入反向代理实现负载均衡

分布式调用与高并发处理 Nginx_第11张图片

 负载均衡就是一个web服务器解决不了的问题可以通过多个web服务器来平均分担压力来解决,并发过来的请求被平均分配到多个后台web服务器来处理,这样压力就被分解开来。

 总结

  1. 它可以高并发连接,官方测试能够支撑5万并发连接,在实际生产环境中可以支撑2到4万并发连接。
  2. 内存消耗少
  3. 购买F5 BIG-IP ,NetScaler等硬件负载均衡交换机需要10多万甚至几十万人民币。而Nginx为开源软件,可以免费试用,并且可用于商业用途。
  4. 内置的健康检查功能:如果Nginx proxy后端的某台服务器宕机了,不会影响前端访问。
  5. 节省带宽,支持gzip压缩。
  6. 稳定性高:用于反向代理(负载均衡),宕机的概率微乎其微。
  7. 支持热部署。在不间断服务的情况下,对软件版本升级。

 二、Nginx安装部署

2.1 环境准备

分布式调用与高并发处理 Nginx_第12张图片

学习环境

操作系统:Centos7.5 X64

四项确认

  1. 确认网络
#使用以下命令检查centos系统能否上网
ping www.baidu.com

     2.确认yum可用

#使用如下命令检查yum源是否可用,出现一堆版本号表示可用。
yum list

     3.确认防火墙关闭

#查看防火墙是否关闭
firewall-cmd --state

#永久关闭防火墙
systemctl disable firewalld.service

    4.确认关闭SELinux安全防护

#进入配置文件
vim /etc/selinux/config

#修改该配置
SELINUX=disabled

 一项安装

yum -y install gcc make automake pcre-devel zlib zlib-devel openssl openssl-devel

参数:

  • gcc:编译依赖gcc环境,c语言的运行环境。
  • pcre:PCRE(Perl Compatible Regular Expressions)是一个Perl库,包括 Perl 兼容的正则表达式库。
  • zlib:zlib库提供了很多种压缩和解压缩的方式,Nginx使用zlib对http包的内容进行gzip,所以需要在linux上安装zlib库。
  • Openssl:OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用。

2.2 Nginx下载与安装

分布式调用与高并发处理 Nginx_第13张图片

下载Nginx源码

官网下载Nginx软件http://Nginx.org

分布式调用与高并发处理 Nginx_第14张图片

Mainline Version:主线版,是最新版,但未经过过多的生产测试。

Stable Version:稳定版,生产环境使用版本。

Legacy Version:老版本。

注意:

我们需要下载的是 Stable Version。其中又分为两种版本:Linux 版与 Windows 版。开发时这两个版本我们都下载。Linux 版用于生产环境,而 Windows 版用于开发测试,选择需要的版本进行下载。

 在虚拟机中下载源码

wget https://nginx.org/download/nginx-1.20.2.tar.gz

 解压文件到usr/local目录下

tar -zxvf nginx-1.20.2.tar.gz -C /usr/local

其中各个目录中存放的文件作用为:

auto:存放 Nginx 自动安装的相关文件

conf:存放 Nginx 服务器配置文件

configure:命令,用于对即将安装的软件的配置,完成 makefile 编译文件的生成

contrib:存放由其他机构贡献的文档材料

html:存放 Nginx 欢迎页面

man:manual,手册,存放 Nginx 帮助文档

src:存放 Nginx 源码

configure 参数:

--prefix:Nginx 安装目录。注意,安装目录与解压目录不一样

--sbin-path:Nginx 命令文件

--modules-path:Nginx 模块存放路径

--conf-prefix:Nginx 配置文件存放路径

--pid-path:Nginx 的进程 id 文件

--error-log-path:错误日志文件

--http-log-path:http访问日志文件

配置ngix参数

#创建目录
[root@node1 Nginx-1.20.1]# mkdir -p /var/temp/nginx/client

#配置参数
[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

编译

make

安装

make install

如果出现ngnix文件就表示ngix安装成功啦! 

 2.3 Nginx目录详解

分布式调用与高并发处理 Nginx_第15张图片

分布式调用与高并发处理 Nginx_第16张图片

conf目录

Nginx所有配置文件的目录,极其重要。在该目录中包含一个Nginx.conf配置文件。

[root@node1 Nginx]# ll conf/
总用量 68
-rw-r--r-- 1 root root 1077 8月 27 15:37 fastcgi.conf
-rw-r--r-- 1 root root 1077 8月 27 15:37 fastcgi.conf.default
-rw-r--r-- 1 root root 1007 8月 27 15:37 fastcgi_params
-rw-r--r-- 1 root root 1007 8月 27 15:37 fastcgi_params.default
-rw-r--r-- 1 root root 2837 8月 27 15:37 koi-utf
-rw-r--r-- 1 root root 2223 8月 27 15:37 koi-win
-rw-r--r-- 1 root root 5231 8月 27 15:37 mime.types
-rw-r--r-- 1 root root 5231 8月 27 15:37 mime.types.default
-rw-r--r-- 1 root root 2656 8月 27 15:37 Nginx.conf
-rw-r--r-- 1 root root 2656 8月 27 15:37 Nginx.conf.default
-rw-r--r-- 1 root root 636 8月 27 15:37 scgi_params
-rw-r--r-- 1 root root 636 8月 27 15:37 scgi_params.default
-rw-r--r-- 1 root root 664 8月 27 15:37 uwsgi_params
-rw-r--r-- 1 root root 664 8月 27 15:37 uwsgi_params.default
-rw-r--r-- 1 root root 3610 8月 27 15:37 win-utf

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/
总用量 5884
-rwxr-xr-x 1 root root 6023208 8月 27 15:37 Nginx #启动关闭等操作的脚本
[root@node1 Nginx]# ./sbin/Nginx #启动Nginx
[root@node1 Nginx]# ps aux|grep Nginx #查看Nginx的进程
root   24514 0.0 0.1 45996 1136 ?     Ss  16:29  0:00 Nginx: master process ./sbin/Nginx
nobody  24515 0.0 0.1 46444 1876 ?     S  16:29  0:00 Nginx: worker process

2.4 Docker安装Nginx服务

分布式调用与高并发处理 Nginx_第17张图片

拉取官方的Nginx镜像 

docker pull nginx

创建并运行Nginx容器

docker run --rm --name nginx-test -p 8080:80 -d nginx

参数的含义如下: 

--rm:容器终止运行后,自动删除容器文件。

 --name nginx-test:容器的名字叫做Nginx-test,名字自己定义.

 -p: 端口进行映射,将本地 8080 端口映射到容器内部的 80 端口

 -d:容器启动后,在后台运行

 Nginx 服务部署,映射本地目录到Nginx容器

创建本地目录,用于存放Nginx的相关文件信息.

mkdir -p /opt/nginx/html  /opt/nginx/conf

参数:

  • html: 目录将映射为 nginx 容器配置的虚拟目录。
  • conf: 目录里的配置文件将映射为 nginx 容器的配置文件。

拷贝容器内 Nginx 默认配置文件到本地当前目录下的 conf 目录,容器ID可以查看 docker ps 命令输入中的第一列 

docker cp 08a37:/etc/nginx/nginx.conf /home/nginx/conf/

08a37是nginx容器的前几位id

 部署命令

docker run --rm -d -p 8081:80 --name nginx-test-web \
  -v /opt/nginx/html:/usr/share/nginx/html \
  -v /opt/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
  nginx

命令说明:

  • --rm:容器终止运行后,自动删除容器文件。
  • -p 8081:80: 将容器的 80 端口映射到主机的 8082 端口.
  • --name nginx-test-web:将容器命名为 Nginx-test-web
  • -v /home/Nginx/html:/usr/share/Nginx/html:将我们自己创建的 html目录挂载到容器的 /usr/share/Nginx/html。
  • -v /home/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:将我们自己创建的 nginx.conf 挂载到容器的 /etc/nginx/nginx.conf。

因为nginx配置较多,因此在后期的学习中使用的是源码的方式使用nginx。

2.5 Nginx启停服务

分布式调用与高并发处理 Nginx_第18张图片

Nginx服务的启动

在Linux 平台下,启动Nginx服务器直接运行安装目录下sbin目录中的二进制文件即可。

./nginx (-h) #参数可选

参数:

  • -v : 打印版本号
  • -V : 打印版本号和配置
  • -t:测试配置正确性并退出
  • -q:测试配置时只显示错误
  • -s:向主进程发送信号
  • -p:指定Nginx服务器路径前缀
  • -c: 指定Nginx配置文件路径
  • -g: 指定Nginx附加配置文件路径

查看nginx进程

ps -ef | grep nginx

在浏览器中打开nginx服务器

nginx服务默认占用的端口是80

分布式调用与高并发处理 Nginx_第19张图片

 nginx已经启动。

Nginx服务的停止

快速停止,快速停止是指立即停止当前Nginx服务正在处理的所有网络请求,马上丢弃连接,停止工作。

./nginx -s stop   # 快速关闭

平缓停止,平缓停止是指允许Nginx服务将当前正在处理的网络请求处理完成,但不再接收新的请求,之后关闭连接,停止工作。

./nginx -s quit   # 等待工作进程处理完成后关闭

Nginx服务的重启

更改Nginx服务器的配置和加入新模块后,如果希望当前的Nginx服务应用新的配置或使新模块生效,就需要重启Nginx服务。当然我们可以先关闭Nginx服务,然后使用新的Nginx配置文件重启服务。

./nginx -s reload  # 向主进程发送信号,重新加载配置文件,热重启
./nginx -s reopen  # 重启 Nginx

三、Nginx配置指令详解

分布式调用与高并发处理 Nginx_第20张图片

 最核心的配置文件是/nginx/conf/nginx.conf 文件 

分布式调用与高并发处理 Nginx_第21张图片

3.1 全局块配置详解

配置运行Nginx服务器用户(组)

用于配置运行Nginx服务器用户(组)的指令是user。

user zj  zj;   #表示将nginx的生杀大权交给了zj用户zj组

注意:

只有被设置的用户或者用户组成员才有权限启动你那个Nginx进程,如果是其他用户尝试启动Nginx进程,将报错

如果希望所有用户都可以启动Nginx进程,有两种办法:一是将次指令注释:

# user zj zj;

或者把用户(和用户组)设置为nobody;

user nobody nobody;

注意:

在Nginx配置文件中,每一条指令配置必须以分号结束,请不要忘记。

 配置允许生成worker process数

worker process是Nginx服务器实现并发处理的关键所在。理论来说worker_process的值越大,可以支持的并发处理也越多。

worker_process number | auto

参数:

  • number 指定Nginx进程最多可以产生的worker_process数。其值通常设置为电脑CPU的个数或者倍数。
  • auto ,设置此值,Nginx进程将自动检测。

在默认的配置文件中,Number=1.启动Nginx服务器后,使用以下命令可以看出Nginx服务器除了主进程master process ../sbin/Nginx之外,还生成了一个worker_process。

ps aux|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)"

配置文件的引入

在一些情况下,我们可能需要将其他的Nginx配置或者第三方模块的配置引用到当前的主配置文件中。Nginx 提供了include指令来完成配置文件的引入。

include file;

 其中,file是要引入的配置文件,它支持相对路径。

注意: 新引用进来的文件同样要求运行Nginx进程的用户对其具有写权限,并且符合Nginx配置文件规定的相关语法和结构。此指令可以放在配置文件的任意地方。

3.2 events块配置详解

分布式调用与高并发处理 Nginx_第22张图片

配置事件驱动模型

 Nginx服务器提供了多种事件驱动模型来处理网络消息。配置文件中为我们提供了相关的指令来强制Nginx服务器选择哪种事件驱动模型进行消息处理。

use method;

其中,method可选择的内容有: select、poll、kqueue、epoll、rtsig、ldev/poll l以及 eventport。

标准事件模型:

  • Select、poll属于标准事件模型,如果当前系统不存在更有效的方法,Nginx会选择select或poll

高效事件模型:

  • Kqueue:使用于FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 和 MacOS X.使用双处理器的MacOS X系统使用kqueue可能会造成内核崩溃。
  • Epoll:多路IO复用高性能网络模型,使用于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和--without-select_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.3 HTTP块配置详解

分布式调用与高并发处理 Nginx_第23张图片

 定义MIME-Type

在常用的浏览器中,可以显示的内容有HTML、XML、GIF及Flash等种类繁多的文本、媒体等资源,浏览器为区分这些资源,需要使用MIME Type。换言之,MIME Type是网络资源的媒体类型。Nginx服务器作为Web服务器,必须能够识别前端请求的资源类型。

include    mime.types;     #mime.types是nginx目录下的一个配置文件
default_type  application/octet-stream;   #默认类型

看下mime.types片段:

分布式调用与高并发处理 Nginx_第24张图片

 自定义服务日志

记录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整体使用单引号括起来。

日志格式:

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';
 

日志格式设置 :

$remote_addr与$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 ...;
server_name  www.baidu.com     //精确匹配
server_name  *.baidu.com;       //通配
server_name  www.baidu.com  *baidu.com;
四种写法:

server_name www.baidu.com;

server_name *.baidu.com;

server_name www.baidu.*;

server_name ~^www\.baidu\.*$;

优先级

分布式调用与高并发处理 Nginx_第25张图片

3.4 配置总结

#运行用户
user nobody;
#启动进程,通常设置成和cpu的数量相等
worker_processes  1;


#全局错误日志及PID文件
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;


#pid     logs/Nginx.pid;


#工作模式及连接数上限
events {
   #epoll是多路复用IO(I/O Multiplexing)中的一种方式,
   #仅用于linux2.6以上内核,可以大大提高Nginx的性能
   use  epoll; 


   #单个worker进程的最大并发链接数  
   worker_connections  1024;


   # 并发总数是 worker_processes 和 worker_connections 的乘积
   # 即 max_clients = worker_processes * worker_connections
   # 在设置了反向代理的情况下,max_clients = worker_processes * worker_connections / 4  为什么
   # 为什么上面反向代理要除以4,应该说是一个经验值
   # 根据以上条件,正常情况下的Nginx Server可以应付的最大连接数为:4 * 8000 = 32000
   # worker_connections 值的设置跟物理内存大小有关
   # 因为并发受IO约束,max_clients的值须小于系统可以打开的最大文件数
   # 而系统可以打开的最大文件数和内存大小成正比,一般1GB内存的机器上可以打开的文件数大约是10万左右
   # 我们来看看360M内存的VPS可以打开的文件句柄数是多少:
   # $ cat /proc/sys/fs/file-max
   # 输出 34336
   # 32000 < 34336,即并发连接总数小于系统可以打开的文件句柄总数,这样就在操作系统可以承受的范围之内
   # 所以,worker_connections 的值需根据 worker_processes 进程数目和系统可以打开的最大文件总数进行适当地进行设置
   # 使得并发总数小于操作系统可以打开的最大文件数目
   # 其实质也就是根据主机的物理CPU和内存进行配置
   # 当然,理论上的并发总数可能会和实际有所偏差,因为主机还有其他的工作进程需要消耗系统资源。
   # ulimit -SHn 65535


}




http {
   #设定mime类型,类型由mime.type文件定义
   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 指令指定 Nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,
   #对于普通应用,必须设为 on,
   #如果用来进行下载等应用磁盘IO重负载应用,可设置为 off,
   #以平衡磁盘与网络I/O处理速度,降低系统的uptime.
   sendfile   on;
   #tcp_nopush   on;


   #连接超时时间
   #keepalive_timeout  0;
   keepalive_timeout  65;
   tcp_nodelay   on;


   #开启gzip压缩
   gzip  on;
   gzip_disable "MSIE [1-6].";


   #设定请求缓冲
   client_header_buffer_size   128k;
   large_client_header_buffers  4 128k;




   #设定虚拟主机配置
   server {
     #侦听80端口
     listen   80;
     #定义使用 www.Nginx.cn访问
     server_name  www.Nginx.cn;


     #定义服务器的默认网站根目录位置(编译的时候--prefix是整个Nginx的根目录,这里的html文件夹是相对--prefix的路径)
     root html;


     #设定本虚拟主机的访问日志
     access_log  logs/Nginx.access.log  main;


     #默认请求
     location / {
      
       #定义首页索引文件的名称
       index index.php index.html index.htm;  


     }


     # 定义错误提示页面
     error_page  500 502 503 504 /50x.html;
     location = /50x.html {
     }


     #静态文件,Nginx自己处理
     location ~ ^/(images|javascript|js|css|flash|media|static)/ {
      
       #过期30天,静态文件不怎么更新,过期可以设大一点,
       #如果频繁更新,则可以设置得小一点。
       expires 30d;
     }


     #PHP 脚本请求全部转发到 FastCGI处理. 使用FastCGI默认配置.
     location ~ .php$ {
       fastcgi_pass 127.0.0.1:9000;
       fastcgi_index index.php;
       fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
       include fastcgi_params;
     }


     #禁止访问 .htxxx 文件
       location ~ /.ht {
       deny all;
     }
   }
}

3.4 location指令

分布式调用与高并发处理 Nginx_第26张图片

location以来处理不同的请求 。 

 配置location块

URL  // http://ip:port/


location [ = | ~ | ~* | ^~] uri { 
    ... 
}
匹配规则 含义 示例
= 精确匹配 location = /images/ {...}
~ 正则匹配,区分大小写 location ~ .(jpg | gif)$ {...}
~* 正则匹配,不区分大小写 location ~* .(jpg | jif)$ {...}
^~ 匹配到即停止搜索 location ^~ /images/ {...}
不带任何符号 location / {...}

示例1:没有修饰符

没有修饰符 表示:必须以指定模式开始,如:

server {
  server_name *.*;
  location  /abc {
    ……
  }
}

#注意  /abc 前后都存在空格

 表示访问的路径中只要包含/abc就能访问到{}中的资源根路径。

注意如下是对的:

http://baidu.com/abc

http://baidu.com/abc?p1=12312&name=w24

http://baidu.com/abc/

http://baidu.com/abcde

示例2:=

= 表示:必须与指定的模式精确匹配

server {
   server_name *.*;
  location = /abc {
    ……
  }
}

 就是说浏览器必须访问192.168.66.100/abc才能访问到资源的根路径。

那么,如下是对的:

 192.168.66.100/abc 

192.168.66.100/abc?p1

如下是错的:

 http://192.168.66.100/abc/ 

192.168.66.100/abcde

示例3:~

~ 表示:指定的正则表达式要区分大小写

server {
  server_name *.*;
  location ~ ^/abc$ {
    ……
  }
}

  ~ ^/abc$表示匹配的路径只能是小写的abc

注意:

对的

192.168.66.100/abc

192.168.66.100/abc?name=wcc&password=123

错误

192.168.66.100/ABC

192.168.66.100/abc/

192.168.66.100/abcde

示例4:~*

~* 表示:指定的正则表达式不区分大小写

server {
server_name *.*;
location ~* ^/abc$ {
    ……
  }
}

注意:

那么,如下是对的: 
192.168.66.100/abc 
192.168.66.100/ABC 
192.168.66.100/abc?p1=11&p2=22 
如下是错的: 
192.168.66.100/abc/ 
192.168.66.100/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 ] 
}

结论:

  1. / -> 匹配A
  2. /index.html -> 匹配B
  3. /documents/a.html -> 匹配C
  4. /images/1.gif -> 匹配D
  5. /documents/1.jpg -> 匹配E

 配置请求的根目录

Web服务器接收到网络请求之后,首先要在服务器端指定目录中寻找请求资源。在Nginx服务器中,指令root就是用来配置这个根目录的。

root path;

例如:

    server {

        #设置nginx端口号
        listen       80;
        server_name  localhost;

        #设置匹配规则
        location / {
            root   html;
            index  index.html index.htm;
        }

        ……
      }

这里的html实际上是nginx根目录下的html文件。这是一种相对路径的指定方式,当然我们还可以使用绝对路径指定资源的位置。

配置完成后需要重启nginx使配置生效一下:

[root@localhost sbin]# ./nginx -s reload

 此时,我们在访问192.168.66.100:80的时候,nginx会根据配置定位到html目录,此时在访问路径后面加上资源的名称,即可访问html目录下的相关的资源。例如:192.168.66.100:80/dog.png 表示访问的是html目录下的dog.png

四、Nginx虚拟主机

4.1虚拟主机的分类

分布式调用与高并发处理 Nginx_第27张图片

虚拟主机是一种特殊的软硬件技术,它可以将网络上的每一台计算机分成多个虚拟主机,每个虚拟主机可以独立对外提供www服务,这样就可以实现一台主机对外提供多个web服务,每个虚拟主机之间是独立的,互不影响的。 

基于IP的虚拟主机

分布式调用与高并发处理 Nginx_第28张图片

 通过不同的ip访问nginx里面不同的项目,在nginx配置文件nginx.conf中存在一个叫server的配置块,其实,一个server配置快就是一个虚拟主机。但是在工作中用的比较少。

基于端口的虚拟主机

分布式调用与高并发处理 Nginx_第29张图片

 基于域名的虚拟主机

分布式调用与高并发处理 Nginx_第30张图片

 4.2 基于单网卡多ip虚拟主机配置

分布式调用与高并发处理 Nginx_第31张图片

 通过不同的IP区分不同的虚拟主机,此类虚拟主机对应的企业应用非常少见,一般不同业务需要使用多IP的常见都会在负载均衡器上进行VIP绑定,而不是在Web上通过绑定IP区分不同的虚拟机。

需求

一台Linux服务器绑定两个ip:192.168.66.100、192.168.66.103 访问不同的ip请求不同的html目录,即: 访问http://192.168.66.100将访问“html100”目录下的html网页 访问http://192.168.66.103将访问“html103”目录下的html网页

Linux绑定多IP

Linux操作系统允许绑定多IP。是在一块物理网卡上可以绑定多个lP地址。这样就能够在使用单一网卡的同一个服务器上运行多个基于IP的虚拟主机。但是在绑定多IP时需要将动态的IP分配方式修改为静态的指定IP。

#进入网卡的配置文件
vim /etc/sysconfig/network-scripts/ifcfg-ens33


#在配置文件中绑定多个ip
IPADDR0=192.168.66.100
IPADDR1=192.168.66.103


#使配置文件生效
service network restart


#查看该虚拟机绑定的ip
ip addr

在nginx服务器下创建两个虚拟主机的资源

 mkdir html100
 mkdir html103

分布式调用与高并发处理 Nginx_第32张图片

#在html100文件夹下创建index.html文件,文件内容为this is html100
echo "this is html100"  > index.html

#同理在html103文件夹创建index.html文件
echo "this is html100"  > index.html

修改Nginx的配置文件ngnix.conf完成基于IP的虚拟主机配置

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

#一个Server就是一个虚拟主机
  server {
    listen    80;
    server_name  192.168.66.100;   #为虚拟机指定IP或者是域名
    #主要配置路由访问信息
    location / {
      root  html100;      #用于指定访问根目录时,访问虚拟主机的web目录
      
      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.103;
      #主要配置路由访问信息
    location / {
      #用于指定访问根目录时,访问虚拟主机的web目录
      root  html103;
      #在不指定访问具体资源时,默认的展示资源的列表
      index index.html index.htm;
     } 
    error_page  500 502 503 504  /50x.html;
    location = /50x.html {
      root  html;
     }
   }
}
#重启nginx服务
[root@localhost sbin]# ./nginx  -s reload

分布式调用与高并发处理 Nginx_第33张图片

4.3 基于域名虚拟主机配置

分布式调用与高并发处理 Nginx_第34张图片

需求

两个域名指向同一个nginx服务器,用户访问不同的域名时显示不同的内容。

域名规划:

1, http://www.qiantai.cn/ => 前台

2, http://www.houtai.cn/ =》 后台

 修改windows的hosts文件配置域名与ip的映射

文件路径:C:\Windows\System32\drivers\etc\hosts

192.168.66.100  www.qiantai.cn www.houtai.cn

在Nginx下创建两个文件夹分别叫qiantai和houtai 

分布式调用与高并发处理 Nginx_第35张图片

分别在两个文件夹中创建index.html文件

[root@localhost qiantai]# echo "this is qiantai" > index.html

[root@localhost houtai]# echo "this is houtai" > index.html

修改nginx.conf配置文件

server {
  listen    80;
    #为虚拟机指定IP或者是域名
  server_name  www.qiantai.cn;
    #主要配置路由访问信息
  location / {
  #用于指定访问根目录时,访问虚拟主机的web目录
    root  qiantai;
  #在不指定访问具体资源时,默认的展示资源的列表
    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.houtai.cn;
#主要配置路由访问信息
  location / {
  #用于指定访问根目录时,访问虚拟主机的web目录
    root  houtai;
  #在不指定访问具体资源时,默认的展示资源的列表
    index index.html index.htm;
   } 
  error_page  500 502 503 504  /50x.html;
  location = /50x.html {
    root  html;
   }
}

 重启ngxin服务

[root@localhost sbin]# ./nginx -s reload

浏览器访问

分布式调用与高并发处理 Nginx_第36张图片

分布式调用与高并发处理 Nginx_第37张图片

 4.4.基于多端口虚拟主机配置

分布式调用与高并发处理 Nginx_第38张图片

通过不同的端口来区分不同的虚拟主机。此类虚拟主机对应的企业应用主要为公司内部的网站。 

需求

Nginx对提供8888与9999两个端口的监听服务

请求8888端口则访问html8888目录下的index.html

请求9999端口则访问html9999目录下的index.html

还原IP地址为192.168.66.100:

vim /etc/sysconfig/network-scripts/ifcfg-ens33
#将:
IPADDR0=192.168.66.100
IPADDR1=192.168.66.101
#改为
IPADDR=192.168.66.100

#重启网络服务
systemctl restart network

在在Nginx下创建两个文件夹分别叫html8888和html9999,在文件夹中创建index.html文件

修改Nginx的配置文件完成基于端口的虚拟主机配置

#一个Server就是一个虚拟主机 基于端口
server {
   listen    8888;
    #为虚拟机指定IP或者是域名
   server_name 192.168.66.100;
    #主要配置路由访问信息
   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.100;


    #主要配置路由访问信息
   location / {
        #用于指定访问根目录时,访问虚拟主机的web目录
     root  html9999;
        #在不指定访问具体资源时,默认的展示资源的列表
     index  index.html index.htm;
   }
   error_page  500 502 503 504  /50x.html;
   location = /50x.html {
     root  html;
   }
}

重启nginx服务

[root@localhost nginx]# sbin/nginx -s reload

浏览器访问

分布式调用与高并发处理 Nginx_第39张图片

分布式调用与高并发处理 Nginx_第40张图片

五、Nginx核心指令 

5.1 root和alias指令区别

区别

  • 共同点 : root和alias两者都都是用来指定URI和磁盘文件的映射关系;
  • 区别: root会将定义路径与URI叠加;而alias只取定义路径;

root示例

在之前的文章中介绍过,nginx的配置文件中的root表示的是目标资源的根路径。

    server {
        listen       80;

        server_name 192.168.66.100;


        location /aaa{
            root /usr/html/;
            index index.html;
        }

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

是不是访问/aaa/aaa.html就能访问到/usr/html/aaa.html这个文件呢?答案是否定的!

因为,使用root指令时,会root会将定义路径与URI叠加。也就是说当我们访问/aaa/aaa.html时,实际上访问的资源路径是/usr/html/aaa/aaa.html  ,但实际上根本没有aaa这层目录,所以访问不到aaa.html.

如何修改呢?只需要将/aaa改为/html,并删除root指令中的/html即可。

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


#重启nginx
[root@localhost sbin]# ./nginx -s reload

 alias示例

 alias不会拼接路径,访问uri就能定位到root 指定的目录。

        location /aaa {
            alias   /usr/html/;  #最后一定加上/
            index  index.html index.htm;
        }


#重启nginx
[root@localhost sbin]# ./nginx -s reload

5.2 return指令

分布式调用与高并发处理 Nginx_第41张图片

return功能

  1. 停止处理请求,直接返回响应码或重定向到其他URL;
  2. 执行return指令后,location中后序指令将不会被执行;

return语法结构

  1. return code [text]; # 如果返回2XX的,text才有意义,text会在body中;
  2. return code URL; #主要用于重定向;
  3. return URL; #须以http或者https开头的;

 常用状态码:

200 请求成功

301 永久转移到其他URL

404 请求资源不存在

500 内部服务器错误

code + text

        location / {
            return 200 "this is return";
        }

#重启nginx
[root@localhost sbin]# ./nginx -s reload

[root@localhost sbin]# curl http://192.168.66.100
this is return[root@localhost sbin]#

code + URL

#302 表示临时性重定向。访问一个Url时,被重定向到另一个url上。常用于页面跳转。
location  /  {
   return 302 /bbs;
}

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

URL

直接访问百度

location  /  {
   return http://baidu.com;
}

5.3 rewrite指令

分布式调用与高并发处理 Nginx_第42张图片

地址重写

地址重写是实际上是为了实现址标准化,就像访问www.baidu.cn可以出现www.baidu.com的首页,服务器会把www.baidu.cn重写成www.baidu.com,浏览器的地址栏也会显示www.baidu.com。

地址转发

地址转发一般发生在同一站点项目内,而地址重写则没有限制。

总结:

  • 地址转发后客户端浏览器地址栏中的地址显示是不改变的;而地址重写后客户端浏览器地址栏中的地址改变为服务器选择确定的地址。
  • 在一次地址转发整个过程中,只产生一次网络请求;而一次地址重写一般会产生两次请求。地址转发一般发生在同一站点项目内;而地址重写没有该限制。
  • 地址转发的速度较地址重定向快。
  • 地址转发过程中,可以将客户端请求的request范围内的属性传递给新的页面,但地址重写不可以。

rewrite常用全局变量

变量 说明
$args 请求中的参数,如www.123.com/1.php?a=1&b=2的$args就是a=1&b=2
$body_bytes_sent 服务器发送给客户端的响应body字节数
$content_length HTTP请求信息里的"Content-Length"
$conten_type HTTP请求信息里的"Content-Type"
$document_root nginx虚拟主机配置文件中的root参数对应的值
$document_uri 当前请求中不包含指令的URI,如www.123.com/1.php?a=1&b=2的$document_uri就是1.php,不包含后面的参数
$http_referer 记录此次请求是从哪个连接访问过来的,可以根据该参数进行防盗链设置
$host 主机头,也就是域名
$http_user_agent 客户端的详细信息,也就是浏览器的标识,用curl -A可以指定
$http_cookie 客户端的cookie信息
$http_x_forwarded_for 当前端有代理服务器时,设置web节点记录客户端地址的配置,此参数生效的前提是代理服务器也要进行相关的x_forwarded_for设置
$limit_rate 如果nginx服务器使用limit_rate配置了显示网络速率,则会显示,如果没有设置, 则显示0
$remote_addr 客户端的公网ip
$remote_port 客户端的port
$remote_user 如果nginx有配置认证,该变量代表客户端认证的用户名
$request 请求的URI和HTTP协议,如“GET /article-10000.html HTTP/1.1”
$request_body_file 做反向代理时发给后端服务器的本地资源的名称
$request_method 请求资源的方式,GET/PUT/DELETE等
$request_filename 当前请求的资源文件的路径名称,相当于是$document_root/$document_uri的组合
$request_uri 请求的链接,包括$document_uri和$args
$scheme 请求的协议,如ftp,http,https
$server_protocol 客户端请求资源使用的协议的版本,如HTTP/1.0,HTTP/1.1,HTTP/2.0等
$server_addr 服务器IP地址
$server_name 服务器的主机名
$server_port 服务器的端口号
$status http状态码,记录请求返回的状态码,例如:200、301、404等
$uri 和$document_uri相同
$http_referer 客户端请求时的referer,通俗讲就是该请求是通过哪个链接跳过来的,用curl -e可以指定
$time_local 记录访问时间与时区,如18/Jul/2014:17:00:01 +0800

rewrite指令

该指令通过正则表达式的使用来改变URI。可以同时存在一个或者多个指令,按照顺序依次对URL进行匹配和处理。

该指令可以在server快或者location块中配置,其语法结构为:

rewrite regex replacement [flag];
关键字  正则  替代内容   flag标记

常用正则表达式 

字符 描述
\ 将后面接着的字符标记为一个特殊字符或者一个原义字符或一个向后引用
^ 匹配输入字符串的起始位置
$ 匹配输入字符串的结束位置
* 匹配前面的字符零次或者多次
+ 匹配前面字符串一次或者多次
? 匹配前面字符串的零次或者一次
. 匹配除“\n”之外的所有单个字符
(pattern) 匹配括号内的pattern

rewrite 最后一项flag参数

标记符号 说明
last 本条规则匹配完成后继续向下匹配新的location URI规则
break 本条规则匹配完成后终止,不在匹配任何规则
redirect 返回302临时重定向
permanent 返回301永久重定向

注意:

regex,用于匹配URI的正则表达式。使用括号 "()" 标记要截取的内容。

示例1

无论/search 后面跟什么内容,最后都会被永久重定向到百度页面

location /search {
   rewrite  ^/(.*)  http://baidu.com permanent;
}

示例2

创建三个文件夹,每个文件夹下有个1.html文件;

分布式调用与高并发处理 Nginx_第43张图片

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;
}

5.4 rewrite实战域名跳转

分布式调用与高并发处理 Nginx_第44张图片

Nginx的rewrite功能在企业里应用非常广泛

  • 可以调整用户浏览的URL,看起来更规范,合乎开发及产品人员的需求。
  • 网址换新域名后,让旧的访问跳转到新的域名上。
  • 根据特殊变量、目录、客户端的信息进行URL调整等。

域名跳转

旧域名www.test.com直接跳转到新域名http://www.baidu.com

server {
   listen   80;
   server_name  www.test.com;
   rewrite ^/(.*) http://www.baidu.com/$1 permanent;
   }
   server {
     listen    80;
     server_name  www.baidu.com;
     location / {
       root  html;
       index  index.html index.htm;
     }
     access_log logs/brian.log main gzip buffer=128k flush=5s; 
     error_page  500 502 503 504  /50x.html;
     location = /50x.html {
       root  html;
     }
 }


[root@localhost sbin]# ./nginx -s reload

修改系统域名与IP映射关系:C:\Windows\System32\drivers\etc\hosts

192.168.66.100 www.test.com

访问www.test.com时会跳转到百度网址。

分布式调用与高并发处理 Nginx_第45张图片

 5.5 if指令

分布式调用与高并发处理 Nginx_第46张图片

 该指令用来支持条件判断,并根据条件判断结果选择不同的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
}

示例1

判断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"
  }
}


#发送请求
curl http://192.168.66.100/search

示例2

不允许谷歌浏览器访问,如果用谷歌浏览器报500

if ($http_user_agent ~ Chrome){
 return 500;
}

5.6 set和break指令

分布式调用与高并发处理 Nginx_第47张图片

set指令

该指令用于设置一个新的变量。

set variable value
  • variable,为变量的名称。注意要用符号“$”作为变量的第一个字符,且变量不能与Nginx服务器预设的全局变量同名。
  • value,为变量的值,可以是字符串、其他变量或变量的组合等。

break指令

该指令用于中断当前相同作用域中的其他Nginx配置。

break;

示例:

location / {
  if ($slow){
   set $id $1 ; # 处于break指令之前,配置生效
   break;    
   limit_rate 10k; #处于break指令之后,配置无效
  }
}

5.7 Gzip压缩指令

分布式调用与高并发处理 Nginx_第48张图片

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-javascripttext/css` `application/xml``; 设置需要压缩的MIME类型,非设置值不进行压缩,即匹配压缩类型
gzip_vary on; 启用应答头"Vary: Accept-Encoding"
gzip_proxied off; nginx做为反向代理时启用,off(关闭所有代理结果的数据的压缩),expired(启用压缩,如果header头中包括"Expires"头信息),no-cache(启用压缩,header头中包含"Cache-Control:no-cache"), no-store(启用压缩,header头中包含"Cache-Control:no-store"),private(启用压缩,header头中包含"Cache-Control:private"),no_last_modefied(启用压缩,header头中不包含 "Last-Modified"),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压缩功能虽然好用,但是下面两类文件资源不太建议启用此压缩功能。

1) 图片类型资源 (还有视频文件) 原因:图片如jpg、png文件本身就会有压缩,所以就算开启gzip后,压缩前和压缩后大小没有多大区别,所以开启了反而会白白的浪费资源。

2) 大文件资源 原因:会消耗大量的cpu资源,且不一定有明显的效果。

六、Nginx场景实践

6.1 浏览器缓存

分布式调用与高并发处理 Nginx_第49张图片

浏览器缓存是为了加速浏览,浏览器在用户磁盘上,对最近请求过的文档进行存储。当访问者再次请求这个页面时,浏览器就可以从本地磁盘显示文档,这样,就可以加速页面的阅览,缓存的方式节约了网络的资源,提高了网络的效率。

 实现浏览器缓存步骤

分布式调用与高并发处理 Nginx_第50张图片

 浏览器缓存可以通过expires指令输出Header头来实现。

语法:expires[time| epoch | max |off]
默认值:expires off
作用域:http、server、location

一个HTML页面,会引用一些JavaScript文件、图片文件、而这些格式的文件很少会被修改,则可以通过expires设置浏览器缓存。

示例1

比如,对常见格式的图片、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(默认): 只能在浏览器中缓存, 只有在第一次请求的时候才访问服务器, 若有- - max-age, 则缓存期间不访问服务器
  • public: 可以被任何缓存区缓存, 如: 浏览器、服务器、代理服务器等
  • max-age: 相对过期时间, 即以秒为单位的缓存时间

location ~ .*\.(gif|jpg|png)$
{
  add_header Cache-Control no-cache;
  add_header Cache-Control private;
}
location ~.*\.(js|css)?$
{
   add_header Cache-Control no-cache;
   add_header Cache-Control private;
}

缓存流程

分布式调用与高并发处理 Nginx_第51张图片

 企业实战示例

  1. 禁用html文件缓存,即cache control设置为no-cache;
  2. 对于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;
  }
}

 6.2 防盗链技术

分布式调用与高并发处理 Nginx_第52张图片

防盗链的概念

内容不在自己的服务器上,通过技术手段将其他网站的内容(比如一些音乐、图片、软件的下载地址)放置在自己的网站中,通过这种方法盗取其他网站的空间和流量。就是在自己的网站上使用其他人的资源作为自己页面的资源。

分布式调用与高并发处理 Nginx_第53张图片

防盗链技术背景

防止第三方引用链接访问我们的图片,消耗服务器资源和网络流量,我们可以在服务器上做防盗链限制。

分布式调用与高并发处理 Nginx_第54张图片

 防盗链设置思路

首要方式:区别那些请求是非正常的用户请求。

分布式调用与高并发处理 Nginx_第55张图片

 基于http_refer防盗链配置模块

HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器借此可以获得一些信息用于处理。比如从我主页上链接到一个朋友那里,他的服务器就能够从HTTP Referer中统计出每天有多少用户点击我主页上的链接访问他的网站。


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;
    valid_referers none blocked 192.168.66.100;
    if ($invalid_referer) {
       return 403;
     }
  } 
}
valid_referers none blocked 192.168.66.100;
if ($invalid_referer) {
   return 403;
}

参数:

  • none : 允许没有http_refer的请求访问资源;
  • blocked : 允许不是http://开头的,不带协议的请求访问资源;
  • 192.168.66.100: 只允许指定ip来的请求访问资源;

 6.3 代理服务

分布式调用与高并发处理 Nginx_第56张图片

正向代理

正向代理,是在用户端的。比如需要访问某些国外网站,我们可能需要购买。简单讲,正向代理就是自己访问外网。

正向代理最大的特点:

  1. 客户端非常明确要访问的服务器地址;
  2. 服务器只清楚请求来自哪个代理服务器,而不清楚来自哪个具体的客户端;
  3. 正向代理模式屏蔽或者隐藏了真实客户端信息。

分布式调用与高并发处理 Nginx_第57张图片

反向代理

客户端给服务器发送的请求,nginx服务器接收到之后,按照一定的规则分发给了后端的业务处理服务器进行处理了。此时请求的来源也就是客户端是明确的,但是请求具体由哪台服务器处理的并不明确了,nginx扮演的就是一个反向代理角色。简单讲,反向代理就是外网访问nginx服务器再通过nginx服务器将请求发送到我们自己的服务器资源,这样可以保证安全。

反向代理,主要用于服务器集群分布式部署的情况下,反向代理隐藏了服务器的信息。

分布式调用与高并发处理 Nginx_第58张图片

 6.4 反向代理

分布式调用与高并发处理 Nginx_第59张图片

 单体架构

分布式调用与高并发处理 Nginx_第60张图片

单体架构问题:

  • 复杂性高:模块多,模块边界模糊,代码质量参差不齐,每次修改代码都心惊胆战
  • 技术债务:随着时间的推移,需求变更和人员迭代,会逐渐形成应用程序的技术债务,并且越积越多
  • 部署频率低:随着代码增多,构建和部署的时间也会增多,每次部署都要重新部署整个项目
  • 可靠性差:某个应用有bug,可能会导致整个应用崩溃
  • 扩展能力受限:单体应用只能作为一个整体应用进行扩展,无法根据业务模块的需要进行伸缩

反向代理设置指令:proxy_pass

学习Nginx服务器的反向代理服务,要涉及与后端代理服务器相关的配置指令比较重要,是为客户端提供正常Web服务的基础,大家应该熟练掌握尤其是proxy_pass指令,该指令用来设置被代理服务器的地址,可以是主机名称、IP地址加端口号等形式。在实际应用过程中需要注意一些配置细节,需要小心使用。

proxy_pass URL;

参数:

URL为要设置的被代理服务器的地址,包含传输协议、主机名称或P地址加端口号、URI等要素。传输协议通常是"http"或者"https://"。

 示例:

server{
  ....
  listen 80;
  server_name *.*;
  location / {
    proxy_pass http://192.168.66.101:8080;
  }
}

反向代理实践

通过纯净虚拟机上的nginx访问到zk-1上的tomcta服务器。首先需要在zk-1虚拟机上安装jdk环境和tomcat,并启动tomcat。详见《生产环境部署与协同开发 Linux》然后在纯净虚拟机上配置反向代理,如上示例。在浏览器访问192.168.66.100即可访问到zk-1虚拟机上的tomcta首页。

分布式调用与高并发处理 Nginx_第61张图片

 6.5 负载均衡

分布式调用与高并发处理 Nginx_第62张图片

什么是负载均衡

负载均衡是高可用网络基础架构的关键组件,通常用于将工作负载分布到多个服务器来提高网站、应用、数据库或其他服务的性能和可靠性。

 没有负载均衡的 web 架构

分布式调用与高并发处理 Nginx_第63张图片

 有负载均衡web架构

分布式调用与高并发处理 Nginx_第64张图片

upstream指令

upstream块不属于虚拟主机(不写在server块中),只能在http块里配置,它定义了在反向代理时Nginx需要访问的后端服务器集群和负载均衡策略。

upstream  back_end {       # upstream 需要一个名字
  server 192.168.66.100 max_conns=2 fail_timeout=1s;
  server 192.168.66.101 weight = 1;
  server 192.168.66.102 weight = 1;
}
server{
  lisetn 80;
  server_name *.*;
  location / {
   proxy_set_header Host $host;  #转发原始请求的host头部(不是必须)
   proxy_pass http://back_end;  #转发到upstream块定义的服务器集群。 
  }
}


[root@localhost sbin]# ./nginx -s reload

upstream参数:

  • max_conns 节点的最大连接数
  • slow_start 缓慢启动时间
  • down 节点下线
  • backup 备用节点
  • max_fails 允许的最大失败数
  • fail_timeout 超过最大失败数后的等待时间

浏览器请求:

分布式调用与高并发处理 Nginx_第65张图片

就算是一台服务挂了,另一台还会提供响应的服务。

6.6 负载均衡算法

轮询(默认)

轮询方式,依次将请求分配到各个后台服务器中,默认的负载均衡方式。 适用于后台机器性能一致的情况。 挂掉的机器可以自动从服务列表中剔除。轮询不是绝对的。

upstream bakend {  
 server 192.168.66.101;  
 server 192.168.66.102;  
}

轮询加权重

根据权重来分发请求到不同的机器中,指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。

upstream bakend {  
 server 192.168.0.14 weight=10;  
 server 192.168.0.15 weight=10;  
} 

IP_hash

每个请求按访问IP的哈希结果分配,使来自同一个IP的访客固定访问一台后端服务器,并且可以有效解决动态网页存在的session共享问题。俗称IP绑定。

分布式调用与高并发处理 Nginx_第66张图片

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软件包。

分布式调用与高并发处理 Nginx_第67张图片

fair

比 weight、ip_hash更加智能的负载均衡算法,fair算法可以根据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间 来分配请求,响应时间短的优先分配。Nginx本身不支持fair,如果需要这种调度算法,则必须安装upstream_fair模块。

6.7 第三方fair模块安装

分布式调用与高并发处理 Nginx_第68张图片

模块介绍 

fair采用的不是内建负载均衡使用的轮换的均衡算法,而是可以根据页面大小、加载时间长短智能的进行负载均衡。

模块安装

将nginx-upstream-fair-master.zip压缩文件上传到Linux并解压到/usr/local下。

切换到nginx-1.20.2目录执行一下操作(之前通过编译该文件得到了nginx文件)

[root@localhost nginx-1.20.2]# ./configure --prefix=/usr/local/nginx/ --add-module=/usr/local/nginx-upstream-fair-mastercal/nginx-upstream-fair-master

编译

[root@localhost nginx-1.20.2]# make

编译完成不需要再次进行安装了因为之前已经安装过nginx-1.20.2了,编译完成后会发现在nginx-1.20.2下多了一个objs文件,该文件下还有一个nginx命令文件,我们要将这个文件替换掉原来的nginx命令文件。因为添加模块之后nginx的指令会变多,所以需要文件的替换。

分布式调用与高并发处理 Nginx_第69张图片

 替换原来的 nginx 命令文件

cp /usr/local/nginx-1.20.2/objs/nginx /usr/local/nginx/sbin/nginx

配置实现fair算法

upstream backserver { 
 fair; 
 server 192.168.66.100; 
 server 192.168.66.101; 
} 


#重启
./nginx -s reload

注意:

已安装Nginx,配置第三方模块时,只需要--add-module=/第三方模块目录,然后make编译一下就可以,不要 make install 安装。编译后复制objs下面的nginx到指定目录下。

 6.8 Nginx配置故障转移

分布式调用与高并发处理 Nginx_第70张图片

当上游服务器(真实访问服务器),一旦出现故障或者是没有及时相应的话,应该直接轮训到下一台服务器,保证服务器的高可用。

故障转移的条件

1.后端返回504、505状态码。

2.执行超时错误

 Nginx配置代码

server {
     listen    80;
     server_name  www.itmayiedu.com;
     location / {
           ### 指定上游服务器负载均衡服务器
           proxy_pass http://backServer;
 
           #http_502 http_504:后端的服务器返回502、50
           #error:连接服务器发生错误
           #timeout:连接服务器超时错误
           #invalid_header:服务器返回空或者错误的应答
           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;

           #重试次数
           proxy_next_upstream_tries = 3
           index  index.html index.htm;
     }
   }

6.9 跨域问题

分布式调用与高并发处理 Nginx_第71张图片

为什么会出现跨域问题

出于浏览器的同源策略限制。同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

什么是跨域

当一个请求URL的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。

当前页面url 被请求页面url 是否跨域 原因
http://www.test.com/ http://www.test.com/index.html 同源(协议、域名、端口号相同)
http://www.test.com/ https://www.test.com/index.html 跨域 协议不同(http/https)
http://www.test.com/ 百度一下,你就知道 跨域 主域名不同(test/baidu)
http://www.test.com/ http://blog.test.com/ 跨域 子域名不同(www/blog)
http://www.test.com:8080/ http://www.test.com:7001/ 跨域 端口号不同(8080/7001)

解决跨域问题

分布式调用与高并发处理 Nginx_第72张图片

  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,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';


   if ($request_method = 'OPTIONS') {
     return 204;
   }
} 

参数:

  1. Access-Control-Allow-Origin 表示服务器可以接受所有的请求源(Origin),即接受所有跨域的请求。
  2. Access-Control-Allow-Methods 明确了客户端所要访问的资源允许使用的方法或方法列表。
  3. Access-Control-Allow-Headers 设置预检请求。

6.10 动静分离

分布式调用与高并发处理 Nginx_第73张图片

Nginx动静分离简单来说就是把动态和静态请求分开,不能理解成只是单纯的把动态页面和静态页面物理分离。严格意义上说应该是动态请求和静态请求分开,可以理解成使用Nginx处理静态请求,Tomcat处理动态请求。

什么是动静分离

动:必须依赖服务器生存的文件 比如jsp。 静:不需要依赖容器的比如css/js或者图片等文件

动静分离的好处

  • Nginx本身就是一个高性能的静态web服务器
  • 其实静态文件有一个特点就是基本上变化不大,所以动静分离以后我们可以对静态文件进行缓存、或者压缩提高网站性能

静态资源的类型

在Nginx的conf目录下,有一个mime.types文件里边列出了 静态资源的类型,如下:

 当用户访问一个网站,然后从服务器端获取相应的资源,通过浏览器进行解析渲染最后展示给用户,服务端可以返回各种类型的内容,比如xml、jpg、png、gif、flash、MP4、html、css等等,浏览器就是根据mime-type来决定用什么形式来解析和展示的。服务器返回的资源给到浏览器时,会把媒体类型告知浏览器,这个告知的标识就是Content-Type,比如Content-Type:text/html。

 动静分离实战

分布式调用与高并发处理 Nginx_第74张图片

通过请求分离 

 将一张图片aaa.jpg上传到/usr/local/nginx/static下,然后在配置文件中添加如下配置:

upstream  webservers  {
     server 192.168.66.101:8080 weight=5;
     server 192.168.66.102: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;
     }

     //访问image会定位到/static/image目录
     location /image/ {
       root static;
     }
     
     //访问web会定位到反向代理指定的服务(也就是占8080端口的tomcat)
     location /web/ {
       proxy_set_header Host $host;
       proxy_pass http://webservers;
     }
   }
}

根据扩展名分离

upstream  webservers {
     server 192.168.66.101:8080 weight=5;
     server 192.168.66.102: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;
     }

     #正则表达式,请求包含如下的会定位到static目录
     location ~ .*.(jpg|png|gif|css|js)$ {
     root static;
     }
   }
}

6.11 限流

分布式调用与高并发处理 Nginx_第75张图片

生活中的限流

春运,一项全人类历史上最大规模的迁移活动,抢火车票一直是每年跨年以后的热点话题。

分布式调用与高并发处理 Nginx_第76张图片

为什么需要限流

系统设计时一般会预估负载,当系统暴露在公网中时,恶意攻击或正常突发流量等都可能导致系统被压垮,而限流就是保护措施之一。

Nginx 的二种限流设置:

  • 控制速率。
  • 控制并发连接数。

分布式调用与高并发处理 Nginx_第77张图片

 限流算法

分布式调用与高并发处理 Nginx_第78张图片

漏桶算法

分布式调用与高并发处理 Nginx_第79张图片

原理:

漏桶算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水,当水流入速度过大会直接溢出,可以看出漏桶算法能强行限制数据的传输速率。

令牌桶算法

分布式调用与高并发处理 Nginx_第80张图片

原理:

令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。

漏桶 vs 令牌桶的区别

漏桶的天然特性决定了它不会发生突发流量,就算每秒1000个请求到来,那么它对后台服务输出的访问速率永远恒定。而令牌桶则不同,其特性可以“预存”一定量的令牌,因此在应对突发流量的时候可以在短时间消耗所有令牌,其突发流量处理效率会比漏桶高,但是导向后台系统的压力也会相应增多。

限流实现

分布式调用与高并发处理 Nginx_第81张图片

根据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的。

 放在server{}内或者location里面

limit_req zone=mylimit burst=1 nodelay;

参数:

  • 第一个参数:zone=one 设置使用哪个配置区域来做限制,与上面limit_req_zone 里的name对应。
  • 第二个参数:burst=5,重点说明一下这个配置,burst爆发的意思,这个配置的意思是设置一个大小为5的缓冲区当有大量请求(爆发)过来时,超过了访问频次限制的请求可以先放到这个缓冲区内。
  • 第三个参数:nodelay,如果设置,超过访问频次而且缓冲区也满了的时候就会直接返回503,如果没有设置,则所有请求会等待排队。

分布式调用与高并发处理 Nginx_第82张图片

 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进行限流。

6.12 WEB缓存机制

分布式调用与高并发处理 Nginx_第83张图片

核心:

响应速度历来是衡量WEB应用和服务性能优劣的重要指标之一,尤其动态网站在网络上泛滥的今天。除了优化发布内容以外,另外一个主要的办法就是把不需要实时更新的动态页面输出结果转为静态网页形式缓存,进而按照静态网页来访问。

 proxy Cache缓存机制

分布式调用与高并发处理 Nginx_第84张图片

 配置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/tmp-test/;
}

参数:

  • 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;  //清理缓存
}

6.13 Nginx高可用

分布式调用与高并发处理 Nginx_第85张图片

什么是高可用?

高可用HA(High Availability)是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间。如果一个系统能够一直提供服务,那么这个可用性则是百分之百,但是天有不测风云。所以我们只能尽可能的去减少服务的故障。

分布式调用与高并发处理 Nginx_第86张图片

 

解决的问题

在生产环境上很多时候是以Nginx做反向代理对外提供服务,但是一天Nginx难免遇见故障,如:服务器宕机。当Nginx宕机那么所有对外提供的接口都将导致无法访问。虽然我们无法保证服务器百分之百可用,但是也得想办法避免这种悲剧,今天我们使用keepalived来实现Nginx的高可用。

双机热备方案 

这种方案是国内企业中最为普遍的一种高可用方案,双机热备其实就是指一台服务器在提供服务,另一台为某服务的备用状态,当一台服务器不可用另外一台就会顶替上去。

6.14 LVS负载均衡

分布式调用与高并发处理 Nginx_第87张图片

 LVS是一个开源的软件,可以实现传输层四层负载均衡。LVS是Linux Virtual Server的缩写,意思是Linux虚拟服务器。

目标

通过 LVS 达到的负载均衡技术和 Linux 操作系统实现一个高性能高可用的 Linux 服务器集群,它具有良好的可靠性、可扩展性和可操作性。从而以低廉的成本实现最优的性能。

分布式调用与高并发处理 Nginx_第88张图片

 

LVS的八种调度算法

  1. 轮叫调度 rr
  2. 加权轮叫 wrr
  3. 最少链接 lc
  4. 加权最少链接 wlc
  5. 基于局部性的最少连接调度算法 lblc
  6. 复杂的基于局部性最少的连接算法 lblcr
  7. 目标地址散列调度算法 dh
  8. 源地址散列调度算法 sh

6.15 keepalived健康监测

分布式调用与高并发处理 Nginx_第89张图片

LVS可以实现负载均衡,但是不能够进行健康检查,比如一个rs出现故障,LVS 仍然会把请求转发给故障的rs服务器,这样就会导致请求的无效性。keepalive 软件可以进行健康检查,而且能同时实现 LVS 的高可用性,解决 LVS 单点故障的问题,其实 keepalive 就是为 LVS 而生的。

keepalived工作原理

keepalived是基于VRRP协议实现的保证集群高可用的一个服务软件,主要功能是实现真机的故障隔离和负载均衡器间的失败切换,防止单点故障。

VRRP协议

VRRP是一种容错协议,它保证当主机的下一跳路由器出现故障时,由另一台路由器来代替出现故障的路由器进行工作,从而保持网络通信的连续性和可靠性。

主要作用:

VRRP可以将两台或者多台物理路由器设备虚拟成一个虚拟路由,这个虚拟路由器通过虚拟IP(一个或者多个)对外提供服务。

 6.16 企业双机热备方案

分布式调用与高并发处理 Nginx_第90张图片

 环境服务配置

两台Nginx服务器
Nginx 主服务器  192.168.66.100
Nginx 备服务器  192.168.66.101
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/

in/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.212.141 #填写本机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.212.110 # 虚拟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.212.141 #填写本机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.212.110 # 虚拟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.sh3

你可能感兴趣的:(java后端,分布式,nginx,运维,linux)