一篇文章让你了解nginx和lua脚本(Nginx详解)
静态资源部署
Rewrite地址重写
正则表达式
反向代理
负载均衡
轮询、加权轮询、ip_hash、url_hash、fair
Web缓存
环境部署
高可用的环境
用户认证模块…
nginx二进制可执行文件
nginx.conf配置文件
error.log错误的日志记录
access.log访问日志记录
一、Nginx核心配置文件结构
首先我们来学习下,我们的配置文件,nginx,conf是最重要的一个配置文件,我们来看下最基本的配置文件中的内容。
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
指令名 指令值; #全局块,主要设置Nginx服务器整体运行的配置指令
#events块,主要设置,Nginx服务器与用户的网络连接,这一部分对
Nginx服务器的性能影响较大
events {
指令名 指令值;
}
#http块,是Nginx服务器配置中的重要部分,代理、缓存、日志记录、
第三方模块配置...
http {
指令名 指令值;
server {
#server块,是Nginx配置和虚拟主机相关的内容
指令名 指令值;
location / {
#location块,基于Nginx服务器接收请求字符串与
location后面的值进行匹配,对特定请求进行处理
指令名 指令值;
}
}
...
}
总结
全局块、events块、http块。http块中可以配置多个server块,每个server块又可以配置多个location块。
1.全局块
1.user指令
user:用于配置运行Nginx服务器的worker进程的用户和用户组
2.work process指令
master_process:用来指定是否开启工作进程。
worker_processes:用于配置Nginx生成工作进程的数量,这个是Nginx
服务器实现并发处理服务的关键所在。
3.daemon
=daemon:设定Nginx是否以守护进程的方式启动。
4.pid
pid:用来配置Nginx当前master进程的进程号ID存储的文件路径。
5.error_log
6.include
include:用来引入其他配置文件,使Nginx的配置更加灵活
2.events块
1.accept_mutex
accept_mutex:用来设置Nginx网络连接序列化
2.multi_accept
multi_accept:用来设置是否允许同时接收多个网络连接
3.worker_connections
worker_connections:用来配置单个worker进程最大的连接数
4.use
use:用来设置Nginx服务器选择哪种事件驱动来处理网络消息。.
3.http块
1.定义MIME-Type
2.自定义服务日志
3.server块和location块
我们举个例子就是,访问如下路径,并且配置conf文件,代码如下
##全局块 begin##
#配置允许运行Nginx工作进程的用户和用户组
user www;
#配置运行Nginx进程生成的worker进程数
worker_processes 2;
#配置Nginx服务器运行对错误日志存放的路径
error_log logs/error.log;
#配置Nginx服务器允许时记录Nginx的master进程的PID文件路径和名
称
pid logs/nginx.pid;
#配置Nginx服务是否以守护进程方法启动
#daemon on;
##全局块 end##
##events块 begin##
events{
#设置Nginx网络连接序列化
accept_mutex on;
#设置Nginx的worker进程是否可以同时接收多个请求
multi_accept on;
#设置Nginx的worker进程最大的连接数
worker_connections 1024;
#设置Nginx使用的事件驱动模型
use epoll;
}
##events块 end##
##http块 start##
http{
#定义MIME-Type
include mime.types;
default_type application/octet-stream;
#配置允许使用sendfile方式运输
sendfile on;
#配置连接超时时间
keepalive_timeout 65;
#配置请求处理日志格式
log_format server1 '===>server1 access log';
log_format server2 '===>server2 access log';
##server块 开始##
include /home/www/conf.d/*.conf;
##server块 结束##
}
##http块 end##
=server1.conf
server{
#配置监听端口和主机名称
listen 8081;
server_name localhost;
#配置请求处理日志存放路径
access_log
/home/www/myweb/server1/logs/access.log server1;
#配置错误页面
error_page 404 /404.html;
#配置处理/server1/location1请求的location
location /server1/location1{
root /home/www/myweb;
index index_sr1_location1.html;
}
#配置处理/server1/location2请求的location
location /server1/location2{
root /home/www/myweb;
index index_sr1_location2.html;
}
#配置错误页面转向
location = /404.html {
root /home/www/myweb;
index 404.html;
}
}
server2.conf
server{
#配置监听端口和主机名称
listen 8082;
server_name localhost;
#配置请求处理日志存放路径
access_log
/home/www/myweb/server2/logs/access.log server2;
#配置错误页面,对404.html做了定向配置
error_page 404 /404.html;
#配置处理/server1/location1请求的location
location /server2/location1{
root /home/www/myweb;
index index_sr2_location1.html;
}
#配置处理/server2/location2请求的location
location /server2/location2{
root /home/www/myweb;
index index_sr2_location2.html;
}
#配置错误页面转向
location = /404.html {
root /home/www/myweb;
index 404.html;
}
}
二、Nginx静态资源部署
通过浏览器发送一个HTTP
请求实现从客户端发送请求到服务器端获取所需要内容后并把内容回显
展示在页面的一个过程。这个时候,我们所请 求的内容就分为两种类
型,一类是静态资源、一类是动态资源。
静态资源即指在服务器端真实
存在并且能直接拿来展示的一些文件,比如常见的html页面、css文件、
js文件、图 片、视频等资源; 动态资源即指在服务器端真实存在但是要
想获取需要经过一定的业务逻辑处理,根据不同的条件展示在页面不同
这 一部分内容,比如说报表数据展示、根据当前登录用户展示相关具体
数据等资源;
(1)静态资源的配置指令
(2)静态资源的配置优化
(3)静态资源的压缩配置指令
(4)静态资源的缓存处理
(5)静态资源的访问控制,包括跨域问题和防盗链问题
Nginx静态资源的配置指令
1.listen指令
listen:用来配置监听端口。
server{
listen 8080;
server_name 127.0.0.1;
location /{
root html;
index index.html;
}
}
server{
listen 8080 default_server;
server_name localhost;
default_type text/plain;
return 444 'This is a error request';
}
2.server_name指令
server_name:用来设置虚拟主机服务名称。
配置方式一:精确匹配
server {
listen 80;
server_name www.itcast.cn www.itheima.cn;
...
}
.
配置方式二:使用通配符配置
server_name中支持通配符"*",但需要注意的是通配符不能出现在域名的
中间,只能出现在首段或尾段,如:
server {
listen 80;
server_name *.itcast.cn www.itheima.*;
# www.itcast.cn abc.itcast.cn www.itheima.cn
www.itheima.com
...
}
配置三:使用正则表达式配置
server_name中可以使用正则表达式,并且使用~作为正则表达式字符
串的开始标记。
server{
listen 80;
server_name ~^www\.(\w+)\.com$;
default_type text/plain;
return 200 $1 $2 ..;
}
匹配执行顺序
由于server_name指令支持通配符和正则表达式,因此在包含多个虚拟
主机的配置文件中,可能会出现一个名称被多个虚拟主机的
server_name匹配成功,当遇到这种情况,当前的请求交给谁来处理
呢?
server{
listen 80;
server_name ~^www\.\w+\.com$;
default_type text/plain;
return 200 'regex_success';
}
server{
listen 80;
server_name www.itheima.*;
default_type text/plain;
return 200 'wildcard_after_success';
}
server{
listen 80;
server_name *.itheima.com;
default_type text/plain;
return 200 'wildcard_before_success';
}
server{
listen 80;
server_name www.itheima.com;
default_type text/plain;
return 200 'exact_success';
}
server{
listen 80 default_server;
server_name _;
default_type text/plain;
return 444 'default_server not found server';
}
3. location指令
server{
listen 80;
server_name localhost;
location / {
}
location /abc{
}
uri变量是待匹配的请求字符串,可以不包含正则表达式,也可以包含正
则表达式,那么nginx服务器在搜索匹配location的时候,是先使用不包
含正则表达式进行匹配,找到一个匹配度最高的一个,然后在通过包含
正则表达式的进行匹配,如果能匹配到直接访问,匹配不到,就使用刚
才匹配度最高的那个location来处理请求。
不带符号,要求必须以指定模式开始
server {
listen 80;
server_name 127.0.0.1;
location /abc{
default_type text/plain;
return 200 "access success";
}
}
以下访问都是正确的
http://192.168.200.133/abc
http://192.168.200.133/abc?p1=TOM
http://192.168.200.133/abc/
http://192.168.200.133/abcdef
= : 用于不包含正则表达式的uri前,必须与指定的模式精确匹配
server {
listen 80;
server_name 127.0.0.1;
location =/abc{
default_type text/plain;
return 200 "access success";
}
}
可以匹配到
http://192.168.200.133/abc
http://192.168.200.133/abc?p1=TOM
匹配不到
http://192.168.200.133/abc/
http://192.168.200.133/abcdef
~ 和~*
~ : 用于表示当前uri中包含了正则表达式,并且区分大小写 ~*: 用于表
示当前uri中包含了正则表达式,并且不区分大小写
server {
listen 80;
server_name 127.0.0.1;
location ~^/abc\w${
default_type text/plain;
return 200 "access success";
}
}
server {
listen 80;
server_name 127.0.0.1;
location ~*^/abc\w${
default_type text/plain;
return 200 "access success";
}
}
^~
^~: 用于不包含正则表达式的uri前,功能和不加符号的一致,唯一不同
的是,如果模式匹配,那么就停止搜索其他模式了。
server {
listen 80;
server_name 127.0.0.1;
location ^~/abc{
default_type text/plain;
return 200 "access success";
}
}
设置请求资源的目录root / alias
举例说明:
(1)在/usr/local/nginx/html目录下创建一个 images目录,并在目
录下放入一张图片mv.png图片
location /images {
root /usr/local/nginx/html;
}
http://192.168.200.133/images/mv.png
root的处理结果是: root路径+location路径
/usr/local/nginx/html/images/mv.png
alias的处理结果是:使用alias路径替换location路径
location /images {
alias /usr/local/nginx/html/images;
}
(3)如果location路径是以/结尾,则alias也必须是以/结尾,root没有要
求
location /images/ {
alias /usr/local/nginx/html/images/;
}
小结:
root的处理结果是: root路径+location路径
alias的处理结果是:使用alias路径替换location路径
alias是一个目录别名的定义,root则是最上层目录的含义。
如果location路径是以/结尾,则alias也必须是以/结尾,root没有要
求
4.index指令
index后面可以跟多个设置,如果访问的时候没有指定具体访问的资源,
则会依次进行查找,找到第一个为止。
location / {
root /usr/local/nginx/html;
index index.html index.htm;
}
访问该location的时候,可以通过 http://ip:port/,地址后面如果
不添加任何内容,则默认依次访问index.html和index.htm,找到第一
个来进行返回
5.error_page指令
error_page:设置网站的错误页面
error_page code … [=[response]] uri;
http、server、location…
server {
error_page 404 http://www.itcast.cn;
}
server{
error_page 404 /50x.html;
error_page 500 502 503 504 /50x.html;
location =/50x.html{
root html;
}
}
server{
error_page 404 @jump_to_error;
location @jump_to_error {
default_type text/plain;
return 404 'Not Found Page...';
}
}
可选项=[response]的作用是用来将相应代码更改为另外一个
server{
error_page 404 =200 /50x.html;
location =/50x.html{
root html;
}
}
这样的话,当返回404找不到对应的资源的时候,在浏览器上可以看到,
最终返回的状态码是200,这块需要注意下,编写error_page后面的内
容,404后面需要加空格,200前面不能加空格
静态资源的缓存处理
缓存(cache),原始意义是指访问速度比一般随机存取存储器(RAM)
快的一种高速存储器,通常它不像系统主存那样使用DRAM技术,而使用昂
贵但较快速的SRAM技术。缓存的设置是所有现代计算机系统发挥高性能的
重要因素之一。
什么是web缓存
Web缓存是指一个Web资源(如html页面,图片,js,数据等)存在于
Web服务器和客户端(浏览器)之间的副本。缓存会根据进来的请求保存
输出内容的副本;当下一个请求来到的时候,如果是相同的URL,缓存会
根据缓存机制决定是直接使用副本响应访问请求,还是向源服务器再次发
送请求。比较常见的就是浏览器会缓存访问过网站的网页,当再次访问这
个URL地址的时候,如果网页没有更新,就不会再次下载网页,而是直接
使用本地缓存的网页。只有当网站明确标识资源已经更新,浏览器才会再
次下载网页
浏览器缓存
是为了节约网络的资源加速浏览,浏览器在用户磁盘上对最近请求过的文
档进行存储,当访问者再次请求这个页面时,浏览器就可以从本地磁盘显
示文档,这样就可以加速页面的阅览.
成本最低的一种缓存实现
减少网络带宽消耗
降低服务器压力
减少网络延迟,加快页面打开速度
浏览器缓存的执行流程
(1)用户首次通过浏览器发送请求到服务端获取数据,客户端是没有对
应的缓存,所以需要发送request请求来获取数据;
(2)服务端接收到请求后,获取服务端的数据及服务端缓存的允许后,
返回200的成功状态码并且在响应头上附上对应资源以及缓存信息;
(3)当用户再次访问相同资源的时候,客户端会在浏览器的缓存目录中
查找是否存在响应的缓存文件
(4)如果没有找到对应的缓存文件,则走(2)步
(5)如果有缓存文件,接下来对缓存文件是否过期进行判断,过期的判
断标准是(Expires),
(6)如果没有过期,则直接从本地缓存中返回数据进行展示
(7)如果Expires过期,接下来需要判断缓存文件是否发生过变化
(8)判断的标准有两个,一个是ETag(Entity Tag),一个是Last-Modified
(9)判断结果是未发生变化,则服务端返回304,直接从缓存文件中获
取数据
(10)如果判断是发生了变化,重新从服务端获取数据,并根据缓存协
商(服务端所设置的是否需要进行缓存数据的设置)来进行数据缓存。
expires指令
expires:该指令用来控制页面缓存的作用。可以通过该指令控制HTTP应
答中的“Expires"和”Cache-Control"
add_header指令
Cache-control: must-revalidate
Cache-control: no-cache
Cache-control: no-store
Cache-control: no-transform
Cache-control: public
Cache-control: private
Cache-control: proxy-revalidate
Cache-Control: max-age=<seconds>
Cache-control: s-maxage=<seconds>
Nginx的跨域问题解决
同源策略
浏览器的同源策略:是一种约定,是浏览器最核心也是最基本的安全功
能,如果浏览器少了同源策略,则浏览器的正常功能可能都会受到影
响。
同源: 协议、域名(IP)、端口相同即为同源
http://192.168.200.131/user/1
https://192.168.200.131/user/1
不
http://192.168.200.131/user/1
http://192.168.200.132/user/1
不
http://192.168.200.131/user/1
http://192.168.200.131:8080/user/1
不
http://www.nginx.com/user/1
http://www.nginx.org/user/1
不
ttp://192.168.200.131/user/1
http://192.168.200.131:8080/user/1
不
http://www.nginx.org:80/user/1
http://www.nginx.org/user/1
满足
跨域问题
有两台服务器分别为A,B,如果从服务器A的页面发送异步请求到服务器B获
取数据,如果服务器A和服务器B不满足同源策略,则就会出现跨域问题。
解决方案
此处用来解决跨域问题,需要添加两个头信息,一个是AccessControl-Allow-Origin , Access-Control-Allow-Methods
Access-Control-Allow-Origin: 直译过来是允许跨域访问的源地址信息,
可以配置多个(多个用逗号分隔),也可以使用*代表所有源
此处用来解决跨域问题,需要添加两个头信息,一个是AccessControl-Allow-Origin , Access-Control-Allow-Methods
Access-Control-Allow-Origin: 直译过来是允许跨域访问的源地址信息,
可以配置多个(多个用逗号分隔),也可以使用*代表所有源
location /getUser{
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods
GET,POST,PUT,DELETE;
default_type application/json;
return 200 '{
"id":1,"name":"TOM","age":18}';
}
静态资源防盗链
资源盗链指的是此内容不在自己服务器上,而是通过技术手段,绕过别
人的限制将别人的内容放到自己页面上最终展示给用户。以此来盗取大
网站的空间和流量。简而言之就是用别人的东西成就自己的网站。
资源盗链指的是此内容不在自己服务器上,而是通过技术手段,绕过别
人的限制将别人的内容放到自己页面上最终展示给用户。以此来盗取大
网站的空间和流量。简而言之就是用别人的东西成就自己的网站。
location ~*\.(png|jpg|gif){
valid_referers none blocked www.baidu.com
192.168.200.222 *.example.com example.*
www.example.org ~\.google\.;
if ($invalid_referer){
return 403;
}
root /usr/local/nginx/html;
}
针对目录进行防盗链
location /images {
valid_referers none blocked www.baidu.com
192.168.200.222 *.example.com example.*
www.example.org ~\.google\.;
if ($invalid_referer){
return 403;
}
root /usr/local/nginx/html;
}
Rewrite功能配置
Rewrite规则
set指令
该指令用来设置一个新的变量。
if指令.
if (-f $request_filename){
#判断请求的文件是否存在
}
if (!-f $request_filename){
#判断请求的文件是否不存在
}
break指令
该指令用于中断当前相同作用域中的其他Nginx配置。与该指令处于同
一作用域的Nginx配置中,位于它前面的指令配置生效,位于后面的指
令配置无效
location /{
if ($param){
set $id $1;
break;
limit_rate 10k;
}
}
return指令
该指令用于完成对请求的处理,直接向客户端返回响应状态代码。在
return后的所有Nginx配置都是无效的。
rewrite指令
该指令通过正则表达式的使用来改变URI。可以同时存在一个或者多个指
令,按照顺序依次对URL进行匹配和处理。
当我们匹配到rewrite/url路径加上后面的任意字符的路径,都将跳转到百度的连接,看第二行,当我们匹配到test路径的时候,我们将会访问/$1,这个表示的是括号里test路径的意思
rewrite_log指令
==
Rewrite的案例
域名镜像
独立域名
目录自动添加"/"
server {
listen 80;
server_name localhost;
location /hm {
root html;
index index.html;
}
}
server {
listen 80;
server_name localhost;
server_name_in_redirect on;
location /hm {
if (-d $request_filename){
rewrite ^/(.*)([^/])$ http://$host/$1$2/
permanent;
}
}
}
合并目录
防盗链
文件防盗链
server{
listen 80;
server_name www.web.com;
locatin ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip)${
valid_referers none blocked server_names
*.web.com;
if ($invalid_referer){
rewrite ^/
http://www.web.com/images/forbidden.png;
}
}
}
目录防盗链
server{
listen 80;
server_name www.web.com;
location /file/{
root /server/file/;
valid_referers none blocked server_names
*.web.com;
if ($invalid_referer){
rewrite ^/
http://www.web.com/images/forbidden.png;
}
}
}
Nginx反向代理
Nginx正向代理案例
http {
log_format main 'client send
request=>clientIp=$remote_addr serverIp=>$host';
server{
listen 80;
server_name localhost;
access_log logs/access.log main;
location {
root html;
index index.html index.htm;
}
}
}
server {
listen 82;
resolver 8.8.8.8;
location /{
proxy_pass http://$host$request_uri;
}
}
Nginx反向代理的配置语法
Nginx反向代理模块的指令是由ngx_http_proxy_module模块进行解
析,该模块在安装Nginx的时候已经自己加装到Nginx中了,接下来我们
把反向代理中的常用指令一一介绍下:
- proxy_pass
- proxy_set_header
- proxy_redirect
proxy_pass
URL:为要设置的被代理服务器地址,包含传输协议( http , https:// )、
主机名称或IP地址加端口号、URI等要素。
我们如果proxy_pass不加斜杠,则代理的请求路径则会拼接location中的/server。如果我们加上了,则我们直接访问的是index.html页面
proxy_set_header
该指令可以更改Nginx服务器接收到的客户端请求的请求头信息,然后
将新的请求头发送给代理的服务器
代理服务器: [192.168.200.133]
proxy_redirect
该指令是用来重置头信息中的"Location"和"Refresh"的值。
服务端[192.168.200.146]
代理服务端[192.168.200.133]
proxy_redirect default;
Nginx的安全控制
如何使用SSL对流量进行加密
翻译成大家能熟悉的说法就是将我们常用的http请求转变成https请求,
那么这两个之间的区别简单的来说两个都是HTTP协议,只不过https是
身披SSL外壳的http.
HTTPS是一种通过计算机网络进行安全通信的传输协议。它经由HTTP进
行通信,利用SSL/TLS建立全通信,加密数据包,确保数据的安全性。
上述这两个是为网络通信提供安全及数据完整性的一种安全协议,TLS和
SSL在传输层和应用层对网络连接进行加密。
- SSL(Secure Sockets Layer)安全套接层
- TLS(Transport Layer Security)传输层安全
Nginx要想使用SSL,需要满足一个条件即需要添加一个模块–withhttp_ssl_module ,而该模块在编译的过程中又需要OpenSSL的支持,
这个我们之前已经准备好了。
》将原有/usr/local/nginx/sbin/nginx进行备份
》拷贝nginx之前的配置信息
》在nginx的安装源码进行配置指定对应模块 ./configure --
with-http_ssl_module
》通过make模板进行编译
》将objs下面的nginx移动到/usr/local/nginx/sbin下
》在源码目录下执行 make upgrade进行升级,这个可以实现不停机添
加新模块的功能
Nginx的SSL相关指令
SSL
ssl_certificate
ssl_certificate:为当前这个虚拟主机指定一个带有PEM格式证书的证
书。
ssl_certificate_key
ssl_session_cache
ssl_session_timeout
ssl_ciphers
ssl_prefer_server_ciphers
生成证书
开启SSL实例
server {
listen 443 ssl;
server_name localhost;
ssl_certificate server.cert;
ssl_certificate_key server.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
反向代理系统调优
相同点:
两种方式都是用来提供IO吞吐效率,都是用来提升Nginx代理的性能。
不同点:
缓冲主要用来解决不同设备之间数据传递速度不一致导致的性能低的问
题,缓冲中的数据一旦此次操作完成后,就可以删除。
缓存主要是备份,将被代理服务器的数据缓存一份到代理服务器,这样的
话,客户端再次获取相同数据的时候,就只需要从代理服务器上获取,效
率较高,缓存中的数据可以重复使用,只有满足特定条件才会删除.
(1)Proxy Buffer相关指令
》proxy_buffering :该指令用来开启或者关闭代理服务器的缓冲区;
》proxy_buffers:该指令用来指定单个连接从代理服务器读取响应的缓
存区的个数和大小。
number:缓冲区的个数
size:每个缓冲区的大小,缓冲区的总大小就是number*size
`
》proxy_buffer_size:该指令用来设置从被代理服务器获取的第一部分响
应数据的大小。保持与proxy_buffers中的size一致即可,当然也可以更
小。`
》proxy_busy_buffers_size:该指令用来限制同时处于BUSY状态的缓
冲总大小。
》proxy_temp_path:当缓冲区存满后,仍未被Nginx服务器完全接受,
响应数据就会被临时存放在磁盘文件上,该指令设置文件路径
》proxy_temp_file_write_size:该指令用来设置磁盘上缓冲文件的大
小。
proxy_buffering on;
proxy_buffer_size 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
负载均衡
负载均衡的原理及处理流程
系统的扩展可以分为纵向扩展和横向扩展。
纵向扩展是从单机的角度出发,通过增加系统的硬件处理能力来提升服
务器的处理能力
横向扩展是通过添加机器来满足大型网站服务的处理能力。
负载均衡的作用
1、解决服务器的高并发压力,提高应用程序的处理性能。
2、提供故障转移,实现高可用。
3、通过添加或减少服务器数量,增强网站的可扩展性。
4、在负载均衡器上进行过滤,可以提高系统的安全性。
负载均衡常用的处理方式
用户手动选择
DNS轮询方式
域名系统(服务)协议(DNS)是一种分布式网络目录服务,主要用于域
名与 IP 地址的相互转换。
大多域名注册商都支持对同一个主机名添加多条A记录,这就是DNS轮
询,DNS服务器将解析请求按照A记录的顺序,随机分配到不同的IP上,
这样就能完成简单的负载均衡。DNS轮询的成本非常低,在一些不重要
的服务器,被经常使用。
四/七层负载均衡
介绍四/七层负载均衡之前,我们先了解一个概念,OSI(open system
interconnection),叫开放式系统互联模型,这个是由国际标准化组织ISO
指定的一个不基于具体机型、操作系统或公司的网络体系结构。该模型
将网络通信的工作分为七层。
Nginx七层负载均衡
Nginx要实现七层负载均衡需要用到proxy_pass代理模块配置。Nginx默
认安装支持这个模块,我们不需要再做任何处理。Nginx的负载均衡是
在Nginx的反向代理基础上把用户的请求根据指定的算法分发到一组
【upstream虚拟服务池】
Nginx七层负载均衡的指令
服务端设置
server {
listen 9001;
server_name localhost;
default_type text/html;
location /{
return 200 '<h1>192.168.200.146:9001</h1>';
}
}
server {
listen 9002;
server_name localhost;
default_type text/html;
location /{
return 200 '<h1>192.168.200.146:9002</h1>';
}
}
server {
listen 9003;
server_name localhost;
default_type text/html;
location /{
return 200 '<h1>192.168.200.146:9003</h1>';
}
}
负载均衡器设置
upstream backend{
server 192.168.200.146:9091;
server 192.168.200.146:9092;
server 192.168.200.146:9093;
}
server {
listen 8083;
server_name localhost;
location /{
proxy_pass http://backend;
}
}
负载均衡状态
down
down:将该服务器标记为永久不可用,那么该代理服务器将不参与负载
均衡。
upstream backend{
server 192.168.200.146:9001 down;
server 192.168.200.146:9002
server 192.168.200.146:9003;
}
server {
listen 8083;
server_name localhost;
location /{
proxy_pass http://backend;
}
}
backup
backup:将该服务器标记为备份服务器,当主服务器不可用时,将用来传
递请求。
upstream backend{
server 192.168.200.146:9001 down;
server 192.168.200.146:9002 backup;
server 192.168.200.146:9003;
}
server {
listen 8083;
server_name localhost;
location /{
proxy_pass http://backend;
}
}
max_fails和fail_timeout
max_conns
upstream backend{
server 192.168.200.133:9001 down;
server 192.168.200.133:9002 backup;
server 192.168.200.133:9003 max_fails=3
fail_timeout=15;
}
server {
listen 8083;
server_name localhost;
location /{
proxy_pass http://backend;
}
}
负载均衡策略
轮询
weight加权[加权轮询]
ip_hash
当对后端的多台动态应用服务器做负载均衡时,ip_hash指令能够将某个
客户端IP的请求通过哈希算法定位到同一台后端服务器上。这样,当来
自某一个IP的用户在后端Web服务器A上登录后,在访问该站点的其他
URL,能保证其访问的还是后端web服务器A。
least_conn
upstream backend{
least_conn;
server 192.168.200.146:9001;
server 192.168.200.146:9002;
server 192.168.200.146:9003;
}
server {
listen 8083;
server_name localhost;
location /{
proxy_pass http://backend;
}
}
url_hash
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务
器,要配合缓存命中来使用。同一个资源多次请求,可能会到达不同的
服务器上,导致不必要的多次下载,缓存命中率不高,以及一些资源时
间的浪费。而使用url_hash,可以使得同一个url(也就是同一个资源请求)
会到达同一台服务器,一旦缓存住了资源,再此收到请求,就可以
从缓存中读取。
fair
fair采用的不是内建负载均衡使用的轮换的均衡算法,而是可以根据页面
大小、加载时间长短智能的进行负载均衡。那么如何使用第三方模块的
fair负载均衡策略。
upstream backend{
fair;
server 192.168.200.146:9001;
server 192.168.200.146:9002;
server 192.168.200.146:9003;
}
server {
listen 8083;
server_name localhost;
location /{
proxy_pass http://backend;
}
}
但是如何直接使用会报错,因为fair属于第三方模块实现的负载均衡。需
要添加nginx-upstream-fair ,如何添加对应的模块:
扩展案例
upstream backend{
server 192.168.200.146:9001;
server 192.168.200.146:9002;
server 192.168.200.146:9003;
}
server {
listen 80;
server_name localhost;
location /file/ {
rewrite ^(/file/.*) /server/$1 last;
}
location / {
proxy_pass http://backend;
}
}
四层负载均衡的案例
stream {
upstream redisbackend {
server 192.168.200.146:6379;
server 192.168.200.146:6378;
}
upstream tomcatbackend {
server 192.168.200.146:8080;
}
server {
listen 81;
proxy_pass redisbackend;
}
server {
listen 82;
proxy_pass tomcatbackend;
}
}
Nginx缓存集成
缓存就是数据交换的缓冲区(称作:Cache),当用户要获取数据的时候,会
先从缓存中去查询获取数据,如果缓存中有就会直接返回给用户,如果
缓存中没有,则会发请求从服务器重新查询数据,将数据返回给用户的
同时将数据放入缓存,下次用户就会直接从缓存中获取数据
Nginx的web缓存服务
Nginx缓存设置的相关指令
Nginx的web缓存服务主要是使用ngx_http_proxy_module模块相关指
令集来完成,接下来我们把常用的指令来进行介绍下。
proxy_cache_path
keys_zone:用来为这个缓存区设置名称和指定大小,如:
proxy_cache
proxy_cache_key
proxy_cache_valid
proxy_cache_min_uses
proxy_cache_methods
Nginx缓存设置案例
http{
proxy_cache_path /usr/local/proxy_cache
levels=2:1 keys_zone=itcast:200m inactive=1d
max_size=20g;
upstream backend{
server 192.168.200.146:8080;
}
server {
listen 8080;
server_name localhost;
location / {
proxy_cache itcast;
proxy_cache_key itheima;
proxy_cache_min_uses 5;
proxy_cache_valid 200 5d;
proxy_cache_valid 404 30s;
proxy_cache_valid any 1m;
add_header nginx-cache
"$upstream_cache_status";
proxy_pass http://backend/js/;
}
}
}
Nginx缓存的清除
方式一:删除对应的缓存目录
rm -rf /usr/local/proxy_cache/......
使用第三方扩展模块
ngx_cache_purge
server{
location ~/purge(/.*) {
proxy_cache_purge itcast itheima;
}
}
Nginx设置资源不缓存
前面咱们已经完成了Nginx作为web缓存服务器的使用。但是我们得思考
一个问题就是不是所有的数据都适合进行缓存。比如说对于一些经常发
生变化的数据。如果进行缓存的话,就很容易出现用户访问到的数据不
是服务器真实的数据。所以对于这些资源我们在缓存的过程中就需要进
行过滤,不进行缓存。
proxy_no_cache
该指令是用来定义不将数据进行缓存的条件。
proxy_no_cache $cookie_nocache $arg_nocache
$arg_comment;
proxy_cache_bypass
该指令是用来设置不从缓存中获取数据的条件。
log_format params $cookie_nocache | $arg_nocache |
$arg_comment;
server{
listen 8081;
server_name localhost;
location /{
access_log logs/access_params.log params;
add_header Set-Cookie 'nocache=999';
root html;
index index.html;
}
}
Nginx实现服务器端集群搭建
环境准备(Tomcat)
环境准备(Nginx)
动静分离实现步骤
配置Nginx的静态资源与动态资源的访问
upstream webservice{
server 192.168.200.146:8080;
}
server {
listen 80;
server_name localhost;
#动态资源
location /demo {
proxy_pass http://webservice;
}
#静态资源
location ~/.*\.(png|jpg|gif|js){
root html/web;
gzip on;
}
location / {
root html/web;
index index.html index.htm;
}
}
Nginx实现Tomcat集群搭建
在使用Nginx和Tomcat部署项目的时候,我们使用的是一台Nginx服务
器和一台Tomcat服务器,效果图如下:
Nginx高可用解决方案
Keepalived
Keepalived配置文件介绍
global全局部分:
global_defs {
#通知邮件,当keepalived发送切换时需要发email给具体的邮箱
地址
notification_email {
tom@itcast.cn
jerry@itcast.cn
}
#设置发件人的邮箱信息
notification_email_from zhaomin@itcast.cn
#指定smpt服务地址
smtp_server 192.168.200.1
#指定smpt服务连接超时时间
smtp_connect_timeout 30
#运行keepalived服务器的一个标识,可以用作发送邮件的主题信
息
router_id LVS_DEVEL
#默认是不跳过检查。检查收到的VRRP通告中的所有地址可能会比较
耗时,设置此命令的意思是,如果通告与接收的上一个通告来自相同的
master路由器,则不执行检查(跳过检查)
vrrp_skip_check_adv_addr
#严格遵守VRRP协议。
vrrp_strict
#在一个接口发送的两个免费ARP之间的延迟。可以精确到毫秒级。
默认是0
vrrp_garp_interval 0
#在一个网卡上每组na消息之间的延迟时间,默认为0
vrrp_gna_interval 0
}
VRRP部分,该部分可以包含以下四个子模块
1. vrrp_script
2. vrrp_sync_group
3. 3. garp_group
4. vrrp_instance
我们会用到第一个和第四个,
#设置keepalived实例的相关信息,VI_1为VRRP实例名称
vrrp_instance VI_1 {
state MASTER #有两个值可选MASTER主 BACKUP备
interface ens33 #vrrp实例绑定的接口,用于发送VRRP
包[当前服务器使用的网卡名称]
virtual_router_id 51#指定VRRP实例ID,范围是0-255
priority 100 #指定优先级,优先级高的将成为
MASTER
advert_int 1 #指定发送VRRP通告的间隔,单位是秒
authentication {
#vrrp之间通信的认证信息
auth_type PASS #指定认证方式。PASS简单密码认证(推
荐)
auth_pass 1111 #指定认证使用的密码,最多8位
}
virtual_ipaddress {
#虚拟IP地址设置虚拟IP地址,供用户
访问使用,可设置多个,一行一个
192.168.200.222
}
}
服务器1
global_defs {
notification_email {
tom@itcast.cn
jerry@itcast.cn
}
notification_email_from zhaomin@itcast.cn
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id keepalived1
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.200.222
}
}
服务器2
! Configuration File for keepalived
global_defs {
notification_email {
tom@itcast.cn
jerry@itcast.cn
}
notification_email_from zhaomin@itcast.cn
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id keepalived2
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.200.222
}
}
Nginx制作下载站点
location /download{
root /usr/local;
autoindex on;
autoindex_exact_size on;
autoindex_format html;
autoindex_localtime on;
}
Nginx的用户认证模块
location /download{
root /usr/local;
autoindex on;
autoindex_exact_size on;
autoindex_format html;
autoindex_localtime on;
auth_basic 'please input your auth';
auth_basic_user_file htpasswd;
}
Nginx的扩展模块
Nginx是可扩展的,可用于处理各种使用场景。本节中,我们将探讨使
用Lua扩展Nginx的功能。
Lua
ngx_lua操作Redis
lua-resty-redis提供了访问Redis的详细API,包括创建对接、连
接、操作、数据处理等。这些API基本上与Redis的操作一一对应。
(1)redis = require "resty.redis"
(2)new
语法: redis,err = redis:new(),创建一个Redis对象。
(3)connect
语
法:ok,err=redis:connect(host,port[,options_table]),设
置连接Redis的连接信息。
ok:连接成功返回 1,连接失败返回nil
err:返回对应的错误信息
(4)set_timeout
语法: redis:set_timeout(time) ,设置请求操作Redis的超
时时间。
(5)close
语法: ok,err = redis:close(),关闭当前连接,成功返回1,
失败返回nil和错误信息
(6)redis命令对应的方法
在lua-resty-redis中,所有的Redis命令都有自己的方法,方
法名字和命令名字相同,只是全部为小写。
location / {
default_type "text/html";
content_by_lua_block{
local redis = require "resty.redis" -- 引入
Redis
local redisObj = redis:new() --创建Redis对象
redisObj:set_timeout(1000) --设置超时数据为1s
local ok,err =
redisObj:connect("192.168.200.1",6379) --设置redis连接
信息
if not ok then --判断是否连接成功
ngx.say("failed to connection redis",err)
return
end
ok,err = redisObj:set("username","TOM")--存入
数据
if not ok then --判断是否存入成功
ngx.say("failed to set username",err)
return
end
local res,err = redisObj:get("username") --从
redis中获取数据
ngx.say(res) --将数据写会消息体中
redisObj:close()
}
}
ngx_lua操作Mysql
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.200.111:3306/nginx_db
username=root
password=123456
(1)引入"resty.mysql"模块
local mysql = require "resty.mysql"
(2)new
创建一个MySQL连接对象,遇到错误时,db为nil,err为错误描
述信息
语法: db,err = mysql:new()
(3)connect
尝试连接到一个MySQL服务器
语法:ok,err=db:connect(options),options是一个参数的
Lua表结构,里面包含数据库连接的相关信息
host:服务器主机名或IP地址
port:服务器监听端口,默认为3306
user:登录的用户名
password:登录密码
database:使用的数据库名
(4)set_timeout
设置子请求的超时时间(ms),包括connect方法
语法:db:set_timeout(time)
(5)close
关闭当前MySQL连接并返回状态。如果成功,则返回1;如果出现任
何错误,则将返回nil和错误描述。
语法:db:close()
(6)send_query
异步向远程MySQL发送一个查询。如果成功则返回成功发送的字节
数;如果错误,则返回nil和错误描述
语法:bytes,err=db:send_query(sql)
(7)read_result
从MySQL服务器返回结果中读取一行数据。res返回一个描述OK包
或结果集包的Lua表,语法:
res, err, errcode, sqlstate = db:read_result()
res, err, errcode, sqlstate =
db:read_result(rows) :rows指定返回结果集的最大值,默认为4
如果是查询,则返回一个容纳多行的数组。每行是一个数据列的
key-value对,如
{
{
id=1,username="TOM",birthday="1988-11-
11",salary=10000.0},
{
id=2,username="JERRY",birthday="1989-11-
11",salary=20000.0}
}
如果是增删改,则返回类上如下数据
{
insert_id = 0,
server_status=2,
warning_count=1,
affected_rows=2,
message=nil
}
返回值:
res:操作的结果集
err:错误信息
errcode:MySQL的错误码,比如1064
sqlstate:返回由5个字符组成的标准SQL错误码,比如
42000
location /{
content_by_lua_block{
local mysql = require "resty.mysql"
local db = mysql:new()
local ok,err = db:connect{
host="192.168.200.111",
port=3306,
user="root",
password="123456",
database="nginx_db"
}
db:set_timeout(1000)
db:send_query("select * from users where id
=1")
local res,err,errcode,sqlstate =
db:read_result()
ngx.say(res[1].id..","..res[1].username..","..res[1].
birthday..","..res[1].salary)
db:close()
}
}
location /{
content_by_lua_block{
local mysql = require "resty.mysql"
local cjson = require "cjson"
local db = mysql:new()
local ok,err = db:connect{
host="192.168.200.111",
port=3306,
user="root",
password="123456",
database="nginx_db"
}
db:set_timeout(1000)
--db:send_query("select * from users where id
= 2")
db:send_query("select * from users")
local res,err,errcode,sqlstate =
db:read_result()
ngx.say(cjson.encode(res))
for i,v in ipairs(res) do
ngx.say(v.id..","..v.username..","..v.birthday..","..
v.salary)
end
db:close()
}
}
location /{
content_by_lua_block{
local mysql = require "resty.mysql"
local db = mysql:new()
local ok,err = db:connect{
host="192.168.200.1",
port=3306,
user="root",
password="123456",
database="nginx_db",
max_packet_size=1024,
compact_arrays=false
}
db:set_timeout(1000)
local res,err,errcode,sqlstate =
db:query("select * from users")
--local res,err,errcode,sqlstate =
db:query("insert into
users(id,username,birthday,salary)
values(null,'zhangsan','2020-11-11',32222.0)")
--local res,err,errcode,sqlstate =
db:query("update users set username='lisi' where id =
6")
--local res,err,errcode,sqlstate =
db:query("delete from users where id = 6")
db:close()
}
}
综合小案例
init_by_lua_block{
redis = require "resty.redis"
mysql = require "resty.mysql"
cjson = require "cjson"
}
location /{
default_type "text/html";
content_by_lua_block{
--获取请求的参数username
local param = ngx.req.get_uri_args()
["username"]
--建立mysql数据库的连接
local db = mysql:new()
local ok,err = db:connect{
host="192.168.200.111",
port=3306,
user="root",
password="123456",
database="nginx_db"
}
if not ok then
ngx.say("failed connect to
mysql:",err)
return
end
--设置连接超时时间
db:set_timeout(1000)
--查询数据
local sql = "";
if not param then
sql="select * from users"
else
sql="select * from users where
username=".."'"..param.."'"
end
local
res,err,errcode,sqlstate=db:query(sql)
if not res then
ngx.say("failed to query from
mysql:",err)
return
end
--连接redis
local rd = redis:new()
ok,err =
rd:connect("192.168.200.111",6379)
if not ok then
ngx.say("failed to connect to
redis:",err)
return
end
rd:set_timeout(1000)
--循环遍历数据
for i,v in ipairs(res) do
rd:set("user_"..v.username,cjson.encode(v))
end
ngx.say("success")
rd:close()
db:close()
}
}