解析同一系统安装RPM包的tomcat与压缩包tomact同时使用问题

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介:

  大部分朋友在使用tomcat的时候,常用的功能是在一个tomcat中为不同的应用设置多个访问路径,然后修改不同的访问端口,比如初始化端口是8080,那么另一个应用使用8081,其他的依次类推,只要做到每个应用的端口号不重复就行。


   但是本人在实际环境中遇到如下的问题,需要在一个系统上面同时安装两个不同“渠道”的tomcat,一个rpm包的tomcat以及一个zip形式的tomcat压缩包,结果发现出问题了,只能其中一个tomact可以启动,谁先启动,谁就是“老大”,第二个启动的tomcat就一直启动失败。


   日志文件等下分析,先说说我为什么会遇到这样的问题,为什么必须要安装两个不同“渠道”的tomcat,OK,问题背景是这样的: 我这边需要实施的项目架构是cloudstack+kvm,在cloudstack之上,我们有一个JAVA应用,用于调用cloudstack的API,用户使用的时候仅仅需要操作我们的上层JAVA应用即可,那么安装过cloudstack的朋友们知道,安装cloudstack-management跟cloudstack-agent最简便的方式就是通过配置Cloudstack的RPM包YUM源,然后直接通过yum install安装即可,在安装cloudstack-management的同时,系统也会安装操作系统自带的tomcat6包,于是,解释了我们为什么要安装rpm的tomcat包,那么我们还有个上层的JAVA应用怎么部署,weblogic or tomcat? 当然都行,但是从简便性来说,tomcat是最佳的选择,weblogic除了安装较为繁琐,还需要创建domain,配置数据源,发布JAVA包等一系列步骤,tomcat相比而言,肯定简便很多,但是安装cloudstack-management的时候安装的tomcat包已经被cloudstack做了很多定制化配置,所以,如果我们想要发布新的JAVA应用,从维护角度去看,尽量不要去动原有的tomcat配置,于是,我们选择重新安装一个tomcat软件,从源码压缩包解压即可,为了最大程度的划分界限,新的JAVA应用,jdk程序我们也不选择已经安装好的openjdk,而是选择oracle jdk解压安装【关于tomcat跟jdk的安装,非常简单,故本文不做过多说明】。

Tomcat路径: /usr/local/jdk1.6/

JDK路径:    /usr/local/jdk1.6

   我们对新的tomcat配置文件做一些修改,告知其使用的jdk是新的oracle jdk

1
2
3
[root@clovemzone ~] # cat /usr/local/tomcat6.0/bin/catalina.sh  |grep -v "#" |grep JAVA_HOME |head -n 2
JAVA_HOME= /usr/local/jdk1 .6
JRE_HOME=$JAVA_HOME /jre

  修改应用监听端口,从8080 修改为10801 ,修改端口的时候,查看/etc/services中,尽量自定义该文件中未定义的端口号,当然范围也在1-65535之内

1
2
3
4
[root@clovemzone ~] # vim /usr/local/tomcat6.0/conf/server.xml
<Connector port= "8080"  protocol= "HTTP/1.1"
修改为
<Connector port= "10801"  protocol= "HTTP/1.1"

   然后,启动两个tomcat【不考虑cloudstack-management服务】

1
2
3
4
5
6
7
8
9
[root@clovemzone ~] # service tomcat6 start   //启动rpm包的tomcat服务
Starting tomcat6:                                          [  OK  ]
[root@loc bin] # pwd
/usr/local/tomcat6 .0 /bin
[root@localhost bin] # ./startup.sh   //启动源码包安装的tomcat服务
Using CATALINA_BASE:    /usr/local/tomcat6 .0
Using CATALINA_HOME:    /usr/local/tomcat6 .0
Using CATALINA_TMPDIR:  /usr/local/tomcat6 .0 /temp
Using JRE_HOME:        /usr/local/jdk1 .6 /jre

检查tomcat启动状态

1
2
3
4
5
6
7
8
[root@localhost bin] # ps -ef |grep java |grep -v grep
tomcat   21266     1  0 13:09 ?        00:00:01  /usr/lib/jvm/jre/bin/java  -Djavax.sql.DataSource.Factory=org.apache.commons.dbcp.BasicDataSourceFactory -classpath : /usr/share/tomcat6/bin/bootstrap .jar: /usr/share/tomcat6/bin/tomcat-juli .jar: /usr/share/java/commons-daemon .jar -Dcatalina.base= /usr/share/tomcat6  -Dcatalina.home= /usr/share/tomcat6  -Djava.endorsed. dirs = -Djava.io.tmpdir= /var/cache/tomcat6/temp  -Djava.util.logging.config. file = /usr/share/tomcat6/conf/logging .properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager org.apache.catalina.startup.Bootstrap start
[root@localhost bin] # lsof -i:8080
COMMAND   PID   USER   FD   TYPE DEVICE SIZE /OFF  NODE NAME
java    21266 tomcat   37u  IPv6 104620      0t0  TCP *:webcache (LISTEN)
[root@localhost ~] # lsof -i:18080  //没有监听18080端口
[root@localhost ~] # lsof -i:18080  |wc -l
0

从如上代码可以看出,系统启动的java进程只有/usr/lib/jre/bin/java,很明显,是rpm包安装的tomact服务启动成功,而源码包安装的并没有启动OK,再通过lsof 查看监听的端口可以确认以上结论。

   这个时候,我们可以来查看日志文件相关信息了,/usr/local/tomcat6.0/log/catalina.out

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
SEVERE: StandardServer.await: create[8005]:
java.net.BindException: Address already  in  use
         at java.net.PlainSocketImpl.socketBind(Native Method)
         at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:383)
         at java.net.ServerSocket.bind(ServerSocket.java:328)
         at java.net.ServerSocket.<init>(ServerSocket.java:194)
         at org.apache.catalina.core.StandardServer.await(StandardServer.java:373)
         at org.apache.catalina.startup.Catalina.await(Catalina.java:630)
         at org.apache.catalina.startup.Catalina.start(Catalina.java:590)
         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
         at java.lang.reflect.Method.invoke(Method.java:597)
         at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
         at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Dec 17, 2013 1:18:53 PM org.apache.coyote.http11.Http11Protocol pause
INFO: Pausing Coyote HTTP /1 .1 on http-18080
Dec 17, 2013 1:18:54 PM org.apache.catalina.core.StandardService stop
INFO: Stopping service Catalina
Dec 17, 2013 1:18:54 PM org.apache.coyote.http11.Http11Protocol destroy

  通过日志分析,Address already in use,按照之前的经验来看,报这个错的,是由于端口的冲突,而且日志里面也会明确指明哪个端口被占用,比如8080之类的,但是这个日志却始终没有提醒,而且tomcat的监听端口8080也不会有冲突,第二个tomcat的默认监听端口已经从8080修改为了18080,那会有什么问题呢?

  那么,Adress 会不会是内存地址呢?会不会是两个tomcat都使用了共享内存,而且使用了相同的地址,导致了这样的冲突呢?不敢确定,只有去检查了,通过ipcs命令列出所有共享内存信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@localhost ~] # ipcs
------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status    
0x00000000 98304      root       600        393216     2          dest       
0x00000000 131073     root       600        393216     2          dest       
0x00000000 163842     root       600        393216     2          dest       
0x00000000 196611     root       600        393216     2          dest       
0x00000000 229380     root       600        393216     2          dest       
0x00000000 262149     root       600        393216     2          dest       
0x00000000 294918     root       600        393216     2          dest       
0x00000000 327687     root       600        393216     2          dest       
0x00000000 360456     root       600        393216     2          dest       
0x00000000 393225     root       600        393216     2          dest       
0x00000000 425994     root       600        393216     2          dest       
0x00000000 458763     root       600        393216     2          dest       
0x00000000 491532     root       600        393216     2          dest       
0x00000000 524301     root       600        393216     2          dest       
0x00000000 557070     root       600        393216     2          dest       
------ Semaphore Arrays --------
key        semid      owner      perms      nsems   
------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages


定位每个shmid的进程使用程序是否有调用java的?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@clovemzone ~] # cat test_java.sh
#!/bin/bash
#使用该脚本查找共享内存是否有Java进程
# 列出所有使用共享内存的shmid对于的cpid号
for  shmid  in   `ipcs  | grep  0x | awk  -F ' '  '{print $2}'  ` ;  do  ipcs -m -i $shmid | grep  cpid | awk  -F ' '  '{print $3}' | awk  -F '='  '{print $2}'  done  > cpid.txt
# 通过cpid号查找进程中的java进程
#如果存在,  输出 java process in cpid:xx
#如果不存在,输出 no java process cpid: xx
for  cpid  in  ` cat  cpid.txt`
do
     ps  -ef | grep  $cpid | grep  - v  grep  | grep  java
     if  [ $? == 0 ]
     then
         echo  "java process in cpid:$cpid"
     else
         echo  "no java process cpid:$cpid"
     fi
done

执行该脚本,进行测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@clovemzone ~] # sh test_java.sh
no java process cpid:16677
no java process cpid:16696
no java process cpid:16718
no java process cpid:16706
no java process cpid:16935
no java process cpid:16747
no java process cpid:16696
no java process cpid:16706
no java process cpid:16958
no java process cpid:16687
no java process cpid:16687
no java process cpid:16715
no java process cpid:16754
no java process cpid:17005
no java process cpid:16785

非常残忍的发现,没有任何一个java进程是使用共享内存的,难道这样的分析有错

那既然这样,就看看已经存在的java进程到底占用了哪些端口吧

1
2
3
4
[root@clovemzone ~] # netstat  -nltup |grep java
tcp        0      0 ::ffff:127.0.0.1:8005       :::*                        LISTEN      21698 /java        
tcp        0      0 :::8009                     :::*                        LISTEN      21698 /java        
tcp        0      0 :::8080                     :::*                        LISTEN      21698 /java

发现除了8080,<Connector port="18080" protocol="HTTP/1.1"..> 提供HTTP服务的端口

还有8009,8005这两个端口也是被监听的,那么就去配置文件里面看下这两个端口到底是干嘛用的吧。

<Server port="8005" shutdown="SHUTDOWN">   看作用是提供关闭服务的端口

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />  AJP端口

既然这么多端口都是每个tomcat实例都要启动监听的,那么就把这些端口都修改一下吧

8005 ==> 18005

8009 ==> 18009

修改完成,保存/usr/local/tomcat6.0/conf/server.xml。再次启动源码包的tomcat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@clovemzone bin] # ./startup.sh  //重新启动tomcat服务
Using CATALINA_BASE:    /usr/local/tomcat6 .0
Using CATALINA_HOME:    /usr/local/tomcat6 .0
Using CATALINA_TMPDIR:  /usr/local/tomcat6 .0 /temp
Using JRE_HOME:        /usr/local/jdk1 .6 /jre
[root@clovemzone bin] # ps -ef |grep java
tomcat   21698     1  0 13:18 ?        00:00:03  /usr/lib/jvm/jre/bin/java  -Djavax.sql.DataSource.Factory=org.apache.commons.dbcp.BasicDataSourceFactory -classpath : /usr/share/tomcat6/bin/bootstrap .jar: /usr/share/tomcat6/bin/tomcat-juli .jar: /usr/share/java/commons-daemon .jar -Dcatalina.base= /usr/share/tomcat6  -Dcatalina.home= /usr/share/tomcat6  -Djava.endorsed. dirs = -Djava.io.tmpdir= /var/cache/tomcat6/temp  -Djava.util.logging.config. file = /usr/share/tomcat6/conf/logging .properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager org.apache.catalina.startup.Bootstrap start
root     24200     1 68 14:20 pts /3     00:00:02  /usr/local/jdk1 .6 /jre/bin/java  -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config. file = /usr/local/tomcat6 .0 /conf/logging .properties -Djava.endorsed. dirs = /usr/local/tomcat6 .0 /endorsed  -classpath : /usr/local/tomcat6 .0 /bin/bootstrap .jar: /usr/local/tomcat6 .0 /bin/commons-logging-api .jar -Dcatalina.base= /usr/local/tomcat6 .0 -Dcatalina.home= /usr/local/tomcat6 .0 -Djava.io.tmpdir= /usr/local/tomcat6 .0 /temp  org.apache.catalina.startup.Bootstrap start
root     24222 21016  0 14:20 pts /3     00:00:00  grep  java
[root@clovemzone bin] # lsof -i:18080
COMMAND   PID USER   FD   TYPE DEVICE SIZE /OFF  NODE NAME
java    24200 root   29u  IPv6 112921      0t0  TCP *:18080 (LISTEN)
[root@clovemzone bin] # netstat  -nltup |grep java
tcp        0      0 ::ffff:127.0.0.1:8005       :::*                        LISTEN      21698 /java        
tcp        0      0 :::8009                     :::*                        LISTEN      21698 /java        
tcp        0      0 :::8080                     :::*                        LISTEN      21698 /java        
tcp        0      0 ::ffff:127.0.0.1:18005      :::*                        LISTEN      24200 /java        
tcp        0      0 :::18009                    :::*                        LISTEN      24200 /java        
tcp        0      0 :::18080                    :::*                        LISTEN      24200 /java

再次查看java进行,查看系统监听的java进程端口,发现两个tomcat实例已经可以“共存”了。


结论:

 还是端口惹的祸!

很多朋友看到这里会郁闷,那干嘛一开始不修改所有的端口呢?

其实,我想表达的是在日志文件不是非常明确的情况下面,更多的需要我们通过自己的经验以及不断尝试才能把问题解决,有的时候,不经意间解决了问题其实也是一种思考的过程!

希望能够帮到大家,不仅问题的答案,而是一种过程!










本文转自 暗黑魔君 51CTO博客,原文链接:http://blog.51cto.com/clovemfong/1341525,如需转载请自行联系原作者
目录
相关文章
|
2月前
|
监控 网络协议 Java
Tomcat源码解析】整体架构组成及核心组件
Tomcat,原名Catalina,是一款优雅轻盈的Web服务器,自4.x版本起扩展了JSP、EL等功能,超越了单纯的Servlet容器范畴。Servlet是Sun公司为Java编程Web应用制定的规范,Tomcat作为Servlet容器,负责构建Request与Response对象,并执行业务逻辑。
Tomcat源码解析】整体架构组成及核心组件
|
18天前
|
人工智能 前端开发 Java
【Tomcat源码分析】启动过程深度解析 (二)
本文深入探讨了Tomcat启动Web应用的过程,重点解析了其加载ServletContextListener及Servlet的机制。文章从Bootstrap反射调用Catalina的start方法开始,逐步介绍了StandardServer、StandardService、StandardEngine、StandardHost、StandardContext和StandardWrapper的启动流程。每个组件通过Lifecycle接口协调启动,子容器逐层启动,直至整个服务器完全启动。此外,还详细分析了Pipeline及其Valve组件的作用,展示了Tomcat内部组件间的协作机制。
【Tomcat源码分析】启动过程深度解析 (二)
http数据包抓包解析
http数据包抓包解析
|
4月前
|
Ubuntu 前端开发 JavaScript
技术笔记:Ubuntu:一个部署好的tomcat应用(war包)怎么用Nginx实现动静分离?
技术笔记:Ubuntu:一个部署好的tomcat应用(war包)怎么用Nginx实现动静分离?
|
18天前
|
网络协议 网络虚拟化
接收网络包的过程——从硬件网卡解析到IP
【9月更文挑战第18天】这段内容详细描述了网络包接收过程中机制。当网络包触发中断后,内核处理完这批网络包,会进入主动轮询模式,持续处理后续到来的包,直至处理间隙返回其他任务,从而减少中断次数,提高处理效率。此机制涉及网卡驱动初始化时注册轮询函数,通过软中断触发后续处理,并逐步深入内核网络协议栈,最终到达TCP层。整个接收流程分为多个层次,包括DMA技术存入Ring Buffer、中断通知CPU、软中断处理、以及进入内核网络协议栈等多个步骤。
|
2月前
|
XML 存储 JavaScript
xml介绍与解析,及xml库包使用
xml介绍与解析,及xml库包使用
26 0
|
2月前
|
机器学习/深度学习 计算机视觉 Python
深度学习项目中在yaml文件中定义配置,以及使用的python的PyYAML库包读取解析yaml配置文件
深度学习项目中在yaml文件中定义配置,以及使用的python的PyYAML库包读取解析yaml配置文件
41 0
|
2月前
|
网络协议 网络虚拟化
解析接收网络包的过程
【8月更文挑战第6天】IP层->TCP层->Socket层
|
3月前
|
存储 数据挖掘 Linux
探索Linux命令rpm2cpio:解析RPM包内容的利器
`rpm2cpio`是Linux下用于从RPM包中提取内容的工具,它将`.rpm`转换为CPIO归档。无需安装,可直接访问包内文件,适合数据分析。命令简单,常与`cpio`结合使用,如`rpm2cpio package.rpm | cpio -idmv`解压文件。示例包括提取特定文件和列出包内所有文件。注意权限、路径和文件完整性,使用前备份数据,并查阅文档以优化使用。
|
4月前
|
Java 应用服务中间件 API
Tomcat处理一个HTTP请求的执行流程的详细解析
Tomcat处理一个HTTP请求的执行流程的详细解析
107 4

推荐镜像

更多
下一篇
无影云桌面