Tomcat / JVM / Servlet / Cgi 的关系?

2016-09-02 10:24:17 +08:00
 lml12377

http 服务器负责接收客户端请求,找资源,返回资源给客户端,比如 apache / nginx ,如果请求的是静态资源,比如 html / image , http 服务器就直接找到并返回给客户端了。

这个时候如果客户端请求比如 php , http 服务器自己无法解析 php 的文件,如果没有配置解释器那它就会直接把这个 php 的源码给展示了出来(当成了文本文件),如果 http 服务器配置了解释器,因此它知道 php 这种后缀的文件应该去请求 php-cgi ,于是它就去让 php-cgi 执行 php , php 完成处理后把结果给 http 服务器, http 服务器把结果再给客户端。另外为了解决非编译型语言每次都初始化应用基础环境的重复工作,于是出现了 fast-cgi 的标准( master 执行初始化后就变成常驻进程,开启 worker 来处理单个请求), php-fpm 就是这个标准的具体实现。

那 tomcat 跟上面对比,是不是也是类似于 php-cgi 实现的一种存在?是不是这样: jsp 请求过来了, http 服务器不知道怎么解析,一看配置,需要去找 tomcat ,于是转给 tomcat ,但是 java 程序是需要 JVM 环境的,所以 tomcat 建立在 JVM 之上执行,而 tomcat 本身是个容器,需要实际的 worker 来解析 jsp ,于是就去实例化一个 servlet 来解析,最后再一层层回归到客户端。

是不是这样理解的?

求指点。。。

其实主要是在研究 ApplicationContext 发现它可以引用装载自己的 ServletContext ,因为是个 phper (世界上最好的语言,你懂的~),对这个 Servlet 有点理解不能。。。

5042 次点击
所在节点    程序员
27 条回复
hcymk2
2016-09-02 11:01:05 +08:00
tomcat 可以单独运行 不需要 webserver 的
misaka19000
2016-09-02 11:10:12 +08:00
Tomcat 本身包含了连接器( connector )和容器( container )

前者可以看作用来获取 HTTP 请求的,后者则是对前者所获取到的请求做进一步的处理
jint
2016-09-02 11:17:26 +08:00
tomcat 是一个 servlet 容器,容器和 servlet 之间按照协议的约定来分工合作。
你思考这个问题的时候,把 JVM 透明化就好了。
jint
2016-09-02 11:18:00 +08:00
每一个 JSP ,归根到底也还是一个 Servlet 。
crazyxin1988
2016-09-02 11:27:09 +08:00
先谈谈 Java web 的体系

首先是 servlet 规范 这个协议是干嘛的呢? 就是规范了应用和容器的通信。简单的说,比如你用 SpringMVC 写了一个 web 应用, springmvc 是遵守 servlet 规范的,所以,它可以跑在任何遵循 servlet 规范的容器上,比如,它可以跑在 tomcat 上, tomcat 就是一个 servlet 容器,当然,它也可以跑在 jetty 上。

tomcat 是用 java 语言开发的,所以, tomcat 就是一个 java 应用,需要跑在 JVM 中,就是 java 虚拟机。

关于 cgi ,在 java 里很少接触,一般都是脚本语言里使用。
hduwzy
2016-09-02 11:35:17 +08:00
基本赞同,但是有一句不赞同。建立 servlet 不是用来解析 jsp 的, servlet 本身就能对请求做出响应。准确的讲是 jsp 被编译成一个 servlet ,是这个 servlet 对请求做出响应
julyclyde
2016-09-02 12:24:42 +08:00
建议把“应用和容器的”“通信”改为“调用关系”,更明确一些
要不然总有人会被带到沟里去
lml12377
2016-09-02 13:41:44 +08:00
@crazyxin1988 明白了,谢谢!
lml12377
2016-09-02 14:18:56 +08:00
@crazyxin1988 是不是这样:[php] 客户端 -> apache -> (cgi request) -> php -> (cgi response) -> apache -> 客户端,[java web] 客户端 -> tomcat -> (servlet request) -> applicationContext -> (servlet response) -> tomcat -> 客户端
lml12377
2016-09-02 14:21:03 +08:00
@lml12377 是不是 tomcat container , servletContext , applicationContext 都是 java 写出来的对象?
lml12377
2016-09-02 14:23:24 +08:00
@julyclyde 好像是这个意思!
lml12377
2016-09-02 14:23:52 +08:00
@hduwzy 收到!
lml12377
2016-09-02 14:24:36 +08:00
@hcymk2 嗯嗯,之前理解有误
lml12377
2016-09-02 14:24:51 +08:00
@jint 收到!
lml12377
2016-09-02 14:25:21 +08:00
@misaka19000 这个我再去研究下~
julyclyde
2016-09-02 14:55:14 +08:00
@lml12377 http://julyclyde.org/?p=534
别把什么都往 CGI 上靠
lml12377
2016-09-02 15:09:57 +08:00
@julyclyde 只是想找个概念上“相似”的东西来做个类比,或许这样可以更好理解一点。。。
crazyxin1988
2016-09-02 21:08:37 +08:00
@lml12377
CGI 我不太了解
你要是想类比 我觉得 servlet 规范 类似于 python web 开发中的 WSGI
SoloCompany
2016-09-03 01:33:52 +08:00
你仔细看的话,会发现 tomcat 有一个隐藏在容器配置下的 web.xml ,
里面包含了所有规范内的内容(也就是 webapp 无需重复定义的内容)

最重要的有这两项配置
定义了 DefaultServlet 处理所有的没有路由的请求,主要是用于处理静态资源以及响应 404
定义了 JspServlet ,以及 mapping with *.jsp *.jspx

所以,在 Tomcat 里面,你可以认为所有的请求最终其实都是由一个 Servlet 来处理,包括静态资源
SoloCompany
2016-09-03 01:49:03 +08:00
Tomcat 只是一个很简单的容器,只支持单进程多线程一种,最大的优点就是一切内存都是共享的,麻烦的地方当然也在于共享内存和并发而无法避免的锁问题

Apache 有 prefork 和 worker 两种 MPM ,无论是哪种都是多进程(除非你把 ServerLimit 限制到 1 ), prefork 完全不需要考虑内存争夺, worker 因为支持线程并发控制要灵活的多但锁的问题当然也会存在

因为多进程, apache 开发必须依赖外部应用(比如数据库或 redis )才能存储状态,打个比方,就实现一个简单的计数器, servlet 直接放内存就行了, cgi 的话就必须要靠数据库或者 redis 了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/303396

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX