Nginx反向代理与负载均衡初步入门
1. 不同种类的集群介绍
1.1 负载均衡集群
负载均衡集群可以把很多客户集中的访问请求负载压力尽可能平均分摊在计算机集群中进行处理。
作用如下:
分担用户访问请求及数据流量(负载均衡)。
保持业务连续性,及7X24小时服务(高可用性)。
应用于Web业务及数据库从库等服务器的业务。
负载均衡集群典型的开源软件包括:LVS、Nginx、Haporxy等。
1.2 高可用性集群
高可用性集群一般指在集群中任意一个节点失效情况下,该节点上的所有任务会自动转移到其他正常的节点上,而且这个过程并不影响整个集群的运行。
作用如下:
当一台机器宕机时,另一台机器接管宕机机器的IP资源和服务资源,提供服务。
常用于不易于实现负载均衡的应用,比如负载均衡器,主数据库、主存储对之间。
高可用性集群常见的开源软件包括:Keepalived、Hearbeat等。
1.3 高性能计算(并行计算)集群
通常高性能计算集群涉及为集群开发的并行应用程序,以解决复杂的科学问题(天气预报、石油勘探、核反应模拟等)。
1.4 网格计算集群
实际工作很少接触,不做介绍。
2. 常用集群软硬件介绍
2.1 企业运维中常见的集群硬件产品
互联网企业常用的开源集群软件有:Nginx、LVS、Haproxy、Keepalived、Hearbeat。
互联网企业常用的商业集群硬件有:F5、Netscaler、Radware、A10等。
3. Nginx负载均衡介绍
3.1 反向代理与负载均衡的区别
严格来说,Nginx仅仅是作为Nginx Proxy反向代理使用的,但是反向代理功能表现的效果是负载均衡效果,所以称之为Nginx负载均衡。
反向代理:用户端发起请求到Nginx代理端,然后由代理节点代替用户重新请求后端节点服务器。
3.2 实现Nginx负载均衡的组件
主要有两个
Nginx HTTP功能模块 | 模块说明 |
---|---|
ngx_http_proxy_module | proxy代理模块,用于把请求后抛给服务器节点或upstream服务器池 |
ngx_http_upstream_module | 负载均衡模块,可以实现网站的负载均衡功能及节点的健康检查 |
4. 快速实践Nginx负载均衡的环境准备
(1)服务器准备
HOSTNAME | IP | 说明 |
---|---|---|
lb01 | 192.168.1.51 | Nginx主负载均衡器 |
lb02 | 192.168.1.52 | Nginx辅负载均衡器 |
web01 | 192.168.1.53 | web01服务器 |
web02 | 192.168.1.54 | web02服务器 |
(2)软件准备
系统:CentOS7.6
软件:nginx-1.18.0.tar.gz
4.1 安装Nginx软件
下面只安装一次,4台服务器都做
(1)安装依赖
[root@lb01 ~]# yum -y install openssl openssl-devel pcre pcre-devel
(2)安装Nginx
# 下载nginx
[root@lb01 /server/tools]# wget http://nginx.org/download/nginx-1.18.0.tar.gz
[root@lb01 /server/tools]# ll -h
total 1016K
-rw-r--r-- 1 root root 1016K Jun 15 17:28 nginx-1.18.0.tar.gz
# 解压安装Nginx
[root@lb01 /server/tools]# useradd nginx -u 1111 -s /sbin/nologin -M
[root@lb01 /server/tools]# tar xf nginx-1.18.0.tar.gz
[root@lb01 /server/tools]# cd nginx-1.18.0/
[root@lb01 /server/tools/nginx-1.18.0]# ./configure --user=nginx --group=nginx --prefix=/application/nginx-1.18.0 --with-http_stub_status_module --with-http_ssl_module
[root@lb01 /server/tools/nginx-1.18.0]# make
[root@lb01 /server/tools/nginx-1.18.0]# make install
[root@lb01 /server/tools/nginx-1.18.0]# ln -s /application/nginx-1.18.0/ /application/nginx
# 设置环境变量
[root@lb01 /server/tools/nginx-1.18.0]# echo 'PATH="/application/nginx/sbin:$PATH"' >> /etc/bashrc
[root@lb01 /server/tools/nginx-1.18.0]# source /etc/bashrc
[root@lb01 /server/tools/nginx-1.18.0]# echo $PATH
/application/nginx/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
4.2 配置用于测试的Web服务
操作web01和web02(这里以web01为例)
(1)配置如下
[root@web01 /application/nginx/conf]# egrep -v "#|^$" nginx.conf.default > nginx.conf
[root@web01 /application/nginx/conf]# cat 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 bbs.etiantian.org;
location / {
root html/bbs;
index index.html index.htm;
}
}
server {
listen 80;
server_name www.etiantian.org;
location / {
root html/www;
index index.html index.htm;
}
}
}
(2)创建站点目录及测试数据
[root@web01 /application/nginx/conf]# mkdir /application/nginx/html/{www,bbs} -p
[root@web01 /application/nginx/conf]# echo www.53 > /application/nginx/html/www/index.html
[root@web01 /application/nginx/conf]# cat /application/nginx/html/www/index.html
www.53
[root@web01 /application/nginx/conf]# echo bbs.53 > /application/nginx/html/bbs/index.html
[root@web01 /application/nginx/conf]# cat /application/nginx/html/bbs/index.html
bbs.53
[root@web01 /application/nginx/conf]#
(3)检查nginx配置文件,启动服务
[root@web01 /application/nginx/conf]# nginx -t
nginx: the configuration file /application/nginx-1.18.0/conf/nginx.conf syntax is ok
nginx: configuration file /application/nginx-1.18.0/conf/nginx.conf test is successful
[root@web01 /application/nginx/conf]# nginx
[root@web01 /application/nginx/conf]# netstat -lntup|grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 6824/nginx: master
######## 注意上述所有操作,需要在web01和web02 上面都做一遍
(4)在web01和web02配置hosts解析后,用curl命令测试下
# web01
[root@web01 /application/nginx/conf]# tail -1 /etc/hosts
192.168.1.53 www.etiantian.org bbs.etiantian.org
[root@web01 /application/nginx/conf]# curl www.etiantian.org
www.53
[root@web01 /application/nginx/conf]# curl bbs.etiantian.org
bbs.53
# web02
[root@web02 /application/nginx/conf]# tail -1 /etc/hosts
192.168.1.54 www.etiantian.org bbs.etiantian.org
[root@web02 /application/nginx/conf]# curl www.etiantian.org
www.54
[root@web02 /application/nginx/conf]# curl bbs.etiantian.org
bbs.54
4.3 实现一个简单的负载均衡
这里只配置lb01,lb02配置和lb01相同
HOSTNAME | IP | 说明 |
---|---|---|
lb01 | 192.168.1.51 | Nginx主负载均衡器 |
# 这里代理www.etiantian.org,节点为web01和web02,nginx.conf内容如下:
[root@lb01 /application/nginx/conf]# egrep -v "#|^$" nginx.conf.default > nginx.conf
[root@lb01 /application/nginx/conf]# vim nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream www { # 这里定义的是web服务器池,名字为www,包含了web01和web02两个节点。
server 192.168.1.53:80 weight=1; # web01
server 192.168.1.54:80 weight=1; # web02
}
server {
listen 80;
server_name www.etiantian.org;
location / {
proxy_pass http://www; # 客户端访问www.etiantian.org的请求,发送给www服务器池里面的节点。
}
}
}
# 检查语法并启动
[root@lb01 /application/nginx/conf]# nginx -t
nginx: the configuration file /application/nginx-1.18.0/conf/nginx.conf syntax is ok
nginx: configuration file /application/nginx-1.18.0/conf/nginx.conf test is successful
[root@lb01 ~]# nginx
[root@lb01 /application/nginx/conf]# netstat -lntup|grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 6744/nginx: master
# 结果测试,linux端,(lb01)
[root@lb01 /application/nginx/conf]# tail -1 /etc/hosts
192.168.1.51 www.etiantian.org bbs.etiantian.org # 这里IP写负载均衡的IP
[root@lb01 /application/nginx/conf]# curl www.etiantian.org
bbs.53
[root@lb01 /application/nginx/conf]# curl www.etiantian.org
bbs.54
## 这里问题来了,虽然负载成功了,但是访问内容确实bbs的?下面会有介绍,这里继续测试
# 宕掉两个节点,测试
[root@web01 /application/nginx/conf]# nginx -s stop
[root@web02 /application/nginx/conf]# nginx -s stop
[root@lb01 /application/nginx/conf]# curl www.etiantian.org
<html>
<head><title>502 Bad Gateway</title></head>
<body>
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
[root@lb01 /application/nginx/conf]# curl www.etiantian.org
<html>
<head><title>502 Bad Gateway</title></head>
<body>
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
# 宕掉1台节点测试
[root@web01 /application/nginx/conf]# nginx
[root@lb01 /application/nginx/conf]# curl www.etiantian.org
bbs.53
[root@lb01 /application/nginx/conf]# curl www.etiantian.org
bbs.53
# 启动所有节点测试
[root@lb01 /application/nginx/conf]# curl www.etiantian.org
bbs.54
[root@lb01 /application/nginx/conf]# curl www.etiantian.org
bbs.53
4.4 反向代理访问www.etiantian.org返回bbs内容解决
# 对于上述问题,原因是因为客户端访问域名时,携带了www.etiantian.org主机头请求nginx反向代理服务器,但是反向代理服务器代替客户端请求后端节点服务器的时候,默认没有在请求头中告诉后端节点服务器要找哪台节点服务器,所以默认访问了第一个虚拟主机(bbs)。
# 解决办法就是添加“proxy_set_header Host $host”,让反向代理服务器代替客户端请求后端节点服务器时,携带主机头去访问。
# 具体配置如下:
[root@lb01 /application/nginx/conf]# cat nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream www {
server 192.168.1.53:80 weight=1;
server 192.168.1.54:80 weight=1;
}
server {
listen 80;
server_name www.etiantian.org;
location / {
proxy_pass http://www;
proxy_set_header Host $host; # 在代理向后端节点发起请求时,携带主机头信息。这是节点服务器多虚拟主机配置的关键。
}
}
}
# 重载nginx服务,并测试
[root@lb01 /application/nginx/conf]# nginx -t
nginx: the configuration file /application/nginx-1.18.0/conf/nginx.conf syntax is ok
nginx: configuration file /application/nginx-1.18.0/conf/nginx.conf test is successful
[root@lb01 /application/nginx/conf]# nginx -s reload
[root@lb01 /application/nginx/conf]# curl www.etiantian.org
www.53
[root@lb01 /application/nginx/conf]# curl www.etiantian.org
www.54
4.5 配置经过反向代理后的节点服务器记录用户IP
# 这里配置好负载均衡后,后端节点服务器的访问日志里面只会记录代理服务器的IP,而不会记录用户端的IP,所以这里要另外配置一下
# 更改配置前,日志内容
[root@web01 /application/nginx/conf]# tail /application/nginx/logs/access.log
192.168.1.51 - - [15/Jun/2020:18:45:22 +0800] "GET / HTTP/1.0" 200 7 "-" "curl/7.29.0" # 第一个字段IP都是代理端的IP
192.168.1.51 - - [15/Jun/2020:19:14:25 +0800] "GET / HTTP/1.0" 200 7 "-" "curl/7.29.0"
# Nginx代理端配置如下
[root@lb01 /application/nginx/conf]# cat nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream www {
server 192.168.1.53:80 weight=1;
server 192.168.1.54:80 weight=1;
}
server {
listen 80;
server_name www.etiantian.org;
location / {
proxy_pass http://www;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr; # 加入这行配置,让后端节点程序、日志记录用户的真实IP
}
}
}
[root@lb01 /application/nginx/conf]# nginx -t
nginx: the configuration file /application/nginx-1.18.0/conf/nginx.conf syntax is ok
nginx: configuration file /application/nginx-1.18.0/conf/nginx.conf test is successful
[root@lb01 /application/nginx/conf]# nginx -s reload
# 后端节点服务器配置如下(后端节点服务器要想记录用户的真实IP,必须要配置X-Forwarded-For)
[root@web01 /application/nginx/conf]# cat nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'; # 如果希望客户端IP在日志中的第一列显示,可以把$http_x_forwarded_for和$remote_addr互换一下。
server {
listen 80;
server_name bbs.etiantian.org;
location / {
root html/bbs;
index index.html index.htm;
}
}
server {
listen 80;
server_name www.etiantian.org;
location / {
root html/www;
index index.html index.htm;
}
access_log logs/access_www.log main;
}
}
[root@web01 /application/nginx/conf]# nginx -t
nginx: the configuration file /application/nginx-1.18.0/conf/nginx.conf syntax is ok
nginx: configuration file /application/nginx-1.18.0/conf/nginx.conf test is successful
[root@web01 /application/nginx/conf]# nginx -s reload
win浏览器测试
再次查看日志
相关重要参数说明
相关重要参数 | 参数说明 |
---|---|
proxy_pass http://server_pools; | 通过proxy_pass功能把用户的请求转向到反向代理定义的upstream服务器池。 |
proxy_set_header Host $host; | 在代理向后端服务器发送的HTTP请求头中加入host字段信息,用于当后端服务器配置有多个虚拟主机时,可以识别代理的是哪个虚拟主机。这是节点服务器多虚拟主机配置的关键 |
proxy_set_header X-Forwarded-For $remote_addr; | 记录用户的真实IP,而不是代理自己的。 |
5. upstream模块调度算法
一般分为7层和4层:
(1)7层:https://nginx.org/en/docs/http/ngx_http_upstream_module.html
round-robin(默认轮询)
加权轮询
least-conn(最小链接)
加权最小链接
ip-hash
hash(如果添加了consistent字段,则变为一致性哈希)
random(随机)
加权随机
(2)4层:https://nginx.org/en/docs/stream/ngx_stream_upstream_module.html
round-robin(默认轮询)
加权轮询
hash(如果添加了consistent字段,则变为一致性哈希)
least-conn(最小链接)
加权最小链接
random(随机)
加权随机