nginx 配置反向代理、负载均衡、动静分离、集群搭建
nginx 配置反向代理、负载均衡、动静分离、集群搭建
反向代理实例一
实现效果
打开浏览器,在浏览器地址栏输入地址www.123.com
,跳转到 web 项目主页(kestrel/tomcat/apache)
步骤
- 在 Windows 系统的 hosts 文件进行域名和IP的对应关系配置
C:\Windows\System32\drivers\etc\hosts
添加这么一行,IP 域名,这样就可以通过域名访问 nginx,这个IP地址是nginx的IP
192.168.0.199 www.123.com
- 在 nginx 进行请求转发的配置(反向代理配置)
在ngnix/sites-enabled
目录新建一个 nginx 的配置文件,命名随意,没有后缀名
server{
# nginx 监听 80 端口,记得关闭默认配置文件的端口设置
listen 80;
# 目标IP地址或域名,可以随意
server_name demo;
location / {
root html;
index index.html index.htm;
# 注意IP地址,这是 Web 项目部署的IP地址
proxy_pass http://192.168.0.200:5000;
}
}
- 启动 Web 项目,我使用是 Web 项目是 Visual Studio 2019 默认创建的 Web API 项目
测试结果,Web API 默认是没有主页的,所以就这样显示了
反向代理实例二
实现效果
使用 nginx 反向代理,根据访问的路径跳转到不同端口的服务中
nginx 监听端口为 9001
访问 http://192.168.0.199:9001/test1/
直接跳转到 192.168.0.200:8081
访问 http://192.168.0.199:9001/test2/
直接跳转到 192.168.0.200:8082
步骤
- 准备两个 web 项目,一个 8081 端口,一个 8082 端口,并启动
- 创建文件夹和测试页面,在 web 项目中随便新建一个 html 文件,我使用的是 RESTful 项目,所以就返回一个IP地址
- 具体配置
server{
listen 9001;
server_name test;
location /test1/ {
proxy_pass http://192.168.0.200:8081/;
}
location /test2/ {
proxy_pass http://192.168.0.200:8082/;
}
}
4.开放端口
5. 重新加载 nginx
测试,项目代码,只是返回 appsettings.json 中 Kestrel 的 Url
[ApiController]
[Route("[controller]")]
public class IndexController : ControllerBase
{
private readonly IConfiguration _configuration;
public IndexController(IConfiguration configuration)
{
this._configuration = configuration;
}
[HttpGet]
public async Task<IActionResult> Test()
{
var result = this._configuration["Kestrel:Endpoints:Http:Url"];
return Ok(result);
}
}
先是 test1 项目
然后是 test2 项目
补充
location 这一块儿挺迷的,有一种写法是这样的
location ~ /test1/ {
proxy_pass http://192.168.0.200:8081;
}
我用正则表达式的结果是 404 ,proxy_pass
最后有没有 /
也有些区别
正则表达式:
=
:用于不含正则表达式的uri前,要求请求字符串与uri严格匹配,如果匹配成功,就停止继续向下搜索并立即处理该请求~
:用于表示uri包含正则表达式,并且区分大小写~*
:用于表示uri包含正则表达式,并且不区分大小写^~
:用于不含正则表达式的uri前,要求nginx服务器找到标识uri和请求字符串匹配度最高的 location 后,立即使用此 location 处理请求,而不再使用 location 块中的正则uri和请求字符串做匹配
注意:如果 uri 包含正则表达式,则必须要有~
或者~*
标识
负载均衡
实现效果
浏览器地址栏输入地址 http://192.168.0.199:9001/test1/index
,负载均衡效果,平均到 8081 和 8082 端口中
步骤
- 准备两个Web项目服务器,一个 8081,一个 8081
- 为这两个项目随便写一个页面
- 配置代码,在 http 块中
# 需要负载均衡的服务器IP
upstream test{
server 192.168.0.200:8081;
server 192.168.0.200:8082;
}
server{
listen 9002;
server_name 192.168.0.200;
location / {
# 对应 upstream 的名称
proxy_pass http://test;
}
}
测试,不停刷新浏览器,会在两个端口之间切换
补充
nginx 提供了几种分配策略
轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器。如果后端服务器宕机,能自动剔除
weight
权重,默认是 1 ,权重越高,被分配的客户端越多。用于后端服务器性能不均的情况
upstream server_pool{
server 192.168.0.200:8081 weight=10;
server 192.168.0.200:8082 weight=10;
}
ip_hash
每个请求按 ip 的 hash 结果分配,这样每个访客固定一个后端服务器,可以解决 session 的问题
upstream server_pool{
ip_hash;
server 192.168.0.200:8081;
server 192.168.0.200:8082;
}
fair
这是第三方的模块
按后端服务器的响应时间来分配请求,响应时间短的优先分配
upstream server_pool{
server 192.168.0.200:8081;
server 192.168.0.200:8082;
fair;
}
动静分离
什么是动静分离?
nginx 动静分离简单来说就是把动态跟静态请求分开,不能理解成只是单纯的把动态页面和静态页面物理分开。
严格意义上说应该是动态请求跟静态请求分开,可以理解成使用 nginx 处理静态页面,web项目处理动态页面
动静分离从目前实现角度来讲大致分为两种
- 纯粹把静态文件独立成单独的域名,放在独立的服务器上,也是目前的主流方案
- 动态跟静态文件混合在一起发布,通过 nginx 来分开
通过 location 指定不同的后缀名实现不同的请求转发
通过 expires 参数设置,可以使浏览器缓存过期时间,减少与服务器之间的请求和流量。访问这个缓存的URL时,会发送一个请求,比较服务器中该文件最后更新时间有无变化。无变化则不会从服务器抓取,返回状态码 304 ;如果有变化,则直接从服务器重新下载,返回状态码 200。此方法适合不经常变动的资源,如果是经常更新的文件,则不建议使用 expires 来缓存
步骤
- 在 linux 系统中准备静态资源,用于进行访问
- 具体配置
server{
listen 8000;
# nginx 地址
server_name 192.168.0.199;
location /Htmls/ {
root /wwwroot/;
}
location /Images/ {
root /wwwroot/;
autoindex on;
}
}
测试
http://192.168.0.199:8000/Images/a.jpg
http://192.168.0.199:8000/Htmls/a.html
a.jpg
是我随手截的图
a.html
也是随手写的
补充
autoindex on
在访问目录时可以列出文件夹中所有文件
http://192.168.199:8000/Images/
集群
问题:nginx 和 web项目都可能宕机,请求就无法实现效果
解决方案:两台 nginx 服务器
主服务器 192.168.0.199
从服务器 192.168.0.200
虚拟IP 192.168.0.201
主服务器宕机,就会转换到从服务器中,从服务器也可以访问web项目
Keepalived
Keepalived 是一个路由,它有一个脚本,会检测 nginx 服务器是否宕机。如果宕机则切换到从服务器
两个 nginx 服务器绑定一个虚拟IP,Keepalived 会将这个绑定到 nginx 服务器上,达到主从切换的效果
两个 nginx 服务器都需要安装 Keepalived
步骤
- 需要两台 nginx 服务器
- 在两台 nginx 都安装 Keepalived,主从的配置就在 Keepalived 的配置中,keepalived.conf
- 需要虚拟IP
- 主从配置
- 把两台服务器上的 nginx 和 keepalived 启动
Keepalived 配置
修改 /etc/keepalived/keepalived.conf
# 全局配置
global_defs {
notification_email { # 设置 keepalived 在发生事件(比如切换)的时候,需要发送到的email地址,可以设置多个,每行一个。
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc # 设置通知邮件发送来自于哪里,如果本地开启了sendmail的话,可以使用上面的默认值。
smtp_server 192.168.0.200 # 指定发送邮件的smtp服务器。
smtp_connect_timeout 30 # 设置smtp连接超时时间,单位为秒。
router_id localhost # 用户标识本节点的名称,通常为 localhost,与 /etc/hosts 中 127.0.0.1 对应,多个集群设置不同。
}
# 脚本配置
vrrp_script nginx_check {
# nginx 检测脚本路径
script "/usr/local/src/nginx_check.sh"
interval 2 # 检测脚本执行的间隔,单位是秒
weight 2 # 权重
}
# 虚拟IP配置
vrrp_instance VI_1{
state MASTER # 主服务器为 MASTER,从服务器为 BACKUP
interface enp0s3 # 网卡,用 ifconfig 查看
virtual_router_id 51 # 设置VRID标记,主从服务器的 virtual_router_id 必须相同,多个集群不能重复(0..255)
priority 100 # 主从服务器取不同的优先级,主服务器的值较大,从服务器的值较小
advert_int 1 # 检测主服务器是否正常运行,单位是秒
authentication {
auth_type PASS # 权限校验方式,PASS 表示密码
auth_pass 123456 # 密码
}
virtual_ipaddress {
192.168.0.201 # 虚拟IP地址
}
track_script {
nginx_check # 脚本名称,与上面定义的相同
}
}
在 /usr/local/src 添加检测脚本 nginx_check.sh
#!/bin/bash
counter=$(ps -C nginx |grep -v PID |wc -l)
if [ $counter -eq 0 ];
then
/usr/sbin/nginx # nginx 启动脚本的路径
sleep 2
counter=$(ps -C nginx |grep -v PID |wc -l)
if [ $counter -eq 0 ];
then
echo "管理员密码" | sudo -S killall keepalived # 关闭 keepalived 进程
fi
fi
测试
上面的检测脚本会重启nginx,所以测试用的脚本改成直接退出 keepalived
#!/bin/bash
counter=$(ps -C nginx |grep -v PID |wc -l)
if [ $counter -eq 0 ];
then
echo "123456" | sudo -S killall keepalived
fi
先把两个服务器的 nginx 和 keepalived 都启动
主服务器,有虚拟IP
从服务器,还没有虚拟IP
使用虚拟 ip 地址 http://192.168.0.201
访问 nginx
停止主服务器的 nginx,nginx_check.sh
脚本会停止主服务器的 keepalived,虚拟IP也没了
从服务器获得了虚拟IP
nginx 仍然可以访问
补充
nginc_check.sh
脚本文件可能无法执行,进入脚本目录,通过ll
命令查看文件,如果不是绿色就不能执行
chmod 775 文件名
chmod +x 文件名
还有一个坑,报Syntax error: "fi" unexpected (expecting "then")
错误
使用cat -v 文件名
查看文件,fi
变成了fi^M
用vim打开文件,使用命令set ff
,如果结果是fileformat=dos
则说明是dos文件
解决方法
使用set ff=unix
命令改变代码模式,然后wq
保存就可以了,再使用ll
命令检查一下文件是否可执行
如果还有问题,就查看 keepalived 日志,命令tail -f /var/log/messages
如果没有日志文件,可以参考这个:https://blog.csdn.net/feinifi/article/details/107037892
使用源码安装 keepalived 参考:https://cloud.tencent.com/developer/article/1766804