Tomcat

Tomcat是一个轻量级的Java应用服务器,是一个servlet标准容器,常用于web服务器,点击至主页下载。一般使用成熟的6.x或7.x版本。基于Java的平台无关性,tomcat可以在windows或linux下无需修改配置运行。

关于tomcat的线程模型

这篇博客介绍了一些servlet规范的特性。其中,线程模型是tomcat一个约束性的限制,知道它可以更好地编写业务逻辑。

对于一个请求,tomcat会分配一条线程服务该请求(thread per request),直到请求完成,线程回收回线程池。也即,在请求未完成之前,即便是IO阻塞等待或Sleep等待等,线程依然服务于该请求,而不会被分配去执行其它事情,所以,ThreadLocal是可以存放当前请求的上下文信息的,这样的限制使得编程可以基于线程模型,更加简单了 。默认线程池线程数最大是200个。也就是说,如果有个连接里面sleep了一秒钟,那么由于servlet线程模型规范的约束,网站的tps就只能到200;所以,对于请求时间比较长的网站,可以加大tomcat的最大线程数。

注:线程的多少消耗的是内存空间。线程切换会有一定的成本,CPU的核心数决定处理线程的并发数和吞吐量。

1. 安装配置

安装

Tomcat主页获取到下载地址直接下载到机器上,windows直接下载,linux下例如:wget http://www.us.apache.org/dist/tomcat/tomcat-6/v6.0.36/bin/apache-tomcat-6.0.36.tar.gz

下载后将tomcat解压到随便一个目录下,windows下使用解压工具,linux下例如:tar zxvf apache-tomcat-6.0.36.tar.gz

对于windows,可以安装service版的32-bit/64-bit Windows Service Installer,启动之后在windows的托盘有tomcat的图标,在那里可以控制tomcat启动和停止,还有页面配置。可能和下面的配置文件不太一致,概念还是一致的。

配置

首先需要配置Java环境,linux下直接运行下面命令并写在~/.bashrc里面:

export JAVA_HOME=/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0 #这个位置根据java安装位置不同而不同

Windows下配置一下环境变量JAVA_HOME,指向例如C:\Program Files\Java\jdk1.7.0_51;或者环境变量JRE_HOME,指向例如C:\Program Files\Java\jre7

启动和停止

Linux下执行:

cd apache-tomcat-6.0.36/bin
./startup.sh # 启动
./shutdown.sh # 关闭

Windows下直接双击tomcat目录下bin\startup.bat运行。

启动之后,可以访问http://127.0.0.1:8080/查看页面。

对于linux,需要注意防火牆是否开放对应的端口,例如8080,编辑/etc/sysconfig/iptables,文件中间新增一行:

-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT

重启防火牆:

service iptables restart

关于强制结束tomcat

使用tomcat的shutdown.sh命令去结束tomcat时,如果tomcat里面实现的业务逻辑涉及到多线程或者比较复杂时,经常会出现tomcat结束不了的情况。这种情况虽然可以通过实验找出具体哪个环节导致的,但从项目管理的角度,却不够妥当。应该有一种结束方式来保证一定结束成功,以免影响tomcat的重启。

在tomcat目录下执行:

CURPATH=`pwd`
PID=`ps aux|grep java|grep "catalina.base=$CURPATH"|awk 'NR==1{print $2}'`
kill -9 $PID

还有另外一种方式是,让tomcat自己去结束,配置bin/catalina.sh文件,增加一行CATALINA_PID=/xxx/tomcat/bin/pid,但是这种方式还是不够稳定,还是会出现tomcat没有被结束掉的情况,并不推荐这种方式。

一台机器运行多个tomcat

tomcat解压就可以使用,但系统端口是互斥资源,因此需要修改conf/server.xml中的3个端口,保证系统全局没被占用:
1) <Server port="8005" shutdown="SHUTDOWN">
2) <Connector port="8080" protocol="HTTP/1.1"
3) <Connector port="8009" protocol="AJP/1.3"

2. 进一步配置

默认页面数据放在目录apache-tomcat/webapps下,其中ROOT是根目录,可以将项目WebRoot重命名后整个放在这个目录下完成部署,或者将项目打包成war包放到apache-tomcat/webapps下重启tomcat,会自动解压完成部署。

设置tomcat对GET请求的参数编码处理(仅tomcat7需要,现在tomcat8默认是utf-8编码,很多默认的框架也是utf-8,不需要下面配置了)

如果不进行该配置,那么GET参数传递的中文可能出现乱码。只需要在tomcat的conf/server.xml里面的Connector标签加上useBodyEncodingForURI属性为true:

    <Connector port="18080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="18443" useBodyEncodingForURI="true"/>

配置其他目录Project

假设有个Project的根目录在/home/my/project/WebRoot目录,则在apache-tomcat/conf/Catalina/localhost下,新建一个文件my.xml,内容:

<?xml version="1.0" encoding="UTF-8"?>
<Context path="/my" docBase="/home/my/project/WebRoot" reloadable="true"/>

然后重启tomcat,访问http://127.0.0.1:8080/my/看看。注意配置里面的path并不决定url的/my,/my是由my.xml的文件名决定的。

新增一个虚拟主机

修改conf/server.xml,并列与localhost的Host新建一个Host:

      <Host name="abc.pugwoo.com"  appBase="/path/to/WebRoot"
            unpackWARs="true" autoDeploy="true"
            xmlValidation="false" xmlNamespaceAware="false">
      </Host>

内存优化

在小内存的VPS上运行tomcat需要配置一下内存选项,编辑bin/catalina.sh(linux)或bin/catalina.bat(windows),加上一行:

JAVA_OPTS="-Xms84m -Xmx84m"  # linux下
set JAVA_OPTS=-Xms84m -Xmx84m  # windows下

具体改成多大参考自己的vps内存大小,注意观察tomcat的运行情况。

启动远程Debug

先把tomcat停掉,然后执行:

export JPDA_ADDRESS=8000
export JPDA_TRANSPORT=dt_socket
bin/catalina.sh jpda start

成功的话tomcat机器上将监听8000端口。然后到Eclipse中配置remote Java Application的ip和端口,然后就可以远程Debug了。

一般线上配置

编辑bin/catalina.sh(linux)或bin/catalina.bat(windows),最前面加上一行:

JAVA_OPTS="-Denv=idc -server -Xms512m -Xmx512m -XX:PermSize=64M -XX:MaxPermSize=128m -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/data/logs/applicationxx_gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/logs/"

3. 运行PHP

前往Quercus下载quercus-4.0.37.war文件,然后在tomcat的webapps目录下新建php文件夹,将quercus-4.0.37.war解压到php目录中,然后啓动tomcat,访问http://localhost:8080/php/,如果看到页面,就表示运行成功了。自己项目的php文件可以放置到php文件夹下并通过浏览器访问,非常简单。此外,还支持jsp并存、php中调用java的类等等,非常方便。

更多PHP的信息详见PHP

4. 运行CGI

Tomcat支持配置运行CGI可执行程序,这里以tomcat 6爲例,配置如下:

  1. 修改tomcat的conf/context.xml文件,把改成,这样修改是爲了放开权限。

  2. 可以配置让整个tomcat支持CGI,也可以配置仅webapps下某些项目支持CGI,爲了避免太大范围修改tomcat,这里以webapps某项目爲例。首先在tomcat的webapps目录下新建目录cgi-bin,然后再在cgi-bin下新建目录WEB-INF,再在WEB-INF下新建文件web.xml,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<!-- CGI servlet configuration -->
<servlet>
<servlet-name>cgi</servlet-name>
<servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class>
    <init-param>
      <param-name>debug</param-name>
      <param-value>0</param-value> <!-- change to 100 to see more info-->
    </init-param>
    <init-param>
      <param-name>cgiPathPrefix</param-name>
      <param-value>/</param-value> <!-- default is WEB-INF/cgi -->
    </init-param>
    <init-param>
      <param-name>executable</param-name>
      <param-value></param-value>
    </init-param>
    <init-param>
      <param-name>passShellEnvironment</param-name>
      <param-value>true</param-value>
    </init-param>
    <load-on-startup>5</load-on-startup>
</servlet>

<!-- CGI servlet mapping --> 
<servlet-mapping>
    <servlet-name>cgi</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

</web-app>

这样就可以了,啓动tomcat,接下来测试一下是不是运行成功,在webapps/cgi-bin/目录下新建文件test.bat(或test.sh,linux下,脚本有些不同):

echo OFF
echo Content-type: text/html
echo.
echo.
echo hello world

然后用浏览器访问http://localhost:8080/cgi-bin/test.bat,看到hello world就成功啦。只要是可执行程序,放在cgi-bin下面就可以被执行,该程序的标准输出就作爲HTTP内容输出到浏览器。Tomcat关于cgi更多的配置详见这里

5. eclipse下的相关问题

eclipse在debug启动tomcat时,默认会在抛出没捕获异常时断点,可以设置不要这个功能:

Window > Preferences > Java > Debug 不要勾选 Suspend execution on uncaught exceptions

6. 常见问题

createSecureRandom Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took

启动时该环节花费太长时间,解决方法:修改${JAVA_HOME}/jre/lib/security/java.security文件,把securerandom.source=file:/dev/random这行改成securerandom.source=file:/dev/urandom

文档更新时间: 2018-11-10 20:18   作者:nick