第十四周《简述LVS调度方案....》

2018-12-12  本文已影响0人  N32_Diamond

一、简述LVS调度方案及应用场景

Lvs的调度算法可分为静态调度和动态调度。
- 静态调度即根据算法本身的结果来进行调度,包括:

1、轮询调度算法(RR),轮询算法适用于所有服务器的处理性能相近的应用场景,因为轮询算法相对简单,其调度方式是不管服务器当前的连接数和响应速度如何的。因此当后端服务器的处理性能残次不齐,请求服务的时间变化较大时,轮询算法很容易导致服务器间的负载不均衡。因此轮询算法只适用于后端服务器性能相近,请求时间变化不大的场景使用。

2、加权轮询调度算法(WRR)可以理解为轮询算法的进阶版。通过设置权重来表示后端服务器的处理型男,权重越大表示服务器能的处理能力越强。但是当请求时间变化很大时,加权轮询算法依然会导致服务器间的负载不平滑。

3、目标地址哈希调度算法(DH)是指针对通过计算目前地址的散列(HASH)函数来将一个目标IP地址映射到一台服务器。DH算法首先根据请求的目标Ip地址作为散列键(Hask key),从静态分配的散列表中找出对应的服务器。若该服务器是可用且未超载,则将请求发送到该服务器,否则返回为空。此调度算法可保证用户访问同一个应用服务时,请求均被送往同一个后端服务器。典型应用场景为正向代理缓存场景中的负载均衡。

4、源地址散列调度算法(SH)是指根据请求的源Ip地址作为散列键(Hash key),从静态分配的散列表中找出其对应的服务器。若服务器是可能且未超载,否则将返回空。SH算法可将来自于同一个IP地址的请求始终发往同一个后端服务器,从而实现会话绑定。

- 动态调度算法即指结合算法及当前每个后端服务器的负载状态进行计算调整选出最优的后端服务器进行分配负载,其包括:

1、最小连接调度算法(LCS)是指把新的连接请求分配到当前连接数最小的服务器。调度器会记录各个服务器已建立连接的数目,当一个请求被调度分配到一个后端服务器,其连接数就加一;当连接超时或终止时,其连接数减一。LCS算法则会把新的连接请求到分分配到已建立连接数最小的服务器上,保证后端服务器,每一个都始终处于工作状态。此算法适用于后端服务器性能差不多,请求时间不一样的情况下使用。

2、加权最小连接调度算法(WLC)是在一个服务器性能差异较大的集群中,根据最小连接数及服务器的权重来分配新的连接请求。对比LCS算法来说,WLC可优化负载均衡的性能,使得具有较高权重的服务器承受较大比例的活动连接负载。
3、最小期望延迟调度算法(SED)是WLC算法的改进版,根据算法(active+1)*256/weight的结果,将请求分配给计算结果最小的服务器。

4、从不排队调度(NQ),增强改进的sed算法,即在sed算法结果之后增加了轮询的机制。如果有台real Server的连接数=0直接分配,不需要再进行sed运算,而是直接分配请求连接到指定的服务器。因此这种算法就会尽量不然请求出现排队的情况,即避免了某个节点非常繁忙而其他节点相对空闲的情况。避免了权重小的节点不会出现没有请求被调度的情况。

  1. 基于本地的LC(LBLC),其实就是动态的DH算法,考虑了服务器的负载;损失了命中率,提高了均衡性;
    针对目标IP地址的负载均衡,目前主要用于cache集群系统;该算法根据请求的目标IP地址找出该目标IP地址最近使用的服务器,若改服务器是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于一半的工作负载,则用最少链接的原则选出一个可用的服务器,将请求发送到该服务器;

  2. 带复制的LBLC(LBLCR),也是针对目标IP地址的负载均衡,目前主要用于cache集群系统;它与LBLC算法的不同之处是它要维护从一个目标IP地址到一组服务器的映射,而LBLC算法维护从一个目标IP地址到一台服务器的映射;该算法根据请求的目标IP地址找出该目标IP地址对应的服务器组,按最小链接原则从服务器组中选出一台服务器,若服务器没有超载,将请求发往该服务器,若服务器超载,则按最小链接原则从这个集群中选出一台服务器,将该服务器加入到服务器组中,将请求发往该服务器;同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的程度;

二、详细描述nginx模块并举例说明

ngx_http_proxy_module模块

可实现动静分离;能够实现将请求发给后端URL指定的主机地址,这里之所以使用URL可以完成URL映射;例如前端的url为bbs,后端url可以是forum。

配置段:location, if in location, limit_except

通常其使用格式类似于:

proxy_pass [http://host[:port][/uri](http://host[:port][/uri)];

值得注意的是proxy_pass的路径后面有没有/uri是有区别的,当proxy_pass后面的路径不带uri时,其会将location的uri传递给后端主机;如:

server {

 ...

 server_name HOSTNAME;

 location /blog/ {

 proxy http://10.10.10.10;

 }

 ...

}

#上述location的/blog/会传递给10.10.10.10主机,实际代理访问的位置为http://10.10.10.10/blog/。

又如当proxy_pass后面的路径带有/uri时,其会将location的uri替换为proxy_pass的uri,如:

server {

 ...

 server_name www.a.com

 location /blog/ {

 proxy_pass http://10.10.10.10/news/;

 }

 ...

}

此时访问http://www.a.com/blog/实际上就是访问http://10.10.10.10/news/,/blog/被替换成了/news/。

此外还要注意点的是如果在location定义uri时使用了正则表达式匹配的模式,或在if语句或limt_execept中使用proxy_pass指令,则proxy_pass之后必须不能使用uri; 用户请求时传递的uri将直接附加代理到的服务的之后,如:

location ~* \.(jpg|png|gif)$ {

proxy_pass http://10.10.10.10;

}

设定向后端主机发送的请求报文的首部及其值;或是在原有首部后添加新值;

配置段:http, server, location

能抓取终端用户IP地址,field可自定义;默认为$proxy_host代理主机的IP地址;可以设定任何首部的值;

server {

 listen 80;

 server_name www.ilinux.io;

 location /blog/blog.html {

#在代理服务器上将远程客户端的Ip设置为X-Real-IP

 proxy_set_header X-Real-IP $remote_addr;

 proxy_pass http://10.10.10.11/news/news.html;

 }

}

#在后端服务器,设置access日志的格式,将原本的$remote_addr替换为$http_x_real_ip

log_format main '$http_x_real_ip - $remote_user [$time_local] "$request" '

 '$status $body_bytes_sent "$http_referer" '

 '"$http_user_agent" "$http_x_forwarded_for"';

#在测试访问几次后,查看后端服务器的access_log文件即可查看到相应的访问客户端IP

proxy_set_header X-Forwarded-For $proxy_add_x_forwared_for;

#表示如果X-Forwarded-For有首部值,会把$remote_addr的值补充在后面;为什么要补充,因为真正的代理费服务器是可以多级代理的;一个客户端可以有多级正向代理,反向代理也可有多级,这样在后端服务器日志记录的有可能不是最终用户的iP地址;所以像这种多级代理场景,每一个代理服务器都会附加一个新首部值,最终会知道最左侧的值是终端用户的iP地址;

proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];

levels参数定义了cache保留路径的层次结构,最多支持三层级结构。levels的值支持1或2,表示以多少个字符命名层级目录。如levels=1:2:3,表示缓存路径为三级目录结构,其中一级子目录以1个字符命名,二级子目录2个,三级子目录3个。
keys_zone参数用于定义cache zone的名称及分配的内存大小,如:keys_zone=cache1:100m。
max_size参数用于设置缓存zone的最大容量是多少;
inactive参数用于设置这个zone中的缓存文件如果在指定的时间内都没有被访问,则文件会被cache manager进程删除掉。

配置示例:

proxy_cache_path  /usr/local/nginx/proxy_cache_dir/cache1  levels=1:2 keys_zone=cache1:100m inactive=1d max_size=10g;
server {
    ...
    server_name HOSTNAME;
    location /uri/ {
        proxy http://hos[:port];
        proxy_cache cache1;
    }
    ...
}
    proxy_cache_valid 200 303 10m;
    proxy_cache_valid 404 1m;

响应码没定义的表示不缓存;
实例:

定义缓存:
]# vim /etc/nginx/nginx.conf
在http中定义:
proxy_cache_path /var/cache/nginx/myproxy levels=2:1:1 keys_zone=mycache:10m max_size=1g;
表示:
/var/cache/nginx/myproxy:定义缓存保存路径,如果目录不存在,要事先创建;
levels=2:1:1 创建3级缓存目录,每一级用1个字符;
max_size=1g:缓存的文件可用空间大小为1G;
keys_zone=mycache:10m:缓存名为mycache,大小为10M;

]# 

还要在server中定义调用缓存的名称:
]# vim /etc/nginx/conf.d/default.conf
    location / {
       # root   /usr/share/nginx/html;
       proxy_cache mycache;
       proxy_cache_key $request_uri;
       proxy_cache_valid 200 302 10m;
       proxy_cache_valid 404 1m;
        proxy_pass http://192.168.1.3;
        index  index.html index.htm;
    }
其中:
proxy_cache mycache 调用缓存名称;
proxy_cache_key $request_uri 指定缓存中的key为请求的uri;
proxy_cache_valid 200 302 10m 缓存响应码为200,302的资源10分钟;
proxy_cache_valid 404 1m 缓存响应码为404的资源为1分钟;
gx_http_headers_module模块

此模块用于在代理服务器响应给客户端的响应报文中添加自定义首部或修改指定首部的值。

server {
        listen 80;
        server_name www.ilinux.io;
        location /blog/blog.html {
                proxy_set_header X-Real-IP  $remote_addr;
#添加自定义首部X-via表示代理服务器IP
                add_header X-Via  $server_addr;
#添加自定义首部X-Accel表示代理服务器的主机名
                add_header X-Accel $server_name;
                proxy_pass http://10.10.10.11/news/news.html;
        }
}
#表示指定路径上的图片在客户端上缓存3天才失效
location ~* \.(gif|jpg|jpeg|png) {

root  /var/mywww/html/public/

expires 3d;

}
ngx_http_fastcgi_module模块
location ~* \.php$ {
        ....
        fastcgi_pass 10.10.10.13:9000;
        ...
}
fastcgi_index  index.php;
fastcgi_param  SCRIPT_FILENAME  /home/www/scripts/php$fastcgi_script_name;
请求uri/page.php的参数SCRIPT_FILENAME将被设置为/home/www/scripts/php/page.php,但是"/"为"/home/www/scripts/php/index.php"。
#将匹配的php内容送到fastcgi服务器的/usr/share/nginx/html目录下进行处理,即指定fastcgi服务器上用于存放PHP内容的目录
location ~* \.php$ {
    root           /usr/share/nginx/html;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  /usr/share/nginx/html$fastcgi_script_name;
    include        fastcgi_params;  #调用nginx的变量定义;
}

levels=levels:缓存目录的层级数量,以及每一级的目录数量;格式为:levels=ONE:TWO:THREE,如:leves=1:2:2。
keys_zone=name:size:指定映射的内存空间的名称及大小
inactive=time:指定缓存文件如果在指定的时间内都没有被访问,则文件会被cache manager进程删除掉。
max_size=size:指定此缓存空间的大小上限。

示例:

fastcgi_cache_path /data/nginx/cache levels=1:2 keys_zone=one:10m;
fastcgi_cache one;
location ~* \.php$ {
    ...
    fastcgi_cache fcgi;
    fastcgi_cache_key $request_uri;
    fastcgi_cache_valid 200 302 10m;  #状态码为200和302的页面内容缓存10分钟
    fastcgi_cache_valid 301 1h;
    fastcgi_cache_valid any 1m; 
    ...
}
综合示例
server {
        listen 80;
        server_name www.ilinux.io;
        index index.php index.html;
        location / {
                root /data/nginx/html;
                proxy_pass http://10.10.10.12:80; 
        }
        location ~* \.php$ {
                fastcgi_pass 10.10.10.11:9000;  #指定fastcgi服务器
                fastcgi_index index.php;  #指定默认的fastcgi主页
                include fastcgi_params;  #调用nginx的变量定义
                fastcgi_param   SCRIPT_FILENAME /data/apps/$fastcgi_script_name;  #指定fastcgi服务器上的php目录
                fastcgi_cache   fcache;  #调用fache缓存空间
                fastcgi_cache_key $request_uri;  #设置缓存的key为$request_uri
                fastcgi_cache_valid 200 302 10m;  #状态码为200和302的页面缓存10分钟
                fastcgi_cache_valid 301         1h;  #状态码为301的页面缓存1小时
                fastcgi_cache_valid any         1m;  #剩下的都缓存1分钟
                fastcgi_keep_conn on;  #开启长连接
        }
        location ~* ^/(status|ping)$ {
                fastcgi_pass 10.10.10.11:9000;
                include fastcgi_params;
                fastcgi_param   SCRIPT_FILENAME /data/apps/$fastcgi_script_name;
        }
}
ngx_http_upstream_conf_module模块

此模块用于定义能够被proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass和memcached_pass配置段所引用的服务器组。

upstream httpdsrvs {
    server 10.10.10.11:80;
    server  10.10.10.12:80;
    ...
}

unix:/PATH/TO/SOME_SOCK_FILE
IP[:PORT]
HOSTNAME[:PORT]

parameters参数包括:

weight=number
    权重,默认为1;
max_fails=number
    失败尝试最大次数;超出此处指定的次数时,server将被标记为不可用,默认为1;
fail_timeout=time
    设置将服务器标记为不可用状态的超时时长;
max_conns=number
    当前的服务器的最大并发连接数;
backup
    将服务器标记为“备用”,即所有服务器均不可用时此服务器才启用;
down
    标记为“不可用”;
upstream backend {  
    least_conn;  
  
    server backend1.example.com;  
    server backend2.example.com;  
}  
hash $request_uri consistent;
hash $remote_addr;
upstream http_backend {
    server 127.0.0.1:8080;

    keepalive 16;
}

示例2:

#对于fastcgi服务器来说,keepalive要结合fastcgi_keep_conn指令一起使用才能生效
upstream fastcgi_backend {
    server 127.0.0.1:9000;

    keepalive 8;
}

server {
    ...

    location /fastcgi/ {
        fastcgi_pass fastcgi_backend;
        fastcgi_keep_conn on;
        ...
    }
}
upsteam模块的综合示例:
##在/etc/nginx/nginx.conf文件中配置:
    upstream websrvs {
            ip_hash;
            server 10.10.10.11:80 weight=2 down;
            server 10.10.10.12:80 weight=1 fail_timeout=1 max_fails=3;
            server 127.0.0.1:80 backup;
        }

#在server配置段:
server {
        listen 80;
        server_name www.ilinux.io;
        location / {
                root /data/nginx/html;
                proxy_pass http://websrvs;
        }
}
ngx_stream_core_module

此模块用于模拟反代基于tcp或udp的服务连接,即工作于四层传输层的反代或调度器。

#可在一个stream中配置upstream服务器组和server配置段
stream {
    upstream sshsrvs {
        server 192.168.22.2:22; 
        server 192.168.22.3:22; 
        least_conn;
    }
    server {
        listen 10.1.0.6:22022;
        proxy_pass sshsrvs;
    }
}

其他的指令与其他模块所使用的指令类似。

详细的指令使用可参考链接:http://nginx.org/en/docs/stream/ngx_stream_core_module.html#proxy_protocol_timeout

上一篇下一篇

猜你喜欢

热点阅读