Web 服务器工作原理
几个关键疑问:
Web服务器是怎么工作的?怎么处理来着世界各地的http请求的?幕后都做了哪些动作?JavaServlet API (如ServerletContext,ServerletRequest, Servlet Response,Session等)都扮演什么角色呢?
1 什么是Web 服务器,应用服务器,Web容器
可以用一句话来总结web服务器和应用服务器的概念关系,
“在过去它们是有区别的,但是慢慢地这两个不同的分类慢慢合并,在如今的大多数情况下可以把它们看出一个整体”。
我们来说说当初的故事,在Web初期,大多数内容都是静态的,Web服务器通过HTTP协议来提供静态页面内容和图片服务。但是用户想要根据自己的输入来动态获取内容时,这意味着我们可以为每个Web请求启动一个进程来动态产生内容,如jsp,ASP,php等动态内容都需要通过CGI,FastCGI,ISAP等接口交给其他程序去处理,这里的其他程序就是应用服务器,如JBoss,WebLogic,WebSphere。通俗来说,Web服务器专门负责处理HTTP请求,应用服务器通过很多协议来为提供商业逻辑。以Java EE为例,Web服务器主要处理静态页面和作为Servlet容器,解释执行servlet/JSP,而应用服务器是运行业务逻辑的,主要是EJB、JNDI和JMX API等J2EE API方面的,还包括事务处理、数据库连接等功能。
现在的应用服务器一般也支持HTTP协议,因此两者之间的区别没有这么清晰,但是应用服务器的HTTP部分仅是支持,没有特别优化,因此很少见tomcat直接暴露给外界,而是和nginx、Apache等配合,只让tomcat处理JSP和Servlet部分。因此当说到“Web服务器”时,通常要把它认为是以HTTP为核心,WebUI为导向的应用;当说到“应用服务器”,可能想到“高负载,企业级特性,食物和队列,多通道通信(HTTP和更多的协议)”。
第三个术语,Web容器,在Java中,web容器一般指servlet容器。
Servlet容器管理servlet的生命周期、把URL映射到特定的servlet、确保URL请求拥有正确的访问权限和更多类似的服务。Servlet容器就是运行servlet和维护它生命周期的运行环境。
2 什么是servlet?作用?
在java里,servlet使开发人员可以编写根据请求动态生成内容的服务端组件。Servlet是一个在javax.servlet包中定义的接口,提供servlet生命周期中的三个基本方法:init()、service()和destroy()。每个servlet都要实现这些方法,并在生命周期中的特定时间由服务器调用这些方法。
2.1 类的懒(延迟)加载和预加载
类加载器通过懒加载(lazy-loading)或预加载(eagerloading)自动的把servlet类加载到容器里。每个请求都有自己的线程,而一个servlet对象可以同时为多个线程服务,当servlet对象不被使用时,会被JVM做垃圾回收。
懒(延迟)加载,是指在请求到来时才加载并初始化servlet,然后使用servlet完成请求的服务。
预加载,是在容器启动时就加载并初始化servlet,当请求到达时就可以直接拿来用。
2.2 什么是ServletContext?由谁创建?
Servlet容器启动时,会部署并加载所有的web应用,当web应用被加载时,Servlet容器会一次性为每个应用创建ServletContext并把它保存在内存里。Servlet容器会处理web应用的web.xml文件,并一次性创建在web.xml里定义的Servlet、Filter和Listener,保存在内存。当Servlet容器关闭时,会写在所有的web应用和ServletContext,所有的Servlet、Filter和Listener 实例都会被销毁。
Web应用的部署文件标明分布式时,web应用的每个虚拟机都有一个ServletContext实例,这时,ServletContext不再是全局共享信息的变量。
2.3 ServletRequest,ServletResponse生命周期
Servlet容器是包含在web服务器中的,web服务器监听来着特定端口(通常是80)的HTTP请求。当客户端发送一个HTTP请求时,Servlet容器会创建新的HttpServletRequest和HttpServletResponse对象,并传递给已经创建的Filter和URL模式与请求URL匹配的Servlet实例的方法,所有的这些都使用同一个线程。
Request对象提供获取HTTP请求的所有信息的入口,如请求头,请求实体。Response对象提供控制和发送HTTP响应的方法,如设置响应头和响应实体。当HTTPResponse被提交并结束后,Request和Response对象就被销毁。
2.4 Session管理
当客户端第一次访问Web应用或第一次使用Request。GetSession(0获取HttpSession时,Servlet容器会创建Session,生成一个long类型的唯一ID并把它保存在服务器内存。Servlet容器同样会在HTTP响应里设置一个cookie,cookie的名是JSESSIONID,并且cookie的值是SessionID
在cookie有效期,客户端之后的请求都要把这个cookie返回服务器,Servlet容器会利用带有名为JSESSIONID的cookie检测每一个到来的HTTP请求头,并使用cookie的值从服务器内存里获取相关的HttpSession。
HttpSession会一直存货,除非超过一段时间没有使用。Web.xml里可以设置这个时间,默认是30分钟。意味着如果客户端30分钟没有访问web应用的话,Servlet容器就会销毁这个Session。之后的每一个请求,即使带有特定的cookie,也不会访问到同一个Session,Servlet容器会新建一个新的Session。
2.5 如何确保Servlet和Filter线程安全?
通过上文,我们知道所有的请求在共享Servlet和Filter实例,不同的线程使用同一个实例。否则,对每个请求都重新创建一个实例会耗费很多资源。
因此,不要使用Servlet或者Filter的实例变量来存放请求或者会话范围内的数据。这些数据会被其他Session的所有请求共享,这是非线程安全的。
主要内容摘自http://www.importnew.com/15020.html