<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>深入拆解 Tomcat &amp; Jetty on Colommar Blog</title><link>https://www.colommar.asia/books/tomcat-jetty/</link><description>Recent content in 深入拆解 Tomcat &amp; Jetty on Colommar Blog</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Mon, 17 Mar 2025 00:00:00 +0800</lastBuildDate><atom:link href="https://www.colommar.asia/books/tomcat-jetty/index.xml" rel="self" type="application/rss+xml"/><item><title>阅读说明</title><link>https://www.colommar.asia/books/tomcat-jetty/tomcat-reading-context/</link><pubDate>Fri, 14 Feb 2025 00:00:00 +0800</pubDate><guid>https://www.colommar.asia/books/tomcat-jetty/tomcat-reading-context/</guid><description>&lt;p>学习参考的是李号双老师的 深入拆解Tomcat &amp;amp; Jetty，写的非常好。
但实际上我没有看完，我只看到第 22 章 （22 章看完），后面对我目前的帮助并不大。&lt;/p></description></item><item><title>1.Servlet规范和Servlet容器</title><link>https://www.colommar.asia/books/tomcat-jetty/tomcat-servlet-specification/</link><pubDate>Fri, 14 Feb 2025 00:00:00 +0800</pubDate><guid>https://www.colommar.asia/books/tomcat-jetty/tomcat-servlet-specification/</guid><description>&lt;p>&lt;img decoding="async" height="500" loading="lazy" sizes="(max-width: 768px) calc(100vw - 48px), 768px" src="https://www.colommar.asia/optimized-images/tomcat-jetty/1/image-01_hu_ec799358f89513af.webp" srcset="https://www.colommar.asia/optimized-images/tomcat-jetty/1/image-01_hu_8037adac607d6924.webp 480w, https://www.colommar.asia/optimized-images/tomcat-jetty/1/image-01_hu_d5029da5f25513ad.webp 768w, https://www.colommar.asia/optimized-images/tomcat-jetty/1/image-01_hu_ec799358f89513af.webp 1200w" width="1200">&lt;/p>
&lt;p>&lt;font style="color:rgb(53, 53, 53);">图的左边表示 HTTP 服务器直接调用具体业务类，它们是紧耦合的。再看图的右边，HTTP 服务器不直接调用业务类，而是把请求交给容器来处理，容器通过 Servlet 接口调用业务类。因此 Servlet 接口和 Servlet 容器的出现，达到了 HTTP 服务器与业务类解耦的目的。&lt;/font>&lt;/p>
&lt;p>&lt;font style="color:rgb(53, 53, 53);">而 Servlet 接口和 Servlet 容器这一整套规范叫作 Servlet 规范。Tomcat 和 Jetty 都按照 Servlet 规范的要求实现了 Servlet 容器，同时它们也具有 HTTP 服务器的功能。作为 Java 程序员，如果我们要实现新的业务功能，只需要实现一个 Servlet，并把它注册到 Tomcat（Servlet 容器）中，剩下的事情就由 Tomcat 帮我们处理了。&lt;/font>&lt;/p>
&lt;h2 id="servlet-接口">&lt;font style="color:rgb(53, 53, 53);">Servlet 接口&lt;/font>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-java" data-lang="java">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">interface&lt;/span> &lt;span class="nc">Servlet&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kt">void&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">init&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ServletConfig&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">config&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">throws&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">ServletException&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">ServletConfig&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">getServletConfig&lt;/span>&lt;span class="p">();&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kt">void&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">service&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ServletRequest&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">req&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">ServletResponse&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">res&lt;/span>&lt;span class="err">）&lt;/span>&lt;span class="kd">throws&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">ServletException&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">IOException&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">String&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">getServletInfo&lt;/span>&lt;span class="p">();&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kt">void&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">destroy&lt;/span>&lt;span class="p">();&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;font style="color:rgb(53, 53, 53);">其中最重要是的 service 方法，具体业务类在这个方法里实现处理逻辑。这个方法有两个参数：ServletRequest 和 ServletResponse。ServletRequest 用来封装请求信息，ServletResponse 用来封装响应信息，因此&lt;/font>&lt;strong>&lt;font style="color:rgb(53, 53, 53);">本质上这两个类是对通信协议的封装。&lt;/font>&lt;/strong>&lt;/p></description></item><item><title>2.运行一个Servlet</title><link>https://www.colommar.asia/books/tomcat-jetty/tomcat-run-servlet/</link><pubDate>Tue, 18 Feb 2025 00:00:00 +0800</pubDate><guid>https://www.colommar.asia/books/tomcat-jetty/tomcat-run-servlet/</guid><description>&lt;p>今天我们就抛弃 IDE、拒绝框架，自己纯手工编写一个 Servlet，并在 Tomcat 中运行起来。一方面进一步加深对 Servlet 的理解；另一方面，还可以熟悉一下 Tomcat 的基本功能使用。&lt;/p>
&lt;p>主要的步骤有：&lt;/p>
&lt;ol>
&lt;li>下载并安装 Tomcat。&lt;/li>
&lt;li>编写一个继承 HttpServlet 的 Java 类。&lt;/li>
&lt;li>将 Java 类文件编译成 Class 文件。&lt;/li>
&lt;li>建立 Web 应用的目录结构，并配置 web.xml。&lt;/li>
&lt;li>部署 Web 应用。&lt;/li>
&lt;li>启动 Tomcat。&lt;/li>
&lt;li>浏览器访问验证结果。&lt;/li>
&lt;li>查看 Tomcat 日志。&lt;/li>
&lt;/ol>
&lt;h1 id="动手时间">动手时间&lt;/h1>
&lt;ol>
&lt;li>安装 tomcat&lt;/li>
&lt;/ol>
&lt;p>&lt;img decoding="async" height="564" loading="lazy" sizes="(max-width: 768px) calc(100vw - 48px), 768px" src="https://www.colommar.asia/optimized-images/tomcat-jetty/2/image-01_hu_8ffbb7e0a160f24c.webp" srcset="https://www.colommar.asia/optimized-images/tomcat-jetty/2/image-01_hu_8ffbb7e0a160f24c.webp 376w" width="376">&lt;/p>
&lt;p>&lt;font style="color:rgb(53, 53, 53);">/bin：存放 Windows 或 Linux 平台上启动和关闭 Tomcat 的脚本文件。&lt;/font>&lt;br>
&lt;font style="color:rgb(53, 53, 53);">/conf：存放 Tomcat 的各种全局配置文件，其中最重要的是 server.xml。&lt;/font>&lt;br>
&lt;font style="color:rgb(53, 53, 53);">/lib：存放 Tomcat 以及所有 Web 应用都可以访问的 JAR 文件。&lt;/font>&lt;br>
&lt;font style="color:rgb(53, 53, 53);">/logs：存放 Tomcat 执行时产生的日志文件。&lt;/font>&lt;br>
&lt;font style="color:rgb(53, 53, 53);">/work：存放 JSP 编译后产生的 Class 文件。&lt;/font>&lt;br>
&lt;font style="color:rgb(53, 53, 53);">/webapps：Tomcat 的 Web 应用目录，默认情况下把 Web 应用放在这个目录下。&lt;/font>&lt;/p></description></item><item><title>3.tomcat架构</title><link>https://www.colommar.asia/books/tomcat-jetty/tomcat-architecture/</link><pubDate>Sun, 02 Mar 2025 00:00:00 +0800</pubDate><guid>https://www.colommar.asia/books/tomcat-jetty/tomcat-architecture/</guid><description>&lt;p>&lt;font style="color:rgb(53, 53, 53);">我们已经了解了 Tomcat 要实现 2 个核心功能：&lt;/font>&lt;/p>
&lt;ul>
&lt;li>&lt;font style="color:rgb(53, 53, 53);">处理 Socket 连接，负责网络字节流与 Request 和 Response 对象的转化。&lt;/font>&lt;/li>
&lt;li>&lt;font style="color:rgb(53, 53, 53);">加载和管理 Servlet，以及具体处理 Request 请求。&lt;/font>&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>&lt;font style="color:rgb(53, 53, 53);">因此 Tomcat 设计了两个核心组件连接器（Connector）和容器（Container）来分别做这两件事情。连接器负责对外交流，容器负责内部处理。&lt;/font>&lt;/strong>&lt;/p>
&lt;h1 id="连接器">&lt;font style="color:rgb(53, 53, 53);">连接器&lt;/font>&lt;/h1>
&lt;p>&lt;font style="color:rgb(53, 53, 53);">Tomcat 支持多种 I/O 模型和应用层协议。&lt;/font>&lt;/p>
&lt;p>&lt;font style="color:rgb(53, 53, 53);">Tomcat 支持的 I/O 模型有：&lt;/font>&lt;/p>
&lt;ul>
&lt;li>&lt;font style="color:rgb(53, 53, 53);">NIO：非阻塞 I/O，采用 Java NIO 类库实现。&lt;/font>&lt;/li>
&lt;li>&lt;font style="color:rgb(53, 53, 53);">NIO2：异步 I/O，采用 JDK 7 最新的 NIO2 类库实现。&lt;/font>&lt;/li>
&lt;li>&lt;font style="color:rgb(53, 53, 53);">APR：采用 Apache 可移植运行库实现，是 C/C++ 编写的本地库。&lt;/font>&lt;/li>
&lt;/ul>
&lt;p>&lt;font style="color:rgb(53, 53, 53);">Tomcat 支持的应用层协议有：&lt;/font>&lt;/p>
&lt;ul>
&lt;li>&lt;font style="color:rgb(53, 53, 53);">HTTP/1.1：这是大部分 Web 应用采用的访问协议。&lt;/font>&lt;/li>
&lt;li>&lt;font style="color:rgb(53, 53, 53);">AJP：用于和 Web 服务器集成（如 Apache）。&lt;/font>&lt;/li>
&lt;li>&lt;font style="color:rgb(53, 53, 53);">HTTP/2：HTTP 2.0 大幅度的提升了 Web 性能。&lt;/font>&lt;/li>
&lt;/ul>
&lt;p>&lt;font style="color:rgb(53, 53, 53);">Tomcat 为了实现支持多种 I/O 模型和应用层协议，一个容器可能对接多个连接器，就好比一个房间有多个门。但是单独的连接器或者容器都不能对外提供服务，需要把它们组装起来才能工作，组装后这个整体叫作 Service 组件。这里请你注意，Service 本身没有做什么重要的事情，只是在连接器和容器外面多包了一层，把它们组装在一起。Tomcat 内可能有多个 Service，这样的设计也是出于灵活性的考虑。通过在 Tomcat 中配置多个 Service，可以实现通过不同的端口号来访问同一台机器上部署的不同应用。&lt;/font>&lt;/p></description></item><item><title>4.tomcat中的池技术：线程池_对象池</title><link>https://www.colommar.asia/books/tomcat-jetty/tomcat-thread-object-pools/</link><pubDate>Sun, 09 Mar 2025 00:00:00 +0800</pubDate><guid>https://www.colommar.asia/books/tomcat-jetty/tomcat-thread-object-pools/</guid><description>&lt;h1 id="executor组件tomcat如何扩展java线程池">Executor组件：Tomcat如何扩展Java线程池？&lt;/h1>
&lt;h2 id="java-线程池">java 线程池&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-java" data-lang="java">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">ThreadPoolExecutor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">corePoolSize&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">maximumPoolSize&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kt">long&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">keepAliveTime&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">TimeUnit&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">unit&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">BlockingQueue&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Runnable&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">workQueue&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">ThreadFactory&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">threadFactory&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">RejectedExecutionHandler&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">handler&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;font style="color:rgb(53, 53, 53);">每次提交任务时，如果线程数还没达到核心线程数&lt;/font>&lt;strong>&lt;font style="color:rgb(53, 53, 53);">corePoolSize&lt;/font>&lt;/strong>&lt;font style="color:rgb(53, 53, 53);">，线程池就创建新线程来执行。当线程数达到&lt;/font>&lt;strong>&lt;font style="color:rgb(53, 53, 53);">corePoolSize&lt;/font>&lt;/strong>&lt;font style="color:rgb(53, 53, 53);">后，新增的任务就放到工作队列&lt;/font>&lt;strong>&lt;font style="color:rgb(53, 53, 53);">workQueue&lt;/font>&lt;/strong>&lt;font style="color:rgb(53, 53, 53);">里，而线程池中的线程则努力地从&lt;/font>&lt;strong>&lt;font style="color:rgb(53, 53, 53);">workQueue&lt;/font>&lt;/strong>&lt;font style="color:rgb(53, 53, 53);">里拉活来干，也就是调用 poll 方法来获取任务。&lt;/font>&lt;/p>
&lt;p>&lt;font style="color:rgb(53, 53, 53);">如果任务很多，并且&lt;/font>&lt;strong>&lt;font style="color:rgb(53, 53, 53);">workQueue&lt;/font>&lt;/strong>&lt;font style="color:rgb(53, 53, 53);">是个有界队列，队列可能会满，此时线程池就会紧急创建新的临时线程来救场，如果总的线程数达到了最大线程数&lt;/font>&lt;strong>&lt;font style="color:rgb(53, 53, 53);">maximumPoolSize&lt;/font>&lt;/strong>&lt;font style="color:rgb(53, 53, 53);">，则不能再创建新的临时线程了，转而执行拒绝策略&lt;/font>&lt;strong>&lt;font style="color:rgb(53, 53, 53);">handler&lt;/font>&lt;/strong>&lt;font style="color:rgb(53, 53, 53);">，比如抛出异常或者由调用者线程来执行任务等。&lt;/font>&lt;/p>
&lt;p>&lt;font style="color:rgb(53, 53, 53);">如果高峰过去了，线程池比较闲了怎么办？临时线程使用 poll（&lt;/font>&lt;strong>&lt;font style="color:rgb(53, 53, 53);">keepAliveTime, unit&lt;/font>&lt;/strong>&lt;font style="color:rgb(53, 53, 53);">）方法从工作队列中拉活干，请注意 poll 方法设置了超时时间，如果超时了仍然两手空空没拉到活，表明它太闲了，这个线程会被销毁回收。&lt;/font>&lt;/p></description></item><item><title>5.spring-boot如何处理tomcat</title><link>https://www.colommar.asia/books/tomcat-jetty/spring-boot-tomcat/</link><pubDate>Mon, 17 Mar 2025 00:00:00 +0800</pubDate><guid>https://www.colommar.asia/books/tomcat-jetty/spring-boot-tomcat/</guid><description>&lt;p>&lt;font style="color:rgb(53, 53, 53);">为了方便开发和部署，Spring Boot 在内部启动了一个嵌入式的 Web 容器。我们知道 Tomcat 和 Jetty 是组件化的设计，要启动 Tomcat 或者 Jetty 其实就是启动这些组件。在 Tomcat 独立部署的模式下，我们通过 startup 脚本来启动 Tomcat，Tomcat 中的 Bootstrap 和 Catalina 会负责初始化类加载器，并解析&lt;/font>&lt;code>&amp;lt;font style=&amp;quot;color:rgb(53, 53, 53);&amp;quot;&amp;gt;server.xml&amp;lt;/font&amp;gt;&lt;/code>&lt;font style="color:rgb(53, 53, 53);">和启动这些组件。&lt;/font>&lt;/p>
&lt;p>&lt;font style="color:rgb(53, 53, 53);">在内嵌式的模式下，Bootstrap 和 Catalina 的工作就由 Spring Boot 来做了，Spring Boot 调用了 Tomcat 和 Jetty 的 API 来启动这些组件。那 Spring Boot 具体是怎么做的呢？而作为程序员，我们如何向 SpringBoot 中的 Tomcat 注册 Servlet 或者 Filter 呢？我们又如何定制内嵌式的 Tomcat？今天我们就来聊聊这些话题。&lt;/font>&lt;/p>
&lt;h2 id="spring-boot-中-web-容器相关的接口">&lt;font style="color:rgb(53, 53, 53);">Spring Boot 中 Web 容器相关的接口&lt;/font>&lt;/h2>
&lt;p>&lt;font style="color:rgb(53, 53, 53);">既然要支持多种 Web 容器，Spring Boot 对内嵌式 Web 容器进行了抽象，定义了&lt;/font>&lt;strong>&lt;font style="color:rgb(53, 53, 53);">WebServer&lt;/font>&lt;/strong>&lt;font style="color:rgb(53, 53, 53);">接口：&lt;/font>&lt;/p></description></item></channel></rss>