Nginx的负载均衡是基于反向代理实现的,因此,本文先讨论什么是反向代理,再在这个的基础上讨论负载均衡以及负载均衡时应该注意哪些策略。 反向代理:如下图所示,
2 J6 D( Z# t! n9 }
↓-----Nginx将结果返回给浏览器---丨 对Tomcat来说,只知道服务对象是Nginx服务器 浏览器 -发起对该域的访问请求-> Nginx --------------Nginx将请求来转发给Tomcat服务器----> Tomcat... 丨-对Tomcat来说,只对nginx负责,将结果返回给Nginx服务器---↑
* q7 \) o& j7 Z& |/ ^. X从图中,我们可以知道,对于浏览器来说,他会发一个http://www.a.com/uri请求到Nginx服务器,对于他来说,他认为数据就是从http://www.a.com/uri域中返回的,事实上,当http://www.a.com/uri到达Nginx服务器后,Nginx服务器会将其转发给http://www.b.com/uri,从http://www.b.com/uri域中取得数据并将其返回给浏览器,这个步骤浏览器是不知道的,也就是说,浏览器并不知道http://www.b.com/uri该域的存在,同理,http://www.b.com/uri所在的域(图中的Tomcat)也并不知道浏览器的存在,他也只对Nginx负责。Nginx的这么一个过程便称为反向代理。9 h }0 Q/ k5 g, M3 ?
$ N g5 e5 T/ B( Q, D
那么,Nginx服务器是如何实现这一步的呢,事实上也很简单,只需要在location中做一下简单的配置即可,命令大概如下图所示:(配置完命令记得reload重新加载才能生效)# H+ [5 M( \. ~! ~; E Z
/ r9 P3 h/ Y3 ~ K) p: ~% j6 F0 U" J3 b" e* w$ Q7 A
- worker_processes 1;
3 G' V: \9 l4 y& J* V - events{
复制代码
, ^7 f" c& N6 X4 @: j
) ?; G" a2 @# z. ], g, ~' B重点在于location处,这样的配置代表的是,所有来自浏览器的请求,在Nginx收到之后,都会代理到http://192.168.1.62:8080所在的地方
! f' W6 t) n9 J. p6 N" b
' x" Q9 u3 D$ V5 p( O# n比如,我浏览器上发起http://192.168.1.61/a/index.html;Nginx收到之后,将会发出http:// 192.168.1.62:8080/a/index.html这么一个请求到所连接的服务器上,如上图的Tomcat。- i: [# o; u# L# i7 b
, N, y7 s0 C4 S' g$ Q- K, i. O) e% p) w
接下来我们做这样一个假设,假如后端连接着几台。几十台服务器呢,这个时候Nginx也是做同样的代理吗,答案是肯定的。图示如下:那么,在这么多台服务器上,Nginx的转发又是基于怎样的策略呢?这个时候就涉及在负载均衡了,说白了就是,应该怎样的分发,才能做到资源的最大限度的利用?3 f' c( w3 B+ ?% G8 }. j
: T& @$ }/ ?4 L' x) t6 X( t) B) U! L
3 |' j* {/ [+ r8 z+ b9 |! b8 U- s
$ n& x0 d5 j2 ^9 L9 |# P
1 S2 p/ _1 R, c' T' W) M. h负载均衡策略( 我们这里假设三台服务器的IP地址分别为 http:// 192.168.1.62:8080 http:// 192.168.1.63:8080 http:// 192.168.1.64:8080 ) 1. 平均轮询配置如下图: - l9 m. f+ W1 D. \3 s/ L
6 x3 x- M, x; I. @, Y6 |$ R; B! h* }6 W* w8 `2 E0 k+ S
这里我们把后台所有的服务器放入upstream中,并在代理中进行引用。( Y* [/ z5 j/ W, W! f. @
2. 加权轮询,使用weight参数设置,配置如下; Q( @( m6 p: l; i* M. t
( b( k; L# V0 s7 L) E1 E3. ip_hash策略7 y$ t" H. s1 r; V) a6 }
(根据用户的IP地址进行hash运算,只要是同个用户发的请求,就会被永远地转发在某台服务器上,比如张三发的请求第一次时是由Tomcat1返回的,李四的是有Tomcat2返回的,那么,以后张三的所有请求,都有由Tomcat1返回,这就是ip_hash策略),配置如下:
; X, Z5 g* @, o g* l 其他地方保持不变,在upstreaem中如下设置:( k7 k7 e$ o* o
F& A( s; s+ J1 ~6 u o' {9 i0 s) |% {0 _" J# \
5 u5 t8 k% D# ~5 i) a' R$ g; g4 Y) s1 q' ]6 i% U1 A- U( ?
4. fair策略
2 ^5 Q- M/ K* C; s+ n* z- y& Q, z: D(动态weight策略,我们的加权轮询是显式指定weight的,而fair策略是根据服务器的响应能力进行动态指定的,而意义上讲,我觉得是更为智能化的解决方法,不过这里要记住一点,fair策略是一个第三方策略)& P" g8 l4 A# }0 v, L" t% U$ ?$ L- L
5. url_hash策略
6 T: L/ d, u) w; Z" M! `# E5 C( w2 f3 J* r' O3 \! o# T! R$ Y6 q [
(类似于ip,只不过绑定的值是url,这个也是第三方策略)
, j9 d" E/ _" D: I3 L) x7 Hfair策略与url_hash策略的配置与ip_hash策略的类似,直接把upstream tomcats 中的ip_hash替换为fair和url_hash即可,不过这里需要注意的是fair和url_hash都是第三方扩展,因此需要先安装第三方扩展模块,直接百度搜索nginx-upstream-fair-master.zip与upstream-url-hash -master.zip;解压安装使用make&&make install重新编译源文件即可
7 F' W/ Y9 L0 y1 ~3 G
6 Z" d, U. g$ b. o B* u5 k% e3 l D5 ]% W
0 H3 Z% Q% r- o8 A$ i
url_hash策略的用处?' |& ?) D" Y& b! S9 X R/ D& U1 H
9 f0 N/ I" r' q% q" ?url_hash策略比较适合于大型电子商务网站,对于不同的商品便是不同的url,我们可以据此进行负载均衡。1 |. ?# {( Q4 C6 x9 Z- Q+ _7 b6 m- ^
2 E! y" A5 O" `
原理就是不同的商品形成不同的静态页面,然后服务器根据不同商品的火爆程度,按照命中率高的放在缓存里,加快访问速度,也就是说实现了一个基于缓存的服务器,相当于把有限的缓存最优化起来;' C7 y; h; d7 {; Z/ {8 s
9 B; ]+ t' S: A+ I ^ w1 ^
. o) A; D c% x- l: L$ m) ]
6 Q; E5 G6 ~. q V( Q其他的配置# S+ @& I0 S+ }' v' i. L# P2 d8 h. {
备份与停机状态:
' C) \+ Y t0 ^& }- I# }server 192.168.1.64 backup;//备份,不参与转发,只有当所有服务器都挂掉时才参与转发;
0 m2 p5 X% V6 o8 [2 V! [
) W, v7 f/ e2 `- Userver 192.168.1.65 down;//临时停机维护,不参与任何转发,是关闭状态,# ~2 N- L8 K. @; `2 E0 @+ h9 ]9 \. g4 h
) H9 m' L! j% v2 E
down存在的意义在于,有时我们需要对服务器做临时停机更新维护,假如我们直接关闭服务器的话,那么对于Nginx来说,他还是会把请求发到该服务器上的,因为他并不知道服务器已关,而设置down后,Nginx则不会再发到该服务器上了,避免造成无用的请求浪费。3 L5 C% B& A1 x) X
, l& h7 ?7 z( j) k$ \4 `4 _& c% f
& M8 T7 Q! A2 [9 H& _( U
# \' u9 p( D; K' `/ _# D1 g( E
max_fails: 达到指定次数后认为服务器挂掉2 u; Z% n# R9 ?) q8 M
' o9 A' H- |4 D
fail_timeout:挂掉多久后再次测试是否已经挂掉: l" H1 m o2 z' V. B R8 ^' B/ ?+ Y ?
7 v% G, s( G& C$ Y: ?& t) L$ `$ w配置命令
# o# T- W8 H+ R; j2 d/ j/ y9 A- L% j! h# M! H
server 192.168.1.66 max_fails=2 fail_timeout=60s;8 \6 H; X% b4 v. ?& q9 @& |
$ U5 ?# C( a2 c' X3 c. y0 C 后记" z! R9 \" a+ m. c" q4 q& j* b
我们知道,服务器是会存储用户的session的,那么,如果按照上文所说的,比如fair策略,每次Nginx会根据后端服务器群的能力把请求分发出去,那假如第一次时分在了A,那么我把数据存储到了A服务器上,第二次时,刚好被分配到了B服务器上,那么问题来了,我的session不就不见了?(这就是我们在访问部分网站时有时我们的登录状态会不见)当然了,你可能 会说,ip_hash策略不就可以避免这一点吗?没错,这确实是一个解决方法,那除了ip_hash呢?其他策略下又当如何呢?下篇博客将会讲到负载均衡下如何对session进行处理。2 [( I/ p: s! U
" C6 U/ }- f' m1 O: v
) z ]5 i; X3 S& v- V7 i+ s& |/ _+ ^2 l/ g
) _, y, D) A1 ` O6 S: O5 C9 `' _8 y- A& B2 t+ b
0 h6 D& B1 G* e- s- A0 I8 p |