Nginx
nginx
Nginx 的简介
Nginx ("engine x") 是一个高性能的 HTTP 和反向代理服务器,特点是占有内存少,并发能力强
反向代理
介绍反向代理前先要了解什么时代理服务器
代理服务器,客户机在发送请求时,不会直接发送给目的主机,而是先发送给代理服务器,代理服务接受客户机请求之后,再向主机发出,并接收目的主机返回的数据,存放在代理服务器的硬盘中,再发送给客户机。
为什么要使用代理服务器
-
提高访问速度
由于目标主机返回的数据会存放在代理服务器的硬盘中,因此下一次客户再访问相同的站点数据时,会直接从代理服务器的硬盘中读取,起到了缓存的作用,尤其对于热门站点能明显提高请求速度。 -
防火墙作用
由于所有的客户机请求都必须通过代理服务器访问远程站点,因此可在代理服务器上设限,过滤某些不安全信息。 -
通过代理服务器访问不能访问的目标站点
互联网上有许多开发的代理服务器,客户机在访问受限时,可通过不受限的代理服务器访问目标站点,通俗说,我们使用的FQ浏览器就是利用了代理服务器,虽然不能出国,但也可直接访问外网
反向代理 VS 正向代理
- 正向代理,架设在客户机与目标主机之间,只用于代理内部网络对Internet的连接请求,客户机必须指定代理服务器,并将本来要直接发送到Web服务器上的http请求发送到代理服务器中。
- 反向代理服务器架设在服务器端,通过缓冲经常被请求的页面来缓解服务器的工作量,将客户机请求转发给内部网络上的目标服务器;并将从服务器上得到的结果返回给Internet上请求连接的客户端,此时代理服务器与目标主机一起对外表现为一个服务器。
反向代理的作用
现在许多大型web网站都用到反向代理。除了可以防止外网对内网服务器的恶性攻击、缓存以减少服务器的压力和访问安全控制之外,还可以进行负载均衡,将用户请求分配给多个服务器。
负载均衡
客户端发送多个请求到服务器,服务器处理请求,有一些可能要与数据库进行交互,服务器处理完毕后,再将结果返回给客户端。 这种架构模式对于早期的系统相对单一,并发请求相对较少的情况下是比较适合的,成本也低。
但是随着信息数量的不断增长,访问量和数据量的飞速增长,以及系统业务的复杂度增加,这种架构会造成服务器相应客户端的请求日益缓慢,并发量特别大的时候,还容易造成服务器直接崩溃。很明显这是由于服务器性能的瓶颈造成的问题,那么如何解决这种情 况呢? 我们首先想到的可能是升级服务器的配置,比如提高 CPU 执行频率,加大内存等提高机器的物理性能来解决此问题,但是我们知道摩尔定律的日益失效,硬件的性能提升已经不能满足日益提升的需求了。最明显的一个例子,天猫双十一当天,某个热销商品的瞬时访问量是极其庞大的,那么类似上面的系统架构,将机器都增加到现有的顶级物理配置,都是不能够满足需求的。那么怎么办呢?
上面的分析我们去掉了增加服务器物理配置来解决问题的办法,也就是说纵向解决问题 的办法行不通了,那么横向增加服务器的数量呢?这时候集群的概念产生了,单个服务器解决不了,我们增加服务器的数量,然后将请求分发到各个服务器上。
将原先请求集中到单个服务器上的情况改为将请求分发到多个服务器上,将负载分发到不同的服务器,也就是我们所说的负载均衡
动静分离
在弄清动静分离之前,我们要先明白什么是动,什么是静。
在Web开发中,通常来说,动态资源其实就是指那些后台资源,而静态资源就是指HTML,JavaScript,CSS,img等文件。
一般来说,都需要将动态资源和静态资源分开,将静态资源部署在Nginx上,当一个请求来的时候,如果是静态资源的请求,就直接到nginx配置的静态资源目录下面获取资源,如果是动态资源的请求,nginx利用反向代理的原理,把请求转发给后台应用去处理,从而实现动静分离。
在使用前后端分离之后,可以很大程度的提升静态资源的访问速度,同时在开过程中也可以让前后端开发并行可以有效的提高开发时间,也可以有些的减少联调时间 。
通过 location 指定不同的后缀名实现不同的请求转发,也可以通过 expires 参数设置,使浏览器缓存文件的过期时间,从而减少与服务器之前的请求和流量。
Expires 具体含义:给一个资源设定一个过期时间,也就是说无需去服务端验证,直接通过浏览器自身确认是否过期即可,所以不会产生额外的流量,也就是所谓的客户端缓存。此种方法非常适合不经常变动的资源。(如果经常更新的文件,不建议使用 Expires 来缓存),假设一下,我们把这个Expires设置 3d,表示在 3 天之内访问这个 URL时,若比对该文件最后更新时间没有变化,则不会从服务器抓取,返回状态码304,如果有修改,则直接从服务器重新下载,返回状态码 200。
使用
常用命令
#进入 nginx 目录中: cd /usr/local/nginx/sbin
#1、查看 nginx 版本号
./nginx -v
#2、启动 nginx
./nginx
#查看是否启动成功:
ps -ef|grep nginx
#3、停止 nginx
./nginx -s stop
#4、重新加载 nginx
./nginx -s reload
配置文件
1)全局块:服务器整体运行的配置指令
从配置文件开始到 events 块之间的内容,主要设置一些影响 nginx 服务器整体运行的配置指令,包括
- 运行 Nginx 服务器的用户(组)
- 允许生成的 worker process 数
- 进程 PID 存放路径
- 日志存放路径和类型
- 配置文件的引入等。
比如第一行配置的worker_processes
这是 Nginx 服务器并发处理服务的关键配置,worker_processes 值越大,可以支持的并发处理量也越多,但是会受到硬件、软件等设备的制约
2)events 块:负责Nginx 服务器与用户的网络连接
events 块涉及的指令主要影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 work process下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个 wordprocess 可以同时支持的最大连接数等。
下面的例子就表示每个 work process 支持的最大连接数为 1024.
这部分的配置对 Nginx 的性能影响较大,在实际中应该灵活配置。
3)http 部分
这算是 Nginx 服务器配置中最频繁的部分
- 代理
- 缓存
- 日志
- 第三方模块的配置
需要注意的是:http 块也可以包括 http 全局块、server 块。
#配置文件上是注释的,指的是nginx的用户权限,
#user nobody;
#设置最大的工作衍生进程数 这里默认是1
worker_processes 1
#最大的连接数 设置最大的连接数默认为1024个连接数
events {
worker_connections 1024;
}
#Http 的主要设置,这里可以添加多个server
http {
#http全局块
include mime.types;
default_type application/octet-stream;
#上传文件大小限制1G,默认1M
client_max_body_size 1024m;
#设置为on表示启动高效传输文件的模式
sendfile on;
#保持连接的时间,默认65s
keepalive_timeout 1800;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
#sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
#keepalive_timeout 65;
#gzip on;
#每一个Server都是一个服务
server{
#这里是过滤请求,/是所有请求都可以
location /{
}
}
- http 全局块
负责http块公共的配置,http 全局块配置的指令包括文件引入、MIME-TYPE 定义、日志自定义、连接超时时间、单链接请求数上限等。
-
**server **
这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了节省互联网服务器硬件成本。每个 server 块就相当于一个虚拟主机,而每个 http 块可以包括多个 server 块,而每个 server 块也分为全局 server 块,以及可以同时包含多个 locaton 块。- 全局server
最常见的配置是本虚拟机主机的监听配置和本虚拟主机的名称或 IP 配置。
- location 块
一个 server 块可以配置多个 location 块。这块的主要作用是基于 Nginx 服务器接收到的请求字符串(例如 server_name/url-string),对虚拟主机名称(也可以是 IP 别名)之外的字符串(例如 前面的 /url-string)进行匹配,对特定的请求进行处理。地址定向、数据缓存和应答控制等功能,还有许多第三方模块的配置也在这里进行。
location:该指令用于匹配 URL
-
=
:用于不含正则表达式的 url前,要求请求字符串与 url 严格匹配,如果匹配成功,就停止继续向下搜索并立即处理该请求。 -
~
:用于表示 url 包含正则表达式,并且区分大小写。 -
~*
:用于表示 url 包含正则表达式,并且不区分大小写。 -
^~
:用于不含正则表达式的 url 前,要求 Nginx 服务器找到标识 url 和请求字符串匹配度最高的 location 后,立即使用此 location 处理请求,而不再使用 location 块中的正则 url 和请求字符串做匹配。
注意:如果 url 包含正则表达式,则必须要有 ~ 或者 ~* 标识。
负载均衡策略
1. 轮询
这是默认的策略,把每个请求逐一分配到不同的server,如果分配到的server不可用,则分配到下一个,直到可用
upstream test.cc {
server 192.168.8.143;
server 192.168.8.144;
}
2.最少连接
把请求分配到连接数最少的server
upstream test.cc {
least_conn;
server 192.168.8.143;
server 192.168.8.144;
}
3.权重
weight默认值为1,值越大则代表被访问的几率越大,如下配置,144的访问数量是143的2倍
upstream test.cc {
server 192.168.8.143 weight=1;
server 192.168.8.144 weight=2;
}
4.ip_hash
根据访问客户端ip的hash值分配,这样同一客户端的请求都会被分配到同一个server上,如果牵扯到session的问题,用这个是最好的选择
upstream test.cc {
ip_hash;
server 192.168.8.143;
server 192.168.8.144;
}
5.fair
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
upstream test.cc {
server localhost:10001 weight=1;
server localhost:10002 weight=2;
fair;
}
高可用集群(Nginx + Keepalived)
下面使用两台Nginx做反向代理服务器,当其中一台Nginx宕机之后,仍能用另一台来工作,两台Nginx之间用keeplived来监测心跳。
环境准备
1、两台 Linux,各自安装tomcat,模拟两台服务器
IP分别是192.168.17.129 、192.168.17.131
2、安装keepalived
keepalived的下载地址 或者使用yum
yum install keepalived –y
keepalived 安装之后,其配置文件目录如下:/etc/keepalived/keepalivec.conf
3、安装nginx
Keepalived
#全局定义
! Configuration File for keepalived
global_defs {
#指定keepalived在发生事件时(比如切换)发送通知邮件的邮箱
notification_email {
#设置报警邮件地址,可以设置多个,每行一个。 需开启本机的sendmail服务
ops@wangshibo.cn
tech@wangshibo.cn
}
#keepalived在发生诸如切换操作时需要发送email通知地址
notification_email_from ops@wangshibo.cn
#指定发送email的smtp服务器
smtp_server 127.0.0.1
#设置连接smtp server的超时时间
smtp_connect_timeout 30
#运行keepalived的机器的一个标识,通常可设为hostname。故障发生时,发邮件时显示在邮件主题中的信息。
router_id master-node
}
#检测nginx服务是否在运行。有很多方式,比如进程,用脚本检测等等
vrrp_script chk_http_port {
script "/opt/chk_nginx.sh" #这里通过脚本监测 不要挂载文件
interval 2 #脚本执行间隔,每2s检测一次
weight -5 #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -5
fall 2 #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间) 1 -100
rise 1 #检测1次成功就算成功。但不修改优先级
}
vrrp_instance VI_1 {
#keepalived在同一virtual_router_id中priority(0-255)最大的会成为master,也就是接管VIP,当priority最大的主机发生故障后次priority将会接管
state MASTER
#指定keepalived的角色,MASTER表示此主机是主服务器,BACKUP表示此主机是备用服务器。注意这里的state指定instance(Initial)的初始状态,就是说在配置好后,这台服务器的初始状态就是这里指定的,但这里指定的不算,还是得要通过竞选通过优先级来确定。如果这里设置为MASTER,但如若他的优先级不及另外一台,那么这台在发送通告时,会发送自己的优先级,另外一台发现优先级不如自己的高,那么他会就回抢占为MASTER
interface ens33
#指定HA监测网络的接口。实例绑定的网卡,因为在配置虚拟IP的时候必须是在已有的网卡上添加的
mcast_src_ip 103.110.98.14
# 发送多播数据包时的源IP地址,这里注意了,这里实际上就是在哪个地址上发送VRRP通告,这个非常重要,一定要选择稳定的网卡端口来发送,这里相当于heartbeat的心跳端口,如果没有设置那么就用默认的绑定的网卡的IP,也就是interface指定的IP地址
virtual_router_id 51
#虚拟路由标识,这个标识是一个数字,同一个vrrp实例使用唯一的标识。即同一vrrp_instance下,MASTER和BACKUP必须是一致的
priority 101
#定义优先级,数字越大,优先级越高,在同一个vrrp_instance下,MASTER的优先级必须大于BACKUP的优先级
advert_int 1 #设定MASTER与BACKUP负载均衡器之间同步检查的时间间隔,单位是秒
#设置验证类型和密码。主从必须一样
#设置vrrp验证类型,主要有PASS和AH两种
authentication {
auth_type PASS
#设置vrrp验证密码,在同一个vrrp_instance下,MASTER与BACKUP必须使用相同的密码才能正常通信
auth_pass 1111
}
#VRRP HA 虚拟地址 如果有多个,继续换行填写
virtual_ipaddress {
103.110.98.20
}
#执行监控的服务。注意这个设置不能紧挨着写在vrrp_script配置块的后面(实验中碰过的坑),否则nginx监控失效!!
track_script {
#引用VRRP脚本,即在 vrrp_script 部分指定的名字。定期运行它们来改变优先级,并最终引发主备切换。
chk_http_port
}
}
使用
1、Keepalive配置文件
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.17.129
smtp_connect_timeout 30
# 通过它,可以访问到主机,在hosts文件中,要做映射关系,类似于 127.0.0.1 LVS_DEVEL
router_id LVS_DEVEL
}
vrrp_script chk_http_port {
# 执行脚本所在的位置
script "/usr/local/src/nginx_check.sh"
#检测脚本执行的间隔,单位秒,每个2秒执行一次脚本
interval 2
weight 2
}
vrrp_instance VI_1 {
# 备份服务器上将 MASTER 改为 BACKUP
state MASTER
# 绑定的网卡,ipconfig可查看
interface ens33
# 主、备机的 virtual_router_id 必须相同
virtual_router_id 51
# 主、备机取不同的优先级,主机值较大,备份机值较小
priority 90
#每隔一秒发送一次心跳,确保从服务器是否还活着
advert_int 1
# 心跳检测需要的密码
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
# VRRP H 虚拟地址,即用户访问地址
192.168.17.50
}
}
2、检测脚本
在/usr/local/src 添加检测脚本,检查Nginx是否还活着
#!/bin/bash
A=`ps -C nginx –no-header |wc -l`
if [ $A -eq 0 ];then
/usr/local/nginx/sbin/nginx #Nginx启动命令的位置
sleep 2
if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
killall keepalived
fi
fi
3、把两台服务器上 nginx 和 keepalived 启动
#启动 nginx:
./nginx
#启动 keepalived:
systemctl start keepalived.service
4、可以使用ipconfig
,查看虚拟Ip的绑定
5、最终测试
(1)在浏览器地址栏输入 虚拟 ip 地址 192.168.17.50
(2)把主服务器上的(192.168.17.129)Nginx 和 keepalived 停止,再输入 192.168.17.50,依旧可以访问Nginx。
实例
反向代理实例1
1、实现效果
打开浏览器,在浏览器地址栏输入地址 www.123.com,跳转到 liunx 系统 tomcat 主页面中
2、准备工作
(1)在 liunx 系统安装 tomcat,使用默认端口 8080
-
tomcat 安装文件放到 liunx 系统中,解压
-
进入 tomcat 的 bin 目录中,
./startup.sh
启动 tomcat 服务器
(2)对外开放访问的端口
firewall-cmd --add-port=8080/tcp --permanent
firewall-cmd –reload
#查看已经开放的端口号
firewall-cmd --list-all
(3)在 windows 系统中通过浏览器访问 tomcat 服务器
3、访问过程的分析
4、具体配置
第一步 在 windows 系统的 host 文件进行域名和 ip 对应关系的配置
添加内容在 host 文件中
第二步 在 nginx 进行请求转发的配置(反向代理配置)
5、最终测试
反向代理实例 2
1、实现效果
使用 nginx 反向代理,根据访问的路径跳转到不同端口的服务中
nginx 监听端口为 9001,
访问 http://192.168.17.129:9001/edu/ 直接跳转到 127.0.0.1:8080
访问 http:// 192.168.17.129:9001/vod/ 直接跳转到 127.0.0.1:8081
2、准备工作
(1)准备两个 tomcat 服务器,一个 8080 端口,一个 8081 端口
(2)创建文件夹和测试页面
3、具体配置
(1)找到 nginx 配置文件,进行反向代理配置
#nginx请求转发功能
server {
#nginx代理端口
listen 9001;
server_name localhost;
#nginx根据路径匹配端口,controller层路径中不要有重名
location ~ /eduservice/ {
#配置后台访问地址和端口号
proxy_pass http://localhost:8001;
}
location ~ /eduoss/ {
proxy_pass http://localhost:8002;
}
}
(2)开放对外访问的端口号 9001 8080 8081
4、最终测试
负载均衡实例
以轮训为例,如下是nginx.conf完整代码。
worker_processes 1;
events {
worker_connections 1024;
}
http {
upstream dalaoyang-server {
server localhost:10001;
server localhost:10002;
}
server {
listen 10000;
server_name localhost;
location / {
proxy_pass http://dalaoyang-server;
proxy_redirect default;
}
}
}
重启nginx,第一次访问http://localhost:10000如图所示,
在次访问如图所示
如果要修改负载均衡算法修改对应upstream模块即可。
动静分离实例1
http {
……
server {
listen 80;
server_name 192.168.17.129;
location /www/ {
root /data/;
index index.html index.htm;
}
location /image/ {
root /data/;
autoindex on; // 列出访问目录
}
}
}
上面的配置表示当请求包含/www/
,则进入/data
目录下找资源
如果路径包含/image
,则进入 /data/
目录下找资源,同时该路径下配置了autoindex on
,当访问/image/目录时,会列出该目录下的所有文件路面。
修改完配置文件后,记得重启Nginx
浏览器中输入地址测试:http://192.168.17.129/image/01.jpg
动静分离实例2
准备工作
需要安装Nginx和Java环境(运行SpringBoot项目)。
关于Linux系统安装Nginx可以参考文章---(传送门)。SpringBoot使用了Thymeleaf模板,项目端口号为8888。
在本地/Users/dalaoyang/Downloads/static文件内存放了jquery.js
修改SpringBoot应用启动类,做简单跳转,使访问根路径可以跳转到index.html,如下代码所示。
@SpringBootApplication
@Controller
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@GetMapping("/")
public String index(){
return "index";
}
}
index.html代码如下所示,注意引入jquery.js,在引用成功会使用jquery给div赋值,代码如下所示。
<!DOCTYPE html>
<!--解决th报错 -->
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>thymeleaf</title>
</head>
<script type="text/javascript" src="jquery.js"></script>
<body>
<h1>这是一个静态页面</h1>
<div id="test_div"></div>
</body>
<script type="text/javascript">
$('#test_div').html('引用jquery.js成功');
</script>
</html>项目结构如下所示,可以看到没有jquery.js,我们要做的就是使用Nginx来访问jquery.js。
Nginx配置
修改nginx.conf配置,其中第一个location负责处理后台请求,第二个负责处理静态资源,如下所示。
worker_processes 1;
events {
worker_connections 1024;
}
http {
server {
listen 10000;
server_name localhost;
#拦截后台请求
location / {
proxy_pass http://localhost:8888;
proxy_set_header X-Real-IP $remote_addr;
}
#拦截静态资源
location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|js|css)$ {
root /Users/dalaoyang/Downloads/static;
}
}
}
测试
启动SpringBoot应用,启动Nginx。
在浏览器访问http://localhost:10000/
,可以看到如下图所示。
通过图中红框内容都可以看出来引用静态资源成功了。