美文网首页
负载均衡和Nginx

负载均衡和Nginx

作者: 攻城狮0902 | 来源:发表于2020-01-19 21:29 被阅读0次

    在经典的框架和组件里,nginx无疑占有一席之地。作为高性能轻量级的反向代理web服务器,其单机并发量可达3万QPS
    使用nginx的初衷,为了解决内部网需要访问外网,但防火墙限制导致只能访问指定ip,但外网比如头条等为了安全使用域名+动态ip的方式,无法开放所有ip的访问权限。所以需要在外网部署服务对内网的请求进行转发。
    有2种方式:一、部署web服务进行接收并访问外网服务;二、部署nginx应用进行代理转发,使用nginx的反向代理功能。无疑使用nginx是最佳的尝试。
    本文介绍自己使用过程的接触到的概念和配置,以及对Nginx真实部署时需要考虑问题的探究。

    基本概念

    应用场景

    静态文件服务器

    实现动静分离

    反向代理服务器

    面向内部服务器的代理,对外接收请求,转到内部服务器

    负载均衡

    内置策略:

    1. 轮询Round-Ribon/RR
    2. 加权轮询 各节点硬件性能不一样,可设置对应的权重
    3. ip hash 基于ip hash算法,对客户端请求的ip进行hash计算,然后根据hash结果将同一个客户端ip的请求分发给同一台服务器进行处理;
    • 能够一定保持用户的session,但免不了节点切换时的session失效【节点失效/超时重试机制】
    • 但前提是nginx作为内部服务器的直接转发者
    • hash算法的影响因素:机器权重、是否存活、负载上限。对象:目标散列调度(利用目标IP)和源地址散列调度(利用源IP)
           n = ServerNode[hashkey(dest_ip)]; 
      if ( (n is dead) OR (W(n) == 0) OR (C(n) > 2*W(n))) then 
      return NULL; 
      return n; // 如果一切OK
    

    注:S(n)是ServerNode列表中第n个服务器,c(n)是负载上限;w(n)是该服务器的权重;hashkey()为散列函数。在实现时,一般采用素数乘法Hash函数,通过乘以素数使得散列键值尽可能地达到较均匀的分布。

    web缓存

    对不同的文件作不同的缓存处理

    正向代理服务器

    适用resolver关键字代理客户端的请求,但不能代理https的

    nginx.conf配置文件

    文件结构:

    1. 全局块 允许生成worker processes数目等
    2. events块 配置与用户的网络连接
    3. http块 嵌套多个server
    • upstream块
    • server块
      • location块 配置请求的路由,及各页面的处理情况
    #worker_processes  auto;    #工作进程数:如果有SSL、gzip这些比较消耗CPU的工作可以设为和CPU的数量一样;要处理很多很多的小文件,充分利用IO带宽
    #worker_cpu_affinity  auto;
    #worker_rlimit_nofile 200000; #更改worker进程的最大打开文件数限制,不受ulimit-a的限制
    
    error_log  logs/error.log;
    error_log  logs/error.log  notice;
    error_log  logs/error.log  info;
    
    
    events {
        worker_connections  1024; #单个工作进程可以允许同时建立外部连接的数量
        use epoll;  #设置用于复用客户端线程的轮询方法
        multi_accept on; #告诉nginx收到一个新连接通知后接受尽可能多的连接
    }
    
    http {
        include       /etc/nginx/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"' 
                          '$request_time - $upstream_cache_status' ;
        access_log  logs/access.log  main;
    
        sendfile        on;  可以在磁盘和TCP socket之间互相拷贝数据(或任意两个文件描述符)
        tcp_nopush      on;  告诉nginx在一个数据包里发送所有头文件,而不一个接一个的发送
        tcp_nodelay     on;  告诉nginx不要缓存数据,而是一段一段的发送--当需要及时发送数据时,就应该给应用设置这个属性
    
        keepalive_timeout  30;
    
        keepalive_requests 100;  
        reset_timedout_connection on;
        client_body_timeout 40;
        send_timeout 2;
    
        #负载均衡列表及算法配置
        upstream mysvr { 
          #ip_hash;  #可以解决session不能跨服务器的问题
          server 10.189.96.92:8002 weight=100;
          server 10.189.96.92:8003 weight=10 max_fails=3 fail_timeout=30s;
          server 10.189.96.92:8004 down; #down表示当前的server暂时不参与负载
          server 10.189.96.92:8005 backup; #backup其它所有的非backup机器down或者忙的时候,请求backup机器
          #server 172.17.0.2:8124 ;
        }
    
        server {
            keepalive_requests 120; #单连接请求上限次数。
            listen       8767;   #监听端口
            server_name  127.0.0.1;   #监听地址   
    
            location  ~*^.+$ {       #请求的url过滤,正则匹配,~为区分大小写,~*为不区分大小写。
               #root path;  #根目录
               #index vv.txt;  #设置默认页
               #proxy_pass  http://mysvr;  #请求转向mysvr 定义的服务器列表
               # deny 127.0.0.1;  #拒绝的ip
               #allow 172.18.5.54; #允许的ip           
            } 
    
            location ~ ^~ /zhjrsl {
               # proxy_pass http://10.189.96.92:8002;   #代理,访问http://10.189.110.30:8764/zhjrsl/时会转向http://10.189.96.92:8002/zhjrsl/
               proxy_pass  http://mysvr;
            } 
    
            location  /zipkin/ {  #有没有/都一样
               proxy_pass http://10.189.96.92:9411;
            } 
    
            location  /kibana {
               #proxy_pass http://10.187.114.10:9202/app/kibana/; #有/时,则将kibana后面的路径放到代理路径后面
               proxy_pass http://10.187.114.10:9202/app;    #无/时,则将kibana后面的路径+kibana放到代理路径后面
            } 
    
            location  ~ ^\/zhjrsl\/* {
               return 301 http://10.189.96.92:8002/zhjrsl/;     #重定向    
            } 
    
            #兜底的
            location / {         
            } 
    
            location /monitor{
                check_status;
                access_log off;
                allow 10.189.110.30;
                deny all;
            }
        }
        include /etc/nginx/conf.d/*.conf;
    
    }
    

    ngnix中location与proxy_pass配置规则:

    代理转发主要用到的配置

    • location配置用于匹配请求的URL,即ngnix中的$request_uri变量
    • proxy_pass配置用于转发URL

    (location =) > (location 完整路径) > (location ^~ 路径) > (location ,* 正则顺序) > (location 部分起始路径) > (/)

    location = /uri    =开头表示精确匹配,只有完全匹配上才能生效。
    location ^~ /uri   ^~ 开头对URL路径进行前缀匹配,并且在正则之前。
    location ~ pattern  ~开头表示区分大小写的正则匹配。
    location ~* pattern  ~*开头表示不区分大小写的正则匹配。
    location /uri     不带任何修饰符,也表示前缀匹配,但是在正则匹配之后,如果没有正则命中,命中最长的规则。
    location /      通用匹配,任何未匹配到其它location的请求都会匹配到,相当于switch中的default


    实际部署

    Nginx的高可用性

    高可用借助于主备节点和监控切换
    主流方案是Keepalived+Nginx实现双机热备

    Keepalived是一个基于VRRP协议来实现的服务高可用方案,可以利用其来避免IP单点故障,类似的工具还有heartbeat、corosync、pacemaker。但是它一般不会单独出现,而是与其它负载均衡技术(如lvs、haproxy、nginx)一起工作来达到集群的高可用。

    image.png

    部署分布式集群

    1. 每台nginx都有公网地址,利用DNS的负载均衡【在域名处设置同个域名多个指向,只能是最简单轮询算法】。但故障切换会慢,且增加网络开销。

    2. 一台公网nginx通过upstream功能,轮询、ip、url多方式分发到内网多台nginx。但公网的nginx如果down机的话,内网全断

    3. 两个公网nginx服务+三个公网ip【2个nginx的实际ip和1个虚拟ip/VIP】,通过keepalive+lvs实现高可用,再upstream到内网

    如果并发量真的巨大的话,一般就要借助硬件F5等设备做负载均衡,跟DNS、CDN等服务商合作做域名解析转发、缓存配置,这也是目前大多数大厂的架构配置

    DNS做负载均衡

    DNS(Domain Name System)是因特网的一项服务,它作为域名和IP地址相互映射的一个分布式数据库,能够使人更方便的访问互联网
    同时许多DNS还支持基于地理位置的域名解析,即会将域名解析成距离用户地理最近的一个服务器地址,这样就可以加速用户访问,改善性能
    域名解析请求都会根据对应的负载均衡算法计算出一个不同的IP地址并返回,这样A记录中配置多个服务器就可以构成一个集群,并可以实现负载均衡

    www.apusapp.com IN A 114.100.20.201;
    www.apusapp.com IN A 114.100.20.202;
    www.apusapp.com IN A 114.100.20.203;
    

    缺点:

    1. DNS是多级解析,且每级缓存A记录。当A调整时,DNS未感知刷新完成,导致访问A的请求失效
    2. DNS采用最简单的RR负载均衡算法,不能满足内部服务动态调整
    3. 造成额外的网络交互,为了在A调整时及时刷新各级DNS的缓存,设置DNS刷新时间小

    大型网站总是部分使用DNS域名解析,利用域名解析作为第一级负载均衡手段,找到同样提供负载均衡服务器的内部服务器,这组内部负载均衡服务器再进行负载均衡,请请求发到真实的服务器上,最终完成请求

    虚拟IP

    VIP,是一种不与特定计算机或者特定计算机网卡相对应的IP地址。所有发往这个IP地址的数据包最后都会经过真实的网卡到达目的主机的目的进程
    用来网络地址转换,提升网络容错和可移动性
    虚拟IP常用于系统高可用性的场景,能够自由漂浮

    原理:当虚拟IP漂浮后,刷新所有其他主机的arp缓存

    CDN服务

    ...


    高级配置

    底层原理

    惊群现象

    相关文章

      网友评论

          本文标题:负载均衡和Nginx

          本文链接:https://www.haomeiwen.com/subject/awhdzctx.html