代理服务可简单的分为正向代理和反向代理:

正向代理: 用于代理内部网络对Internet的连接请求(如×××/NAT),客户端指定代理服务器,并将本来要直接发送给目标Web服务器的HTTP请求先发送到代理服务器上, 然后由代理服务器去访问Web服务器,并将Web服务器的Response回传给客户端:

反向代理: 与正向代理相反,如果局域网向Internet提供资源,并让Internet上的其他用户可以访问局域网内资源, 也可以设置一个代理服务器, 它提供的服务就是反向代理. 反向代理服务器接受来自Internet的连接,然后将请求转发给内部网络上的服务器,并将Response回传给Internet上请求连接的客户端:

一、nginx反向代理:Web服务器的调度器

1、反向代理(ReverseProxy)方式是指以代理服务器来接受客户端的连接请求,然后将请求转发给网络上的web服务器(可能是apache、nginx、tomcat、iis等),并将从web服务器上得到的结果返回给请求连接的客户端,此时代理服务器对外就表现为一个服务器。

wKiom1kSY_iQY7K0AAGBf4rptSY659.jpg

从上图可以看出:反向代理服务器代理网站Web服务器接收Http请求,对请求进行转发。而且nginx作为反向代理服务器可以根据用户请求的内容把请求转发给后端不同的web服务器,例如静动分离,再例如在nginx上创建多个虚拟主机,这样就成功的做到了在浏览器中输入不同域名(url)的时候访问后端的不同web服务器或web群集。

 

2、反向代理的作用

①保护网站安全:任何来自Internet的请求都必须先经过代理服务器;

wKioL1kSY_mR8OyvAAERTWX_GKs678.jpg

②通过配置缓存功能加速Web请求:可以缓存真实Web服务器上的某些静态资源,减轻真实Web服务器的负载压力;

wKioL1kSY_nShnkpAAEXP--OGZM164.jpg

③实现负载均衡:充当负载均衡服务器均衡地分发请求,平衡集群中各个服务器的负载压力;

wKiom1kSY_rQC3sXAAC9NbLXAto221.jpg

二、什么是nginx

1、nginx简介

Nginx是一款轻量级的网页服务器、反向代理器以及电子邮件代理服务器。因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。Nginx(发音同engine x),它是由俄罗斯程序员Igor Sysoev所开发的。起初是供俄国大型的门户网站及搜索引擎Rambler(俄语:Рамблер)使用。此软件BSD-like协议下发行,可以在UNIX、GNU/Linux、BSD、Mac OS X、Solaris,以及MicrosoftWindows等操作系统中运行。

Nginx的应用现状

Nginx已经在俄罗斯最大的门户网站── Rambler Media(www.rambler.ru)上运行,同时俄罗斯超过20%的虚拟主机平台采用Nginx作为反向代理服务器。

在国内,已经有淘宝、新浪博客、新浪播客、网易新闻、六间房、56.com、Discuz!、水木社区、豆瓣、YUPOO、海内、迅雷在线 等多家网站使用 Nginx 作为Web服务器或反向代理服务器。

2、Nginx的核心特点

(1)跨平台:Nginx 可以在大多数OS编译运行,而且也有Windows的版本;

(2)配置异常简单:非常容易上手。

(3)非阻塞、高并发连接:官方测试能够支撑5万并发连接,在实际生产环境中跑到2~3万并发连接数。(这得益于Nginx使用了最新的epoll模型);

注:

对于一个Web服务器来说,首先看一个请求的基本过程:建立连接—接收数据—发送数据,在系统底层看来 :上述过程(建立连接—接收数据—发送数据)在系统底层就是读写事件。

 

如果采用阻塞调用的方式,当读写事件没有准备好时,那么就只能等待,当前线程被挂起,等事件准备好了,才能进行读写事件。

如果采用非阻塞调用的方式:事件马上返回,告诉你事件还没准备好呢,过会再来吧。过一会,再来检查一下事件,直到事件准备好了为止,在这期间,你就可以先去做其它事情,然后再来看看事件好了没。虽然不阻塞了,但你得不时地过来检查一下事件的状态,你可以做更多的事情了,但带来的开销也是不小的。非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程

(4)事件驱动:通信机制采用epoll模型,支持更大的并发连接。

非阻塞通过不断检查事件的状态来判断是否进行读写操作,这样带来的开销很大,因此就有了异步非阻塞的事件处理机制。这种机制让你可以同时监控多个事件,调用他们是非阻塞的,但可以设置超时时间,在超时时间之内,如果有事件准备好了,就返回。这种机制解决了上面阻塞调用与非阻塞调用的两个问题。

以epoll模型为例:当事件没有准备好时,就放入epoll(队列)里面。如果有事件准备好了,那么就去处理;当事件没有准备好时,才在 epoll里面等着。这样,我们就可以并发处理大量的并发了,当然,这里的并发请求,是指未处理完的请求。线程只有一个,所以同时能处理的请求当然只有一个了,只是在请求之间进行不断地切换而已,切换也是因为异步事件未准备好,而主动让出的。这里的切换是没有任何代价,你可以理解为循环处理多个准备好的事件。

多线程方式相比,这种事件处理方式是有很大的优势的,不需要创建线程,每个请求占用的内存也很少,没有上下文切换,事件处理非常的轻量级,并发数再多也不会导致无谓的资源浪费(上下文切换)。对于apache服务器,每个请求会独占一个工作线程,当并发数上到几千时,就同时有几千的线程在处理请求了。这对操作系统来说,是个不小的挑战:因为线程带来的内存占用非常大,线程的上下文切换带来的cpu开销很大,自然性能就上不 去,从而导致在高并发场景下性能下降严重。

总结:通过异步非阻塞的事件处理机制,Nginx实现由进程循环处理多个准备好的事件,从而实现高并发和轻量级。

(5)Master/Worker结构:一个master进程,生成一个或多个worker进程。

wKiom1kSY_vge-8bAAD3k23EEvo947.jpg

注:Master-Worker设计模式主要包含两个主要组件Master和Worker,Master维护着Worker队列,将请求下发到多个Worker并行执行,Worker主要进行实际逻辑计算,并将结果返回给Master。

nginx采用这种进程模型有什么好处?采用独立的进程,可以让互相之间不会影响,一个进程退出后,其它进程还在工作,服务不会中断,Master 进程则很快重新启动新的Worker进程。当然,Worker进程的异常退出,肯定是程序有bug了,异常退出,会导致当前Worker上的所有请求失败,不过不会影响到所有请求,所以降低了风险。

(6)内存消耗小:处理大并发的请求内存消耗非常小。在3万并发连接下,开启的10个Nginx 进程才消耗150M内存(15M*10=150M)。

(7)内置的健康检查功能:如果 Nginx 代理的后端的某台 Web 服务器宕机了,不会影响前端访问。

(8)节省带宽:支持 GZIP 压缩,可以添加浏览器本地缓存的 Header 头。

(9)稳定性高:用于反向代理,宕机的概率微乎其微。

三、Nginx+apache构筑Web服务器集群的负载均衡

nginx配置反向代理

配置nginx作为反向代理和负载均衡,同时利用其缓存功能,将静态页面在nginx缓存,以达到降低后端服务器连接数的目的并检查后端web服务器的健康状况。

wKioL1kSY_vDzyfiAADKHdBWMRg909.jpg

1、安装nginx

环境:

OS:centos7.2

nginx:192.168.1.6

apache1:192.168.1.7

apache2:192.168.1.8

安装zlib-devel、pcre-devel等依赖包

wKioL1kSY_ujDUcuAACXAgfScZI649.jpg

注:

结合proxy和upstream模块实现后端web负载均衡

使用proxy模块实现静态文件缓存

结合nginx默认自带的 ngx_http_proxy_module模块 和ngx_http_upstream_module模块实现后端服务器的健康检查,也可以使用第三方模块nginx_upstream_check_module

使用nginx-sticky-module扩展模块实现Cookie会话黏贴(保持会话)

使用ngx_cache_purge实现更强大的缓存清除功能

上面提到的2个模块都属于第三方扩展模块,需要提前下好源码,然后编译时通过--add-moudle=src_path一起安装。

安装nginx

wKiom1kSY_yAHmDIAAFZbgPdlUk537.jpg

wKiom1kSY_yTi-QIAAHQVLkrTrQ281.jpg

wKioL1kSY_2TtVpAAAJLf8i0Hy4637.jpg

上图中内容如下:

./configure--prefix=/usr/local/nginx1.10 --user=www --group=www--with-http_stub_status_module --with-http_realip_module --with-http_ssl_module--with-http_gzip_static_module --http-client-body-temp-path=/var/tmp/nginx/client--http-proxy-temp-path=/var/tmp/nginx/proxy--http-fastcgi-temp-path=/var/tmp/nginx/fcgi --with-pcre--add-module=../ngx_cache_purge-2.3 --with-http_flv_module --add-module=../nginx-goodies-nginx-sticky-module-ng-08a395c66e42&& make && make install

注:nginx的所有模块必须在编译的时候添加,不能再运行的时候动态加载。

解释:

--add-module:添加第三方模块

--with-http_gzip_static_module:添加gzip模块

--http-client-body-temp-path=/var/tmp/nginx/client:添加缓存目录,该目录需要手动创建

优化nginx程序的执行路径

wKioL1kSY_6QhrA2AAFxwyxndo8920.jpg

2、编写nginx服务脚本:

wKiom1kSY_7A0srAAACzxmiOC6E901.jpg

#!/bin/bash

#chkconfig: 2345 99 20

#description: Nginx Service Control Script

PROG="/usr/local/nginx1.10/sbin/nginx"

PIDF="/usr/local/nginx1.10/logs/nginx.pid"

case"$1" in

  start)

   netstat -anplt |grep ":80"&> /dev/null && pgrep "nginx" &> /dev/null

   if [ $? -eq 0 ]

   then

     echo "Nginx service alreadyrunning."

   else

     $PROG -t &> /dev/null

     if [ $? -eq 0 ] ; then

       $PROG

       echo "Nginx service start success."

     else

     $PROG -t

     fi

   fi

   ;;

  stop)

   netstat -anplt |grep ":80"&> /dev/null && pgrep "nginx" &> /dev/null

   if [ $? -eq 0 ]

   then

    kill -s QUIT $(cat $PIDF)

    echo "Nginx service stopsuccess."

   else

    echo "Nginx service already stop"

   fi

   ;;

  restart)

    $0 stop

    $0 start

    ;;

  status)

   netstat -anplt |grep ":80"&> /dev/null && pgrep "nginx" &> /dev/null

   if [ $? -eq 0 ]

   then

     echo "Nginx service is running."

   else

     echo "Nginx is stop."

   fi

  ;;

  reload)

   netstat -anplt |grep ":80"&> /dev/null && pgrep "nginx" &> /dev/null

   if [ $? -eq 0 ]

   then

    $PROG -t &> /dev/null

    if [ $? -eq 0 ] ; then

      kill -s HUP $(cat $PIDF)

      echo "reload Nginx configsuccess."

    else

      $PROG -t

    fi

   else

    echo "Nginx service is not run."

   fi

    ;;

  *)

   echo "Usage: $0{start|stop|restart|reload}"

   exit 1

esac

wKioL1kSY_-CB7bXAAHzNutWu8o039.jpg

wKioL1kSY__QzDRuAAE1BXBg8aU101.jpg

注:如果你想在已安装好的nginx上添加第三方模块,依然需要重新编译,但为了不覆盖你原有的配置,请不要makeinstall,而是直接拷贝可执行文件,解决办法如下:

nginx   -V   //可以查看你当前nginx已经安装的模块

[root@wwwnginx-1.10.2]#./configure  --add-module=……   #你的第三方模块

[root@wwwnginx-1.10.2] #make后不要make install,改为手动拷贝,先备份

[root@wwwnginx-1.10.2] #cp /usr/local/nginx1.10/sbin/nginx/usr/local/nginx1.10/sbin/nginx.bak

[root@wwwnginx-1.10.2] #cp objs/nginx/usr/local/nginx1.10/sbin/nginx

配置nginx反向代理:反向代理+负载均衡+健康探测

查看nginx加载的模块:

wKiom1kSY__SZT9hAAIyfrHUMsg639.jpg

再次申明:nginx的所有模块必须在编译的时候添加,不能再运行的时候动态加载。

 

3、nginx-sticky-module模块:

这个模块的作用是通过cookie黏贴的方式将来自同一个客户端(浏览器)的请求发送到同一个后端服务器上处理,这样一定程度上可以解决多个backend servers的session同步的问题 —— 因为不再需要同步,而RR轮询模式必须要运维人员自己考虑session同步的实现。

另外内置的 ip_hash 也可以实现根据客户端IP来分发请求,但它很容易造成负载不均衡的情况,而如果nginx前面有CDN网络或者来自同一局域网的访问,它接收的客户端IP是一样的,容易造成负载不均衡现象。nginx-sticky-module的cookie过期时间,默认浏览器关闭就过期。

这个模块并不合适不支持 Cookie 或手动禁用了cookie的浏览器,此时默认sticky就会切换成RR。它不能与ip_hash同时使用。

wKioL1kSZADhneVqAADuQ70YQbA770.jpg

说明:配置起来超级简单,一般来说一个sticky指令就够了。

相关信息可以查看官方文档https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng

4、load-balance其它调度方案:

这里顺带介绍一下nginx的负载均衡模块支持的其它调度算法:

轮询(默认) : 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端某台服务器宕机,故障系统被自动剔除,使用户访问不受影响。Weight 指定轮询权值,Weight值越大,分配到的访问机率越高,主要用于后端每个服务器性能不均的情况下。

ip_hash: 每个请求按访问IP的hash结果分配,这样来自同一个IP的访客固定访问一个后端服务器,有效解决了动态网页存在的session共享问题。当然如果这个节点不可用了,会发到下个节点,而此时没有session同步的话就注销掉了。

least_conn:请求被发送到当前活跃连接最少的realserver上。会考虑weight的值。

url_hash: 此方法按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率。Nginx本身是不支持url_hash的,如果需要使用这种调度算法,必须安装Nginx 的hash软件包nginx_upstream_hash 。

fair:这是比上面两个更加智能的负载均衡算法。此种算法可以依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx本身是不支持fair的,如果需要使用这种调度算法,必须下载Nginx的 upstream_fair 模块。

5、负载均衡与健康检查:

严格来说,nginx自带是没有针对负载均衡后端节点的健康检查的,但是可以通过默认自带的ngx_http_proxy_module 模块和 ngx_http_upstream_module 模块中的相关指令来完成当后端节点出现故障时,自动切换到下一个节点来提供访问。

wKiom1kSZAGjFhBhAAJR1NtQCjo119.jpg

weight : 轮询权值也是可以用在ip_hash的,默认值为1

max_fails : 允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误。

fail_timeout : 有两层含义,一是在10s 时间内最多容许2 次失败;二是在经历了 2 次失败以后,10s时间内不分配请求到这台服务器。


本文出自 “IT技术助手” 博客,请务必保留此出处http://zpf666.blog.51cto.com/11248677/1923935