1、引出nginx
- 引出nginx——访问不同微服务、轮询访问微服务
- 解决方案nginx——动静分离
2、基本介绍
是什么?Nginx(“engine x”)是一个高性能的 HTTF 和反向代理WEB服务器
能干什么?反向代理 负载均衡 动静分离
牛逼之处?高性能,高负载 有报告表明能支持高达 50,000个并发连接数
详细说明:https://Inmp.org/nginx.html
官方资料:
官网:https://nginx.org/
使用文档:https://nginx.org/en/docs/
3、Nginx核心功能
正向代理
一句话: 如果我们要访问www.google.com,但是直接访问不到,则需要通过代理服务器来访问,这种代理服务就称为正向代理
图解:
1.我们知道www.google.com,但是访问不到。
2.所以使用代理服务器帮助我们(即客户端)来上网,注意帮助的对象是客户端,这种代理,我们称正向代理。
3.正向代理同时也隐藏了客户端信息.。
4.再次说明,正向代理帮助的是客户端
,因此可以把 客户端+正向代理服务,视为一个整体。
反向代理
一句话:客户端将请求发送到代理服务器,由代理服务器去选择目标服务器
获取数据后,返回给客户端,这种代理方式为反向代理
图解
1.项目设计者,不希望客户端直接访问目标Web服务器(比如目标Web服务器是集群
,如果直接访问就会提供多个公网IP),而是希望提供一个统一的访问IP,这个是理解反向代理的前提
,即为什么要反向代理.
2.反向代理帮助的对象是目标Web服务器
3.当客户端请求达到反向代理服务后,由反向代理服务来决定如何访问目标Web服务器(或者是 哪个Web服务器), 这个过程对客户端是透明的.
4.反向代理服务会暴露公共的IP,只要能上网,就可以访问,但是对于反向代理服务器管理的/代理的
Web服务器通常是在局域网内,不能直接访问,只能通过反向理来访问.
5.我们可以将反向代理服务+反向代理服务代理的Web服务器视为一个整体
6.反向代理会屏蔽内网服务器(也就是他代理的服务)信息,并实现负载均衡访问
负载均衡
一句话:当客户端向反向代理服务器(比如Nginx)发出请求,如果Nginx代理了多个WEB服务器(集群),Nginx会将请求/负载分发到不同的服务器,也就是负载均衡
动静分离
一句话:为了加快网站的解析速度,可以把动态资源和静态资源由不同的服务器来解析,降低单个服务器的压力。
传统的项目资源部署:
动静分离项目资源部署:
4、nginx下载&安装&启动
下载
https://nginx.org/en/download.html
版本:nginx-1.20.2.tar.gz
具体安装步骤
- 搭建gcc环境
yum -y install gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel
提示:执行上面指令的时候,可能会报Centos Another app is currently holding the yum lock…错误,是因为yum不时会自动升级,占用了端口或文件,解决方案(1)可以重启Linux,立即执行该指令(2)或者等一会再执行(3)或者参考其他
- 将nginx-1.20.2.tar.gz上传至
/opt/
,并解压
tar -zxcf nginx-1.20.2.tar.gz
- 将解压好的文件移动到指定位置
mv nginx-1.20.2 /usr/local/nginx
- 进入/usr/local/nginx目录
- 配置nginx路径,在当前路径控制台输入:
./configure --prefix=/usr/local/nginx --pid-path=/var/run/nginx/nginx.pid --lock-path=/var/lock/nginx.lock --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --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 --http-scgi-temp-path=/var/temp/nginx/scgi --conf-path=/usr/local/nginx/nginx.conf
-
补全nginx配置目录
mkdir /var/temp/nginx -p
-
编译并安装
make && make install
-
测试配置文件nginx是否正常,当出现successful即可
./sbin/nginx -t
-
nginx指定配置文件启动
./sbin/nginx -c nginx.conf
-
查看进程/或端口
ps -ef | grep nginx
-
如果遇到错误,如
"open error log file: open() "/usr/local/nginx/logs/error.log" failed (2: No such file or directory)"
,这通常意味着 Nginx 试图写入一个不存在的日志文件目录。
解决办法:
修改conf/nginx.conf
新建文件夹:mkdir /usr/local/nginx/logs
-
验证是否安装成功
-
配置防火墙开放端口,让windows可以访问Nginx
firewall-cmd --zone=public --add-port=80/tcp --permanent
# 配置防火墙开放 80端口
firewall-cmd --reload
# 更新防火墙配置
firewall-cmd --zone=public --list-ports
# 查看已经开放的端口号
5、命令行参数
指令说明:https://nginx.org/en/docs/switches.html
启动:/usr/local/nginx/nginx -c nginx.conf
停止:/usr/local/nginx/nginx -s stop
重新加载:/usr/local/nginx/nginx -s reload
查看版本:/usr/local/nginx/nginx -v
查看版本、配置参数:/usr/local/nginx/nginx -V
6、nginx.conf配置详解
介绍
使用/usr/local/nginx/sbin/nginx启动Nginx,默认用的是目录\nginx.conf配置文件
作用:完成对Nginx的各种配置,包括端口,并发数,重写写规则等。
nginx.conf组成:
#Nginx用户及组:用户 组。window下不指定
#user nobody;
#工作进程:数目。根据硬件调整,通常等于CPU数量或者2倍于CPU。
worker_processes 1;
#错误日志:存放路径。
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid(进程标识符):存放路径
pid /usr/local/nginx/logs/nginx.pid;
#一个进程能打开的文件描述符最大值,理论上该值因该是最多能打开的文件数除以进程数。
#但是由于nginx负载并不是完全均衡的,所以这个值最好等于最多能打开的文件数。
#LINUX系统可以执行 sysctl -a | grep fs.file 可以看到linux文件描述符。
worker_rlimit_nofile 65535;
events {
#使用epoll的I/O 模型。linux建议epoll,FreeBSD建议采用kqueue,window下不指定。
use epoll;
#单个进程最大连接数(最大连接数=连接数*进程数)
worker_connections 1024;
#客户端请求头部的缓冲区大小。这个可以根据你的系统分页大小来设置,
#一般一个请求头的大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。
#client_header_buffer_size 4k;
}
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"';
#用了log_format指令设置了日志格式之后,需要用access_log指令指定日志文件的存放路径
#记录了哪些用户,哪些页面以及用户浏览器、ip和其他的访问信息
#access_log logs/host.access.log main;
#access_log logs/host.access.404.log log404;
#服务器名字的hash表大小
server_names_hash_bucket_size 128;
#客户端请求头缓冲大小。
#nginx默认会用client_header_buffer_size这个buffer来读取header值,
#如果header过大,它会使用large_client_header_buffers来读取。
#如果设置过小HTTP头/Cookie过大 会报400 错误 nginx 400 bad request
#如果超过buffer,就会报HTTP 414错误(URI Too Long)
#nginx接受最长的HTTP头部大小必须比其中一个buffer大
#否则就会报400的HTTP错误(Bad Request)
#client_header_buffer_size 32k;
#large_client_header_buffers 4 32k;
#隐藏ngnix版本号
#server_tokens off;
#忽略不合法的请求头
#ignore_invalid_headers on;
#让 nginx 在处理自己内部重定向时不默认使用 server_name设置中的第一个域名
#server_name_in_redirect off;
#客户端请求体的大小
#client_body_buffer_size 8m;
#开启文件传输,一般应用都应设置为on;若是有下载的应用,则可以设置成off来平衡网络I/O和磁盘的I/O来降低系统负载
sendfile on;
#告诉nginx在一个数据包里发送所有头文件,而不一个接一个的发送。
#tcp_nopush on;
#tcp_nodelay off 会增加通信的延时,但是会提高带宽利用率。在高延时、数据量大的通信场景中应该会有不错的效果
#tcp_nodelay on,会增加小包的数量,但是可以提高响应速度。在及时性高的通信场景中应该会有不错的效果
tcp_nodelay on;
#长连接超时时间,单位是秒
keepalive_timeout 65;
#gzip模块设置,使用 gzip 压缩可以降低网站带宽消耗,同时提升访问速度。
#gzip on; #开启gzip
#gzip_min_length 1k; #最小压缩大小
#gzip_buffers 4 16k; #压缩缓冲区
#gzip_http_version 1.0; #压缩版本
#gzip_comp_level 2; #压缩等级
#gzip_types text/plain text/css text/xml text/javascript application/json application/x-javascript application/xml application/xml+rss;#压缩类型
#负载均衡
#max_fails为允许请求失败的次数,默认为1
#weight为轮询权重,根据不同的权重分配可以用来平衡服务器的访问率。
# upstream myServer{
# server 192.168.247.129:8080 max_fails=3 weight=2;
# server 192.168.247.129:8081 max_fails=3 weight=4;
# }
#server {
# listen 80;
#
# #IP/域名可以有多个,用空格隔开
# server_name 192.168.247.129;
# #server_name www.test.com;
#
# #charset koi8-r;
#
# #access_log logs/host.access.log main;
#
# #反向代理配置,
# #将所有请求为www.test.com的请求全部转发到upstream中定义的目标服务器中。
# location / {
#
# #此处配置的域名必须与upstream的域名一致,才能转发。
# proxy_pass http://myServer;
# #proxy_pass http://192.168.247.129:8080;
#
# proxy_connect_timeout 20; #nginx跟后端服务器连接超时时间(代理连接超时)
#
# #client_max_body_size 10m; #允许客户端请求的最大单文件字节数
# #client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数
# #proxy_send_timeout 300; #后端服务器数据回传时间(代理发送超时)
# #proxy_read_timeout 300; #连接成功后,后端服务器响应时间(代理接收超时)
# #proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
# #proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
# #proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2)
# #proxy_temp_file_write_size 64k; #设定缓存文件夹大小,大于这个值,将从upstream服务器传
#
# root html;
#
# #定义首页索引文件的名称
# index index.html index.htm;
# }
#
# #动静分离 静态资源走linux 动态资源走tomcat
# # 注意 /source/image/下面寻找资源
# location /image/ {
# root /source/;
# autoindex on;
# }
#
#
# # 出现50x错误时,使用/50x.html页返回给客户端
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# root html;
# }
#}
#下面是配置生产环境中既支持HTTP又支持HTTPS,保证用户在浏览器中输入HTTP也能正常访问
# SSL证书 配置
ssl_certificate cert/yphtoy.com.pem; #加密证书路径
ssl_certificate_key cert/yphtoy.com.key; #加密私钥路径
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #加密协议
ssl_session_cache shared:SSL:1m; #加密访问缓存设置,可以大大提高访问速度
ssl_session_timeout 10m; #加密访问缓存过期时间
ssl_ciphers HIGH:!aNULL:!MD5; #加密算法
ssl_prefer_server_ciphers on; #是否由服务器决定采用哪种加密算法
# 负载均衡
upstream api_upstream
{
server 127.0.0.1:8080 max_fails=3 weight=1;
server 127.0.0.1:8081 max_fails=3 weight=1;
}
#api 接口(兼容HTTP)
server{
listen 80;
server_name api.test.com;
# 301重定向跳转到HTTPS接口
return 301 https://$server_name$request_uri;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
#api 接口(兼容HTTPS)
server{
listen 443 ssl;
server_name api.test.com;
location / {
root html;
index index.html index.htm;
proxy_pass http://api_upstream;
#语法: proxy_cookie_path oldpath replacepath;
#oldpath就是你要替换的路径 replacepath 就是要替换的值
#作用:同一个web服务器下面多个应用之间能获取到cookie
proxy_cookie_path /api/ /;
#服务端接收的请求头Cooke值不变
proxy_set_header Cookie $http_cookie;
}
}
#管理后台端(兼容HTTP)
server{
listen 80;
server_name manage.test.com;
# 301重定向跳转到HTTPS接口
return 301 https://$server_name/$request_uri;
error_page 500 502 503 504 /50x.html;
location = /50x.html{
root html
}
}
#管理后台端(兼容HTTPS)
server{
listen 443 ssl;
server_name manage.test.com;
location / {
root /home/test/web/dist
index /index.html;
#语法:try_files 【$uri】 【 $uri/】 【参数】
#当用户请求https://manage.test.com/login时,
#一.如果配置了上面的默认index,会依次请求
#1./home/test/web/dist/login 查找有没有login这个文件,没有的话
#2./home/test/web/dist/index.html 有就直接返回
#二.如果没有配置了上面的默认index或者配置了没有找到对应的资源,会依次请求
#1./home/test/web/dist/login 查找有没有login这个文件,没有的话
#2./home/test/web/dist/login/ 查找有没有login这个目录,没有的话
#3.请求https://manage.test.com/index.html nginx内部做了一个子请求
#三.总的来说,index的优先级比try_files高,请求会先去找index配置,这里最后一个参数必须存在
try_files $uri $uri/ /index.html;
#解决跨域问题
#允许跨域请求地址(*表示全部,但是无法满足带cookie请求,因为cookie只能在当前域请求)
add_header Access-Control-Allow-Origin $http_origin;
#允许接收cookie和发送cookie
add_header Access-Control-Allow-Credentials 'true';
#允许请求的方法
add_header Access-Control-Allow-Methods 'GET,POST,DELETE,PUT,OPTIONS';
#允许请求头(Content-Type:请求数据/媒体类型 x-requested-with:判断请求是异步还是同步 自定义header 比如 token)
add_header Access-Control-Allow-Headers $http_access_control_request_headers;
#浏览器缓存请求头信息,1800秒内,只会有1次请求,不会出现"OPTIONS"预请求,节约资源
#add_header Access-Control-Max-Age '1800';
if ($request_method = 'OPTIONS') {
return 204;
}
#服务端HttpServletRequest可以获得用户的真实ip
proxy_set_header X-Real-IP $remote_addr;
#服务端HttpServletRequest可以获得用户的真实ip和经过的每一层代理服务器的ip
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#服务端接收的请求头Host值不变
proxy_set_header Host $http_host;
proxy_set_header X-Nginx-Proxy true;
}
}
}
全局块
1.从配置文件开始到events块之间的内容
2.主要会设置一些影响 nginx服务器整体运行的配置指令,主要包括配置运行Nginx服务器的用户(组)、允许生成的worker process数,进程PID存放路径、日志存放路径和类型以及配置文件的引入等
3.#这是 Nginx服务器并发处理服务的关键配置,worker_processes值越大,可以支持的并发处理量也越 多,但是会受到硬件、软件等设备的制约
events 块
1.events块涉及的指令主要影响Nginx服务器与用户的网络连接
2.常用的设置包括是否开启对多 work process下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个word process可以同时支持的最大连接数等。
server 块
- 这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了节省互联网服务器硬件成本。
- 每个 http块可以包括多个server块,而每个 server 块就相当于一个虚拟主机。
- 每个 server 块也分为全局server 块,以及可以同时包含多个locaton 块
(1) 全局 server 块
最常见的配置是本虚拟机主机的监听配置和本虚拟主机的名称或IP配置。
(2) location 块
一个server 块可以配置多个location 块 - 小结:这块的主要作用是基于 Nginx服务器接收到的请求字符串(例如server_name/uri-string),虚拟主机名称(也可以是IP别名)之外的字符串(例如前面的/uri-string)进行匹配,对特定的请求进行处理。比如地址定向、数据缓存和应答控制等功能,还有许多第三方模块的配置也在这里进行。
7. 反向代理案例
需求:在window通过浏览器访问Linux的Nginx服务,Nginx代理访问到Tomcat,实际访问到资源是Tomcat,此过程客户端并不知道Tomcat的存在,Tomcat理解为隐藏起来的服务,称反向代理。
前提:在Linux安装了Nginx和Tomcat,并且处于启动状态,防火墙开放相应的端口(80,8080)
8. Location语法规则
Location规则
语法规则:location [=|\~|\~*|^~] /url/{...}
首先匹配 = ,其次匹配^~,是按文件中顺序正常匹配,最后是交给/通用匹配,当有匹配成功时候,停止匹配,按当前匹配规则处理请求。
符号 | 含义 |
---|---|
= | = 开头表示精确匹配 |
^~ | ^~ 开头表示uri以某个常规字符串开头,理解为匹配url路径即可。nginx不对uri做编码,因此请求为/static/20%/aa,可以被规则 ^~/static/ /aa 匹配到(注意是空格) |
~ | ~ 开头表示区分大小写的正则匹配 |
~* | ~* 开头表示不区分大小写的正则匹配 |
! ~ 和 ! ~* | ! ~ 和 ! ~* 分别表示为区分大小写不匹配 和不区分大小写不匹配 的正则 |
/ | 用户所使用的代理(一般为浏览器) |
$http_x_forwarded_for | 可以记录客户端IP,通过代理服务器来记录客户端的ip地址 |
$http_referer | 可以记录用户是从哪个链接访问过来的 |
匹配规则示例
location = / {
# 规则A
}
location = /login {
# 规则B
}
location ^~ /static/ {
# 规则C
}
location ~ \.(gif|jpg|png|js|css)$ {
# 规则D (区分大小写匹配)
}
location ~* \.(gif|jpg|png|js|css)$ {
# 规则E (不区分大小写匹配)
}
location !~ \.xhtml$ {
# 规则F
}
location !~* \.xhtml$ {
# 规则G
}
location / {
# 规则H
}
产生效果如下:
1.访问根目录/,比如 http://localhost/将匹配规则A
2.访问 http://localhost/login,将匹配规则B,http://localhost/register,将匹配规则H
3.访问 http://localhost/static/a.html, 将匹配规则C
4.访问 http://localhost/a.gif,http://localhost/b.jpg 将匹配规则D和E,但是规则D顺序优先,规则E不起作用,而http://localhost/static/c.png则优先匹配规则C
5.访问 http://localhost/a.PNG 匹配规则E,而不会匹配规则D,因为规则E不区分大小写
6.访问 http://localhost/a.xhtml 不会匹配规则F和规则G,http://localhost/a.XHTML 不会匹配规则G,因为不区分大小写。规则F,规则G属于排除法,符合匹配规则但是不会匹配到,所以想想看实际应用中哪里会用到。
7.访问 http://localhost/category/id/111 最终会匹配规则H,因为以上规则都不匹配,这个时候应该是nginx转发请求给后端应用服务器,比如:FaseCGI(PHP),tomcat(jsp),nginx作为反向代理服务器存在。
实际常用规则
#直接匹配网站根目录,通过域名访问网站首页比较频繁,使用这个会加速处理。
#这里是直接转发给后端应用服务器了,也可以是一个静志首页
#第一个必选规则
location = / {
proxy_pans http://tomcat:8000/index;
}
#第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项
#有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用
location ^~ /static/ {
# 请求/static/a.txt 将被映射到实际目录文件:/webroot/res/static/a.txt
root /webroot/res/;
}
location ~* \.(gif|jpg|jpeg|png|html|js|css|ico)$ {
root /webroot/res/;
}
# 第三个规则就是通用规则,用来转发动态请求到后端应用服务器
# 非静态文件请求就默认是动态请求,自己根据实际把握
# 毕竟目前的一些框架的流行,带.pho,.jsp后缀的情况更少了
location / {
proxy_pass http://tomcat:8080/;
}
Location 解析过程
解读:
1、先判断精确命中,如果命中,立即返回结果并结束解析过程
2、判断普通命中,如果多个命中,“记录下来最长”的命中结果(记录但是不结束,最长的为准)。
3、继续判断正则表达式的解析结果,按配置里的正则表达式顺序为准,由上至下开始匹配,一旦匹配成功1个就立即返回结果,并结束解析过程。
4、普通命中顺序无所谓,是因为按照命中的长短来确定。正则命中,顺序有所谓,因为是从前往后命中的。
nginx的location指令配置语法如下:
location [= | ~ | ~* | ^~ ] /url/ {...}
说明:
=
表示精准匹配
~
表示正则匹配(区分大小写)
~*
表示正则匹配(不区分大小写)
^~
表示普通匹配完成后不使用正则匹配(可以看完下面匹配顺序之后再来理解)uri之前不包含=、~、~ *、^~
时为普通匹配
location指令可以嵌套,所以可以出现在server指令内部和location指令内部。
location匹配规则:
nginx为了找到匹配请求的location,搜索匹配规则如下:
判断是否精准匹配,如果匹配,直接返回结果并结束搜索匹配过程。
判断是否普通匹配,如果匹配,看是否包含^~
前缀,包含则返回,否则记录匹配结果,(如果匹配到过个location时返回或记录最长匹配
的那个)
判断是否正则匹配,按配置文件里的正则表达式的顺序,由上到下开始匹配,一旦匹配成功,直接返回结果,并结束搜索匹配过程。
如果正则匹配没有匹配到结果,则返回步骤2记录的匹配结果。
注:
多个普通匹配的location时,和location的顺序无关,总是匹配所有的location,然后取匹配最长的location作为结果多个正则匹配的location时,和顺序有关,从上到下依次匹配,一旦匹配成功便结束,直接返回结果
location配置实例案例
需求: 在Linux的Tomcat安装目录下,新建webapps/product/hi.html,在Windows的Tomcat安装目录下,新建webapps/memeber/hi.html。通过Linux的Nginx10000端口访问,演示使用Location语法规则。
9. 负载均衡
负载均衡配置规则
——负载均衡就是将负载分摊到不同的服务单元,既保证服务的可用性,又保证响应足够快
——linux下有 Nginx、LVS、Haproxy等等服务可以提供负载均衡服务,Nginx 提供了几种分配方式(策略)
1、轮轮(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down 掉,能自动剔除
2、weight
weight 代表权,重默认为1,权重越高被分配的客户端越多指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。例如
upstream lxcservers{
server 192.168.31.59:8080 weight=1;
server 192.168.31.59:8081 weight=2
}
3、ip_hash
每个请求按访问ip的hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决 session 的问题
例如:
upstream lxcservers{
ip_hash;
server 192.168.31.59:8081;
server 192.168.31.59:8080;
}
4、fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配
upstream lxcservers{
server 192.168.31.59:8080;
server 192.168.31.59:8081;
fair;
}
实现步骤
配置nginx:
1、在Linux下的Tomcat安装目录下创建webapps\search\look.html(内容自定)
2、在Linux下重新安装一份Tomcat,并将端口修改成8081
修改另一个Tomcat的conf\server.xml,注意要修改如下位置,否则该Tomcat是不能正常工作
3、在Linux的Tomcat 8081创建webapps\search\look.html
4、启动两个Tomcat,启动Nginx,浏览器输入:http://192.168.31.59/search/look.html ,查看默认是轮询访问的
。
注意事项和避免的坑
1.nginx.conf的upstream
不能带下划线,否则会失败,但是语法检测不到
2.如果你的浏览器是无痕上网,负载均衡可能失效,因为Nginx无法采集到相关信息, 用其它浏览器即可(比如chrome)
3.提示
:如果某Tomcat没有监听对应端口,说明启动失败了,可以尝试先执行 shutdown.sh 再执行startup.sh 解决
文档: Nginx的upstream配置技巧
1、基本介绍
Nginx是一个反向代理软件,大部分的网站都采用Nginx作为网站/平台的服务器软件。Nginx除了可以直接作为web服务器使用外,更多的情况是通过反向代理将请求转发给上游服务器
配置上游服务器可以使用upstream进行设置,通过upstream可以实现服务的负载均衡规则,可以提高服务器的高可用性。
2、地址:
https://zhuanlan.zhihu.com/p/409693332
10. 动静分离
介绍
1.Nginx动静分离简单来说就是把动态跟静态请求分开,可以理解成使用Nginx处理静态页面/资源Tomcat 处理动态页面。
2.动静分离可以减轻Tomcat压力,静态请求由Nginx处理,提供系统整体性能。
需求:在Tomcat处理后台计算.jsp文件,在nginx则处理静态资源文件(如:图片资源)。客户端访问时,Tomcat处理返回jsp, Nginx处理返回图片,各自分工。
实现步骤
- 在两个Tomcat 新建 webapps/search/cal.jsp, 内容如下:
<%@ page contentType="texthtml;charset=UTF-8" language="java" %>
<html>
<head>
<title>hello, jsp</title></head>
<body>
<img src="image/cal.jpg"/>
<h1>JSP,计算器 8081</h1>
<%
int i = 20;
int j = 80;
int res = i + j;
out.println(i +"+"+ j + "=" + res);
%>
</body>
</html>
- nginx.conf 新增静态资源文件路径访问。
- nginx的目录下,新建html/search/image/cal.jpg,放一张图片cal.jpg。
- 启动两个Tomcat,启动Nginx, 浏览器输入:192.168.32.59/search.jsp
11. Nginx 工作机制&参数设置
master-worker 机制
master-worker工作原理图
图解
一个master管理多个worker
一说master-worker 机制
争抢机制示意图
图解:
1.一个master Process 管理多个worker process r结构.,也就是说Nginx采用的是多进程结构
,而不是多线程
2.当 client 发出请求(任务)时,master Proeess 会通知管理的 worker process
3.worker process 开始争抢任务,争抢到的worker process 会开启连接,完成任务
4.每个 worker 都是一个独立的进程,每个进程里只有一个主线程
5.Nginx采用了 IO 多路复用机制(需要在Linux环境),使用IO多路复用机制,是Nginx在使用为数不多的worker process 就可以实现高并发的关键
二说master-worker 机制
对上图说明
MeMaster-Worker模式
1、Nginx在启动后,会有一个 master 进程和多个相互独立的 worker 进程。
2、Master 进程接收来自外界的信号,向各worker 进程发送信号,每个进程都有可能来处理这个连接。
3、Master进程能监控Worker进程的运行状态,当worker 进程退出后(异常情况下),会自动启动新的worker 进程。
accept_mutex解决"惊群现象
1、所有子进程都继承了父进程的sockfd,当连进来时,所有子进程都将收到通知并“争着"与它建立连接这就叫"惊群现象”。
2、大量的进程被激活又挂起,只有一个进程可以ccept()到这个连接,会消耗系统资源。
3、Nginx 提供了一个accept_mutex,这是一个加在accept上的一把共享锁。即每个worker进程在行accept之前都需要先获取锁,获取不到就放弃执行 accept()。有了这把锁之后,同一时刻,就只会有一进程去accpet(),就不会有惊群问题了。
4、当一个 worker 进程在 accept() 这个连接,后,就开始读取请求,解析请求,处理请求,产生数据后再返回给客户端,最后才断开连接,完成一个完整的请求。
5、一个请求,完全由 worker 进程来处理,而且只能在一个 worker 进程中处理。
用多进程结构而不用多线程结构的好处/理论
1、节省锁带来的开销,每个worker进程都是独立的进程,不共享资源,不需要加锁。在编程以及问题查上时也会方便很多。
2、独立进程,减少风险。采用独立的进程,可以上互相之间不会影响,一个进程退出后,其它进程还在工作,服务不会中断,master进程则很快重新启动新的worker 进程
实现高并发的秘密-IO多路复用
1、对于Nginx来讲,一个进程只有一个主线程那么它是怎么实现高并发的呢?
2、采用了IO多路复用
的原理,通过异步非阻塞的事件处理机制,epol模型
,实现了轻量级和高并发
3、Nginx是如何具体实现的呢,举例来说:每进来一个request,会有一个worker进程去处理。但不是全程的处理,处理到什么程度呢?处理到可能发生阻寒的地方,比如向上游(后端)服务器转发request,并等待请求返回。那么,这个处理的worker不会这么傻等着,他会在发送完请求后,注册一个事件:“如果upstream返回了,告诉我一声,我再接着干”。于是他就休息去了。此时,如果再有request 进来,他就可以很快再按这种方式处理。而一旦上游服务器返回了,就会触发这个事件,worker才会来接手,这个reguest才会接着往下走。由于webserver的工作性质决定了每个request的大部份生命都是在网络传输中,实际上花费在server机器上的时间片不多,这就是几个进程就能解决高并发的秘密所在.
小结:Nginx的master-worker工作机制的优势
1、支持 nginx-s reload 热部署,这个特征在前面我们使用过
2、对于每个 worker 进程来说,独立的进程,不需要加锁,所以省掉了锁带来的开销,同时在编程以及问题查找时,也会方便很多
3、每个 worker 都是一个独立的进程,但每个边程里只有一个主线程,通过异步非阳塞的方式/IO多路复用
来处理请求,即使是高并发请求也能应对。
4、采用独立的进程,互相之间不会影响,一个wrker进程退出后,其它worker进程还在工作,服务不会中断,master进程则很快启动新的worker进程
5.一个worker 分配一个CPU,那么worker的线程可以把一个cpu的性能发挥到极致
参数设置
worker processes
需要设置多少个 worker
每个 worker 的线程可以把一个cpu的性能发挥到极致。所以 worker 数和服务器的 cpu数相等是最为适宜的
。设少了会浪费cpu,设多了会造成cpu 频繁切换上下文带来的损耗。
设置 worker 数量,Nginx默认没有开启利用多核cpu,可以通过增加worker_cpu_affinity配置参数来充分利用多核cpu的性能
#2核cpu,开启2个进程
worker processes 2;
worker_cpu affinity 01 10;
#2核cpu,开启4个进程,
worker processes 4;
worker_cpu affinity 01 10 01 10:
#4核cpu,开启2个进程,0101表示开启第一个和第三个内核,1010表示开启第二个和第四个内核;
worker processes 2;
worker cpu affinity 0101 1010;
#4个cpu,开启4个进程
worker processes 4;
worker_cpu_affinity 0001 0010 0100 1000;
#8核cpu,开启8个进程
worker processes 8;
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
worker_cpu_affinity理解
worker_connection
1.worker_connection 表示每个 worker 进程所能建立连接的最大值
,所以,一个 nginx 能建立的最大连接数,应该是worker connections * worker processes
(1)默认:worker_connections: 1024
(2)调大:worker connections:60000,(调大到6万连接)
(3)同时要根据系统的最大打开文件数来调整
系统的最大打开文件数>=worker_connections*worker_process
根据系统的最大打开文件数来调整,worker_connections进程连接数量要小于等于系统的最大打开文件数,worker_connections进程连接数量真实数量=worker connections * worker process
查看系统的最大打开文件数
ulimit -a lgrep "open files"
open files (-n) 65535
2.根据最大连接数计算最大并发数
:如果是支持http1.1的浏览器每次访问要占两个连接,所以普通的静态访问最大并发数是: workerconnections * workerprocesses / 2
,而如果是HTTP 作 为反向代理来说,最大并发数量应该是worker connections * worker_processes / 4
。因为作为反向代理服务器,每个并发会建立与客户端的连接和与后端服务的连接,会占用两个连接,看一个示意图
配置Linux最大打开文件数
1.使用ulimit -a
可以查看当前系统的所有限制值,使用ulimit -n
可以查看当前的最大打开文件数。
2.新装的linux默认只有1024,当作负载较大的服务器时,很容易遇到error:too many open files。因此,需要将其改大。
3.使用 ulimit -n 65535
可即时修改,但重启后就无效了。(注ulimit -SHn 65535 等效 ulimit -n 65535,-S指soft,-H指hard)
4.有如下三种修改方式:
(1)在/etc/rc.local 中增加一行 ulimit -SHn 65535
(2)在/etc/profile 中增加一行 ulimit -SHn 65535
(3)在/etc/security/limits.conf最后增加如下两行记录
* soft nofile 65535
* hard nofile 65535
在CentOS中使用第1种方式无效果,使用第3种方式有效果,而在Debian中使用第2种有效果
5.参考: https://blog.csdn.net/weixin_43055250/article/details/124980838
12. 搭建高可用集群
Keepalived+Nginx高可用集群(主从模式)
集群架构图
示意图
解读
1.准备两台 Nginx服务器,一台做主服务器,一台做备份服务器
2.两台Nginx服务器的IP地址,可以自己配置(具体配置看 Linux 网络配置章节)
3.安装keepalived,保证主从之间的通讯
4.对外提供统一的访问IP(虚拟IP-VIP)
搭建步骤
1、 准备两台Linux服务器 192.168.xx.xx和192.168.xx.xx
- 可以克隆来完成
- 也可以直接拷贝一份
ifconfig 看下这两台随机的ip是:92.168.31.194 和 192.168.31.254
,下面以这两个ip展开演示。
2、 在两台Linux服务器,修改原来的配置Nginx和Tomcat,启动并验证,没问题往下。
- 安装配置Nginx步骤前面讲过,如果你克隆的Linux,本身就有安装好了Nginx,直接使用即可
- 验证安装是否成功,在windows可以通过IP访问到Nginx,具体的操作步骤和注意事项,前面也都是说过
- 因为我们是拷贝了一份Linux,而新的Linux的Ip 已经变化了,所以需要克隆的Linux的nginx.conf文件中的IP地址,做相应的修改
3、在两台Linux服务器,安装 keepalived
-
下载keepalived-2.0.20.tar.gz 源码安装包https://keepalived.org/download.html
-
上传到两台Linux/root 目录下
-
mkdir /root/keepalived
-
解压文件到指定目录:
tar -zxvf keepalived-2.0.20.tar.gz -C ./keepalived
-
进入目录:
cd /root/keepalived/keepalived-2.0.20
-
执行:
./configure --sysconf=/etc --prefix=/usr/local
说明:将配置文件放在/etc目录下,安装路径在/usr/local -
make && make install
说明:编译并安装 -
如果成功,就会安装好keepalived 【
可以检查一下
】
说明: keepalived 的配置目录在/etc/keepalived/
有keepalived.conf
keepalived 的启动指令在/usr/local/sbin
有/keepalived
-
提示:两台Linux都要安装keepalived
完成高可用集群配置:
1、将其中一台Linux(比如192.168.31.194)指定为Master: vi /etc/keepalived/keepalived.conf
2、将其中一台Linux(比如192.168.31.254)指定为Backup(备份服务器):vi /etc/keepalived/keepalived.conf
3、启动 两台Linux的keepalived 指令: /usr/local/sbin/keepalived
4、观察两台linux的ens33 是否已经绑定192.168.31.18 指令: ip a
测试
1、首先保证 windows 可以连通 192.168.31.18这个虚拟IP
2、访问http://192.168.31.18/search/cal.jsp
说明:大家可以看到,因为192.168.31.194是Master
他的优先级高,所以访问的就是192.168.1.31.194的Nginx,同时仍然是支持负载均衡的。
3、停止 192.168.31.194的keepalived 服务或者直接关闭192.168…31.194 主机再次访问 http://192.168.31.18/search/cal.jsp,这时虚拟IP 绑定发生漂移,绑定到192.168.31.254 Backup服务
,访问效果如图:
这里直接关闭192.168.31.194 Master的 keepalived 来测试
注意事项和细节
1、keepalived启动后无法ping通VIP,提示ping:sendmsg: Operation not permitted
https://blog.csdn.net/xjuniao/article/details/101793935
2、nginx+keepalived配置说明和需要避开的坑
https://blog.csdn.net/qq_42921396/article/details/123074780
自动检测Nginx异常,终止keepalived
如果Master主服务器Nginx挂了,Client还一直访问这个服务器Nginx就会出错,无法切换到Backup从服务器Nginx,这个时候就需要来一个能自动检测主服务器Nginx异常的程序脚本来终止该服务器下的keepalived,以达到切换访问Backup从服务器Nginx的效果。
实现步骤:
1、编写shell脚本: vi /etc/keepalived/ch_nginx.sh
简单说明:下面的脚本就是去统计ps -C nginx --no-header
的行数,如果为0,说明nginx已经异常终止了就执行 killall keepalived
#!/bin/bash
num = `ps -C nginx --no-header | wc -l`
if [ $num -eq 0 ];then
killall keepalived
fi
2、修改ch_nginx.sh权限chmod 755 ch_nginx.sh
3、修改192.168.31.194 主Master 配置文件,指令: vi /etc/keepalived/keepalived.conf
4、新启动192.168.31.194 Master的keepalived,这时因为Master的优先级高,会争夺到VIP优先绑定.
5、手动关闭 192.168.31.194 Master的Nginx,这时脚本就开始运行,关闭keepalived
注意观察 keepalived也终止了
6、再次访问nginx,发现192.168.31.18这个虚拟IP 又和 192.168.131.254备份服务器绑定了。
注意事项
1、keepalived vrrp_script脚本不执行解决办法
打开日志观察:
tail -f /var/log/messages
重启keepalived:
systemctl restart keepalived.service
曾经出现过文件找不到可以修改执行脚本文件名,不要有_就OK
2.如果配置的定时检查Nginx异常的脚本,需要先启动nginx,在启动 keepalived,否则keepalived一起动就被killall 了
配置文件keep alive的.conf详解
#这里只注释要修改的地方
global_defs {
notification_email(
test@foxmail.com #接收通知的邮件地址
}
notification_email_from Alexandre.Cassen@frewall.loc #发送邮件的邮箱
smtp _server 192.168.200.1 #smtp server 地址
smtp_connect timeout 30
router_id Node132 # #Node132为号机标识
vrrp_skip check_adv_ addr
#vrrp_strict #这里需要注释,避免虚拟ip无法ping通
vrrp _garp interval 0
vrrp gna interval 0
}
vrrp_instance VI_1 {
state MASTER #主节点MASTER备用节点为BACKUP
interface ens33 #网卡名称
virtual router id 51 #VRRP组名,两个节点的设置必须一样,指明属于同-VRRP组
priority 100 #主节点的优先级(1-254之间),备用节点必须比主节点优先级低
advert int 1 #组播信息发送间隔,两个节点设置必须一样
authentication( #设置验证信息,两个节点必须一致
auth _type PASS
auth pass 1111
}
virtual ipaddress{
192.168.200.16 #指定虚拟IP,两个节点设置必须一样
}
}
小结
Keepalived+Nginx 是高可用集群(主从模式)的一种解决方案,不一定都会用到这个Keepalived,小伙伴还可以查找其他的产品解决方案,这里是提供了一种解决思路。