从web服务方式到nginx

作者 Claymore 日期 2017-03-16
从web服务方式到nginx

常见web服务方式

  • 多进程方式:为每个请求启动一个进程来处理。由于在操作系统中,生成进程、销毁进程、进程间切换都很消耗CPU和内存,当负载高是,性能会明显降低。

    优点: 稳定性!由于采用独立进程处理独立请求,而进程之间是独立的,单个进程问题不会影响其他进程,因此稳定性最好。

    缺点: 资源占用!当请求过大时,需要大量的进程处理请求,进程生成、切换开销很大,而且进程间资源是独立的,造成内存重复利用。

  • 多线程方式:一个进程中用多个线程处理用户请求。由于线程开销明显小于进程,而且部分资源还可以共享,因此效率较高。

    优点:开销较小!线程间部分数据是共享的,且线程生成与线程间的切换所需资源开销比进程间切换小得多。

    缺点:稳定性!线程切换过快可能造成线程抖动,且线程过多会造成服务器不稳定。

  • 异步方式:使用非阻塞方式处理请求,是三种方式中开销最小的。但异步方式虽然效率高,但要求也高,因为多任务之间的调度如果出现问题,就可能出现整体故障,因此使用异步工作的,一般是一些功能相对简单,但却符合服务器任务调度、且代码中没有影响调度的错误代码存在的程序。

一个web请求的处理过程

  1. 客户发起情况到服务器网卡;
  2. 服务器网卡接受到请求后转交给内核处理;
  3. 内核根据请求对应的套接字,将请求交给工作在用户空间的Web服务器进程
  4. Web服务器进程根据用户请求,向内核进行系统调用,申请获取相应资源(如index.html)
  5. 内核发现web服务器进程请求的是一个存放在硬盘上的资源,因此通过驱动程序连接磁盘
  6. 内核调度磁盘,获取需要的资源
  7. 内核将资源存放在自己的缓冲区中,并通知Web服务器进程
  8. Web服务器进程通过系统调用取得资源,并将其复制到进程自己的缓冲区中
  9. Web服务器进程形成响应,通过系统调用再次发给内核以响应用户请求
  10. 内核将响应发送至网卡
  11. 网卡发送响应给用户

通过这样的一个复杂过程,一次请求就完成了。

简单来说就是:用户请求–>送达到用户空间–>系统调用–>内核空间–>内核到磁盘上读取网页资源->返回到用户空间->响应给用户。上述简单的说明了一下,客户端向Web服务请求过程,在这个过程中,有两个I/O过程,一个就是客户端请求的网络I/O,另一个就是Web服务器请求页面的磁盘I/O.

linux I/O 模型

  • select
  • epoll

我们这里直说这两种,还有其它模型,有的是其他系统,如iocp是Windows实现的,select、poll、epoll是Linux实现的,kqueue是FreeBSD实现的,/dev/poll是SUN的Solaris实现的。

每次select()都要通过遍历FD_SETSIZE个Socket来完成调度,不管哪个Socket是活跃的,都遍历一遍。这会浪费很多CPU时间。如果能给套接字注册某个回调函数,当他们活跃时,自动完成相关操作,那就避免了轮询,这正是epoll、kqueue、/dev/poll做的。

说一个现实中的例子,假设你在大学读书,住的宿舍楼有很多间房间,你的朋友要来找你。select版宿管大妈就会带着你的朋友挨个房间去找,直到找到你为止。而epoll版宿管大妈会先记下每位同学的房间号,你的朋友来时,只需告诉你的朋友你住在哪个房间即可,不用亲自带着你的朋友满大楼找人。如果来了10000个人,都要找自己住这栋楼的同学时,select版和epoll版宿管大妈,谁的效率更高,不言自明。

Apache Http的工作模式

Apache有三种工作模块,分别为prefork、worker、event。

  • prefork:多进程,每个请求用一个进程响应,这个过程会用到select机制来通知。
  • worker:多线程,一个进程可以生成多个线程,每个线程响应一个请求,但通知机制还是select不过可以接受更多的请求。
  • event:基于异步I/O模型,一个进程或线程,每个进程或线程响应多个用户请求,它是基于事件驱动(也就是epoll机制)实现的。

event基于时间机制的特性:

一个进程响应多个用户请求,利用callback机制,让套接字复用,请求过来后进程并不处理请求,而是直接交由其他机制来处理,通过epoll机制来通知请求是否完成;在这个过程中,进程本身一直处于空闲状态,可以一直接收用户请求。可以实现一个进程程响应多个用户请求。支持持海量并发连接数,消耗更少的资源。

提高web服务器的并发连接处理能力

有几个基本条件:

  • 基于线程,即一个进程生成多个线程,每个线程响应用户的每个请求。
  • 基于事件的模型,一个进程处理多个请求,并且通过epoll机制来通知用户请求完成。
  • 基于磁盘的AIO(异步I/O)
  • 支持mmap内存映射,mmap传统的web服务器,进行页面输入时,都是将磁盘的页面先输入到内核缓存中,再由内核缓存中复制一份到web服务器上,mmap机制就是让内核缓存与磁盘进行映射,web服务器,直接复制页面内容即可。不需要先把磁盘的上的页面先输入到内核缓存去。

Nginx优异之处

Nginx 支持以上所有特性。所以Nginx官网上说,Nginx支持50000并发,是有依据的。

高性能web服务器/web服务器反向代理:Nginx(Engine X),nginx的主要着眼点就是其高性能以及对物理计算资源的高密度利用,因此其采用了不同的架构模型。受启发于多种操作系统设计中基于“事件”的高级处理机制,nginx采用了模块化、事件驱动、异步、单线程及非阻塞的架构,并大量采用了多路复用及事件通知机制。在nginx中,连接请求由为数不多的几个仅包含一个线程的进程worker以高效的回环(run-loop)机制进行处理,而每个worker可以并行处理数千个的并发连接及请求。

工作原理

Nginx会按需同时运行多个进程:一个主进程(master)和几个工作进程(worker),配置了缓存时还会有缓存加载器进程(cache loader)和缓存管理器进程(cache manager)等。所有进程均是仅含有一个线程,并主要通过“共享内存”的机制实现进程间通信。主进程以root用户身份运行,而worker、cache loader和cache manager均应以非特权用户身份运行。

主进程主要工作:

  • 读取并验正配置信息;
  • 创建、绑定及关闭套接字;
  • 启动、终止及维护worker进程的个数;
  • 无须中止服务而重新配置工作特性;
  • 控制非中断式程序升级,启用新的二进制程序并在需要时回滚至老版本;
  • 重新打开日志文件;
  • 编译嵌入式perl脚本;

worker进程主要完成的任务:

  • 接收、传入并处理来自客户端的连接;
  • 提供反向代理及过滤功能;
  • nginx任何能完成的其它任务;

如果负载以CPU密集型应用为主,如SSL或压缩应用,则worker数应与CPU数相同;如果负载以IO密集型为主,如响应大量内容给客户端,则worker数应该为CPU个数的1.5或2倍。

为什么选择Nginx

  • 在高连接并发的情况下,Nginx是Apache服务器不错的替代品。
  • Nginx作为负载均衡服务器: Nginx 既可以在内部直接支持 Rails 和 PHP 程序对外进行服务, 也可以支持作为 HTTP代理 服务器对外进行服务. Nginx采用C进行编写, 不论是系统资源开销还是CPU使用效率都比 Perlbal 要好很多。
  • 作为邮件代理服务器: Nginx 同时也是一个非常优秀的邮件代理服务器(最早开发这个产品的目的之一也是作为邮件代理服务器)
  • Nginx 安装非常的简单 , 配置文件非常简洁(还能够支持perl语法),Bugs 非常少的服务器: Nginx 启动特别容易, 并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动. 你还能够 不间断服务的情况下进行软件版本的升级 。

正向代理与反向代理

正向代理:

我们常说的代理也就是只正向代理,正向代理的过程,它隐藏了真实的请求客户端,服务端不知道真实的客户端是谁,客户端请求的服务都被代理服务器代替来请求,知名的科学上网工具shadowsocks
扮演的就是典型的正向代理角色。在天朝用浏览器访问 www.google.com
时,被残忍的拒绝了,于是你可以在国外搭建一台代理服务器,让代理帮我去请求google.com,代理把请求返回的相应结构再返回给我。

反向代理:

反向代理隐藏了真实的服务端,当我们请求 www.baidu.com
的时候,就像拨打10086一样,背后可能有成千上万台服务器为我们服务,但具体是哪一台,你不知道,也不需要知道,你只需要知道反向代理服务器是谁就好了,www.baidu.com
就是我们的反向代理服务器,反向代理服务器会帮我们把请求转发到真实的服务器那里去。Nginx就是性能非常好的反向代理服务器,用来做负载均衡。

两者的区别在于代理的对象不一样:正向代理代理的对象是客户端,反向代理代理的对象是服务端