Tomcat是由Apache软件基金会下属的Jakarta项目开发的一个Servlet容器,按照SunMicrosystems提供的技术规范,实现了对Servlet和JavaServerPage(JSP)的支持,并提供了作为Web服务器的一些特有功能,如Tomcat管理和控制平台、安全域管理和Tomcat阀等。由于Tomcat本身也内含了一个HTTP服务器,它也可以被视作一个单独的Web服务器。但是,不能将Tomcat 和 Apache Web 服务器混淆,Apache Web Server 是一个用 C 语言实现的 HTTP web server;这两个HTTP web server 不是捆绑在一起的。Apache Tomcat 包含了一个配置管理工具,也可以通过编辑 XML 格式的配置文件来进行配置。
java程序在JVM中运行的前提:加载器将程序自身使用的class和公共的java APIclass加载之后,通过执行引擎来运行;执行引擎需要跟主机上的系统调用进行交互;执行引擎可以调用Java的API,也可以调用系统的API,也称Native API(DSO,动态共享对象)
Java Runtime Data Areas
method area;加载的公共class库中的class
heap;运行java线程的公共内存
Java stacks ;栈,每个java线程都有独有的栈,用于保存运行时的变量;
pc register;pc寄存器,或java 寄存器,线程所独有,用于保存当前线程执行的指令,指令计数器;
native method statck;本地方法栈,调用本地类库;
execution engine;所有的数据需要在执行引擎中运行;
native method interface;跟本地系统调用交互的接口;
native method libraries;本地方法库,系统调用;
Generations of Data in Garbage Collection
Eden:新对象在Eden创建,过一段时间后,将不在使用的对象删除,正在使用的对象移动到Survivor;在幸存者区域里,继续使用的移动到老年代,不使用的移动到未使用空间;
Young:新生代
Tenured:老年代
Perm:持久代,方法区
Configuring the Heap and Garbage Collector
-Xmx:新生代和老年代最大可以使用的内存空间;
-Xms:当前可以使用的最小内存空间,除去预留空间,包含新生代和老年代使用的内存;
reserved:以后可以申请使用的空间;
applet:小的可运行程序,本身是一种API,applet在服务器端编译好,通过HTTP协议传送到客户端,客户端浏览器需要安装java插件(JRE)来运行这种applet;
servlet:另一种class,程序员开发好的程序在服务器端第一次执行时被编译成java类,类在JVM中执行;但它不能把结果直接响应给客户端,前端需要有HTTP服务器来分析客户请求的报文。
JSP:jsp是servlet的升级版,java开发的程序能够像php一样,利用代码嵌入的方式,放到网页文件里面,只需事先加入标签即可;有了jsp之后,前端是一个jsp分析器(jasper),当用户请求含有jsp代码的页面时,应用程序将jsp代码发送给jasper,jasper将代码转换成servlet类,再由编译器进行编译,servlet被编译成java类,JVM调用公共类,然后在JVM中运行,将生成的结果发送给http服务器,由http服务器构建响应报文;包含jasper和servlet等其他工具容器称为web容器,web容器通常可以使用内部的java类或公共类组件提供http服务,能够分析http请求,并构建响应报文。tomcat是一个完整意义上的web容器,但不是J2EE的实现;
JavaSE包含了Java二进制程序(如JVM和Java字节码编译器)和Java的核心代码库;
JaveEE标准包含了一组适用于创建企业级Web应用程序的API。Jave EE建立在Java SE的基础上,并依赖于JavaSE才能正常工作。当然,任何级别的应用程序均能从Java EE中获益,但Jave EE却更适合解决大型软件系统设计中的问题。
JAVAEE包含多个独立的API,Servlet和JSP就是其中的两个,而JAVA EE中著名的API中还包含如下的几个:
JAVA EEAPIs:
EJB(Enterprise JavaBeans):JAVA相关的诸多高级功能的实现,如RMI(Remote Method Invocation),对象/关系映射,跨越多个数据源的分布式事务等;
JMS(Java MessageService):高性能异步消息服务,实现JAVA EE应用程序与非JAVA程序的“透明”通信;
JMX(Java ManagementExtensions):在程序运行时对其进行交互式监控和管理的机制;
JTA(Java TransactionAPI):允许应用程序在自身的一个或多个组件中平滑地处理错误的机制;
JavaMail:通过工业标准的POP/SMTP/IMAP协议发送和接收邮件的机制;
安装tomcat:
首先安装JDK (开发工具): jdk下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html [root@node2 ~]# chmod +x jdk-6u31-linux-x64-rpm.bin [root@node2 ~]# ./jdk-6u31-linux-x64-rpm.bin 安装目录在/usr/java/latest 导出环境变量: [root@node2 ~]# vi /etc/profile.d/jdk.sh export JAVA_HOME=/usr/java/latest export PATH=$JAVA_HOME/bin:$PATH 测试一下: [root@node2 ~]# java -version java version "1.6.0_31" Java(TM) SE Runtime Environment (build 1.6.0_31-b04) Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01, mixed mode) (mixed mode,编译和即时执行都支持)
安装tomcat程序:
下载地址:http://tomcat.apache.org/download-70.cgi
[root@node2 ~]# tar xf apache-tomcat-7.0.42.tar.gz -C /usr/local/ [root@node2 ~]# cd /usr/local/ [root@node2 src]# ln -sv apache-tomcat-7.0.42 tomcat `tomcat' -> `apache-tomcat-7.0.42' [root@node2 src]# cd tomcat/ [root@node2 tomcat]# ls bin conf lib LICENSE logs NOTICE RELEASE-NOTES RUNNING.txt temp webapps work # tomcat运行需要2个变量 [root@node2 tomcat]# vi /etc/profile.d/tomcat.sh export CATALINA_HOME=/usr/local/tomcat export PATH=$CATALINA_HOME/bin:$PATH [root@node2 tomcat]# . /etc/profile.d/tomcat.sh [root@node2 local]# catalina.sh -h Using CATALINA_BASE: /usr/local/tomcat Using CATALINA_HOME: /usr/local/tomcat Using CATALINA_TMPDIR: /usr/local/tomcat/temp Using JRE_HOME: /usr/java/latest Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar Usage: catalina.sh ( commands ... ) commands: debug Start Catalina in a debugger debug -security Debug Catalina with a security manager jpda start Start Catalina under JPDA debugger run Start Catalina in the current window run -security Start in the current window with security manager start Start Catalina in a separate window start -security Start in a separate window with security manager stop Stop Catalina, waiting up to 5 seconds for the process to end stop n Stop Catalina, waiting up to n seconds for the process to end stop -force Stop Catalina, wait up to 5 seconds and then use kill -KILL if still running stop n -force Stop Catalina, wait up to n seconds and then use kill -KILL if still running configtest Run a basic syntax check on server.xml - check exit code for result version What version of tomcat are you running? Note: Waiting for the process to end and use of the -force option require that $CATALINA_PID is defined 启动tomcat: [root@node2 local]# catalina.sh start #默认监听8080端口;
安装成功后效果:
tomcat启动脚本: vi /etc/init.d/tomcat #!/bin/sh # Tomcat init script for Linux. # # chkconfig: 2345 96 14 # description: The Apache Tomcat servlet/JSP container. JAVA_HOME=/usr/java/latest CATALINA_HOME=/usr/local/tomcat export JAVA_HOME CATALINA_HOME exec $CATALINA_HOME/bin/catalina.sh $* [root@node2 local]# chkconfig --add tomcat [root@node2 local]# chkconfig tomcat on [root@node2 local]# service tomcat stop env: /etc/init.d/tomcat: Permission denied [root@node2 local]# chmod +x /etc/init.d/tomcat [root@node2 local]# service tomcat stop Using CATALINA_BASE: /usr/local/tomcat Using CATALINA_HOME: /usr/local/tomcat Using CATALINA_TMPDIR: /usr/local/tomcat/temp Using JRE_HOME: /usr/java/latest Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar [root@node2 local]# service tomcat start Using CATALINA_BASE: /usr/local/tomcat Using CATALINA_HOME: /usr/local/tomcat Using CATALINA_TMPDIR: /usr/local/tomcat/temp Using JRE_HOME: /usr/java/latest Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar # tomcat配置文件目录: /usr/local/tomcat/conf # web.xml:部署描述符定义文件 # tomcat-users.xml:用户授权信息 # server.xml:主配置文件 # jps命令用以显示正在运行的虚拟机;
一个tomcat实例可以有多个servlet容器,当外部请求从connector进来之后,送到与该connector关联的某个引擎上,connector需要通过service与引擎进行交互,引擎内部的host提供虚拟主机服务。
Java程序要运行需要class loader把程序使用的类以及公共类加载进JVM;
部署(deployment):手动通知tomcat把程序用到的各种类加载完毕,通过部署描述符文件定义程序可以识别的MIME类型以及其他组件属性,每个jsp的源程序不能直接执行,需要在第一次被访问时进行编译或部署的时候被编译,当源文件修改后,还需要重新编译,tomcat可以配置为自动部署。在引擎内部的host组件中有context子组件,用以描述需要单独部署的访问路径;
在server.xml中的Listener用来监听组件之间通信的通道;
global naming resources;全局命名资源,用以定义认证信息等
应用程序目录结构:
/WEB-INF 此目录为私有资源目录,其内部的所有文件和子目录均不能被公开访问;包含着此Web应用程序的配置文件web.xml(程序结构描述符文件)通常放置于此目录;
/WEB-INF/classes 当前Web应用程序的类文件的存在目录;
/WEB-INF/lib 可被打包为JAR格式的类文件通常放置于此目录;
# 修改访问tomcat的默认端口和状态页面: [root@node2 conf]# cd /usr/local/tomcat/conf [root@node2 conf]# vi server.xml# 定义用户 [root@node2 conf]# cd /usr/local/tomcat/conf [root@node2 conf]# vi tomcat-users.xml
定义一个虚拟主机:
[root@node2 conf]# cd /usr/local/tomcat/conf [root@node2 conf]# vi server.xml # 在# 然后修改默认主机: # 添加tomcat为系统服务: [root@node2 tomcat]# vi /etc/init.d/tomcat #!/bin/sh # Tomcat init script for Linux. # # chkconfig: 2345 96 14 # description: The Apache Tomcat servlet/JSP container. JAVA_HOME=/usr/java/latest CATALINA_HOME=/usr/local/tomcat export JAVA_HOME CATALINA_HOME exec $CATALINA_HOME/bin/catalina.sh $* [root@node2 tomcat]# chmod +x /etc/init.d/tomcat [root@node2 tomcat]# chkconfig --add tomcat [root@node2 tomcat]# chkconfig tomcat on # 重启服务: [root@node2 tomcat]# service tomcat stop [root@node2 tomcat]# service tomcat start #创建虚拟主机目录: [root@node2 tomcat]# mkdir /tomcat/app1/WEB-INF/{classes,lib} -pv [root@node2 tomcat]# vi /tomcat/app1/index.jsp <%@ page language="java" %> <%@ page import="java.util.*" %> JSP test page. <% out.println("Hello,world!"); %>
[root@node2 Catalina]# cd /usr/local/tomcat/work/Catalina #运行成功后,将自动生成以主机名命名的目录 [root@node2 Catalina]# ls localhost www.magedu.com
#使用浏览器查看:
可以装一个论坛试试:以JspRun为例
1、清空/tomcat/app1,然后将软件解压后生成的upload目录中的内容移动到/tomcat/app1
2、将tomcat服务重启启动
3、安装mysql数据库,为JspRun创建一个用户;
4、http://172.16.1.2/install.jsp根据提示进行安装即可,最后如下图
利用nginx为tomcat实现前端代理
# 一、配置Nginx [root@node1 conf.d]# cd /etc/nginx/conf.d [root@node1 conf.d]# vi virtual.conf # A virtual host using mix of IP-, name-, and port-based configuration # server { listen 80; server_name www.magedu.com alias bbs.magedu.com; location / { index index.jsp ; proxy_pass http://172.16.1.2; } location ~* \.(jsp|do)$ { proxy_pass http://172.16.1.2; } location ~* \.(html|gif|png|css|js|jpeg|jpg|htm)$ { proxy_pass http://172.16.1.3; } } # # # 将论坛程序安装完成后生成的文件全部复制到静态服务器上 [root@node2 ~]# scp -rp /tomcat/app1/* 172.16.1.3:/var/www/html # 查看访问日志 # 1、在tomcat服务器上查看访问日志 172.16.1.1 - - [01/Oct/2013:10:21:52 +0800] "GET /test.jsp HTTP/1.0" 200 114 172.16.1.1 - - [01/Oct/2013:10:21:53 +0800] "GET /favicon.ico HTTP/1.0" 304 - 172.16.1.1 - - [01/Oct/2013:10:25:50 +0800] "GET / HTTP/1.0" 200 10955 # 2、在apache服务器上查看访问日志: 172.16.1.1 - - [26/Sep/2013:23:09:11 +0800] "GET /include/javascript/keyboard.js HTTP/1.0" 304 - "http://www.magedu.com/" "Mozilla/5.0 (X11; Linux x86_64; rv:10.0.12) Gecko/20130109 Firefox/10.0.12" 172.16.1.1 - - [26/Sep/2013:23:09:11 +0800] "GET /forumdata/cache/style_1.css HTTP/1.0" 304 - "http://www.magedu.com/" "Mozilla/5.0 (X11; Linux x86_64; rv:10.0.12) Gecko/20130109 Firefox/10.0.12" 172.16.1.1 - - [26/Sep/2013:23:09:11 +0800] "GET /forumdata/cache/style_1_append.css HTTP/1.0" 304 - "http://www.magedu.com/" "Mozilla/5.0 (X11; Linux x86_64; rv:10.0.12) Gecko/20130109 Firefox/10.0.12" 172.16.1.1 - - [26/Sep/2013:23:09:11 +0800] "GET /p_w_picpaths/default/logo.gif HTTP/1.0" 304 - "http://www.magedu.com/" "Mozilla/5.0 (X11; Linux x86_64; rv:10.0.12) Gecko/20130109 Firefox/10.0.12" 172.16.1.1 - - [26/Sep/2013:23:09:11 +0800] "GET /p_w_picpaths/default/header.gif HTTP/1.0" 304 - "http://www.magedu.com/forumdata/cache/style_1_append.css" "Mozilla/5.0 (X11; Linux x86_64; rv:10.0.12) Gecko/20130109 Firefox/10.0.12"
apache为tomcat提供代理:
# 安装apr-devel、apr-util-devel、tomcat-connectors [root@node1 ~]# yum -y install apr-devel apr-util-devel [root@node1 ~]# yum -y install httpd-devel [root@node1 ~]# tar xf tomcat-connectors-1.2.37-src.tar.gz [root@node1 ~]# cd tomcat-connectors-1.2.37-src/native [root@node1 native]# ./configure --with-apxs [root@node1 native]# make [root@node1 native]# make install [root@node1 native]# ls /etc/httpd/modules/ mod_jk.so # 加载mod_jk模块: [root@node1 ~]# cd /etc/httpd/conf.d/ [root@node1 conf.d]# vi mod_jk.conf # Load the mod_jk LoadModule jk_module modules/mod_jk.so JkWorkersFile /etc/httpd/conf.d/workers.properties JkLogFile logs/mod_jk.log JkLogLevel debug JkMount /* TomcatA JkMount /status/ stat1 [root@node1 conf.d]# vi workers.properties worker.list=tomcatA,stat1 worker.TomcatA.port=8009 worker.TomcatA.host=172.16.1.2 worker.TomcatA.type=ajp13 worker.TomcatA.lbfactor=1 worker.stat1.type = status #查看模块是否加载 [root@node1 conf.d]# httpd -t -D DUMP_MODULES jk_module (shared) #重启服务 [root@node1 conf.d]# service httpd restart 在tomcat服务器上定义jvmRoute [root@node2 conf]# vi server.xml#重启tomcat服务: [root@node2 conf]# service tomcat stop [root@node2 conf]# service tomcat start
最后测试:
再添加一台tomcat服务器使apache对tomcat进行负载均衡:
安装过程……
#修改tomcat服务器引擎参数jvmRoute [root@node3 conf]# vi server.xml#添加一个虚拟主机: #创建目录: [root@node3 ~]# mkdir -pv /tomcat/app1/WEB-INF/{classes,lib} #创建测试页面: [root@node3 ~]# vi /tomcat/app1/test.jsp <%@ page language="java" %> TomcatB TomcatB
#重启服务: [root@node3 ~]# service tomcat stop [root@node3 ~]# service tomcat start
Session ID <% session.setAttribute("abc","abc"); %><%= session.getId() %> Created on <%= session.getCreationTime() %>
测试:
# 在第一台tomcat也建立测试页: [root@node2 ~]# vi /tomcat/app1/test.jsp <%@ page language="java" %>TomcatA TomcatA
Session ID | <% session.setAttribute("abc","abc"); %><%= session.getId() %> |
Created on | <%= session.getCreationTime() %> |
测试:
#在apache服务器上: [root@node1 ~]# cd /etc/httpd/conf.d/ [root@node1 conf.d]# vi mod_jk.conf [root@node1 conf.d]# more mod_jk.conf # Load the mod_jk LoadModule jk_module modules/mod_jk.so JkWorkersFile /etc/httpd/conf.d/workers.properties JkLogFile logs/mod_jk.log JkLogLevel debug JkMount /* lbcluster1 JkMount /status/ stat1 [root@node1 conf.d]# vi workers.properties worker.list = lbcluster1,stat1 worker.TomcatA.type = ajp13 worker.TomcatA.host = 172.16.1.2 worker.TomcatA.port = 8009 worker.TomcatA.lbfactor = 1 worker.TomcatB.type = ajp13 worker.TomcatB.host = 172.16.1.3 worker.TomcatB.port = 8009 worker.TomcatB.lbfactor = 1 worker.lbcluster1.type = lb worker.lbcluster1.method = R worker.lbcluster1.sticky_session = 0 worker.lbcluster1.balance_workers = TomcatA, TomcatB worker.stat1.type = status
# 使用mod_proxy为tomcat进行反向代理: [root@node1 conf.d]# vi /etc/httpd/conf.d/mod_proxy.conf ProxyVia Off ProxyRequests Off ProxyPass / ajp://172.16.1.2:8009/ ProxyPa***everse / ajp://172.16.1.2:8009/Order allow,deny Allow from all Order allow,deny Allow from all
参数介绍:
ProxyPreserveHost{On|Off}:如果启用此功能,代理会将用户请求报文中的Host:行发送给后端的服务器,而不再使用ProxyPass指定的服务器地址。如果想在反向代理中支持虚拟主机,则需要开启此项,否则就无需打开此功能。
ProxyVia {On|Off|Full|Block}:用于控制在http首部是否使用Via:,主要用于在多级代理中控制代理请求的流向。默认为Off,即不启用此功能;On表示每个请求和响应报文均添加Via:;Full表示每个Via:行都会添加当前apache服务器的版本号信息;Block表示每个代理请求报文中的Via:都会被移除。
ProxyRequests{On|Off}:是否开启apache正向代理的功能;启用此项时为了代理http协议必须启用mod_proxy_http模块。同时,如果为apache设置了ProxyPass,则必须将ProxyRequests设置为Off。
ProxyPass [path] !|url [key=value key=value...]]:将后端服务器某URL与当前服务器的某虚拟路径关联起来作为提供服务的路径,path为当前服务器上的某虚拟路径,url为后端服务器上某URL路径。使用此指令时必须将ProxyRequests的值设置为Off。需要注意的是,如果path以“/”结尾,则对应的url也必须以“/”结尾,反之亦然。
ProxyPa***everse:用于让apache调整HTTP重定向响应报文中的Location、Content-Location及URI标签所对应的URL,在反向代理环境中必须使用此指令避免重定向报文绕过proxy服务器。
另外,mod_proxy模块在httpd2.1的版本之后支持与后端服务器的连接池功能,连接在按需创建在可以保存至连接池中以备进一步使用。连接池大小或其它设定可以通过在ProxyPass中使用key=value的方式定义。常用的key如下所示:
min:连接池的最小容量,此值与实际连接个数无关,仅表示连接池最小要初始化的空间大小。
max:连接池的最大容量,每个MPM都有自己独立的容量;都值与MPM本身有关,如Prefork的总是为1,而其它的则取决于ThreadsPerChild指令的值。
loadfactor:用于负载均衡集群配置中,定义对应后端服务器的权重,取值范围为1-100。
retry:当apache将请求发送至后端服务器得到错误响应时等待多长时间以后再重试。单位是秒钟。
如果Proxy指定是以balancer://开头,即用于负载均衡集群时,其还可以接受一些特殊的参数,如下所示:
lbmethod:apache实现负载均衡的调度方法,默认是byrequests,即基于权重将统计请求个数进行调度,bytraffic则执行基于权重的流量计数调度,bybusyness通过考量每个后端服务器的当前负载进行调度。
maxattempts:放弃请求之前实现故障转移的次数,默认为1,其最大值不应该大于总的节点数。
nofailover:取值为On或Off,设置为On时表示后端服务器故障时,用户的session将损坏;因此,在后端服务器不支持session复制时可将其设置为On。
stickysession:调度器的stickysession的名字,根据web程序语言的不同,其值为JSESSIONID或PHPSESSIONID。
上述指令除了能在banlancer://或ProxyPass中设定之外,也可使用ProxySet指令直接进行设置
在httpd.conf中的配置实例:
[root@node1 ~]# vi /etc/httpd/conf/httpd.conf NameVirtualHost 172.16.1.1:80 ProxyRequests OffBalancerMember ajp://172.16.1.2:8009 loadfactor=10 route=TomcatA BalancerMember ajp://172.16.1.3:8009 loadfactor=10 route=TomcatB #ServerAdmin [email protected] ServerName www.magedu.com ProxyPass / balancer://lbcluster1/ stickysession=jsessionid ProxyPa***everse / balancer://lbcluster1/ ErrorLog logs/dummy-host.example.com-error_log CustomLog logs/dummy-host.example.com-access_log common
开启tomcat会话保持机制(基于内存复制的集群)
需要在server.xml中引擎和主机定义之间加入如下内容:
……………… ……
定义在Engine容器中,则表示对所有主机均启动用集群功能。如果定义在某Host中,则表示仅对此主机启用集群功能。此外,需要注意的是,Receiver中的address="auto"一项的值最好改为当前主机集群服务所对应的网络接口的IP地址。
特别需要注意的地方:
在后端服务器上要定义默认路由,虽然后端服务器不需要网关就可以提供服务;但是如果需要做成会话共享的tomcat集群就需要添加默认网关;否则catalina.sh启动不了,并提示不能加入Multicast组中。