1.常见web服务器
- webLogic:oracle公司,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。
- webSphere:IBM公司,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。
- JBOSS:JBOSS公司的,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。
- Tomcat:Apache基金组织,中小型的JavaEE服务器,仅仅支持少量的JavaEE规范。开源的,免费的。
2.Web服务器工作原理
2.1 Http工作原理 从图上你可以看到,这个过程是: 1) 用户通过浏览器进行了一个操作,比如输入网址并回车,或者是点击链接,接着浏览器获取了这个事件。 2) 浏览器向服务端发出TCP连接请求。 3) 服务程序接受浏览器的连接请求,并经过TCP三次握手建立连接。 4) 浏览器将请求数据打包成一个HTTP协议格式的数据包。 5) 浏览器将该数据包推入网络,数据包经过网络传输,最终达到端服务程序。 6) 服务端程序拿到这个数据包后,同样以HTTP协议格式解包,获取到客户端的意图。 7) 得知客户端意图后进行处理,比如提供静态文件或者调用服务端程序获得动态结果。 8) 服务器将响应结果(可能是HTML或者图片等)按照HTTP协议格式打包。 9) 服务器将响应数据包推入网络,数据包经过网络传输最终达到到浏览器。 10) 浏览器拿到数据包后,以HTTP协议的格式解包,然后解析数据,假设这里的数据是HTML。 11) 浏览器将HTML文件展示在页面上。
2.2.1 Http服务器请求处理 浏览器发给服务端的是一个HTTP格式的请求,服务器收到这个请求后,需要调用服务端程序来处理,所谓的服务端程序就是你写的Java类,一般来说不同的请求需要由不同的Java类来处理。 1) 图1,表示HTTP服务器直接调用具体业务类,它们是紧耦合的。 2) 图2,HTTP服务器不直接调用业务类,而是把请求交给容器来处理,容器通过Servlet接口调用业务类。因此Servlet接口和Servlet容器的出现,达到了HTTP服务器与业务类解耦的目的。而Servlet接口和Servlet容器这一整套规范叫作Servlet规范。 Tomcat是按照Servlet规范的要求实现了的Servlet容器,同时它们也具有HTTP服务器的功能。作为Java程序员,如果我们要实现新的业务功能,只需要实现一个Servlet,并把它注册到Tomcat(Servlet容器)中,剩下的事情就由Tomcat帮我们处理了。 2.2.2 Servlet容器工作流程 当客户请求某个资源时,HTTP服务器(Tomcat)会用一ServletRequest对象把客户的请求信息封装起来,然后调用Servlet容器service方法,Servlet容器拿到请求后,根据请求的URL和Servlet的映射关系,找到相应的Servlet,如果Servlet还没有被加载,就用反射机制创建这个Servlet,并调用Servlet的init方法来完成初始化,接着调用Servlet的service方法来处理请求,把ServletResponse对象返回给HTTP服务器,HTTP服务器会把响应发送给客户端。
3 Tomcat整体架构
通过上面分析,我们已经了解了Tomcat要实现两个核心功能: 1) 处理Socket连接,负责网络字节流与Request和Response对象的转化。 2) 加载和管理Servlet,以及具体处理Request请求。 因此Tomcat设计了两个核心组件连接器(Connector)和容器(Container)来分别做这两件事情。连接器负责对外交流,容器负责内部处理。 3.1 连接器 - Coyote Coyote 封装了底层的网络通信(Socket 请求及响应处理),为Catalina 容器提供了统一的接口,使Catalina 容器与具体的请求协议及IO操作方式完全解耦。Coyote 将Socket 输入转换封装为 Request 对象,交由Catalina 容器进行处理,处理请求完成后, Catalina 通过Coyote 提供的Response 对象将结果写入输出流 。Coyote 作为独立的模块,只负责具体协议和IO的相关操作, 与Servlet 规范实现没有直接关系,因此即便是 Request 和 Response 对象也并未实现Servlet规范对应的接口, 而是在Catalina 中将他们进一步封装为ServletRequest 和 ServletResponse 。 3.1.1 连接器组件 连接器(Coyote)中的各个组件的作用如下:
- Coyote 通信端点,即通信监听的接口,是具体Socket接收和发送处理器,是对传输层的抽象,因此EndPoint用来实现TCP/IP协议的。Tomcat 并没有EndPoint 接口,而是提供了一个抽象类AbstractEndpoint , 里面定义了两个内部类:Acceptor和SocketProcessor。Acceptor用于监听Socket连接请求。SocketProcessor用于处理接收到的Socket请求,它实现Runnable接口,在Run方法里调用协议处理组件Processor进行处理。为了提高处理能力,SocketProcessor被提交到线程池来执行。而这个线程池叫作执行器(Executor)。
- Processor : Coyote 协议处理接口 ,如果说EndPoint是用来实现TCP/IP协议的,那么Processor用来实现HTTP协议,Processor接收来自EndPoint的Socket,读取字节流解析成Tomcat Request和Response对象,并通过Adapter将其提交到容器处理,Processor是对应用层协议的抽象。
- ProtocolHandler: Coyote 协议接口, 通过Endpoint 和 Processor , 实现针对具体协议的处理能力。Tomcat 按照协议和I/O 提供了6个实现类 : AjpNioProtocol ,AjpAprProtocol, AjpNio2Protocol , Http11NioProtocol ,Http11Nio2Protocol ,Http11AprProtocol。我们在配置tomcat/conf/server.xml 时 , 至少要指定具体的ProtocolHandler , 当然也可以指定协议名称 , 如 : HTTP/1.1 ,如果安装了APR,那么将使用Http11AprProtocol , 否则使用 Http11NioProtocol 。
- Adapter:由于协议不同,客户端发过来的请求信息也不尽相同,Tomcat定义了自己的Request类来“存放”这些请求信息。ProtocolHandler接口负责解析请求并生成Tomcat Request类。
但是这个Request对象不是标准的ServletRequest,也就意味着,不能用TomcatRequest作为参数来调用容器。Tomcat设计者的解决方案是引入CoyoteAdapter,这是适配器模式的经典运用,连接器调用CoyoteAdapter的Sevice方法,传入的是Tomcat Request对象,CoyoteAdapter负责将Tomcat Request转成ServletRequest,再调用容器的Service方法。
3.2 容器 - Catalina 如上图所示,Catalina负责管理Server,而Server表示着整个服务器。Server下面有多个服务Service,每个服务都包含着多个连接器组件Connector(Coyote 实现)和一个容器组件Container。在Tomcat 启动的时候, 会初始化一个Catalina的实例。
3.2.1 Catalina 各个组件的职责: 3.2.2 Container 结构 Tomcat设计了4种容器,分别是Engine、Host、Context和Wrapper。这4种容器不是平行关系,而是父子关系。Tomcat通过一种分层的架构,使得Servlet容器具有很好的灵活性。
4 Tomcat 启动流程
步骤 : 1) 启动tomcat , 需要调用 bin/startup.bat (在linux 目录下 , 需要调用 bin/startup.sh), 在startup.bat 脚本中, 调用了catalina.bat。 2) 在catalina.bat 脚本文件中,调用了BootStrap 中的main方法。 3)在BootStrap 的main 方法中调用了 init 方法 , 来创建Catalina 及 初始化类加载器。 4)在BootStrap 的main 方法中调用了 load 方法 , 在其中又调用了Catalina的load方法。 5)在Catalina 的load 方法中 , 需要进行一些初始化的工作, 并需要构造Digester 对象, 用于解析 XML。 6) 然后在调用后续组件的初始化操作 。。。 最后,加载Tomcat的配置文件,初始化容器组件 ,监听对应的端口号, 准备接受客户端请求
|