Web服务器如何保证请求的独立处理

在了解Web服务器如何保证并发线程的独立性以前,咱们先了解一下Web服务器处理并发请求的工做模型php

  1. 单线程的Web服务器,也即Servlet是单例模式。Web服务器一次处理一个请求,结束后读取并处理下一个请求。在某请求处理过程当中,其余请求将被挂起,所以在并发量较大的场景中将会出现严重的性能问题。
  2. 多进程/多线程Web服务器。这种服务器生成多个进程或线程并行处理多个用户请求,进程或线程能够事先生成,也能够按需生成。这种服务器能够为每一个用户请求生成一个单独的进程或线程来进行相应,不过,一旦并发请求达到成千上万时,多个同事运行的进程或线程将会大量消耗系统资源,而且新建一个线程,销毁一个线程的开销是很大的,它时常会大于实际处理请求自己的额开销,所以这种方式并不能充分利用计算机资源,提高并发的效率也是有限的,若是碰到线程安全的问题,须要使用到线程的锁机制,那并发提高就会受到更大的限制。
  3. 线程池策略Web服务器。为了改善以上两个web服务器架构,不少服务器利用了线程池技术。线程池技术就是事先建立一批线程,这批线程在到达服务器以前,这些线程处于待命状态,当请求到达后,程序从线程池中去除一个线程,这个线程处理到达的请求,请求处理完毕,该线程被线程池回收。通常地,一个线程对应一个请求,当线程数达到服务器所能处理的最大数量,则线程挂起等待或者启用线程池拒绝策略(请求实在太多了,线程池处理不过来了,JDK的线程池提供了一个队列机制,让这些请求排队等待,这样避免请求丢失。若是队列容量超过了计算机处理能力,队列会抛弃没法处理的请求,这个叫作线程池的拒绝策略)
  4. I/O多路复用Web服务器。这个服务器原理我尚未仔细研究过,有兴趣的你抽时间能够问问度娘。其实实现一个非阻塞的请求是个大课题,里面使用到了不少先进和复杂的技术例如:回调函数和轮询等,对于非阻塞的开发我目前掌握的还不够好,等我有天彻底掌握了它我必定会再写一篇文章,不过这里要提到的是像java里netty技术,nginx,php的并发处理都用到这种机制的原理,特别是如今很火的nodejs它产生的缘由就是依靠这种非阻塞的技术来编写更高效的web服务器,能够说nodejs把这种技术用到了极致,不过这里要纠正下,非阻塞是针对IO操做的技术,对于nodejs,netty的实现机制有更好的术语描述就是事件驱动(其实就是使用回调函数,观察者模式实现的)以及异步的IO技术(就是非阻塞的IO技术)

    如今了解了Web服务器处理并发请求的工做模型,那咱们接下来接着谈一下Web服务器并发环境下如何保证线程独立。线程独立也就是线程安全。java

    线程安全的定义:在多线程环境下可以正确执行的代码就是线程安全的。在单线程环境下,运行程序总能返回惟一结果。node

    Servlet是多线程环境下的,即有可能有多个请求发给一个Servlet实例,每一个请求就是一个线程。在JavaWeb服务器环境下并发,要注意的安全问题最简单的实现方法就是不要再Servlet或者Struts的Action中使用类变量或者实例变量。若是有这些变量,能够将它们转化为方法的参数传入,以消除它们。被Servlet或Action调用的类中(如值对象、领域模型类)中是否能够安全的使用实例变量?若是你在每次方法调用时新建一个对象,再调用它们的方法,则不存在同步问题---由于它们不是多个线程共享的资源,只有共享的资源才须要同步---而Servlet和Action的实例对于多个线程是共享的。换句话说,Servlet和Action的实例会被多个线程同时调用,而过了这一层,若是在你本身的代码中没有另外启动线程,且每次调用后续业务对象时都是先新建一个实例再调用,则都是线程安全的。nginx

相关文章
相关标签/搜索