本文是生产环境中的一个案例,主要是为了通过反向代理实现多条线路容灾。在原有的基础上升级了openssl,openssh,nginx,通过一些模块来实现我们的需求。

正常情况下,反向代理会去请求online下面的主机,使用sticky模块实现session粘连。如果online的下面的主机全部挂掉了,这个时候,它会去出502报错(或404,具体与你的环境有关),此时它会启用下failover下面的主机,以实现线路容灾。具体的容灾方式,你可以选择多个。比如使用backup来进行标识。使用了nginx_upstream_check_module进行后端的主机健康检查。

 
  
  1. 重新部署新应用nginx 
  2.  
  3. 1、升级openssh 
  4. 2、升级nginx 
  5. 3、增加nignx模块 
  6.  
  7. 本次升级主要是从容灾的角度和反向代理安全性的角度考虑.通过升级openssh,避免一些低版本漏洞。 
  8. 添加nginx的一些常规支持: 
  9. a、支持多个SSL证书 
  10. b、支持反端http 健康检查 
  11. c、支持session 粘滞 nginx-sticky-module //支持sticky+rr ,sticky+weight  
  12. d、通过nginx的权重+粘滞实现多线路容灾 
  13. e、添加geoip模块支持,未来考虑智能CDN+GeoIP配合(在nginx前端对来源IP,判断从哪个机房取数据) 
  14.  
  15.  
  16. 安装telnet服务器: 
  17. #yum install -y telnet-server telnet 
  18.  
  19. 编译托管的服务 
  20.  
  21. # chkconfig telnet on  
  22. # /etc/init.d/xinetd restart 
  23. Stopping xinetd:                                           [FAILED] 
  24. Starting xinetd:                                           [  OK  ] 
  25.  
  26. # netstat -tnlp  
  27. Active Internet connections (only servers) 
  28. Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name    
  29. tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      2632/sshd            
  30. tcp        0      0 0.0.0.0:23                  0.0.0.0:*                   LISTEN      21977/xinetd  
  31.  
  32. //在防火墙中加入自己的IP允许23的规则 
  33.  
  34. 建立普通用户进行登录 
  35. # useradd sshinstall 
  36. # echo "123456@sshinstall" | passwd --stdin sshinstall 
  37. Changing password for user sshinstall. 
  38. passwd: all authentication tokens updated successfully. 
  39.  
  40. 将该用户加入到sudo组里 
  41. echo "sshinstall ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers 
  42.  
  43. 开始安装包了 
  44. # tar -xzf openssl-1.0.1c.tar.gz  
  45. # cd openssl-1.0.1c 
  46. # ./config enable-tl***t  --prefix=/usr/local/openssl-1.0.0c 
  47. # make  
  48. # make test 
  49. # make install 
  50.  
  51. # echo /usr/local/openssl-1.0.0c/lib/ >> /etc/ld.so.conf  
  52. # ln -s /usr/local/openssl-1.0.0c/ /usr/local/openssl 
  53.  
  54. echo ' 
  55. PATH=/usr/local/openssl/bin:$PATH 
  56. export PATH' >>   /etc/profile 
  57.  
  58. # source /etc/profile  
  59. # openssl version -a 
  60. OpenSSL 1.0.1c 10 May 2012 
  61. built on: Fri Jan  4 00:32:23 CST 2013 
  62. platform: linux-x86_64 
  63. options:  bn(64,64) rc4(16x,int) des(idx,cisc,16,int) idea(int) blowfish(idx)  
  64. compiler: gcc -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -Wa,--noexecstack -m64 -DL_ENDIAN -DTERMIO -O3 -Wall -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM 
  65. OPENSSLDIR: "/usr/local/openssl-1.0.0c/ssl 
  66.  
  67. 开始删除openssh  
  68. # rpm -e openssh-server-4.3p2-41.el5 --nodeps 
  69. # rpm -e openssh-4.3p2-41.el5 --nodeps 
  70. # rpm -e openssh-askpass-4.3p2-41.el5 --nodeps 
  71. # rpm -e openssh-clients-4.3p2-41.el5 --nodeps 
  72.  
  73. # rm -rf /etc/ssh/ 
  74.  
  75. 开始安装openssh 
  76. # tar -xzf openssh-6.1p1.tar.gz 
  77. # cd openssh-6.1p1  
  78. # ./configure --prefix=/usr --sysconfdir=/etc/ssh --with-pam --with-ssl-dir=/usr/local/openssl-1.0.0c --with-md5-passwords --mandir=/usr/share/man  
  79. # make 
  80. # make install  
  81.  
  82. 将sshd加入到服务列表里面去 
  83.  
  84. # cp ./contrib/redhat/sshd.init /etc/init.d/sshd 
  85. # chmod u+x /etc/init.d/sshd 
  86. # chkconfig --add sshd 
  87. # chkconfig sshd on 
  88. # service sshd start 
  89. Starting sshd:  OK  ] 
  90. # ssh -v 
  91. OpenSSH_6.1p1, OpenSSL 1.0.1c 10 May 2012 
  92.  
  93. 关掉telnetserver,删除sshinstall用户 
  94. # chkconfig telnet off 
  95. # /etc/init.d/xinetd restart 
  96. Stopping xinetd:                                           [  OK  ] 
  97. Starting xinetd:                                           [  OK  ] 
  98. # netstat -tnlp  
  99. Active Internet connections (only servers) 
  100. Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name    
  101. tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      29602/sshd           
  102.  
  103. # userdel -r sshinstall  
  104.  
  105. 安装Nginx 
  106. # tar zxvf libunwind-0.99.tar.gz 
  107. # cd libunwind-0.99/ 
  108. CFLAGS=-fPIC ./configure && make CFLAGS=-fPIC 
  109. # make CFLAGS=-fPIC install 
  110.  
  111. # tar xzf google-perftools-1.6.tar.gz 
  112. # cd google-perftools-1.6 
  113. # ./configure  
  114. # make && make install  
  115.  
  116. # tar -xzf pcre-8.12.tar.gz  
  117. # cd pcre-8.12 
  118. # ./configure && make && make install  
  119.  
  120. 安装geoip 
  121. # wget http://geolite.maxmind.com/download/geoip/api/c/GeoIP.tar.gz 
  122. # tar -xzf GeoIP.tar.gz  
  123. # cd GeoIP-1.4.8/ 
  124. # ./configure && make && make install 
  125. # wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz 
  126. # gunzip GeoIP.dat.gz  
  127. # echo '/usr/local/lib' > /etc/ld.so.conf.d/geoip.conf 
  128. # ldconfig 
  129.  
  130. 解压各个模块,在安装nginx时,加入该模块 
  131. # unzip nginx_upstream_jvm_route.zip    //tomcat session 
  132. Archive:  nginx_upstream_jvm_route.zip 
  133.    creating: nginx-upstream-jvm-route/ 
  134.    creating: nginx-upstream-jvm-route/nginx_upstream_jvm_route/ 
  135.   inflating: nginx-upstream-jvm-route/nginx_upstream_jvm_route/CHANGES   
  136.   inflating: nginx-upstream-jvm-route/nginx_upstream_jvm_route/config   
  137.   inflating: nginx-upstream-jvm-route/nginx_upstream_jvm_route/jvm_route.patch   //补丁文件,需要手工进行执行 
  138.   inflating: nginx-upstream-jvm-route/nginx_upstream_jvm_route/ngx_http_upstream_jvm_route_module.c   
  139.   inflating: nginx-upstream-jvm-route/nginx_upstream_jvm_route/README   
  140.  
  141. # unzip master.zip  //nginx_upsteam check_module 
  142. # tar -xzf nginx-sticky-module-1.1.tar.gz  //session 
  143. # tar -xzf nginx-1.2.6.tar.gz    
  144. # cd nginx-1.2.6 
  145. 开始打补丁了 
  146. # patch -p0 < /root/upgrade/nginx-upstream-jvm-route/nginx_upstream_jvm_route/jvm_route.patch  
  147. patching file src/http/ngx_http_upstream.c 
  148. Hunk #1 succeeded at 4117 (offset 380 lines). 
  149. Hunk #3 succeeded at 4249 (offset 380 lines). 
  150. Hunk #5 succeeded at 4348 (offset 380 lines). 
  151. patching file src/http/ngx_http_upstream.h 
  152. Hunk #1 succeeded at 90 (offset 5 lines). 
  153. Hunk #3 succeeded at 118 (offset 5 lines). 
  154.  
  155. # patch -p1 < /root/upgrade/nginx_upstream_check_module-master/check_1.2.6+.patch  
  156. patching file src/http/modules/ngx_http_upstream_ip_hash_module.c 
  157. patching file src/http/modules/ngx_http_upstream_least_conn_module.c 
  158. patching file src/http/ngx_http_upstream_round_robin.c 
  159. patching file src/http/ngx_http_upstream_round_robin.h 
  160.  
  161. # ./configure --prefix=/usr/local/nginx  --user=nobody --group=nobody  --with-http_stub_status_module --with-http_gzip_static_module --with-http_realip_module --with-http_sub_module --with-http_geoip_module  --with-http_ssl_module  --with-http_ssl_module --with-openssl=/root/upgrade/openssl-1.0.1c --with-pcre=/root/upgrade/pcre-8.12 --add-module=/root/upgrade/nginx-upstream-jvm-route/nginx_upstream_jvm_route/  --add-module=/root/upgrade/nginx_upstream_check_module-master/ --add-module=/root/upgrade/nginx-sticky-module-1.1/ --with-google_perftools_module 
  162. # make && make install  
  163.  
  164. # /usr/local/nginx/sbin/nginx -v 
  165. nginx version: nginx/1.2.6 
  166.  
  167. 如果你的nginx是正常运行的,请对当前nginx进行在线升级. 
  168. # ps aux | grep master 
  169. root     13589  0.0  0.0  26772  3884 ?        S     2012   0:01 nginx: master process /usr/local/nginx/sbin/nginx 
  170. root     20834  0.0  0.0  61140   768 pts/4    S+   17:14   0:00 grep master 
  171.  
  172. 进程替换 
  173. # kill -USR2 13589 
  174. # ps aux | grep master 
  175. root     13589  0.0  0.0  26772  3884 ?        S     2012   0:01 nginx: master process /usr/local/nginx/sbin/nginx 
  176. root     21395  0.5  0.0  40272  3504 ?        S    17:16   0:00 nginx: master process /usr/local/nginx/sbin/nginx 
  177. root     21416  0.0  0.0  61140   768 pts/4    S+   17:16   0:00 grep master 
  178.  
  179. # kill -WINCH 13589   //发送WINCH信号到旧的nginx主进程以杀掉旧的nginx子进程 
  180. # kill -QUIT 13589  // 退出旧的nginx主进程  
  181. # ps aux |grep master 
  182. root     21395  0.0  0.0  40272  3504 ?        S    17:16   0:00 nginx: master process /usr/local/nginx/sbin/nginx 
  183. root     21749  0.0  0.0  61140   772 pts/4    S+   17:16   0:00 grep master 
  184.  
  185. 删除老的版本 
  186. # rm -rf /usr/local/nginx/sbin/nginx.old  
  187. 查看当前版本 
  188. # /usr/local/nginx/sbin/nginx -v 
  189. nginx version: nginx/1.2.6 
  190.  
  191. 完成所以安装,收工! 
  192. # /usr/local/nginx/sbin/nginx -V 
  193. nginx version: nginx/1.2.6 
  194. built by gcc 4.1.2 20080704 (Red Hat 4.1.2-52) 
  195. TLS SNI support enabled  //用于支持SSL多域名证书的哟 
  196. configure arguments: --prefix=/usr/local/nginx --user=nobody --group=nobody --with-http_stub_status_module --with-http_gzip_static_module --with-http_realip_module --with-http_sub_module --with-http_geoip_module --with-http_ssl_module --with-http_ssl_module --with-openssl=/root/upgrade/openssl-1.0.1c --with-pcre=/root/upgrade/pcre-8.12 --add-module=/root/upgrade/nginx-upstream-jvm-route/nginx_upstream_jvm_route/ --add-module=/root/upgrade/nginx_upstream_check_module-master/ --add-module=/root/upgrade/nginx-sticky-module-1.1/ --with-google_perftools_module 
  197.  
  198. 环境验证: 
  199. 前端一台反向代理,后端两台异地机房(A\B机房),A机房具有较高的带宽、B机房作为备用机房。 
  200. 要求: 正常情况下,访问全部走A机房,在A机房不可用时,全部访问走B机房。理论上我们不需要进行session粘滞便可以轻松实现。但基于未来多机房分布,session粘滞还是必须需要的。那么当前情况下,我有两个模块nginx_upstream_jvm_route(需要配置tomcat\resin等,应用环境有限),nginx-sticky-module-1.1. 根据不同情况使用。 
  201.  
  202. 目前可以分为两种情况: 
  203. 1、只有一条主线路和一条备线路 
  204. 要求: 在主线路可以使用时,尽量使用主线路,备线路在主线路故障时使用。 
  205. 实际情况: A机房一线主线路,B机房一条备用线路(因为线路质量差,所以备用)
  206. 具体配置如下: 
  207. upstream.conf 
  208. // 
  209.         upstream online { 
  210.         server 172.28.10.161:8080 max_fails=0 fail_timeout=3s ; 
  211.         server 172.28.10.163:8080  backup; 
  212.      
  213.         check interval=3000 rise=2 fall=1 timeout=1000 type=http
  214.         check_http_send "GET / HTTP/1.0\r\n\r\n"; 
  215.         check_http_expect_alive http_2xx http_3xx; 
  216.         } 
  217.  
  218. 2、有多条主线路和一条备线路 
  219. 要求: 多条主线路进行负载均衡,在所有主线路都故障时,使用备用线路. 
  220. 实际情况:A、C两条线路进行负载均衡、B线路最终备用线路. 
  221. 具体配置如下: 
  222. server.conf 
  223. // 
  224. server { 
  225.         ...... 
  226.         location / { 
  227.         proxy_pass http://online; 
  228.         } 
  229.         error_page  404 502 = @backup; //加502的原因是因为线上系统在online里的upstream全部挂掉时,页面会报502,并不是404 
  230.          
  231.         location @failover { 
  232.             proxy_pass http://backup; 
  233.         } 
  234.  
  235.         location /status { 
  236.                 check_status; 
  237.                 access_log   off; 
  238.                 allow all;  //生产环境请允许特定IP访问 
  239.         } 
  240.         ...... 
  241.  
  242. upstream.conf 
  243. // 
  244.     proxy_next_upstream  http_404 http_502;  //让404报错进入max_fails计数 
  245.         upstream online { 
  246.         sticky; 
  247.         server 172.28.70.161:8080 max_fails=0 fail_timeout=3s ; 
  248.         server 172.28.70.163:8080  max_fails=0 fail_timeout=3s ; 
  249.      
  250.         check interval=3000 rise=2 fall=1 timeout=1000 type=http
  251.         check_http_send "GET / HTTP/1.0\r\n\r\n"; 
  252.         check_http_expect_alive http_2xx http_3xx; 
  253.         } 
  254.  
  255.         upstream backup { 
  256.         server 172.28.22.29:7777  max_fails=0 fail_timeout=3s
  257.         } 
  258.  
  259.  如果upstream里的主机全部挂掉了,日志会报
  260. 2013/01/12 22:57:37 [error] 7627#0: *23641 no live upstreams while connecting to upstream, client: 100.120.111.94, server: *.mydomain.com, request: "GET http://www.mydomain.com/.....(省略) HTTP/1.1", upstream: "http://online/.....(省略), host: "www.mydomain.com", referrer: "http://www.mydomain.com/.....(省略)" 

 最后需要指出的就是后端的日志记录问题!这个在nginx升级安装时已经考虑到了,增加http_realip_module模块。