一旦工作,那就要努力的干,聪明的干,快速的干——用省下来的时间干自己喜欢干的事情。!

02-亿级流量网站架构核心技术-负载均衡与反向代理

WEB服务器 lampnick 746℃ 0评论

负载均衡

  • 关注点
    • 上游服务器配置:使用upstream server配置上游服务器
    • 负载均衡算法:配置多个上游服务器时的负载均衡机制
    • 失败重试机制:配置当超时或上游服务器不存活时,是否需要重试其他上游服务器
    • 服务器心跳检查:上游服务器的健康检查/心跳检查
  • nginx提供的负载均衡可以实现上游服务器的负载均衡、故障转移、失败重试、容错、健康检查等,当某些上游服务器出问题时,可以将请求转移到其他上游服务器保障高可用,使用OpenResty实现更智能的负载均衡,如热点与非热点流量分离、正常流量与爬虫流量分离等;同时也是反向代理服务器,将用户请求通过nginx代理到上游服务器,反向代理服务器可以将响应结果进行缓存、压缩等提升性能。
  • upstream配置:第一步,给nginx配置上游服务器,即负载均衡到真实的处理业务的服务器,通过在http指令下配置upstream即可:
        upstream backend {
            server 192.168.61.1:9080 weight=1;
            server 192.168.61.1:9090 weight=2;
        }
    

    权重:默认都是1,值越大,分配的请求越多。 第二步,可以配置proxy_pass来处理用户请求

        location / {
            proxy_pass http://backend;
        }
    

    当访问nginx时,会将请求反向代理到backend配置的upstream server.

  • 负载均衡算法:解决用户请求到时如何选择upstream server进行处理,默认用round-robin(轮询),同时支持其他几种算法
    • round-robin:轮询,默认负载均衡算法,即以轮询的方式将请求转发到上游服务器,通过配合weight配置可以实现基于权重的轮询。
    • ip_hash:根据客户IP进行负载均衡,即相同的IP将负载均衡到同一个upstream server.
        upstream backend{
            ip_hash;
            server 192.168.61.1:9080 weight=1;
            server 192.168.61.1:9090 weight=2;
        }
    
    • hash key[consistent]:对某一个key进行hash或者使用一致性哈希算法进行负载均衡。使用hash存在的问题是,当添加/删除服务器时,将导致很多key被重新负载均衡到不同的服务器(从而导致后端可能出现 问题),因此,建义使用一致性哈希,当添加/删除一台服务器时,只有少数key将被重新负载均衡到不同的服务器。
      • 哈希算法:根据请求uri进行负载均衡,可以使用nginx变量,实现复杂算法。
          upstream backend{
              hash $uri;
              server 192.168.61.1:9080 weight=1;
              server 192.168.61.1:9090 weight=2;
          }
      
      • 一致性哈希算法:consistent_key动态指定
          upstream backend{
              hash $consistent_key consistent;
              server 192.168.61.1:9080 weight=1;
              server 192.168.61.1:9090 weight=2;
          }
      

      如下location指定了一致性hash key,此处会优先考虑请求参数cat,如果没有,则再根据请求uri进行负载均衡

      location /{
          set $consistent_key $arg_cat;
          if ($consistent_key = "") {
              set $consistent_key $request_uri;
          }
      }
      

      而实际会通过lua设置一致性哈希key.

      set_by_lua_file $consistent_key "lua_balancing.lua"
      
      lua_balancing.lua代码如下:
      local consistent_key = args.cat
      if not consistent_key or consistent_key == '' then
          consistent_key = ngx_var.request_uri
      end
      
      loca value = balancing_cache:get(consistent_key)
      if not value then
          success,err = balancing_cache:set(consistent_key,1,60)
      else
          newval,err = balancing_cache:incr(consistent_key,1)
      end
      

      如果某一个分类请求量太大,上游服务器可能处理不了这么多请求,此时可以在一致性哈希key后加上递增计数以实现类似轮询的算法。

      if newval > 5000 then
          consistent_key = consistent_key .. '_' .. newval
      
      • least_conn:将请求负载均衡到最少活跃连接的上游服务器。
  • 失败重试:upstream server 和 proxy_pass
upstream backend{
    server 192.168.61.1:9080 weight=1 max_fails=2 fail_timeout=10s;
    server 192.168.61.1:9090 weight=1 max_fails=2 fail_timeout=10s;
}

通过配置上游服务器的max_fails和fail_timeout,来指定每个上游服务器,当fail_timeout时间内失败了max_fails次请求,则认为该上游服务器不可用/不存活,然后将摘掉该上游服务器,fail_timeout时间后再次将该服务器加入到存活上游服务器列表进行重试。

location /test {
    proxy_connect_timeout 5s;
    proxy_read_timeout 5s;
    proxy_send_timeout 5s;
    
    proxy_next_upstream error timeout;
    proxy_next_upstream_timeout 10s;
    proxy_next_upstream_tries 2;
    
    proxy_pass http://backend;
    add_header upstream_addr $upstream_addr;
}

进行proxy_next_upstream相关配置,当遇到配置的错误时,会重试下一台上游服务器。

  • 健康检查:nginx对上游服务器的健康检查默认采用的是惰性策略,nginx商业版提供了health_check进行主动健康检查。也可以集成nginx_upstream_check_module模块来进行主动健康检查(支持tcp/http心跳来实现健康检查)
  • TCP心跳检查
    upstream backend{
        server 192.168.61.1:9080 weight=1;
        server 192.168.61.1:9090 weight=2;
        check interval=3000 rise=1 fall=3 timeout=2000 type=tcp;
    }
    
    • interval:检测间隔时间,此处3S检测一次
    • fall:检测失败多少次后,上游服务器下线
    • rise:检测成功多少次后,上上游服务器被标识为存活并可以处理请求
    • timeout:检测请求超时时间设置
  • HTTP心跳检查
        upstream backend{
            server 192.168.61.1:9080 weight=1;
            server 192.168.61.1:9090 weight=2;
            check interval=3000 rise=1 fall=3 timeout=2000 type=http;
            check_http_send "HEAD / status HTTP/1.0\r\n\r\n";
            check_http_expect_alive http_2xx http_3xx;
        }
    
    • check_http_send:检查时发的HTTP请求内容
    • check_http_expect_alive:当上游服务器返回匹配的响应状态码时,则认为上游服务器存活 需要注意,检查时间间隔不能太短,否则可能因为心跳检查包太多造成上游服务器挂掉,同时要设置合理的超时时间
  • 域名上游服务器
upstream backend{
    server c0.3.cn;
    server c1.3.cn;
}

在nginx社区版中,是在nginx解析配置文件阶段将域名解析成IP地址并记录到upstream上,当域名对应IP变化时,upstream不会更新。nginx商业版支持动态更新。不过,使用proxy_pass http://c0.3.cn是支持动态域名解析的

  • 备份上游服务器
upstream backend{
    server 192.168.61.1:9080 weight 1;
    server 192.168.61.1:9090 weight 1 backup;
}

将9090服务器设置为备份上游服务器,当所有主上游服务器不存活时,请求转发给备份上游服务器。

  • 不可用上游服务器
upstream backend{
    server 192.168.61.1:9080 weight 1;
    server 192.168.61.1:9090 weight 1 down;
}

HTTP反向代理示例:反向代理除了实现负载均衡外,还提供如缓存来减少上游服务器的压力

  • 全局配置(proxy cache)
    proxy_buffering on;
    proxy_buffer_size 4k;
    proxy_buffers 512 4k;
    proxy_busy_buffers_size 64k;
    proxy_temp_file_write_size 256k;
    proxy_cache_lock on;
    proxy_cache_lock_timeout 200ms;
    proxy_temp_path /tmpfs/proxy_temp;
    proxy_cache_path /tmpfs/proxy_cache levels=1:2 keys_zone=cache:512m inactive=5m max_size=8g;
    proxy_connect_timeout 3s;
    proxy_read_timeout 5s;
    proxy_send_timeout 5s;
    

    开放proxy buffer,缓存内容将存放在tmpfs以提升性能,设置超时时间。 对内容型数据建议开启gzip压缩,gzip_comp_level压缩级别根据实际压测来决定(带宽和吞吐量之间的抉择

  • HTTP动态负载均衡:如上的负载均衡实现中,每次upstream列表有变更,都要到服务器进行修改,首先管理容易出现问题,而且upstream服务上线无法自动注册到Nginx upstream列表。因此,我们需要一种服务注册,可以将upstream动态注册到Nginx上,从而实现upstream服务的自动发现。
    • Consul:开源的分布式服务注册与发现系统,通过HTTP API可以使得服务器注册与发现实现起来很简单。有如下特性
      • 服务注册
      • 服务发现
      • 故障检测
      • K/V存储
      • 多数据中心
      • Raft算法 通过Consul可以管理服务注册与发现,接下来需要有一个与Nginx部署在同一台机器的Agent来实现Nginx配置更改和Nginx重启功能。有Confd或者Consul-template两个选择,Consul-template是Consul官方提供的。除了Consul外,还有一个选择是etcd3,其使用了GRPC和protobuf可以说是一个亮点,不过etcd3没有提供多数据中心、故障检测、Web管理界面。
  • Nginx四层负载均衡:目前四层软件负载均衡用的比较多的是HaProxy;而Nginx也支持四层负载均衡
    • 静态负载均衡
      默认情况下,ngx_stream_core_module是没有启用的,需要在安装Nginx时,添加--with-stream配置参数启用
      ./configure --prefix-/usr/local/nginx --with-stream
      
      • stream指令 我们配置HTTP负载均衡时,都是配置在http指令下,而四层负载均衡是配置在stream指令下
        stream {
            upstream mysql_backend{
                ... 
            }
            server{
                ...
            }
        }
        
      • upstream配置:类似于http upstream配置
        upstream mysql_backend{
            server 192.168.0.10:3306 max_fails=2 fail_timeout=10s wieght=1;
            server 192.168.0.11:3306 max_fails=2 fail_timeout=10s wieght=1;
            least_conn;
        }
        
      • servers配置
        server {
            
        }
        
  • 动态负载均衡:nginx-stream-upsync-module有一个兄弟nginx-upsync-module,提供了HTTP七层动态负载均衡,动态更新上游服务器不需要reload nginx。

转载请注明:lampNick » 02-亿级流量网站架构核心技术-负载均衡与反向代理

喜欢 (1)or分享 (0)
头像
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址