V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
lml12377
V2EX  ›  程序员

Tomcat / JVM / Servlet / Cgi 的关系?

  •  
  •   lml12377 · 2016-09-02 10:24:17 +08:00 · 5250 次点击
    这是一个创建于 3033 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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 有点理解不能。。。

    第 1 条附言  ·  2016-09-04 18:11:10 +08:00
    http://www.ibm.com/developerworks/cn/java/j-lo-tomcat1/image001.gif

    这个 container 里面是 N 个 ServletContext ,每个 ServletContext 里面是一个 ApplicationContext ?
    27 条回复    2016-09-03 19:46:02 +08:00
    hcymk2
        1
    hcymk2  
       2016-09-02 11:01:05 +08:00   ❤️ 1
    tomcat 可以单独运行 不需要 webserver 的
    misaka19000
        2
    misaka19000  
       2016-09-02 11:10:12 +08:00   ❤️ 1
    Tomcat 本身包含了连接器( connector )和容器( container )

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

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

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

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

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

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

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

    因为多进程, apache 开发必须依赖外部应用(比如数据库或 redis )才能存储状态,打个比方,就实现一个简单的计数器, servlet 直接放内存就行了, cgi 的话就必须要靠数据库或者 redis 了
    guoziyan
        21
    guoziyan  
       2016-09-03 03:49:52 +08:00   ❤️ 1
    并不是非编译型的语言每次请求需要初始化环境,而是无法常驻内存的语言才需要,比如 PHP
    lml12377
        22
    lml12377  
    OP
       2016-09-03 10:48:18 +08:00
    @SoloCompany 是不是像 WSGI /servlet 这种都是各自的语言自己来实现的?比如 tomcat 是 servlet 容器,那静态请求来了, tomcat 创建默认的 servlet 来处理静态请求,动态页面请求比如 .jsp 就实例化一个内含 ApplicationContext 的 servlet 去处理?因为它们都是 java 编写的,所以它们之间嵌套,并最终在 JVM 这个环境上执行。

    而不是像 apache + fpm , apache 只负责静态资源,动态资源每次申请创建新的解释器进程,通过 cgi 标准来通信。

    是不是可以这样理解~
    lml12377
        23
    lml12377  
    OP
       2016-09-03 10:48:40 +08:00
    @guoziyan 收到!
    lml12377
        24
    lml12377  
    OP
       2016-09-03 11:01:23 +08:00
    @guoziyan 是不是常驻型的可以自己实现容器,容器内自己处理静态请求的同时处理动态请求,相当于它自己既充当了 http 服务器的角色,又充当了 application server 的角色(每次这么打比方都有点怕。。。)

    假设我用 c 写了一个程序,本身可以处理静态请求比如 html / image ,而当用户请求 blog-list-p1.c 的时候,我还能用这个程序去连接数据库,编写可复用的组件,是不是这个就相当于 tomcat / servlet 或者 WSGI 实现的一种存在?并且还不需要 jvm 这种解释器。。。(好先进啊,你懂的。。。)
    lml12377
        25
    lml12377  
    OP
       2016-09-03 11:05:36 +08:00
    @SoloCompany 谢谢!有点头绪了~
    julyclyde
        26
    julyclyde  
       2016-09-03 18:06:41 +08:00   ❤️ 1
    @lml12377 fpm 不是通过 cgi 标准的,而是 fastcgi
    lml12377
        27
    lml12377  
    OP
       2016-09-03 19:46:02 +08:00
    @guoziyan 假设做个 php 的解释器,常驻内存,去掉比如 nginx / apache 的 http 静态资源服务器, master 负责格式化 http 请求,分发给 worker , defaultWorker 处理静态资源,其余的处理动态 .php 请求,而现在 php 是有中间码 opcode ,是不是这样,我将来直接运行这个“高级”的解释器,它就可以处理所有的 http 请求了,甚至连 apache 和 jvm 都不需要,因为这个“高级”的解释器都是内含的?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   835 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 21:18 · PVG 05:18 · LAX 13:18 · JFK 16:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.