使用nginx做负载均衡的模块解读
使用nginx做负载均衡的两大模块:
- upstream定义负载节点池。
- location模块进行URL匹配。
- proxy模块发送请求给upstream定义的节点池。
upstream模块解读
nginx的负载均衡功能依赖于ngx_http_upstream_module模块,所支持的代理方式有proxy_pass(一般用于反向代理),fastcgi_pass(一般用于和动态程序交互),memcached_pass,proxy_next_upstream,fastcgi_next_pass,memcached_next_pass。
upstream模块应该放于http{}标签内。
模块写法:
upstreambackend{ ip_hash; serverbackend1.example.comweight=5; serverbackend2.example.com:8080; serverbackup1.example.com:8080backup; serverbackup2.example.com:8080backup; }
实例一:
upstreamdynamic{ zoneupstream_dynamic64k; serverbackend1.example.comweight=5; serverbackend2.example.com:8080fail_timeout=5sslow_start=30s; server192.0.2.1max_fails=3; serverbackend3.example.comresolve; serverbackup1.example.com:8080backup; serverbackup2.example.com:8080backup; }
语法解释:
nginx默认支持四种调度算法
- 轮询(rr),每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器故障,故障系统自动清除,使用户访问不受影响。
- 轮询权值(weight),weight值越大,分配到的访问几率越高,主要用于后端每个服务器性能不均的情况。
- ip_hash,每个请求按访问IP的hash结果分配,这样来自同一个IP的固定访问一个后端服务器,主要解决动态网站session共享的问题。
- url_hash,按照访问的URL的hash结果来分配请求,是每个URL定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率,nginx本身不支持,如果想使用需要安装nginx的hash软件包。
- fair,这个算法可以依据页面大小和加载时间长短智能的进行负载均衡,也就是根据后端服务器的响应时间来分配请求,相应时间短的优先分配,默认不支持,如果想使用需要安装upstream_fail模块。
- least_conn最少链接数,那个机器连接数少就分发。
server模块的写法
serverIP调度状态
server指令指定后端服务器IP地址和端口,同时还可以设定每个后端服务器在负载均衡调度中的状态。
- down表示当前的server暂时不参与负载均衡。
- backup预留的备份服务器,当其他所有的非backup服务器出现故障或者忙的时候,才会请求backup机器,因为这台集群的压力最小。
- max_fails允许请求失败的次数,默认是1,当超过最大次数时,返回proxy_next_upstream模块定义的错误。0表示禁止失败尝试,企业场景:2-3.京东1次,蓝汛10次,根据业务需求去配置。
fail_timeout,在经历了max_fails次失败后,暂停服务的时间。京东是3s,蓝汛是3s,根据业务需求配置。常规业务2-3秒合理。
例:如果max_fails是5,他就检测5次,如果五次都是502.那么,他就会根据fail_timeout的值,等待10秒,再去检测。
server如果接域名,需要内网有DNS服务器,或者在负载均衡器的hosts文件做域名解析。server后面还可以直接接IP或IP加端口。
长连接keepalive
upstreambackend{ serverbackend2.example.com:8080; serverbackup1.example.com:8080backup; keepalive100; }
通过该指令配置了每个worker进程与上游服务器可缓存的空闲连接的最大数量。
当超出这个数量时,最近最少使用的连接将被关闭。keepalive指令不限制worker进程与上游服务器的总连接。
location/{ #支持keep-alive proxy_http_version1.1; proxy_set_headerConnection""; proxy_passhttp://backup; }
- 如果是http/1.0需要配置发送"Connection:Keep-Alive"请求头。
- 上游服务器不要忘记开启长连接支持。
连接池配置建议
- 总长连接数是"空闲连接池"+"释放连接池"的长连接总数。
- 首先,长连接配置不会限制worker进程可以打开的总连接数(超了的作为短连接)。另外连接池一定要根据场景合理进行设置。
空闲连接池太小,连接不够用,需要不断建连接。
空闲连接池太大,空闲连接太多,还没使用就超时。
建议只对小报文开启长连接。
location模块解读
location作用:基于一个指令设置URI。
基本语法:
Syntax:location[=|~|~*|^~]uri{...} location@name{...} Default:— Context:server,location
- =精确匹配,如果找到匹配=号的内容,立即停止搜索,并立即处理请求(优先级最高)
- ~区分大小写
- ~*不区分大小写
- ^~只匹配字符串,不匹配正则表达式
- @指定一个命名的location,一般用于内部重定义请求,location@name{…}
匹配是有优先级的,不是按照nginx的配置文件进行。
官方的例子:
location=/{ [configurationA] } location/{ [configurationB] } location/documents/{ [configurationC] } location^~/images/{ [configurationD] } location~*\.(gif|jpg|jpeg)${ [configurationE] }
结论:
- /匹配A。
- /index.html匹配B
- /documents/document.html匹配C
- /images/1.gif匹配D
- /documents/1.jpg匹配的是E。
测试用的例子:
location/{ return401; } location=/{ return402; } location/documents/{ return403; } location^~/images/{ return404; } location~*\.(gif|jpg|jpeg)${ return500; }
测试结果(重点看):
[root@lb01conf]#curl-I-s-o/dev/null-w"%{http_code}\n"http://10.0.0.7/ 402 [root@lb01conf]#curl-I-s-o/dev/null-w"%{http_code}\n"http://10.0.0.7/index.html 401 [root@lb01conf]#curl-I-s-o/dev/null-w"%{http_code}\n"http://10.0.0.7/documents/document.html 403 [root@lb01conf]#curl-I-s-o/dev/null-w"%{http_code}\n"http://10.0.0.7/images/1.gif 404 [root@lb01conf]#curl-I-s-o/dev/null-w"%{http_code}\n"http://10.0.0.7/dddd/1.gif 500
结果总结:
匹配的优先顺序,=>^~(匹配固定字符串,忽略正则)>完全相等>~*>空>/。
工作中尽量将'='放在前面
proxy_pass模块解读
proxy_pass指令属于ngx_http_proxy_module模块,此模块可以将请求转发到另一台服务器。
写法:
proxy_passhttp://localhost:8000/uri/;
实例一:
upstreamblog_real_servers{ server10.0.0.9:80weight=5; server10.0.0.10:80weight=10; server10.0.0.19:82weight=15; } server{ listen80; server_nameblog.etiantian.org; location/{ proxy_passhttp://blog_real_servers; proxy_set_headerhost$host; } }
- proxy_set_header:当后端Web服务器上也配置有多个虚拟主机时,需要用该Header来区分反向代理哪个主机名,proxy_set_headerhost$host;。
- proxy_set_headerX-Forwarded-For:如果后端Web服务器上的程序需要获取用户IP,从该Header头获取。proxy_set_headerX-Forwarded-For$remote_addr;
配置后端服务器接收前端真实IP
配置如下:
log_formatcommonlog'$remote_addr-$remote_user[$time_local]"$request"' '$status$body_bytes_sent"$http_referer"' '"$http_user_agent""$http_x_forwarded_for"';
rs_apache节点的httpd.conf配置
LogFormat"\"%{X-Forwarded-For}i\"%l%u%t\"%r\"%>s%b\"%{Referer}i\"\"%{U ser-Agent}i\""combined修改日志记录 apache LogFormat"\"%{X-Forwarded-For}i\"%l%u%t\"%r\"%>s%b"common
proxy_pass相关的优化参数
- client_max_body_size10m;允许客户端请求的最大的单个文件字节数。
- client_body_buffer_size128k;缓冲区代理缓冲用户端请求的最大字节数可以理解为先保存到本地再传给用户。
- proxy_connect_timeout600;跟后端服务器连接的超时时间_发起握手等候响应超时时间。
- proxy_read_timeout600;连接成功后_等候后端服务器响应时间_其实已经进入后端的排队之中等候处理。
- proxy_send_timeout600;后端服务器回传数据时间,就是在规定时间之内后端服务器必须传完所有的数据。
- proxy_buffer_size8k;代理请求缓存区,这个缓存区间会保存用户的头信息以供Nginx进行规则处理,一般只要设置能保存下头信息即可。
- proxy_buffers432k;同上告诉Nginx保存单个页面使用的空间大小,假设网页大小平均在32k以下的话。
- proxy_busy_buffers_size64k;如果系统很忙的时候可以申请更大的proxy_buffers官方推荐(proxy_buffers*2)。
- proxy_max_temp_file_size1024m;当proxy_buffers放不下后端服务器的响应内容时,会将一部分保存到硬盘的临时文件中,这个值用来设置最大临时文件大小,默认1024M,它与proxy_cache没有关系。大于这个值,将从upstream服务器传回。设置为0禁用。
- proxy_temp_file_write_size64k;proxy缓存临时文件的大小proxy_temp_path(可以在编译的时候)指定写到哪那个目录。
健康检查
Nginx提供了health_check语句来提供负载(upstream)时的键康检查机制(注意:此语句需要设置在location上下文中)。
支持的参数有:
- interval=time:设置两次健康检查之间的间隔值,默认为5秒
- fails=number:设置将服务器视为不健康的连续检查次数,默认为1次
- passes=number:设置一个服务器被视为健康的连续检查次数,默认为1次
- uri=uri:定义健康检查的请求URI,默认为”/“
- match=name:指定匹配配置块的名字,用记测试响应是否通过健康检测。默认为测试返回状态码为2xx和3xx
一个简单的设置如下,将使用默认值:
location/{ proxy_passhttp://backend; health_check; }
对就应用,我们可以专门定义一个API用于健康检查:/api/health_check,并只返回HTTP状态码为200。并设置两次检查之间的间隔值为1秒。这样,health_check语句的配置如下:
health_checkuri="/api/health_check"interval;
匹配match的方法
http{ server{ ... location/{ proxy_passhttp://backend; health_checkmatch=welcome; } } matchwelcome{ status200; headerContent-Type=text/html; body~"Welcometonginx!"; } }
match例子举例
- status200;:status等于200
- status!500;:status不是500
- status200204;:status是200或204
- status!301302;:status不是301或302。
- status200-399;:status在200到399之间。
- status!400-599;:status不在400到599之间。
- status301-303307;:status是301,302,303,或307。
- headerContent-Type=text/html;:“Content-Type”得值是text/html。
- headerContent-Type!=text/html;:“Content-Type”不是text/html。
- headerConnection~close;:“Connection”包含close。
- headerConnection!~close;:“Connection”不包含close。
- headerHost;:请求头包含“Host”。
- header!X-Accel-Redirect;:请求头不包含“X-Accel-Redirect”。
- body~"Welcometonginx!";:body包含“Welcometonginx!”。
- body!~"Welcometonginx!";:body不包含“Welcometonginx!”。
一个完整的nginx实例
[root@lb01conf]#catnginx.conf worker_processes1; events{ worker_connections1024; } http{ includemime.types; default_typeapplication/octet-stream; sendfileon; keepalive_timeout65; #bloglbbyoldboyat201303 upstreamblog_real_servers{ server10.0.0.9:80weight=1max_fails=1fail_timeout=10s; server10.0.0.10:80weight=1max_fails=2fail_timeout=20s; } server{ listen80; server_nameblog.etiantian.org; location/{ proxy_passhttp://blog_real_servers; includeproxy.conf; } } } [root@lb01conf]#catproxy.conf proxy_set_headerHost$host; proxy_set_headerX-Forwarded-For$remote_addr; proxy_connect_timeout90; proxy_send_timeout90; proxy_read_timeout90; proxy_buffer_size4k; proxy_buffers432k; proxy_busy_buffers_size64k;proxy_temp_file_write_size64k;
扩展补充
只允许使用GET,HEAD,POST方法去请求
##Onlyallowtheserequestmethods## if($request_method!~^(GET|HEAD|POST)$){ return444; }
实战
根据URI及location实现动静分离。
最终实现:
- /static/的URL都去访问10.0.0.9。
- /dynamic/的URL都去访问10.0.0.10。
- 图片这些静态文件去访问10.0.0.9。
- /upload/的URL都去访问10.0.0.10。
[root@lb01conf]#catnginx.conf worker_processes1; events{ worker_connections1024; } http{ includemime.types; default_typeapplication/octet-stream; sendfileon; keepalive_timeout65; #bloglbbyoldboyat201303 upstreamstatic_pools{ server10.0.0.9:80; } upstreamdynamic_pools{ server10.0.0.10:80; } upstreamupload_pools{ server10.0.0.9:80; } server{ listen80; server_nameblog.biglittleant.cn; location/{ proxy_passhttp://static_pools; includeproxy.conf; } location/static/{ proxy_passhttp://static_pools; includeproxy.conf; } location~*\.(gif|jpg|jpeg)${ proxy_passhttp://static_pools; includeproxy.conf; } location/dynamic/{ proxy_passhttp://dynamic_pools; includeproxy.conf; } location/upload/{ proxy_passhttp://upload_pools; includeproxy.conf; } } }
实现苹果手机和安卓手机访问不同的地址
server{ listen80; server_nameblog.etiantian.org; location/{ if($http_user_agent~*"android") { proxy_passhttp://android_pools; } if($http_user_agent~*"iphone") { proxy_passhttp://iphone_pools; } proxy_passhttp://pc_pools; includeextra/proxy.conf; } access_logoff; }
参考文档
nginx-proxy_pass官网
到此这篇关于使用nginx做负载均衡的模块解读的文章就介绍到这了,更多相关nginx负载均衡内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!