欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

web服务器和应用服务器的区别,一分钟带你搞懂这两者的关联

程序员文章站 2023-12-05 23:48:52
很多时候我们都想知道,web容器或web服务器(比如tomcat或者jboss)是怎样工作的?它们是怎样处理来自全世界的http请求的?它们在幕后做了什么动作?java servlet api(例如s...

很多时候我们都想知道,web容器或web服务器(比如tomcat或者jboss)是怎样工作的?它们是怎样处理来自全世界的http请求的?它们在幕后做了什么动作?java servlet api(例如servletcontext,servletrequest,servletresponse和session这些类)在其中扮演了什么角色?这些都是web应用开发者或者想成为web应用开发者的人必须要知道的重要问题或概念。在这篇文章里,我将会尽量给出以上某些问题的答案。请集中精神!

文章章节:

  • 什么是web服务器、应用服务器和web容器?
  • 什么是servlet?他们有什么作用?
  • 什么是servletcontext?它由谁创建?
  • servletrequest和servletresponse从哪里进入生命周期?
  • 如何管理session?知道cookie吗?
  • 如何确保线程安全?

什么是web服务器,应用服务器和web容器?

我先讨论web服务器和应用服务器。让我在用一句话大概讲讲:

“在过去它们是有区别的,但是这两个不同的分类慢慢地合并了,而如今在大多在情况下和使用中可以把它们看成一个整体。”

在mosaic浏览器(通常被认为是第一个图形化的web浏览器)和超链接内容的初期,演变出了“web服务器”的新概念,它通过http协议来提供静态页面内容和图片服务。在那个时候,大多数内容都是静态的,并且http 1.0只是一种传送文件的方式。但在不久后web服务器提供了cgi功能。这意味着我们可以为每个web请求启动一个进程来产生动态内容。现在,http协议已经很成熟了并且web服务器变得更加复杂,拥有了像缓存、安全和session管理这些附加功能。随着技术的进一步成熟,我们从kiva和netdynamics学会了公司专属的基于java的服务器端技术。这些技术最终全都融入到我们今天依然在大多数应用开发里使用的jsp中。

web服务器和应用服务器的区别,一分钟带你搞懂这两者的关联

以上是关于web服务器的。现在我们来讨论应用服务器

在同一时期,应用服务器已经存在并发展很长一段时间了。一些公司为unix开发了tuxedo(面向事务的中间件)、topendencina等产品,这些产品都是从类似ims和cics的主机应用管理和监控环境衍生而来的。大部分的这些产品都指定了“封闭的”产品专用通信协议来互连胖客户机(“fat” client)和服务器。在90年代,这些传统的应用服务器产品开始嵌入http通信功能,刚开始要利用网关来实现。不久后它们之间的界线开始变得模糊了。

同时,web服务器越来越成熟,可以处理更高的负载、更多的并发和拥有更好的特性;应用服务器开始添加越来越多的基于http的通信功能。所有的这些导致了web服务器与应用服务器的界线变得更窄了。

目前,“应用服务器”和“web服务器”之间的界线已经变得模糊不清了。但是人们还把这两个术语区分开来,作为强调使用。

当有人说到“web服务器”时,你通常要把它认为是以http为核心、web ui为向导的应用。当有人说到“应用服务器”时,你可能想到“高负载、企业级特性、事务和队列、多通道通信(http和更多的协议)”。但现在提供这些需求的基本上都是同一个产品。

以上就是关于web服务器和应用服务器的全部内容。现在我们来看看第三个术语,即web容器。

web服务器和应用服务器的区别,一分钟带你搞懂这两者的关联

在java方面,web容器一般是指servlet容器。servlet容器是与java servlet交互的web容器的组件。web容器负责管理servlet的生命周期、把url映射到特定的servlet、确保url请求拥有正确的访问权限和更多类似的服务。综合来看,servlet容器就是用来运行你的servlet和维护它的生命周期的运行环境。

什么是servlet?他们有什么作用?

在java里,servlet使你能够编写根据请求动态生成内容的服务端组件。事实上,servlet是一个在javax.servlet包里定义的接口。它为servlet的生命周期声明了三个基本方法——init()、service()和destroy()。每个servlet都要实现这些方法(在sdk里定义或者用户定义)并在它们的生命周期的特定时间由服务器来调用这些方法。

类加载器通过懒加载(lazy-loading)或者预加载(eager loading)自动地把servlet类加载到容器里。每个请求都拥有自己的线程,而一个servlet对象可以同时为多个线程服务。当servlet对象不再被使用时,它就会被jvm当做垃圾回收掉。

懒加载的servlet

web服务器和应用服务器的区别,一分钟带你搞懂这两者的关联
web服务器和应用服务器的区别,一分钟带你搞懂这两者的关联

预加载的servlet

web服务器和应用服务器的区别,一分钟带你搞懂这两者的关联
web服务器和应用服务器的区别,一分钟带你搞懂这两者的关联

什么是servletcontext?它由谁创建?

当servlet容器启动时,它会部署并加载所有的web应用。当web应用被加载时,servlet容器会一次性为每个应用创建servlet上下文(servletcontext)并把它保存在内存里。servlet容器会处理web应用的web.xml文件,并且一次性创建在web.xml里定义的servlet、filter和listener,同样也会把它们保存在内存里。当servlet容器关闭时,它会卸载所有的web应用和servletcontext,所有的servlet、filter和listner实例都会被销毁。

从java文档可知,servletcontext定义了一组方法,servlet使用这些方法来与它的servlet容器进行通信。例如,用来获取文件的mime类型、转发请求或者编写日志文件。在web应用的部署文件(deployment descriptor)标明“分布式”的情况下,web应用的每一个虚拟机都拥有一个上下文实例。在这种情况下,不能把servlet上下文当做共享全局信息的变量(因为它的信息已经不具有全局性了)。可以使用外部资源来代替,比如数据库。

servletrequest和servletresponse从哪里进入生命周期?

servlet容器包含在web服务器中,web服务器监听来自特定端口的http请求,这个端口通常是80。当客户端(使用web浏览器的用户)发送一个http请求时,servlet容器会创建新的httpservletrequest和httpservletresponse对象,并且把它们传递给已经创建的filter和url模式与请求url匹配的servlet实例的方法,所有的这些都使用同一个线程。

request对象提供了获取http请求的所有信息的入口,比如请求头和请求实体。response对象提供了控制和发送http响应的便利方法,比如设置响应头和响应实体(通常是jsp生成的html内容)。当http响应被提交并结束后,request和response对象都会被销毁。

如何管理session?知道cookie吗?

当客户端第一次访问web应用或者第一次使用request.getsession()获取httpsession时,servlet容器会创建session,生成一个long类型的唯一id(你可以使用session.getid()获取它)并把它保存在服务器的内存里。servlet容器同样会在http响应里设置一个cookie,cookie的名是jsessionid并且cookie的值是session的唯一id。

根据http cookie规范(正规的web浏览器和web服务器必须遵守的约定),在cookie的有效期间,客户端(web浏览器)之后的请求都要把这个cookie返回给服务器。servlet容器会利用带有名为jsessionid的cookie检测每一个到来的http请求头,并使用cookie的值从服务器内容里获取相关的httpsession。

httpsession会一直存活着,除非超过一段时间没使用。你可以在web.xml里设定这个时间段,默认时间段是30分钟。因此,如果客户端已经超过30分钟没有访问web应用的话,servlet容器就会销毁session。之后的每一个请求,即使带有特定的cookie,都再也不会访问到同一个session了。servletcontainer会创建一个新的session。

现有的session

web服务器和应用服务器的区别,一分钟带你搞懂这两者的关联

新的session

web服务器和应用服务器的区别,一分钟带你搞懂这两者的关联

另外,在客户端的session cookie拥有一个默认的存活时间,这个时间与浏览器的运行时间相同。因此,当用户关闭浏览器后(所有的标签或者窗口),客户端的session就会被销毁。重新打开浏览器后,与之前的session关联的cookie就再也不会被发送出去了。再次使用request.getsession()会返回一个全新的httpsession并且使用一个全新的session id来设置cookie。

如何确保线程安全?

你现在应该已经知道所有的请求都在共享servlet和filter。这是java的一个很棒的特性,它是多线程的并且不同的线程(即http请求)可以使用同一个实例。否则,对每一个请求都重新创建一个实体会耗费很多的资源。

web服务器和应用服务器的区别,一分钟带你搞懂这两者的关联