image.png

  • 严格的来说,nginx仅仅作为Proxy反向代理的作用,因为这个反向代理的效果正是负载均衡的作用,所以称之为nginx负载均衡

    负载均衡、反向代理区别

    image.png
    image.png

    Nginx负载均衡部署

    nginx提供负载均衡的模块式是:

  • ngx_http_proxy_module proxy代理模块,用于把请求抛给后端的服务器节点,或是upstream服务器池

  • ngx_http_upstream_module 负载均衡池,实现服务器的负载均衡节点配置,以及健康检查

Nginx负载均衡实践

测试准备

  • 4台虚拟机 ==>> lb1,lb2,web1,web2
  • 均安装nginx即可,以为nginx可以实现如下功能
    • 负载均衡的功能
    • 反向代理,请求转发的过程
    • 静态页面的功能
  1. 准备web机器的数据展示,简单展示html首页即可,为了直观看到负载均衡请求分发效果,设置不同内容页面
  2. 准备负载均衡,简单设置,不考虑高可用性

    nginx.conf配置文件

    worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream;

    通过关键字upstream定义负载均衡地址池,请求分给如下2个节点

    upstream my_web { server 192.168.47.130; server 192.168.47.134; }

    此时这个虚拟主机就不再是静态页面的作用,而是请求转发的作用,转发给一个地址池

    server { listen 80; servername ; location / { proxy_pass http://my_web; } } }

效果:我们通过刷新负载均衡的地址ip,可以轮换的得到web1,web2的内容,如果12是同内容网页,也就做到负载均衡的作用,减轻了服务器的压力

upstream

nginx的负载均衡功能是来自于 ngx_http_upstream_module ,该模块支持的代理形式有如下

  • proxy_pass 转发http请求
  • Fastcgi_pass
  • uwsgi_pass 和python后台结合
  • memcached_pass

该模块作用是允许nginx定义一组或者多组的服务器节点,在nginx接收到请求的时候,可以通过proxy_pass代理方式,把用户的请求发送到预先定义好的upstream地址池中

nginx负载均衡地址池的语法定义,通过upstream关键字定义负载均衡池的名字,例如my_web ; 然后在地址池中通过server关键字定义服务器节点的信息,可以填入ip,域名,以及负载均衡算法的定义

upstream my_web { server 192.168.178.122; server 192.168.178.140; } proxY_pass http://my_web;

upstream参数解释

  1. upstream my_web {
  2. server 192.168.178.122 weight=1 max_fails=1 fail_timeout=10s backup;
  3. server backup1.luffy.com:8000 weight=2
  4. }

server:是一个固定的关键词,后面跟着服务器ip或者主机名,域名地址,默认是80端口,也可以指定端口转发
weight:表示定义服务器的权重,权重的数字越大,权重的地位越高,nginx就会优先给与分发请求,注意结尾写;
max_fails:nginx尝试连接该节点的失败的次数,根据企业情况调整
backup:当其他非backup的机器挂掉,或者繁忙的时候,请求才回转发给backup机器,因此它是备份机器的效果
fail_timeout:表示在max_fails参数定义好的连接失败数之后,距离下次检查的时间
down:剔除,暂停当前节点的请求解析,不参与负载均衡

  • 注意的是upstream关键词应该卸载nginx.conf中的http{}标签内,并且默认的算法是轮询算法。

    1. upstream www_pools {
    2. server 192.168.178.160;
    3. server 192.168.178.161:80 weight=1 max_fails=1 fail_timeout=10s;
    4. server 192.168.178.162:98 weight=2 max_fails=2 fail_timeout=20s backup;
    5. server 192.168.178.162:99 weight=3 max_fails=3 fail_timeout=30s backup;
    6. }

    使用域名形式,或者Unix套接字形式
    nginx请求转发的目的地有两类

  • 网络中的机器,因此可以填写该机器的ip,域名,端口

  • 本地的进程,可以使用socket套接字进行通信文件去转发请求
    1. upstream my_web {
    2. server backup1.example.com;
    3. server backend2.example.com:8080 weight=9;
    4. server unix:/tmp/backend3.sock;
    5. }

upstream模块调度算法

调度算法一般分几类:

  • 第一类是静态调度算法:负载均衡器根据自身设定的规则进行分配,不需要考虑后端节点的健康情况。例如轮询、加权轮询、哈希轮询调度算法
  • 第二类是动态调度算法,负载均衡器会判断后端节点的当前状态,来决定是否分发请求。例如链接数最少的优先分发,响应时间短的优先分发,如least_conn , fail等都是动态调度

    rr轮询(round-robin)

    按照请求顺序逐一分配给不同的后端节点服务器,如果后端节点宕机,宕机的服务器会被自动从地址池中剔除,新的请求会发给正常的服务器

    wrr(权重轮询)

    给后端节点服务器增加权重,数值越大,优先获得客户端请求,可以以服务器配置来决定比例大小,从而解决新旧服务器的性能不均衡问题等。

    upstream backup { server 192.168.47.130 weight=1; server 192.168.47.131 weight=2; }

ip_bash

每个请求按客户端IP的hash结果分配,当新的请求到达,将其客户端ip通过哈希算法得到一个唯一值,在随后的客户端请求中,如果客户端的ip哈希值相等,该请求就会固定发给一台服务器
该调度算法可以解决动态网页中的session共享问题
注意使用ip_hash不得再使用weight , backup两个参数,造成冲突,写了也不生效

upstream chaoge_backend { ip_hash; server 192.168.47.130; server 192.168.47.131; }

fail

该算法根据后端服务器节点的响应时间来分配,响应时间短的优先分配,该算法根据页面大小和加载时间长短进行负载均衡,nginx本身不支持fail形式,如果要支持该算法,必须下载nginx的 upstream_fail 模块

upstream chaoge_backend { fair; server 192.168.47.130; server 192.168.47.131; }

least_conn

该算法根据后端节点的链接数决定分配请求,哪个机器链接数少,就发给谁

url_hash

和ip_hash类似,该算法根据客户端请求的URL信息进行hash得到唯一值,让每个URL固定的发给同一个后端服务器,后端服务器为缓存服务器效果最佳
nginx本身是不支持url_hash的需要单独安装hash模块
url_hash(web缓存节点)和ip_hash(会话保持)功能类似

upstream chaoge_backend { server squid1:3128; server squid:3128; hash $request_url; hash_method crc32; }

proxy_pass指令

proxy_pass指令属于 ngx_http_proxy_module 模块,此模块可以把请求转发给另一台服务器,在实际的反向代理工作中,会通过location功能指定的URL,然后把接受到的符合URL的请求通过proxy_pass参数抛给定义好的 upstream 地址池

proxy_pass案例

  1. #在nginx.conf配置文件中定义,server{}标签内
  2. location /name/ {
  3. proxy_pass http://127.0.0.1/remote/;
  4. }
  5. #例如当请求url是 http://192.168.47.130/name 时,会进入该location的作用域,通过参数proxy_pass请求转发
  1. location ~ .*\.php$ {
  2. proxy_pass http://www.example.cn$request_uri;
  3. proxy_set_header Host $proxy_host;
  4. proxy_set_header X-Forwarded-For $remote_addr;
  5. }
  6. #所有请求以 .php 结尾的URL,进行转发

proxy_pass参数

image.png

nginx负载均衡实战

当real server存在多虚拟主机的时候,如何实现反向代理

环境准备

  1. 准备2太linux机器,安装好nginx服务,且配置基于域名的多虚拟主机,server{}标签,保证负载均衡机器和两台节点服务器能够通信即可

    节点1:node01 172.20.0.66 节点2:node02 172.20.0.67

  2. 在2台新建的linux机器上,安装好nginx后,配置nginx.conf,创建2个server{}标签

    第一个基于域名的虚拟主机配置

    server { listen 80; server_name mp3.chaoge.com; charset uft-8; location / { root html/mp3; index index.html index.htm; } }

    第二个基于域名的虚拟主机配置

    server { listen 80; server_name game.chaoge.com; charset uft-8; location / { root html/game; index index.html index.htm; } }

  3. 创建多域名的虚拟主机目录站点,以及首页文件index.html

    mkdir -p /opt/nginx/html/{mp3,game} echo “…” > /opt/nginx/html/mp3/index.html echo “…” > /opt/nginx/html/game/index.html

  4. 做好本地的dns解析关系,修改/etc/hosts文件

  5. 测试访问对应节点内容
    • linux本地设置的hosts,可以使用curl命令查看网页反应情况
    • 如果想要在客户端浏览器查看,在我们设置了域名的情况下,要在对应客户端设置好hosts文件,mac与linux设置流程大抵相同,win在c盘找到hosts文件

进阶测试(负载均衡测试)

  1. 再准备一台负载均衡机器,负责负载均衡转发操作

    负载均衡器:lb01 172.20.0.50 节点1:node01 172.20.0.66 节点2:node02 172.20.0.67

  2. 修改lb01的nginx.conf,添加负载均衡池,以及对请求转发的虚拟机

    1. #定义节点服务器地址池
    2. upstream my_node {
    3. server 172.20.0.66;
    4. server 172.20.0.67;
    5. }
    6. #作用是反向代理的虚拟主机配置
    7. server{
    8. listen 80;
    9. server_name lb.chaoge.com;
    10. location / {
    11. proxy_pass http://my_node;
    12. }
    13. }
  3. 添加主机名解析关系,以及启动nginx负载均衡服务器

    修改/etc/hosts/文件,添加代码

    172.20.0.50 lb.chaoge.com

  4. 此时访问nginx负载均衡器,查看请求分发

    curl lb.chaoge.com

    无论刷新多少次网页,只显示出了mp3虚拟主机的首页内容,game主机的内容并没有得到显示

    首先为什么会得到mp3,却不现实game,默认读取是从上至下的,所以默认优先读取了mp3的虚拟主机内容,至于为什么没有读取game,我们往下看~

  5. 配置多域名的负载均衡请求分发

    修改/etc/hosts/文件,添加代码

    172.20.0.50 lb.chaoge.com 172.20.0.50 mp3.chaoge.com 172.20.0.50 game.chaoge.com

  6. 重点!!nginx转发请求的时候,添加头部信息

    1. server{
    2. listen 80;
    3. server_name lb.chaoge.com;
    4. location / {
    5. proxy_pass http://my_node;
    6. #添加下行内容
    7. proxy_set_header Host $host;
    8. }
    9. }
  7. 验证效果

    这个时候我们再curl一下两个虚拟主机,可以得到对应的两个站点的内容,实验成功~

    curl mp3.chaoge.com curl game.chaoge.com