Nginx【反向代理、负载均衡、动静分离】
一、基本介绍
1. Nginx是什么?能干什么?
- 是什么
- Nginx(“engine x”)是一个高性能的HTTP和反向代理WEB服务器
- 能干什么
- 反向代理
- 负载均衡
- 动静分离
- 厉害之处
- 高性能
- 高负载
- 有报告表明能支持高达50000个并发连接数
- 详细说明:https://lnmp.org/nginx.html
2.官方资料
- 官网:https://nginx.org/
- 使用文档:https://nginx.org/en/docs/
二、Nginx核心功能
1.正向代理
一句话:如果我们要访问www.google.com 但是直接访问不到,则需要通过代理服 务器来访问,这种代理服务就称为正向代理
正向代理:如科学上网,隐藏客户端信息
解读
我们知道www.google.com,但是访问不到
所以使用代理服务器帮助我们(即客户端)来上网,注意帮助的对象是客户端,这种代理,我们称为正向代理
正向代理同时也隐藏了客户端信息
再次说明,正向代理帮助的是客户端,因此可以把 客户端+正向代理服务,视为一个整体
2.反向代理
- 一句话:客户端将请求发送到代理服务器,由代理服务器去选择目标服务器获取数 据后,返回给客户端,这种代理方式为反向代理
- 反向代理:屏蔽内网服务器信息,负载均衡访问
- 解读
- 项目设计者,不希望客户端直接访问目标Web服务器(比如目标Web服务器是集群,如果直接访问就会提供多个公网IP),而是希望提供一个统一的访问IP,这个是理解反向代理的前提,即为什么要反向代理
- 反向代理帮助的对象是目标Web服务器
- 当客户端请求达到反向代理服务后,由反向代理服务来决定如何访问目标Web服务器 (或者是哪个Web服务器),这个过程对客户端是透明的
- 反向代理服务会暴露公共的IP,只要能上网,就可以访问,但是对于反向代理服务器管理的/代理的 Web服务器通常是在局域网内,不能直接访问,只能通过反向代理来访问
- 我们可以将反向代理服务+反向代理服务代理的Web服务器视为一个整体
- 反向代理会屏蔽内网服务器(也就是他代理的服务)信息,并实现负载均衡访问
3.负载均衡
一句话:当客户端向反向代理服务器(比如Nginx)发出请求,如果Nginx代理了多个 WEB服务器(集群),Nginx会将请求/负载分发到不同的服务器,也就是负载均衡
示意图
4.动静分离
一句话:为了加快网站的解析速度,可以把动态资源和静态资源由不同的服务器来 解析,降低单个服务器的压力
传统的项目资源部署
动静分离项目资源部署
三、Nginx下载和安装以及启动
1. 下载
- 下载网址:https://nginx.org/en/download.html
- 版本:nginx-1.20.2.tar.gz
2. 安装
2.1首先是需要安装Linux系统
2.2 具体安装
搭建gcc环境,指令
yum -y install gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel
本次使用的CentOS8版本,在使用如下指令时遇到报错
yum -y install gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel
报错图
解决方案
首先可以去换一下yum源,如果换源后运行指令
yum makecache
- 报如下错误,则参考下面网址方案进行解决
网址:https://blog.csdn.net/qeqpoququtt/article/details/122855846
提示1:一定要保证当前的linux系统,可以连接外网,因为yum需要到外网,获取数据
提示2: 如何在 Linux 配置网络,可以连接到外网,参考视频 (https://www.bilibili.com/video/BV1Sv411r7vd?p=63).
提示3: 执行上面指令的时候,可能会报CentosAnotherappiscurrentlyholdingtheyumlock..错误,是因为yum不时会自动升级, 占用了端口或文件。
- 解决方案
- (1)可以重启Linux,立即执行该指令
- (2)或者等一会再执行
- (3) 或者参考 https://www.cnblogs.com/lzxianren/p/4254059.html
将nginx-1.20.2.tar.gz 上传到 Linux /opt 目录
切换到/opt目录, 解压nginx-1.20.2.tar.gz,指令:
tar -zxvf nginx-1.20.2.tar.gz
将解压后的文件放到指定位置
mv nginx-1.20.2 /usr/local/nginx
进入文件目录
cd /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
编译并安装,需要在/usr/local/nginx下进行
make && make install
测试配置与nginx是否正常,当出现successful即可
./sbin/nginx -t
启动nginx
./sbin/nginx -c nginx.conf
查看进程/或端口(默认端口是80)
ps -ef | grep nginx
2.3启动Nginx 可能的错误 和解决方案
解决nginx 启动报错nginx:[emerg] open() “/var/run/nginx/nginx.pid” failed (2: No such file or directory)
解决方法
进入nginx.conf配置文件:指令
cd /usr/local/nginx/conf/ vim nginx.conf
将注释解开,键入i修改自定义 logs/nginx.pid目录路径
修改为pid /usr/local/nginx/logs/nginx.pid
键Esc进入命令模式,键入:wq保存退出
在/usr/local/nginx,目录下创建logs目录
mkdir /usr/local/nginx/logs
启动nginx
/usr/local/nginx/sbin/nginx -c nginx.conf
3. 验证是否安装成功
Nginx默认端口是80
在浏览器输入http://localhost,看是否会出现界面
4. 配置防火墙,让Windows访问Nginx
说明:默认情况下 Windows 是不能访问Nginx, 因为防火墙是关闭80端口的
具体配置
查看开放的端口号
firewall-cmd --list-all
设置开放端口
firewall-cmd --add-service=http --permanent #增加Http服务,默认会监听80端口 firewall-cmd --add-port=80/tcp --permanent
重启防火墙
firewall-cmd --reload
防火墙配置,可参考视频: https://www.bilibili.com/video/BV1Sv411r7vd?p=77
在Windows系统测试连接:http://192.168.180.130
四、Nginx命令行参数
1. 指令说明
- 网址:https://nginx.org/en/docs/switches.html
2. 使用演示
启动
/usr/local/nginx/sbin/nginx -c nginx.conf
停止
/usr/local/nginx/sbin/nginx -s stop
重新加载(不需要重启)
/usr/local/nginx/sbin/nginx -s reload
查看版本
/usr/local/nginx/sbin/nginx -v
查看版本、配置参数
/usr/local/nginx/sbin/nginx -V
五、nginx.conf配置文件
1.基本说明
Nginx 的配置文件位置
文件位置
- 安装目录/conf/nginx.conf
- 安装目录/nginx.conf
两个文件是一样的
使用/usr/local/nginx/sbin/nginx启动Nginx,默认用的是安装目录 \nginx.conf配置文件
作用:完成对Nginx的各种配置,包括端口,并发数,重写规则等
nginx.conf组成
全局块
events块
http块
nginx.conf详细文档
文档地址:https://blog.csdn.net/liuchang19950703/article/details/110792007
详细内容
#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; } } }
2.nginx.conf讲解
一张图说明nginx.conf结构
看一下/usr/local/nginx/conf/nginx.conf
#user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { worker_connections 1024; } http { 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 on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; server { listen 80; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / { root html; index index.html index.htm; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} } # another virtual host using mix of IP-, name-, and port-based configuration # #server { # listen 8000; # listen somename:8080; # server_name somename alias another.alias; # location / { # root html; # index index.html index.htm; # } #} # HTTPS server # #server { # listen 443 ssl; # server_name localhost; # ssl_certificate cert.pem; # ssl_certificate_key cert.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; # } #} }
全局块
说明
从配置文件开始到events块之间的内容
主要会设置一些影响nginx服务器整体运行的配置指令,主要包括配置运行Nginx 服务器的用户(组)、允许生成的worker process数,进程PID存放路径、日志存放路径 和类型以及配置文件的引入等
简单分析
这是 Nginx 服务器并发处理服务的关键配置,worker_processes 值越大,可以支持 的并发处理量也越多,但是会受到硬件、软件等设备的制约
配置举例
worker_processes 1;
events块
说明
- events 块涉及的指令主要影响 Nginx 服务器与用户的网络连接
- 常用的设置包括是否开启对多 workprocess 下的网络连接进行序列化,是否允许同时 接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个 workprocess 可以同 时支持的最大连接数等
简单分析
上述例子就表示每个 workprocess 支持的最大连接数为 1024, 这部分的配置对 Nginx 的性能影响较大,在实际中应根据实际情况配置
配置举例
events { worker_connections 1024; }
http块
说明
- 这是 Nginx 服务器配置中最复杂的部分,代理、缓存和日志定义等绝大多数功能和第 三方模块的配置都在这里
- http 块也可以包括 http 全局块、server 块
http全局块
http 全局块配置的指令包括文件引入、MIME-TYPE 定义、日志自定义、连接超时时间、单连接请求数上限等
配置举例
http { 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 on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; }
server块
这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全 一样的,该技术的产生是为了节省互联网服务器硬件成本。
每个http块可以包括多个server块,而每个server块就相当于一个虚拟主机。
每个server块也分为全局server块,以及可以同时包含多个location块。
全局server块
- 最常见的配置是本虚拟机主机的监听配置和本虚拟主机的名称或IP配置
location块
- 一个server块可以配置多个location块
server { listen 80; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / { root html; index index.html index.htm; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
小结:这块的主要作用是基于Nginx服务器接收到的请求字符串(例如 server_name/uri-string),对虚拟主机名称(也可以是IP别名)之外的字符串(例如前面 的/uri-string)进行匹配,对特定的请求进行处理。比如地址定向、数据缓存和应答控制等功能,还有许多第三方模块的配置也在这里进行。
六、反向代理-快速入门
1.反向代理配置-思路分析/图解
2.实现步骤
2.1 安装JDK-jdk11
参考视频网址:https://www.bilibili.com/video/BV1Sv411r7vd?p=86
安装步骤
在opt目录下创建java_jdk目录
mkdir /opt/java_jdk
通过xftp6 将jdk包上传到 /opt/java_jdk 下
切换到java_jdk目录
cd /opt/java_jdk
解压jdk
tar -zxvf jdk-11.0.23_linux-x64_bin.tar.gz
创建实际存放目录
mkdir /usr/local/java
将java_jdk下解压的jdk剪切到/usr/local/java目录下
mv /opt/java_jdk/jdk-11.0.23 /usr/local/java
配置环境变量,在/etc/profile文件中添加环境变量
export JAVA_HOME=/usr/local/java/jdk-11.0.23 export PATH=$JAVA_HOME/bin:$PATH
让文件立即生效指令
source /etc/profile
然后输入指令查看是否配置成功
java -version
2.2 安装Tomcat
参考视频网址:https://www.bilibili.com/video/BV1Sv411r7vd?p=87
安装步骤
创建存放目录
mkdir /opt/tomcat
通过xftp6 将tomcat包上传到 /opt/tomcat 下
将文件进行解压
tar -zxvf apache-tomcat-9.0.89.tar.gz
创建实际存放目录
mkdir /usr/local/tomcat9
将tomcat剪切到tomcat9
mv /opt/tomcat/apache-tomcat-9.0.89 /usr/local/tomcat9
进入到指定目录
cd /usr/local/tomcat9/apache-tomcat-9.0.89/bin
启动tomcat
./startup.sh
是否成功
2.3 修改Nginx的nginx.conf配置文件
修改/usr/local/nginx/nginx.conf
操作指令
vim /usr/local/nginx/nginx.conf
如何查看nginx.conf的配置错误
检测默认配置文件,操作指令:
/usr/local/nginx/sbin/nginx -t
指定检测配置文件,操作指令
/usr/local/nginx/sbin/nginx -t -c nginx.conf
3.注意事项和细节
Nginx对外提供访问入口,充当反向代理服务器,Tomcat的端口就无需对外暴露
开启和关闭防火墙端口
开启防火墙端口,以8080端口为例
firewall-cmd --add-port=8080/tcp --permanent firewall-cmd --reload
关闭防火墙端口,以8080端口为例
firewall-cmd --remove-port=8080/tcp --permanent firewall-cmd --reload
查看防火墙的状态
firewall-cmd --list-all
七、反向代理配置-Location实例
1.反向代理配置-思路分析/图解
2.Location语法规则
解读1-location 语法规则,参考文件:location语法规则.docx
解读2-nginx 的 location 解析过程
3.实现步骤
3.1 修改Nginx的nginx.conf配置文件
3.2 在 Linux 的 两个Tomcat中的webapps目录下创建\product\hi.html和\member\hi.html
首先在8080端口下的tomcat的webapps目录下创建product目录,然后在创建hi.html
首先在8000端口下的tomcat的webapps目录下创建member目录,然后在创建hi.html
- 然后启动这两个tomcat
八、负载均衡-配置实例
1. 负载均衡配置-思路分析/图解
2. 负载均衡配置规则
负载均衡就是将负载分摊到不同的服务单元,既保证服务的可用性,又保证响应足够快
linux 下有 Nginx、LVS、Haproxy 等等服务可以提供负载均衡服务, Nginx 提供了几种分 配方式(策略):
轮询(默认)
- 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除
weight
weight代表权,重默认为1,权重越高被分配的客户端越多
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
upstreamhspservers{ server192.168.180.130:8080 weight=1; server192.168.180.130:8000 weight=2; }
ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决 session的问题
upstreamhspservers{ ip_hash; server192.168.180.130:8000; server192.168.180.130:8080; }
fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配
upstreamhspservers{ server192.168.12.134:8080; server192.168.12.134:8081; fair; }
3. 实现步骤
3.1 修改Nginx的nginx.conf配置文件
3.2 在两个tomcat的webapps目录下添加search目录,再添加look.html文件
4. 注意事项和避免的坑
- 两个tomcat如果要启动需要注意,要去修改其中一个tomcat的server.xml文件,以防端口冲突,启动不了,报错
- nginx.conf的upstream不能带下划线,否则会失败,但是语法检测不到
- 如果你的浏览器是无痕上网,负载均衡可能失效,因为Nginx无法采集到相关信息,遇到这个情况。改用其它浏览器即可(比如chrome)
- 提示:如果某tomcat没有监听对应端口,说明启动失败了,可以尝试先执行 shutdown.sh再执行startup.sh解决
- 文档:Nginx的upstream配置技巧
- 基本介绍
- Nginx是一个反向代理软件,大部分的网站都采用Nginx作为网站/平台的 服务器软件。Nginx除了可以直接作为web服务器使用外,更多的情况是 通过反向代理将请求转发给上游服务器
- 配置上游服务器可以使用upstream进行设置,通过upstream可以实现服 务的负载均衡规则,可以提高服务器的高可用性。
- 参考地址:https://zhuanlan.zhihu.com/p/409693332
九、动静分离-应用实例
1. 什么动静分离
Nginx 动静分离简单来说就是把动态跟静态请求分开,可以理解成使用 Nginx 处理静态 页面/资源,Tomcat 处理动态页面/资源。
动静分离可以减轻Tomcat 压力,静态请求由Nginx处理,提供系统整体性。
回顾前面-示意图
2. 动静分离配置-思路分析/图解
3.先使用传统方式实现
创建tomcat\webapps\search\cal.jsp [老韩说明: 为了测试方便, 在tomcat2也对应创建一份]
cal.jsp文件
<%-- To change this template use File | Settings | File Templates.--%> <%@pagecontentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>hello, jsp</title> </head> <body> <img src="image/cal.jpg"/> <h1>JSP, 计算器</h1> <% int i = 20; int j = 70; int res = i + j; out.println(i + " + " + j + " = " + res); %> </body> </html>
4.动静分离优化步骤
- 修改Nginx的nginx.conf配置文件
- 创 建 /usr/local/nginx/html/search/image 目 录 , 因 为 图 片 路 径 其 实 是ip/search/image
- 将 Linux 的 两 个 Tomcat\webapps\search\image 目 录 删 除 , 在/usr/local/nginx/html/search/image 目录下放入图片
5. 注意事项和细节
- 注意:配置的静态资源路径要和页面上的路径相匹配否则找不到
- 这里的路径要是实际请求的静态资源路径
- 如果还有其它的静态资源,按照配置规则配置即可
十、Nginx工作机制和参数设置
1. master-worker机制
1.1 master-worker工作原理图
图解
一个master 管理多个worker
1.2 一说master-worker机制
争抢机制示意图
图解
一个masterProcess 管理多个workerprocess, 也就是说Nginx采用的是多进程结构, 而不是多线程结构
当client 发出请求(任务)时,masterProcess 会通知管理的 workerprocess
worker process 开始争抢任务, 争抢到的workerprocess 会开启连接,完成任务
每个 worker 都是一个独立的进程,每个进程里只有一个主线程
Nginx 采用了 IO 多路复用机制(需要在Linux环境), 使用IO多路复用机制, 是Nginx在使用为数不多的workerprocess 就可以实现高并发的关键
1.3 二说master-worker机制
二说master-worker模式
解说
master-worker模式
- Nginx 在启动后,会有一个 master 进程和多个相互独立的 worker 进程
- Master 进程 接收来自外界的信号,向各worker进程发送信号,每个进程都有可能来处理这个连接。
- Master 进程能监控Worker进程的运行状态,当 worker 进程退出后(异常情况下),会 自动启动新的 worker 进程
accept_mutex 解决 “惊群现象”/理论
- 所有子进程都继承了父进程的 sockfd,当连接进来时,所有子进程都将收到通知并“争着”与它建立连接,这就叫“惊群现象”
- 大量的进程被激活又挂起,只有一个进程可以accept() 到这个连接,会消耗系统资源
- Nginx 提供了一个accept_mutex,这是一个加在accept上的一把共享锁。即每个worker进程在执行accept之前都需要先获取锁,获取不到就放弃执行accept()。有了这把锁之后,同一时刻,就只会有一个进程去 accpet(),就不会有惊群问题了。
- 当一个 worker 进程在 accept() 这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接,完成一个完整的请求。
- 一个请求,完全由 worker 进程来处理,而且只能在一个 worker 进程中处理。
用多进程结构而不用多线程结构的好处/理论
- 节省锁带来的开销, 每个 worker 进程都是独立的进程,不共享资源,不需要加锁。在编程以及问题查上时,也会方便很多。
- 独立进程,减少风险。采用独立的进程,可以让互相之间不会影响,一个进程退出后, 其它进程还在工作,服务不会中断,master进程则很快重新启动新的worker进程
实现高并发的秘密-IO多路复用
- 对于Nginx来讲,一个进程只有一个主线程,那么它是怎么实现高并发的呢?
- 采用了IO多路复用的原理,通过异步非阻塞的事件处理机制,epoll模型,实现了轻量级和高并发
- nginx 是如何具体实现的呢,举例来说:每进来一个request,会有一个worker进程去 处理。但不是全程的处理,处理到什么程度呢?处理到可能发生阻塞的地方,比如向上游(后 端)服务器转发request,并等待请求返回。那么,这个处理的worker不会这么傻等着,他 会在发送完请求后,注册一个事件:“如果upstream返回了,告诉我一声,我再接着干”。 于是他就休息去了。此时,如果再有request 进来,他就可以很快再按这种方式处理。而 一旦上游服务器返回了,就会触发这个事件,worker才会来接手,这个request才会接着 往下走。由于webserver的工作性质决定了每个request的大部份生命都是在网络传输中, 实际上花费在server机器上的时间片不多,这就是几个进程就能解决高并发的秘密所在
小结:Nginx的master-worker工作机制的优势
- 支持 nginx-sreload 热部署, 这个特征在前面使用过
- 对于每个 worker 进程来说,独立的进程,不需要加锁,所以省掉了锁带来的开销,同时在编程以及问题查找时,也会方便很多
- 每个 worker 都是一个独立的进程,但每个进程里只有一个主线程,通过异步非阻塞的 方式/IO多路复用 来处理请求, 即使是高并发请求也能应对
- 采用独立的进程,互相之间不会影响,一个worker进程退出后,其它worker进程还在 工作,服务不会中断,master 进程则很快启动新的worker 进程
- 一个worker 分配一个CPU , 那么worker 的线程可以把一个 cpu 的性能发挥到极致
2. 参数设置
2.1 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 理解
配置实例
vim /usr/local/nginx/nginx.conf
- 重新加载nginx
/usr/local/nginx/sbin/nginx -s reload
查看nginx 的 workerprocess 情况
worker_connection
worker_connection 表示每个 worker 进程所能建立连接的最大值,所以,一个 nginx 能 建立的最大连接数,应该是 worker_connections*worker_processes
默认:worker_connections: 1024
调大:worker_connections:60000,(调大到6万连接)
同时要根据系统的最大打开文件数来调整
系统的最大打开文件数>=worker_connections*worker_process 根据系统的最大打开文件数来调整,worker_connections进程连接数量要小 于等于系统的最大打开文件数,worker_connections进程连接数量真实数量= worker_connections*worker_process 查看系统的最大打开文件数 ulimit-a|grep"openfiles" openfiles (-n)65535
根据最大连接数计算最大并发数:如果是支持http1.1的浏览器每次访问要占两个连接, 所以普通的静态访问最大并发数是:worker_connections*worker_processes/2,而如果 是HTTP作为反向代理来说,最大并发数量应该是worker_connections * worker_processes/4。因为作为反向代理服务器,每个并发会建立与客户端的连接和与后端 服务的连接,会占用两个连接,看一个示意图
配置 Linux 最大打开文件数
使用ulimit-a 可以查看当前系统的所有限制值,使用ulimit-n 可以查看当前的最大打开文件数
新装的linux默认只有1024,当作负载较大的服务器时,很容易遇到error: too many open files。因此,需要将其改大。
使用 ulimit-n 65535 可即时修改,但重启后就无效了。(注ulimit -SHn 65535 等效 ulimit -n 65535,-S 指 soft,-H 指 hard)
有如下三种修改方式:
在/etc/rc.local 中增加一行 ulimit -SHn 65535
在/etc/profile 中增加一行 ulimit -SHn 65535
在/etc/security/limits.conf 最后增加如下两行记录
soft nofile 65535
hard nofile 65535
在 CentOS中使用第1种方式无效果,使用第3种方式有效果,而在Debian中使用第2种 有效果
参考网址:https://blog.csdn.net/weixin_43055250/article/details/124980838
十一、搭建高可用集群
1. Keepalived+Nginx高可用集群(主从模式)
1.1 集群架构图
准备两台 nginx 服务器, 一台做主服务器, 一台做备份服务器
两台Nginx服务器的IP地址, 可以自己配置
安装keepalived, 保证主从之间的通讯
对外提供统一的访问IP(虚拟IP-VIP)
示意图
1.2 具体搭建步骤
搭建高可用集群基础环境
准备两台Linux服务器 192.168.180.130 和 192.168.180.131
- 可以克隆来完成
- 也可以直接拷贝一份
在两台Linux服务器, 安装并配置好 Nginx
- 安装配置Nginx步骤前面讲过, 如果是克隆的Linux, 本身就有安装好了Nginx, 直接使用即可.
- 验证安装是否成功,在windows可以通过IP访问到Nginx,,具体的操作步骤和注意事项,前面也都是说过了
- 因为是拷贝了一份Linux, 而新的Linux的IP已经变化了, 所以需要克隆的Linux 的nginx.conf 文件中的IP地址, 做相应的修改
在两台Linux服务器, 安装 keepalived
下载keepalived-2.0.20.tar.gz 源码安装包
官方网址:https://keepalived.org/download.html
上传到两台Linux/root 目录下
创建keepalived目录
mkdir /usr/local/keepalived
解压文件到指定目录:
tar -zxvf keepalived-2.0.20.tar.gz -C /usr/local/keepalived
切换到解压的目录
cd /usr/local/keepalived/keepalived-2.0.20
将配置文件放在 /etc 目录下, 安装路径在 /usr/local
./configure --sysconf=/etc --prefix=/usr/local
编译并安装
make && make install
如果成功, 就会安装好keepalived 【可以检查一下】
说明:
- keepalived 的配置目录在 /etc/keepalived/keepalived.conf
- keepalived 的启动指令在 /usr/local/sbin/keepalived
提示: 两台Linux都要安装keepalived
完成高可用集群配置
将 其 中 一 台 Linux( 比 如 192.168.180.130) 指 定 为 Master :
vi /etc/keepalived/keepalived.conf
将其中一台 Linux(比如 192.168.198.131)指定为 Backup(备份服务器):
vim /etc/keepalived/keepalived.conf
启动 两台Linux的keepalived 指令
/usr/local/sbin/keepalived
观察两台linux的ens160 是否已经绑定 192.168.198.18
ip a
注意事项和细节
- keepalived 启动后无法ping 通VIP,提示ping:sendmsg:Operationnotpermitted
- 参考网址: https://blog.csdn.net/xjuniao/article/details/101793935
- nginx+keepalived 配置说明和需要避开的坑
- 参考网址:https://blog.csdn.net/qq_42921396/article/details/123074780
1.3 自动检测Nginx异常,终止keepalived
编写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
修改ch_nginx.sh 权限
chmod 755 ch_nginx.sh
修改192.168.180.130 主 Master 配置文件
vi /etc/keepalived/keepalived.conf
重新启动192.168.180.130 Master 的 keepalived , 这时因为 Master 的优先级高,会争 夺到VIP优先绑定
手动关闭 192.168.180.130Master 的 Nginx
注意观察 keepalived 也终止了
再次访问nginx, 发现192.168.180.18 这个虚拟IP 又和 192.168.180.131 备份服务器 绑定了.
注音事项
keepalived vrrp_script 脚本不执行解决办法
打开日志观察
tail -f /var/log/messages
-重启keepalived
systemctl restart keepalived.service
说明一下:出现文件找不到,可以修改执行脚本文件名,不要有_看一下是否可行
如果配置有定时检查Nginx异常的脚本,需要先启动nginx,在启动keepalived,否则keepalived一起动就被killall了
1.4 配置文件keepalived.conf详解
#这里只注释要修改的地方
global_defs{
notification_email{
test@foxmail.com #接收通知的邮件地址
}
notification_email_fromAlexandre.Cassen@firewall.loc #发送邮件的邮箱
smtp_server192.168.200.1 #smtpserver地址
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 {#指定虚拟 IP, 两个节点设置必须一样
192.168.200.16
}
}