<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>-Flyぁ梦- &#187; Tomcat</title>
	<atom:link href="http://blog.11034.org/tag/tomcat/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.11034.org</link>
	<description></description>
	<lastBuildDate>Sun, 22 Jun 2025 08:59:05 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.2.38</generator>
	<item>
		<title>Tomcat监听shutdown释放数据库连接池</title>
		<link>http://blog.11034.org/2016-06/tomcat_shutdown.html</link>
		<comments>http://blog.11034.org/2016-06/tomcat_shutdown.html#comments</comments>
		<pubDate>Wed, 08 Jun 2016 12:41:47 +0000</pubDate>
		<dc:creator><![CDATA[-Flyぁ梦-]]></dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Tomcat]]></category>
		<category><![CDATA[数据库]]></category>
		<category><![CDATA[进程]]></category>

		<guid isPermaLink="false">http://blog.11034.org/?p=2836</guid>
		<description><![CDATA[开发时因为更新代码，频繁重启Tomcat，遇到一个问题：在执行shutdown脚本后，Tomcat进程没有关闭 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>开发时因为更新代码，频繁重启Tomcat，遇到一个问题：在执行shutdown脚本后，Tomcat进程没有关闭依然存在（但是HTTP服务已经停止），需要手动执行kill命令才行。查了一些资料结合经验，应该是所使用的数据库连接池中的连接没有被释放的问题引起的。所以解决的办法，就是想办法做一个Tomcat的shutdown的事件监听，然后手动释放数据库连接即可。<span id="more-2836"></span></p>
<h2>Tomcat的shutdown的事件监听</h2>
<p>很简单，实现一个ServletContextListener的实例，并注册到web.xml中即可。</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ShutdownListener <span style="color: #000000; font-weight: bold;">implements</span> ServletContextListener  <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> Logger logger <span style="color: #339933;">=</span> Logger.<span style="color: #006633;">getLogger</span><span style="color: #009900;">&#40;</span>ShutdownListener.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	@Override
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> contextDestroyed<span style="color: #009900;">&#40;</span>ServletContextEvent arg0<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		logger.<span style="color: #006633;">info</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;contextDestroyed&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		logger.<span style="color: #006633;">info</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;DBPool shutdown start...&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
			DBPool.<span style="color: #006633;">clear</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			DBPool.<span style="color: #006633;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">Throwable</span> e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			logger.<span style="color: #006633;">fatal</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;&quot;</span>, e<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		logger.<span style="color: #006633;">info</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;DBPool shutdown done&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	@Override
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> contextInitialized<span style="color: #009900;">&#40;</span>ServletContextEvent arg0<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		logger.<span style="color: #006633;">info</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;contextInitialized&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>


<div class="wp_syntax"><table><tr><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;listener<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;listener-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>xxx.xxx.xxx.ShutdownListener<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/listener-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/listener<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<h2>数据库连接池的关闭和释放</h2>
<p>代码中没有使用复杂的数据库连接池，是用<code class="markdown_inline_code">org.apache.commons.pool.impl.GenericObjectPool</code>和<code class="markdown_inline_code">org.apache.commons.pool.BasePoolableObjectFactory</code>组合实现的。</p>
<p>在ServletContextListener的contextDestroyed方法中</p>
<ol>
<li>执行GenericObjectPool.clear()，是将池内缓存的对象全部销毁</li>
<li>执行GenericObjectPool.close()，关闭对象池，不再支持borrowObject()，但依然支持returnObject()方法且return后将对象立即销毁</li>
</ol>
<p>做完这两步，执行Tomcat的shutdown脚本后，Tomcat进程过几秒就会自动关闭了。</p>
<h4  class="related_post_title">看看 Tomcat , 数据库 , 进程</h4><ul class="related_post"><li>2016-06-06 -- <a target="_blank" href="http://blog.11034.org/2016-06/tomcat_https.html" title="Tomcat启用https服务">Tomcat启用https服务</a></li><li>2015-08-28 -- <a target="_blank" href="http://blog.11034.org/2015-08/tomcat_linux.html" title="Linux下搭建Tomcat环境">Linux下搭建Tomcat环境</a></li><li>2015-01-07 -- <a target="_blank" href="http://blog.11034.org/2015-01/prevent_db_duplicate.html" title="防止数据库数据重复的几种方法">防止数据库数据重复的几种方法</a></li><li>2013-05-20 -- <a target="_blank" href="http://blog.11034.org/2013-05/coyote.html" title="Tomcat的Connector：Coyote">Tomcat的Connector：Coyote</a></li><li>2013-05-19 -- <a target="_blank" href="http://blog.11034.org/2013-05/tomcat6.html" title="Tomcat6源码学习">Tomcat6源码学习</a></li></ul><h4 class="related_post_title">看看 Java </h4><ul class="related_post"><li>2016-09-09 -- <a target="_blank" href="http://blog.11034.org/2016-09/64bits_linux_arena_memory.html" title="64位Linux下Java进程堆外内存迷之64M问题">64位Linux下Java进程堆外内存迷之64M问题</a></li><li>2016-08-18 -- <a target="_blank" href="http://blog.11034.org/2016-08/java_concurrency_in_practice.html" title="读java concurrency in practice">读java concurrency in practice</a></li><li>2016-08-05 -- <a target="_blank" href="http://blog.11034.org/2016-08/thread_stop.html" title="线程清理">线程清理</a></li><li>2016-06-21 -- <a target="_blank" href="http://blog.11034.org/2016-06/futuretask.html" title="FutureTask简单分析和用法">FutureTask简单分析和用法</a></li><li>2016-06-21 -- <a target="_blank" href="http://blog.11034.org/2016-06/semaphore.html" title="Semaphore简单分析">Semaphore简单分析</a></li>]]></content:encoded>
			<wfw:commentRss>http://blog.11034.org/2016-06/tomcat_shutdown.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Tomcat启用https服务</title>
		<link>http://blog.11034.org/2016-06/tomcat_https.html</link>
		<comments>http://blog.11034.org/2016-06/tomcat_https.html#comments</comments>
		<pubDate>Mon, 06 Jun 2016 14:27:44 +0000</pubDate>
		<dc:creator><![CDATA[-Flyぁ梦-]]></dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[HTTPS]]></category>
		<category><![CDATA[Tomcat]]></category>
		<category><![CDATA[安全]]></category>
		<category><![CDATA[证书]]></category>

		<guid isPermaLink="false">http://blog.11034.org/?p=2816</guid>
		<description><![CDATA[第一步，获取证书 这个就去百度吧，既有免费证书，也有收费的证书，当然收费的证书会更靠谱更受大众认同（比如Geo [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><span id="more-2816"></span></p>
<h2>第一步，获取证书</h2>
<p>这个就去百度吧，既有免费证书，也有收费的证书，当然收费的证书会更靠谱更受大众认同（比如GeoTrust的）。</p>
<p>然后证书分为3个等级，DV（Domain Validation，证明当前站点在指定域名下，最常见的），OV（Organization Validation，证明当前站点在指定公司or组织下，浏览器会在URL前显示公司名称的），EV（Extended Validation，比OV更加复杂安全的证书，一般为网银所使用）。</p>
<p>这里选择国内的免费证书：https://www.wosign.com/</p>
<p>在它家网站上注册用户，申请免费证书，要填写指定的域名地址和证书保护密码，然后就可以下载到证书了。下载的zip包里有专门供tomcat使用的jks证书。</p>
<h2>第二步，部署https</h2>
<p>将<code class="markdown_inline_code">apache-tomcat/conf/server.xml</code>中原来被注释的&lt;Connector port=&#8221;8443&#8243; &#8230; /&gt;打开，如下配置：</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Connector</span> <span style="color: #000066;">port</span>=<span style="color: #ff0000;">&quot;443&quot;</span> <span style="color: #000066;">protocol</span>=<span style="color: #ff0000;">&quot;org.apache.coyote.http11.Http11NioProtocol&quot;</span></span>
<span style="color: #009900;">    <span style="color: #000066;">acceptCount</span>=<span style="color: #ff0000;">&quot;100&quot;</span> <span style="color: #000066;">executor</span>=<span style="color: #ff0000;">&quot;tomcatThreadPool&quot;</span> <span style="color: #000066;">URIEncoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span> </span>
<span style="color: #009900;">    <span style="color: #000066;">compression</span>=<span style="color: #ff0000;">&quot;on&quot;</span> <span style="color: #000066;">compressableMimeType</span>=<span style="color: #ff0000;">&quot;text/html,text/css,application/javascript&quot;</span></span>
<span style="color: #009900;">    <span style="color: #000066;">SSLEnabled</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">scheme</span>=<span style="color: #ff0000;">&quot;https&quot;</span> <span style="color: #000066;">secure</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">clientAuth</span>=<span style="color: #ff0000;">&quot;false&quot;</span> <span style="color: #000066;">sslProtocol</span>=<span style="color: #ff0000;">&quot;TLS&quot;</span></span>
<span style="color: #009900;">    <span style="color: #000066;">keystoreFile</span>=<span style="color: #ff0000;">&quot;/home/.../xxx.com.jks&quot;</span> <span style="color: #000066;">keystorePass</span>=<span style="color: #ff0000;">&quot;xxxxxxx&quot;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">/&gt;</span></span></pre></td></tr></table></div>

<p>这里的配置要和<code class="markdown_inline_code">&lt;Connector port="80"  .../&gt;</code>的配置要完全一致，第一行是基础协议，第二行是优化参数和设置编码，第三行是开启静态资源压缩，最后两行是对于SSL特殊的设置。</p>
<pre class="markdown_pre"><code>在https的Connector中忘记加上URIEncoding="UTF-8"，会导致https中文异常而http正常
（http的&lt;Connector /&gt;自带这个属性）</code></pre>
<h2>第三步，http自动跳转到https</h2>
<p>给<code class="markdown_inline_code">&lt;Connector port="80"  .../&gt;</code>加上属性<code class="markdown_inline_code">redirectPort="443"</code>，这个默认就有。</p>
<p>然后再修改<code class="markdown_inline_code">apache-tomcat/conf/web.xml</code>，最后加上一段：</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;security-constraint<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;web-resource-collection<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;web-resource-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Protected Context<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/web-resource-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>/*<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/web-resource-collection<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #808080; font-style: italic;">&lt;!-- auth-constraint goes here if you requre authentication --&gt;</span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;user-data-constraint<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;transport-guarantee<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>CONFIDENTIAL<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/transport-guarantee<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/user-data-constraint<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/security-constraint<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>搞定</p>
<h2>第三步，https的注意事项</h2>
<ul>
<li>在https下，如果页面内还存在有http链接的内容（图片、js等静态资源），则会产生警告，并在浏览器URL栏中失去绿色锁的标志</li>
<li>在https下，如果页面内企图发起http的post请求，则会默认被浏览器禁止，并产生警告</li>
</ul>
<h4  class="related_post_title">看看 HTTPS , Tomcat , 安全 , 证书</h4><ul class="related_post"><li>2016-06-08 -- <a target="_blank" href="http://blog.11034.org/2016-06/tomcat_shutdown.html" title="Tomcat监听shutdown释放数据库连接池">Tomcat监听shutdown释放数据库连接池</a></li><li>2015-08-28 -- <a target="_blank" href="http://blog.11034.org/2015-08/tomcat_linux.html" title="Linux下搭建Tomcat环境">Linux下搭建Tomcat环境</a></li><li>2013-05-20 -- <a target="_blank" href="http://blog.11034.org/2013-05/coyote.html" title="Tomcat的Connector：Coyote">Tomcat的Connector：Coyote</a></li><li>2013-05-19 -- <a target="_blank" href="http://blog.11034.org/2013-05/tomcat6.html" title="Tomcat6源码学习">Tomcat6源码学习</a></li></ul><h4 class="related_post_title">看看 Java </h4><ul class="related_post"><li>2016-09-09 -- <a target="_blank" href="http://blog.11034.org/2016-09/64bits_linux_arena_memory.html" title="64位Linux下Java进程堆外内存迷之64M问题">64位Linux下Java进程堆外内存迷之64M问题</a></li><li>2016-08-18 -- <a target="_blank" href="http://blog.11034.org/2016-08/java_concurrency_in_practice.html" title="读java concurrency in practice">读java concurrency in practice</a></li><li>2016-08-05 -- <a target="_blank" href="http://blog.11034.org/2016-08/thread_stop.html" title="线程清理">线程清理</a></li><li>2016-06-21 -- <a target="_blank" href="http://blog.11034.org/2016-06/futuretask.html" title="FutureTask简单分析和用法">FutureTask简单分析和用法</a></li><li>2016-06-21 -- <a target="_blank" href="http://blog.11034.org/2016-06/semaphore.html" title="Semaphore简单分析">Semaphore简单分析</a></li>]]></content:encoded>
			<wfw:commentRss>http://blog.11034.org/2016-06/tomcat_https.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Linux下搭建Tomcat环境</title>
		<link>http://blog.11034.org/2015-08/tomcat_linux.html</link>
		<comments>http://blog.11034.org/2015-08/tomcat_linux.html#comments</comments>
		<pubDate>Fri, 28 Aug 2015 07:21:34 +0000</pubDate>
		<dc:creator><![CDATA[-Flyぁ梦-]]></dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Tomcat]]></category>

		<guid isPermaLink="false">http://blog.11034.org/?p=2507</guid>
		<description><![CDATA[多年没有碰Java Web了，之前也一直在Windows下玩耍。在Linux下跑起Tomcat也折腾了一阵。  [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>多年没有碰Java Web了，之前也一直在Windows下玩耍。在Linux下跑起Tomcat也折腾了一阵。</p>
<p>看Apache Tomcat官网，已经有Tomcat 8.x（据说支持Oracle Java 7.0标准），7.x和6.x，习惯还是使用6.0.44版本。</p>
<p><span id="more-2507"></span></p>
<h2>设置环境变量</h2>
<p>打开<code class="markdown_inline_code">~/.profile</code>文件，或者/etc/profile文件</p>
<pre class="markdown_pre"><code>JAVA_HOME=/usr/.../java
PATH=$PATH:$JAVA_HOME/bin
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
CATALINA_HOME=/home/.../tomcat
export JAVA_HOME PATH CLASSPATH CATALINA_HOME</code></pre>
<p>使用<code class="markdown_inline_code">source ~/.profile</code>命令重新加载文件（或重新登陆ssh即可），查看命令<code class="markdown_inline_code">echo $JAVA_HOME</code></p>
<h2>给Tomcat脚本加执行权限</h2>
<p>进入<code class="markdown_inline_code">$CATALINA_HOME/bin</code>，<code class="markdown_inline_code">chmod +x *.sh</code></p>
<p>然后<code class="markdown_inline_code">./startup.sh</code>，应该就能启动了</p>
<p>启动成功显示：</p>
<pre class="markdown_pre"><code>Using CATALINA_BASE: /home/.../apache-tomcat-6.0.44
Using CATALINA_HOME: /home/.../apache-tomcat-6.0.44
Using CATALINA_TMPDIR: /home/.../apache-tomcat-6.0.44/temp
Using JRE_HOME: /usr/.../java
Using CLASSPATH: /home/.../apache-tomcat-6.0.44/bin/bootstrap.jar</code></pre>
<p>用netstat -ntlp显示：</p>
<pre class="markdown_pre"><code>tcp6 0 0 :::8009 :::* LISTEN 25424/java    # AJP服务
tcp6 0 0 :::8080 :::* LISTEN 25424/java    # HTTP服务
tcp6 0 0 127.0.0.1:8005 :::* LISTEN 25424/java  # 关闭命令接收服务</code></pre>
<p>修改Tomcat启动端口，在conf/server.xml，修改<code class="markdown_inline_code">Connector port="8080"</code>中的端口号即可</p>
<h2>以根目录启动</h2>
<p>可以在conf/server.xml中，修改Host标签中添加一行，docBase指向含有WEB-INF的目录即可</p>
<p><code class="markdown_inline_code">&lt;Context path="" docBase="/home/.../app" debug="0" reloadable="true" /&gt;</code></p>
<h4  class="related_post_title">看看 linux , Tomcat</h4><ul class="related_post"><li>2016-09-09 -- <a target="_blank" href="http://blog.11034.org/2016-09/64bits_linux_arena_memory.html" title="64位Linux下Java进程堆外内存迷之64M问题">64位Linux下Java进程堆外内存迷之64M问题</a></li><li>2016-06-08 -- <a target="_blank" href="http://blog.11034.org/2016-06/tomcat_shutdown.html" title="Tomcat监听shutdown释放数据库连接池">Tomcat监听shutdown释放数据库连接池</a></li><li>2016-06-06 -- <a target="_blank" href="http://blog.11034.org/2016-06/tomcat_https.html" title="Tomcat启用https服务">Tomcat启用https服务</a></li><li>2015-08-12 -- <a target="_blank" href="http://blog.11034.org/2015-08/rails_nginx.html" title="Liunx下搭建Rails和Nginx环境">Liunx下搭建Rails和Nginx环境</a></li><li>2013-05-20 -- <a target="_blank" href="http://blog.11034.org/2013-05/coyote.html" title="Tomcat的Connector：Coyote">Tomcat的Connector：Coyote</a></li></ul><h4 class="related_post_title">看看 Java </h4><ul class="related_post"><li>2016-09-09 -- <a target="_blank" href="http://blog.11034.org/2016-09/64bits_linux_arena_memory.html" title="64位Linux下Java进程堆外内存迷之64M问题">64位Linux下Java进程堆外内存迷之64M问题</a></li><li>2016-08-18 -- <a target="_blank" href="http://blog.11034.org/2016-08/java_concurrency_in_practice.html" title="读java concurrency in practice">读java concurrency in practice</a></li><li>2016-08-05 -- <a target="_blank" href="http://blog.11034.org/2016-08/thread_stop.html" title="线程清理">线程清理</a></li><li>2016-06-21 -- <a target="_blank" href="http://blog.11034.org/2016-06/futuretask.html" title="FutureTask简单分析和用法">FutureTask简单分析和用法</a></li><li>2016-06-21 -- <a target="_blank" href="http://blog.11034.org/2016-06/semaphore.html" title="Semaphore简单分析">Semaphore简单分析</a></li>]]></content:encoded>
			<wfw:commentRss>http://blog.11034.org/2015-08/tomcat_linux.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Tomcat的Connector：Coyote</title>
		<link>http://blog.11034.org/2013-05/coyote.html</link>
		<comments>http://blog.11034.org/2013-05/coyote.html#comments</comments>
		<pubDate>Mon, 20 May 2013 14:01:09 +0000</pubDate>
		<dc:creator><![CDATA[-Flyぁ梦-]]></dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[coyote]]></category>
		<category><![CDATA[Socket]]></category>
		<category><![CDATA[Tomcat]]></category>
		<category><![CDATA[多线程]]></category>
		<category><![CDATA[异步IO]]></category>
		<category><![CDATA[线程池]]></category>

		<guid isPermaLink="false">http://blog.stariy.org/?p=1808</guid>
		<description><![CDATA[上一篇博文讲了Tomcat的系统架构，今天花了一天时间研究了下coyote的源码，大致对普通IO版本有所了解。 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>上一篇博文讲了<a title="Tomcat6源码学习" href="/2013-05/tomcat6.html" target="_blank">Tomcat的系统架构</a>，今天花了一天时间研究了下coyote的源码，大致对普通IO版本有所了解。被同学提醒后发现，Tomcat6已经支持异步IO了，但默认是普通IO版本，需要在Connector的protocol参数中定义为Http11NioProtocol才开启异步IO模式。</p>
<p>主要的代码，Socket的服务在org.apache.tomcat.util.net.JIoEndpoint类，解析处理HTTP请求在org.apache.coyote.http11包的Http11Protocol类和Http11Processor类，org.apache.catalina.connector.CoyoteAdapter负责连接Connector模块（coyote）和Container模块。</p>
<p>线程池默认用的JIoEndpoint类中的子类WorkerStack，若在server.xml配置使用了Executor，则使用org.apache.catalina.core.StandardThreadExecutor（对ThreadPoolExecutor的一层包装）。并发量高的情况下Executor的效率会高一些。<span id="more-1808"></span></p>
<h2>Coyote普通IO流程</h2>
<p>在Catalina主线程启动过程中：</p>
<p>StandardService的init()中，在JIoEndpoint.init()中，ServerSocket(port = 8080, backlog = 100)被new出来。</p>
<p>StandardService的start()中，在JIoEndpoint.start()中，一个新的线程（名叫http-8080-Acceptor-0）被start()，这个由JIoEndpoint.Accept内部类执行run()的线程干的活就是不停地从serverSocket.accept()，然后根据线程池的选择拿一个线程去处理socket。因为处理在新的线程，Acceptor线程继续等待accept()。</p>
<p>若使用默认的WorkerStack线程池，JioEndpoint.getWorkerThread().assign(socket);使Worker线程获得socket实例后，就可以在新线程中处理socket。</p>
<p>若使用Executor线程池，则new出一个JioEndpoint.SocketProcessor()交给Executor.execute()，在新线程中处理socket。</p>
<p>不管哪种线程池方法，新线程中使用一样的代码，调用Http11Protocol$Http11ConnectionHandler.process(socket)，这里使用了一个ConcurrentLinkedQueue用来保存Http11Processor实例，拿一个进行处理。</p>
<p>Http11Protocol.process()具体解析HTTP请求。解析过程中，将参数塞进request和response，再调用CoyoteAdapter.service(request, response)，这样就进入Container模块去调用Servlet代码。</p>
<p>结束后，回收Http11Processor实例，回收线程。</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;流程结束分割线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>好像代码也没有太难看不懂，大多数复杂的线程同步操作都由java.util.concurrnt包里的类实现了。</p>
<h2>Worker线程的assign()和await()</h2>
<p>Acceptor线程调用Worker.assign( socket )，将socket对象赋给Worker线程，然后Worker线程中的await()方法通过线程同步，Worker线程被唤醒并拿到了socket就可以在自己线程里顺利执行了。</p>
<p>这块线程同步的代码蛮有意思的，而且Worker线程也借助这边的wait()和notifyall()实现挂起和唤醒。</p>
<h2>server.xml参数调优</h2>
<p><strong>开启异步IO</strong></p>
<p>Connector的配置中，将protocol=“HTTP/1.1”改为“org.apache.coyote.http11.Http11NioProtocol”就可以使用nio包的异步IO，效率高不少。</p>
<p>对java.nio包特别是异步IO这一块了解甚浅，而且Tomcat对这一块的实现略复杂，看懂略有难度，努力！</p>
<p>同样地方还能改为“org.apache.coyote.http11.Http11AprProtocol”，据说利用底层OS的异步IO，需要APR和Native这其他两个组件的支持才能工作，效率更高，不是太确定。</p>
<p><strong>开启Executor并在Connector中使用</strong></p>
<p>Executor的2个配置参数，minSpareThreads和maxThreads，对应到ThreadPoolExecutor(int <strong>corePoolSize</strong>,  int <strong>maximumPoolSize</strong>, &#8230;)这个构造的前面2个参数。分别表示活跃线程数和最大线程数。</p>
<p><strong>Connector的参数：</strong></p>
<ul>
<li>maxThreads，对应JIoEndpoint类中的maxThreads变量，默认为200。若有Executor加入则maxThreads被取代。</li>
<li>acceptCount，对应JIoEndpoint类中的backlog变量，默认为100，用作ServerSocket的第二个参数。ServerSocket里等待队列的长度。</li>
</ul>
<h4  class="related_post_title">看看 coyote , Socket , Tomcat , 多线程 , 异步IO , 线程池</h4><ul class="related_post"><li>2013-05-19 -- <a target="_blank" href="http://blog.11034.org/2013-05/tomcat6.html" title="Tomcat6源码学习">Tomcat6源码学习</a></li><li>2016-06-08 -- <a target="_blank" href="http://blog.11034.org/2016-06/tomcat_shutdown.html" title="Tomcat监听shutdown释放数据库连接池">Tomcat监听shutdown释放数据库连接池</a></li><li>2016-06-06 -- <a target="_blank" href="http://blog.11034.org/2016-06/tomcat_https.html" title="Tomcat启用https服务">Tomcat启用https服务</a></li><li>2016-03-17 -- <a target="_blank" href="http://blog.11034.org/2016-03/java_client_socket_exceptions.html" title="Java客户端Socket在服务端重启后的异常情况处理">Java客户端Socket在服务端重启后的异常情况处理</a></li><li>2016-03-01 -- <a target="_blank" href="http://blog.11034.org/2016-03/simpledateformat_thread_not_safe.html" title="jdk中SimpleDateFormat的实例线程不安全">jdk中SimpleDateFormat的实例线程不安全</a></li></ul><h4 class="related_post_title">看看 Java </h4><ul class="related_post"><li>2016-09-09 -- <a target="_blank" href="http://blog.11034.org/2016-09/64bits_linux_arena_memory.html" title="64位Linux下Java进程堆外内存迷之64M问题">64位Linux下Java进程堆外内存迷之64M问题</a></li><li>2016-08-18 -- <a target="_blank" href="http://blog.11034.org/2016-08/java_concurrency_in_practice.html" title="读java concurrency in practice">读java concurrency in practice</a></li><li>2016-08-05 -- <a target="_blank" href="http://blog.11034.org/2016-08/thread_stop.html" title="线程清理">线程清理</a></li><li>2016-06-21 -- <a target="_blank" href="http://blog.11034.org/2016-06/futuretask.html" title="FutureTask简单分析和用法">FutureTask简单分析和用法</a></li><li>2016-06-21 -- <a target="_blank" href="http://blog.11034.org/2016-06/semaphore.html" title="Semaphore简单分析">Semaphore简单分析</a></li>]]></content:encoded>
			<wfw:commentRss>http://blog.11034.org/2013-05/coyote.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Tomcat6源码学习</title>
		<link>http://blog.11034.org/2013-05/tomcat6.html</link>
		<comments>http://blog.11034.org/2013-05/tomcat6.html#comments</comments>
		<pubDate>Sun, 19 May 2013 10:27:43 +0000</pubDate>
		<dc:creator><![CDATA[-Flyぁ梦-]]></dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[ClassLoader]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[Servlet]]></category>
		<category><![CDATA[Socket]]></category>
		<category><![CDATA[Tomcat]]></category>
		<category><![CDATA[事件驱动]]></category>
		<category><![CDATA[多线程]]></category>
		<category><![CDATA[容器]]></category>
		<category><![CDATA[生命周期]]></category>

		<guid isPermaLink="false">http://blog.stariy.org/?p=1803</guid>
		<description><![CDATA[在上一篇博文中说到因为电脑风扇坏了2天于是看完了《How tomcat works》译本，不过这本书是针对To [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>在<a title="小黑风扇坏两天，被逼看完一本书" href="/2013-05/fan_error.html" target="_blank">上一篇博文</a>中说到因为电脑风扇坏了2天于是看完了《How tomcat works》译本，不过这本书是针对Tomcat4和5来讲的比较老了，然后再结合Tomcat6.0.26的源代码调试学习了总共一周的时间，算是大致将Tomcat6.0的一部分工作机制（JSP、JMX、安全管理等模块没研究）给搞清楚了。大概是因为平时基于Java的Web程序写的太多，对Tomcat这一块源码研究特别感兴趣，有时候为了想通一个问题兴奋地吃饭睡觉都在一直想，非常有动力并且也有效率，好久没有这种感觉了。</p>
<p><span id="more-1803"></span>列几点觉得Tomcat设计上比较有意思的地方。</p>
<h2>Connector模块</h2>
<p>Tomcat主要分为Connector模块和Container模块，前者就是处理Socket和HTTP请求，后者是就是常听到的Servlet容器。</p>
<p>Connector模块由于功能比较独立，然后Tomcat内部接口的设计允许第三方组件的使用，就使用了Coyote组件，虽然也是apache下的。有空可以再好好来学习下Coyote的源代码，因为这块涉及了多线程和线程同步、资源优化、效率优化等方面，很值得学习。</p>
<p>Tomcat默认一共占用了3个端口，8080（HTTP/1.1）、8009（AJP/1.3，接受其他服务器转发的请求）和8005（等待SHUTDOWN命令，由Server类在主线程中开启）。其中8080和8009由Connector模块管理，所以默认有2个Connector在运作。</p>
<h2>Container模块</h2>
<p>由Engine、Host、Context、Wrapper四个容器组合而成，分别表示整个引擎、虚拟主机、Web应用、Servlet，通过父子关系连接，然后配套相应的Pipeline和Valve实现过程流。</p>
<h2>Lifecycle接口</h2>
<p>包括启动类（Catalina）、Server、Service、Connector、Container、Executor、Loader、Manager、Realm、Resources、Pipeline都实现了这个接口，通过简单的start()和stop()来递归实现生命周期的管理。</p>
<p>并且这一模块中还用到了LifecycleListener和LifecycleEvent这套事件驱动模型，虽然觉得Tomcat的事件驱动做的比较一般性，注册在某个Lifecycle的LifecycleListener会收到这个Object的所有事件通知，要靠自己去辨别事件类型并作出相应反应，效率较低且定制性弱。</p>
<h2>ClassLoader的设计</h2>
<p>Tomcat为了使类库的私有性，有commonLoader用来加载lib下的jar包，catalinaLoader和sharedLoader分别用来加载Tomcat类库和应用程序共享类库且都以commonLoader为parent。但是在Tomcat6的配置中，默认没有开启catalinaLoader和sharedLoader也没有相应的server和shared目录，导致这3个loader就是同一个commonLoader。这3个loader是StandardClassLoader的实例。</p>
<p>然后对于每一个Web应用程序，都有自己的一个WebappClassLoader，其parent为sharedLoader。这样可以防止不同Web应用程序之间加载互相类库。WebappClassLoader和前面提到的StandardClassLoader都继承自java.net.URLClassLoader，直接从指定目录中读取jar包或class文件。WebappClassLoader直接通过管理Servlet类的字节流来实现Servlet的加载然后缓存。</p>
<p>一般的Servlet只有一个实例，若是实现了STM（SingleThreadModel接口，已Deprecated）的Servlet则会有多个实例缓存着。</p>
<p>但似乎无论怎么设计，都无法避免Web应用程序中的Servlet可以获取到Tomcat启动库中的Bootstrap类（这个包由JVM自带的AppClassLoader加载），默认情况下还可以获取到Tomcat主类库中的所有类（比如Catalina类，因为都是由commonLoader加载，而它又是WebappClassLoader的parent）。尝试过将Tomcat的lib目录中关于Tomcat的类库放到server目录下并配置server.loader属性值（conf/catalina.properties）启动catalinaLoader，这样可以避免Servlet访问到Tomcat主类库，但是这样勉强的同时也阻止了比如ContainerServlet接口（使Servlet能访问Wrapper容器）的运作。</p>
<p>这样的一个坏处就是，可以在Web应用程序的Servlet中获取到Catalina类或者Bootstrap类，再启动一次Tomcat。Servlet中，如果在service方法中这么干会被Tomcat的安全机制给发现使得Tomcat整个关闭，若是配置了loadOnStartup后在init方法中这么干则会引发无限循环导致死机&#8230;</p>
<p>不过通过对Tomcat的ClassLoader的学习，对Java的ClassLoader机制有了大大的实践的了解，无论Tomcat是否真正实现了它设计上的初衷，整个设计思想是值得学习的。</p>
<h2>backgroundProcessor()和后台线程</h2>
<p>Engine容器和Context容器都会通过启动一个后台线程间断执行backgroundProcessor方法，比如重新加载Web应用程序的类文件和资源、扫描Session过期等。</p>
<h2>静态资源</h2>
<p>向Tomcat请求静态资源，和请求Servlet没有太大区别，仍然通过Connector和Container这一流程后，交到Tomcat内部的DefaultServlet来处理读取文件内容并写回客户端，下一次请求会返回304 Not Modified。</p>
<p>所以Tomcat对静态资源的管理比较差速度比较慢，才有apache + tomcat结合的说法吧。</p>
<h4  class="related_post_title">看看 ClassLoader , HTTP , Servlet , Socket , Tomcat , 事件驱动 , 多线程 , 容器 , 生命周期</h4><ul class="related_post"><li>2013-05-20 -- <a target="_blank" href="http://blog.11034.org/2013-05/coyote.html" title="Tomcat的Connector：Coyote">Tomcat的Connector：Coyote</a></li><li>2016-06-08 -- <a target="_blank" href="http://blog.11034.org/2016-06/tomcat_shutdown.html" title="Tomcat监听shutdown释放数据库连接池">Tomcat监听shutdown释放数据库连接池</a></li><li>2016-06-06 -- <a target="_blank" href="http://blog.11034.org/2016-06/tomcat_https.html" title="Tomcat启用https服务">Tomcat启用https服务</a></li><li>2016-03-17 -- <a target="_blank" href="http://blog.11034.org/2016-03/java_client_socket_exceptions.html" title="Java客户端Socket在服务端重启后的异常情况处理">Java客户端Socket在服务端重启后的异常情况处理</a></li><li>2016-03-01 -- <a target="_blank" href="http://blog.11034.org/2016-03/simpledateformat_thread_not_safe.html" title="jdk中SimpleDateFormat的实例线程不安全">jdk中SimpleDateFormat的实例线程不安全</a></li></ul><h4 class="related_post_title">看看 Java </h4><ul class="related_post"><li>2016-09-09 -- <a target="_blank" href="http://blog.11034.org/2016-09/64bits_linux_arena_memory.html" title="64位Linux下Java进程堆外内存迷之64M问题">64位Linux下Java进程堆外内存迷之64M问题</a></li><li>2016-08-18 -- <a target="_blank" href="http://blog.11034.org/2016-08/java_concurrency_in_practice.html" title="读java concurrency in practice">读java concurrency in practice</a></li><li>2016-08-05 -- <a target="_blank" href="http://blog.11034.org/2016-08/thread_stop.html" title="线程清理">线程清理</a></li><li>2016-06-21 -- <a target="_blank" href="http://blog.11034.org/2016-06/futuretask.html" title="FutureTask简单分析和用法">FutureTask简单分析和用法</a></li><li>2016-06-21 -- <a target="_blank" href="http://blog.11034.org/2016-06/semaphore.html" title="Semaphore简单分析">Semaphore简单分析</a></li>]]></content:encoded>
			<wfw:commentRss>http://blog.11034.org/2013-05/tomcat6.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
