最近在配合客户做一个老项目的国产化中间件替换,任务很明确:把原先跑在WebLogic上的Java应用,迁到东方通TongWeb上,并且完成一套可交给运维的环境部署。说实话,这类需求在国产化中间件选型里非常典型,参考资料却常常只写“支持JavaEE、部署方便”这种销售话术,真正关于TongWeb环境安装部署的细节文档少得可怜。我这次从拿到安装包到控制台跑出第一个应用,前后踩了不少坑,这篇文章就把完整过程写下来,包括安装、建服务、部署war包、调内存、查日志,适合刚接触东方通TongWeb的运维和开发照着操作。
1. 先弄清TongWeb在系统里干的活,再谈安装
1.1 TongWeb到底负责哪一层
TongWeb是东方通旗下的Java应用服务器中间件,和Tomcat、Jetty这些Servlet容器不一样,它更像是WebLogic、WebSphere在国产化替代里的“平替”角色。一个典型的Java Web系统请求链路是:浏览器先打到Nginx,Nginx再把动态请求转发给TongWeb,TongWeb跑你的Servlet、JSP、EJB,最后通过数据源连数据库。也就是说,TongWeb负责的是整个业务应用运行环境这一层,它不直接面对用户,但用户能不能用上系统,完全取决于它运行得稳不稳。
很多刚接触的人会拿它和Tomcat比,然后发现部署war包的方式有点像,于是直接照着Tomcat习惯来用。这个思路能用,但不完全对。TongWeb自带管理系统,支持数据源配置、连接池管理、集群、会话同步,还带一套独立的管理控制台。你做国产化中间件替代,不是简单把Tomcat目录覆盖一下,而是要把它当作一个完整Java EE运行平台来对待。
1.2 给从WebLogic迁过来的同事一张对应表
我在迁移过程中发现,凡是能熟练操作WebLogic的人,上手TongWeb都会快很多,因为两者的功能模块在逻辑上几乎是互相对应的。这里给一张我在项目里整理的功能对照表,方便迁移时找对应入口:
| 功能点 | WebLogic | TongWeb | 备注 |
|---|---|---|---|
| 管理控制台 | Console | TongWeb控制台 | 都是浏览器访问,端口不同 |
| 部署单元 | Applications | 应用管理/部署 | 支持war、ear包 |
| JDBC数据源 | Data Sources | 数据源管理 | 连接池参数位置类似 |
| JVM参数配置 | setDomainEnv.sh | 启动脚本JAVA_OPTS | 改完必须重启 |
| 应用目录 | domain/applications | deploy目录 | 对应war解压位置 |
| 日志 | domain/servers/logs | logs目录 | 需要看实际目录名 |
| 集群会话复制 | Cluster | 集群/会话共享 | 配置项名称有差异 |
这张表并不会百分之百匹配你手头的版本,不同发行版的菜单名称和目录布局会有差异,但对应关系是一致的。如果你过去管理过WebLogic,遇到问题先想“这个功能在WebLogic里叫什么名字”,再按这个名去TongWeb控制台里找,基本都能找到。
1.3 本次部署的环境基线
为了避免后面操作内容太空泛,我先交代一下这次部署的基线环境。操作系统是x86_64架构的Linux,内核版本是3.10以上的老牌发行版,JDK用的是1.8.0_291,TongWeb版本是商业发行版中的常见版本。为什么用JDK 8?因为被迁移的老应用是基于JDK 8开发的,TongWeb当前主流版本对JDK 8支持最成熟,很多依赖第三方组件的应用直接上JDK 11、17大概率会踩类加载问题。
另外,我强烈建议生产环境用独立系统用户运行中间件,而不是直接用root。后面讲systemd托管TongWeb的时候会细说。安装目录我规划在/opt/tongweb,应用部署目录独立在/data/tongweb-deploy,这么做是为了将来磁盘满了或者要单独备份时,不用把整个安装包一起折腾。
2. 安装前先干完这5件事,能省一下午
2.1 确认JDK版本和JAVA_HOME
TongWeb本身是基于Java开发的,没有JDK它就是一堆脚本和class文件。绝大多数商用发行版要求JDK 1.8以上,部分新版本已经支持更高版本,但在没确认应用兼容性之前,不要贸然用最新JDK。安装前第一件事就是执行java -version,确认系统默认的Java版本。如果机器上有多个JDK,我建议在启动脚本里显式指定JAVA_HOME,而不是依赖PATH,否则很容易出现“我明明装了JDK,启动却说找不到Java”的情况。
还有一个细节:有些操作系统自带的OpenJDK只有JRE,没有完整开发工具链。中间件运行一般不强制要javac,但某些TongWeb管理功能或JSP编译会用到JDK里的工具类。保险起见,装一个完整JDK,不要只依赖系统精简版。
2.2 看清操作系统和CPU架构
国产化环境里经常遇到ARM架构服务器,或者麒麟、统信UOS这类操作系统。TongWeb安装包有x86_64和aarch64版本之分,如果拿错包,启动时经常报“bad ELF interpreter”或者直接提示无法执行二进制文件。安装前用两行命令确认基线:
uname -m cat /etc/os-releaseuname -m输出x86_64就选x86_64安装包,输出aarch64就选ARM版本。操作系统发行版影响不大,但会影响你装systemd服务、防火墙规则等外围操作。我这次是在x86_64的老Linux上部署,所以下文命令都是基于这个环境写的。
2.3 授权文件与安装介质
TongWeb商业版是需要授权文件的,一般随安装介质一起提供,常见文件名类似license.dat,也可以在管理控制台的“授权管理”里导入。不同厂商项目拿到的授权形式不太一样,有的给单独文件,有的给一个授权码。我的经验是:拿到介质后,先把授权文件放到一个固定位置并备份,然后在安装目录或控制台里完成激活,再启动服务。不要等到控制台都打不开了才开始找授权,那会浪费很多时间。
有一点必须提醒:授权文件绑定机器信息的情况是存在的,比如有些授权是绑定IP或MAC地址的。如果之后虚拟机迁移、网卡名变了,授权可能会失效。生产环境做快照迁移前,先确认授权是否支持迁移,否则装完新环境发现中间件起不来,问题就大了。
2.4 目录规划与运行账号
安装目录最好不要直接放在根分区下。我之前见过有人把TongWeb装在/usr下,结果磁盘满把系统分区撑爆了。建议单独规划一个数据盘目录,比如/opt/tongweb安装程序,/data/tongweb-deploy放应用,日志也独立一个目录。这样后续备份、扩容、清理日志都清晰。
运行账号方面,创建一个名为tongweb的系统账号:
useradd -r -s /sbin/nologin tongweb mkdir -p /opt/tongweb /data/tongweb-deploy chown -R tongweb:tongweb /opt/tongweb /data/tongweb-deploy使用/sbin/nologin是防止有人直接切到这个账号下执行命令,对中间件来说降低了运维误操作风险。后面用systemd托管时,直接指定User=tongweb,比传统startserver.sh裸奔更可控。
2.5 端口规划与防火墙放通
TongWeb默认管理控制台端口是9060,业务HTTP端口常见8080,实际以你安装包的配置为准。部署前先查一下目标端口有没有被占用:
netstat -lnp | grep -E '8080|9060'如果端口被占用,要么清掉占用进程,要么改TongWeb配置,二选一。改配置的话要同步改Nginx反向代理,很容易漏。防火墙需要放通控制台端口和业务端口:
firewall-cmd --add-port=9060/tcp --permanent firewall-cmd --add-port=8080/tcp --permanent systemctl reload firewalld如果是内网环境且安全策略允许,也可以临时关闭防火墙做验证,但生产环境不要这么干。放通后先在本机用curl验证控制台端口是否通,再去浏览器访问,否则你很难分清楚是防火墙的问题还是中间件没起来。
3. 从解压到看到控制台登录页,全流程实操
3.1 解压安装包并看目录结构
TongWeb安装包通常是tar.gz或zip格式。我这次拿到的是tar.gz包,解压到/opt/tongweb:
tar -zxvf TongWeb.tar.gz -C /opt/tongweb/解压完成后,不要急着启动,先花两分钟看目录结构。常见目录大致如下:
/opt/tongweb/ ├── bin/ # 启动、停止脚本 ├── conf/ # 全局配置文件 ├── deploy/ # 应用部署目录 ├── lib/ # 中间件运行依赖库 ├── logs/ # 日志目录 └── domains/ # 实例级配置目录(部分版本存在)不同版本目录名会有一点差异,有的版本把日志放在domains/xxx/logs下,有的版本没有deploy目录而是统一用控制台管理。我的建议是:进目录先找两个文件,一个是启动脚本,一个是安装说明或README。TongWeb很多发行版会自带简版部署手册,里面写了默认端口、初始账号这一系列关键信息,网上找半天不如先看包内文档。
3.2 设置环境变量并执行启动脚本
启动前先把JAVA_HOME在启动脚本里定义好,或者临时在会话里导出:
export JAVA_HOME=/usr/local/jdk1.8.0_291 export PATH=$JAVA_HOME/bin:$PATH然后切到安装目录的bin下,找到启动脚本。不同版本这个脚本的名字不一样,常见是startserver.sh或start.sh。启动时使用tongweb用户执行:
su - tongweb -s /bin/bash -c "export JAVA_HOME=/usr/local/jdk1.8.0_291; /opt/tongweb/bin/startserver.sh"如果启动成功,终端会输出一段提示,同时后台开始初始化。这里有个特别容易犯的错误:直接双击执行后看不到任何报错,就以为启动成功,其实进程在几十秒后因为端口冲突或授权失效又退出了。所以下一步必须看日志和端口。
3.3 首次启动日志:该看哪些关键信息
启动后先找日志文件。TongWeb日志路径不统一,有的在安装根目录的logs下,有的在domains下。最快的定位方法是看启动脚本里的LOG_FILE变量,或者通过find命令找最新的日志文件:
find /opt/tongweb -name '*.log' -mmin -5日志里需要重点确认几件事:控制台端口是否监听、业务端口是否监听、有没有“started successfully”类似的关键字、有没有报错堆栈。日志文件末尾显示Server open for business或者“启动完成”才说明中间件真的起来了。不要只看终端里输出几行就放心,中间件属于典型的重型服务,终端退出了进程可能还在跑,反过来终端没退出但进程已经崩了也常发生。
端口监听状态用这条命令确认:
netstat -lnp | grep java看到9060和8080都在监听,这才算过了第一关。
3.4 控制台登录与初始账号问题
浏览器访问http://服务器IP:9060/console,正常情况下会看到TongWeb控制台登录界面。这里是最容易翻车的地方:不同版本的初始用户名密码差异很大,有人说是admin,有人说是thanos,还有人说是eosadmin。我自己的经验是,千万别盲猜,直接查安装包内的说明文档或介质上贴的账号信息。如果安装包内提供了初始化脚本,首次启动时会让你设置管理员密码,那就在初始化时把密码设成符合公司密码策略的强密码。
登录控制台后,第一件事不是去部署应用,而是找到“系统管理”或“服务器配置”里的密码策略、会话超时配置,把默认安全选项改掉。控制台默认账号如果没改,相当于把你中间件管理入口暴露在网络上,这是安全问题。实在忘记密码的话,最稳妥的办法是查介质包内的管理员手册,看恢复密码部分的说明。不要自己乱删配置文件,我在现场见过有人删了用户配置文件,结果控制台直接登录不了,最后只能重新初始化环境。
3.5 用systemd把TongWeb托管成服务
传统部署方式是直接跑启动脚本,但机器重启后中间件不会自动拉起,还得专门写开机启动项。我建议直接用systemd管理,配置示例:
[Unit] Description=TongWeb Application Server After=network.target [Service] Type=forking User=tongweb Group=tongweb Environment=JAVA_HOME=/usr/local/jdk1.8.0_291 ExecStart=/opt/tongweb/bin/startserver.sh ExecStop=/opt/tongweb/bin/stopserver.sh Restart=on-failure [Install] WantedBy=multi-user.target把这个文件保存到/usr/lib/systemd/system/tongweb.service,然后执行:
systemctl daemon-reload systemctl enable tongweb --now注意Type=forking能否用对,取决于启动脚本到底是后台启动还是前台启动。如果你的启动脚本会一直占住终端不退出,应该把Type改成simple,并且脚本里不要自己调nohup。判断方法很简单:直接手动执行脚本,如果执行完终端还能返回到命令提示符,说明是forking型;如果终端被卡住,就改成simple型并去掉脚本里的后台化处理。
4. 部署第一个应用:控制台部署和目录部署两条路
4.1 通过管理控制台上传war包
登录TongWeb控制台后,找“应用管理”或“部署”菜单。整个菜单在不同版本里显示中文或英文不同,中文化版本一般在“应用管理”里,英文版本在“Deployments”里。上传war包的流程大致是:
- 选择war包文件并上传;
- 设置应用名称和上下文路径;
- 确认部署目标实例;
- 点击部署,再点击启动。
上下文路径决定应用的访问URL。比如应用包名是oa.war,上下文路径默认可能是/oa,那么启动后访问地址是http://IP:8080/oa/。如果项目希望直接用根路径访问,比如http://IP:8080/就进系统,可以把上下文路径设置为/或者留空,具体看版本支持情况。
上传完成后,控制台会把war包复制到中间件的部署目录,并完成解压。这里有我非常想强调的一点:控制台部署时,war包在部署过程中处于半更新状态,如果同时有其他管理员在操作同一个应用,会互相覆盖。生产环境发布窗口内,最好协调所有人都不要登录控制台乱点。
4.2 直接丢到deploy目录的部署方式
有些维护场景不适合用控制台,比如自动化发布脚本要批量替换应用,这时可以直接将war包拷贝到部署目录。TongWeb的deploy目录相当于一个应用放置区,把app.war复制进去后,有版本支持自动解压部署,有版本需要重启中间件或手动在控制台刷新才能识别。
直接部署的好处是快,适合发布流程已经固化的项目;坏处是容易留下旧目录。比如你重新上传了app.war,但旧的app解压目录可能还在,同名覆盖时旧class文件没清理干净,会出现修改了代码但行为不变这种诡异问题。我处理的顺序是:先停应用,删除旧的应用解压目录,再拷贝新war包,最后启动应用。别图省事直接覆盖。
4.3 项目目录到底指什么
很多入行不久的同学问“项目目录放哪”,其实这里的项目目录有两层意思:一是war包解压后的物理目录,二是应用的上下文路径。物理目录通常在TongWeb的deploy目录下,比如deploy/oa/里面是WEB-INF/classes、static等。上下文路径则决定了外部访问URL。
如果应用里需要读取配置文件,建议让应用把配置外置,不要打包进war里。TongWeb部署后war包会解压到项目目录,你直接修改解压出来的配置文件是能生效的,但下次重新部署war包时这些修改会被覆盖。正确做法是使用TongWeb控制台里的配置项或系统属性引用外部目录,让应用从/data/appconfig/这类路径读配置,发布时只更新war包不动配置。
4.4 前端静态资源项目怎么部署
现在的项目经常是前后端分离,前端打出来是纯静态文件,没有war包。这种情况下不需要特意打成war再部署。两种做法:一是把打包出来的dist目录直接放到一个静态目录下,由TongWeb的HTTP端口直接访问;二是在前面再架一个Nginx,用Nginx托管静态资源,动态API请求再代理到TongWeb。
我倾向第二种。因为Nginx处理静态文件性能比Java中间件强很多,而且还能一并解决证书、跨域、负载均衡。部署的时候注意,Nginx的proxy_pass要指向TongWeb实际监听端口,如果不改中间件端口,那默认就是8080。如果Nginx和后端TongWeb之间有超时需求,比如报表导出很耗时,需要单独调整Nginx代理超时时间,默认的60秒不够用。
5. TongWeb内存溢出排查实录:从卡死到定位
5.1 一次典型的内存溢出现场
热搜里“tongweb内存溢出”这么高频,说明这确实是使用TongWeb时绕不开的坑。我遇到的一次现场是:一个TongWeb实例上部署了三个应用,运行两周后其中一个应用突然响应变慢,最后直接无法访问,但另外两个应用还正常。查看日志,发现反复出现java.lang.OutOfMemoryError: Java heap space,紧接着还有GC overhead limit exceeded。
很多人第一次看到OOM会直接怀疑中间件有问题,但内存溢出绝大多数是应用本身或整体配置导致的。TongWeb只是Java进程,它不会自己把内存吃掉,真正吃内存的是跑在它里面的业务代码。可能是某个应用缓存设计不当、数据源连接池开得太大、批量任务没有释放引用。遇到OOM,第一步是看日志确认是堆内存还是持久代/Metaspace问题,第二步再看物理内存剩余情况。
5.2 修改JVM启动参数的正确姿势
确认是堆内存不足后,最直接的调整是修改TongWeb启动脚本里的JVM参数。找到启动脚本里的JAVA_OPTS,示例:
JAVA_OPTS="-Xms2048m -Xmx2048m -XX:MaxMetaspaceSize=512m -XX:+UseG1GC"这里有两个细节。第一,生产环境建议-Xms和-Xmx设成一样,避免JVM运行时动态扩容触发性能抖动;第二,如果物理内存只给机器分配了4G,非要设置-Xmx4096m,那JVM启动就可能会因为无法申请到内存直接退出。调参前先看物理内存:
free -h结合机器上其他进程的占用情况,把堆大小控制在物理内存的一定比例内。比如机器总内存8G,其他进程占2G,那TongWeb堆设置3G到4G比较合理,别贪。
5.3 确保参数真的生效
改完启动脚本后,不要重启完就完事了,一定要确认参数被实际使用。检查方法:
jps -lv这个命令会列出Java进程以及启动参数,如果你的-Xmx2048m出现在输出里,说明脚本里的配置生效了。如果没生效,大概率是启动脚本里还有其他地方定义了JVM参数,或者你修改的JAVA_OPTS变量根本就没被引用。还有一种情况是脚本里使用-D方式传递了配置文件路径,但JVM内存参数在另一处定义,需要仔细看脚本里的命令拼接顺序。
另外,TongWeb控制台通常也会显示当前JVM内存使用情况。如果它有图形化监控,可以直接看到堆内存曲线,这比命令行方式直观得多,适合给不熟悉jps的运维同事用。
5.4 调完内存还溢出的下一步
加大堆内存只能延缓问题,不代表根治。如果-Xmx4g跑几天又OOM了,就该做线程和堆转储分析了。先用jstack看所有线程状态,重点找有没有大量阻塞的线程;再用jmap导出堆转储文件,用MAT分析大对象。这一步需要一点JVM排查经验,不是运维一两句话能说清的,但作为中间件管理员至少要做到能导出这些现场资料,然后交给开发人员去定位。
还有一种情况是应用不再OOM,但TongWeb管理控制台响应特别慢,这通常是多个应用共用一个实例导致的。一个应用的内存泄漏会拖垮整个实例,包括控制台。这种场景下,最干净的方案是把应用拆到多个TongWeb实例里,隔离故障。代价是每个实例都要占用一定的内存和端口资源,但稳定性提升是非常值得的。
6. 部署落地之后容易踩的坑:端口、日志、多实例
6.1 端口冲突:启动失败最常见的直接原因
TongWeb启动失败,一半以上是端口被占用。常见情况有两种:一是8080业务端口被另一个Web服务占用,比如你自己装的Tomcat或者Nginx;二是上一次启动没有正常停止,残留Java进程还占着9060端口。
排查命令:
netstat -lnp | grep 8080找到占用进程的PID后,确认是什么进程再处理。如果是遗留的TongWeb进程,直接杀掉:
kill -9 PID但如果是其他重要服务,就不要随便杀。这时候改TongWeb端口更安全。TongWeb业务端口一般在conf目录下的配置里,改完端口后记得同步修改Nginx、防火墙规则、快捷访问链接。我见过一个人改完端口忘了改运维脚本,第二天批量发布脚本对着旧端口探测,一直报服务不可用。
6.2 日志到底在哪,怎么找
“日志找不到”也是提问最多的问题之一。很多网上资料会说TongWeb日志在logs目录,但具体到某个版本,可能日志在/opt/tongweb/domains/xxx/logs下面。找日志的正确方式不是背路径,而是看启动脚本里的LOG_FILE和配置里的日志路径。手动启动时,终端输出通常也会提示日志文件路径。
日志文件权限问题也要注意。如果你用root启动过TongWeb,再用tongweb用户重启,日志文件的所有者可能变成root,导致新用户进程写不进去,启动时直接报权限错误。解决办法是把整个安装目录的所有者重新chown给tongweb:
chown -R tongweb:tongweb /opt/tongweb日志滚动也是需要关注的。TongWeb自带的日志策略一般会按大小滚动,但业务量大的系统一天能产生好几GB访问日志。建议在部署完成后,配一个crontab定期清理历史日志,或者交给elk系统收集后本地保留几天即可。日志分区独立也是这个原因,避免日志写满系统分区。
6.3 多实例部署的目录规划
在国产化项目里,同一个中间件版本,很多公司会选择一台物理机部署多套环境,比如一套给核心业务,一套给非核心业务,或者一套给开发、一套给测试。多实例最忌讳的是所有人都把应用往同一个deploy目录里塞。这样不仅互相争抢内存,连重启也无法单独操作一个应用。
我推荐的方式是复制安装目录为多个实例目录,或者按TongWeb官方多实例方式创建domain。每个实例使用独立的端口组合、独立的日志目录、独立的应用部署目录。比如:
/data/tongweb/node1:业务端口8081、控制台9061/data/tongweb/node2:业务端口8082、控制台9062
两个实例之间互不影响,一个实例内存溢出重启,另一个实例继续对外提供服务。缺点是多实例会让机器内存占用变高,部署前要根据物理内存算好每个实例堆大小,别一个实例分2G,结果机器总共就4G内存。
6.4 旧应用迁移中的ClassLoader和jar包冲突
从WebLogic或WebSphere迁到TongWeb,最隐蔽的坑不是中间件装不上,而是应用能启动但运行时报ClassNotFoundException、NoSuchMethodError这类类加载问题。核心原因是WebLogic默认的类加载优先级和TongWeb不同,应用里打包了一些旧版本的第三方jar,之前跑在WebLogic时被中间件屏蔽了,换到TongWeb环境后这些jar和中间件自带的类冲突了。
处理思路也和WebLogic迁移时一样:清理应用WEB-INF/lib目录里重复的旧jar,特别是Servlet API、JSP API这类提供者jar,不要打包进应用,应该由中间件来提供。遇到NoSuchMethodError,通常是jar版本冲突,用jar tf看包里的类,确认哪个jar提供该类,再统一版本。迁移一个新应用,部署时间可能只要十分钟,但类加载问题排查可能花一天,这个心理准备要有。
7. 我整理的一份TongWeb运维检查清单
7.1 启动后必看的三类信息
每次中间件重启完,不要只看到“启动完成”就离开。我个人习惯按固定顺序确认三件事:进程状态、端口监听、控制台登录。命令组合如下:
ps -ef | grep tongweb netstat -lnp | grep java curl -I http://127.0.0.1:9060/consoleps确认进程在跑,netstat确认9060和8080端口都在监听,curl确认管理控制台确实有HTTP响应。如果进程在但端口没监听,基本可以判断中间件没有完整加载,需要看日志;如果端口监听但curl无响应,可能是控制台应用异常。这套检查做完,整个环境状态才叫真的确认完成。
7.2 升级补丁时的备份策略
TongWeb版本升级或打补丁前,一定要备份的可不止安装目录。至少要把这几样单独复制一份:conf目录、deploy目录下的所有应用、授权文件。lib目录一般不需要全备,因为补丁包会替换它,备份了反而可能恢复出错时版本混淆。
我的备份习惯是打成时间戳压缩包:
tar -czf tongweb-backup-$(date +%Y%m%d).tar.gz /opt/tongweb/conf /data/tongweb-deploy /opt/tongweb/license升级过程中如果遇到问题,第一时间不是去翻补丁包,而是把备份恢复到原路径,先让业务恢复,再分析升级失败原因。这个顺序不能反,业务可用永远优先于排查原因。
7.3 给接触TongWeb不久的人一句话建议
接触这套中间件的人,多多少少都带着“国产软件不好用”的预期而来。我实际用下来的感受是,TongWeb的核心功能和部署逻辑,和主流Java应用服务器没有本质区别,出问题的地方往往是对它不熟悉,拿习惯了的东西直接套上去。安装部署是最简单的一环,难的是应用适配和后续调优,这两件事都需要你在生产环境里一遍遍试出来。只要保留好变更记录,稳扎稳打,TongWeb跑生产完全没问题。
最后再分享一个小习惯:我会在每次部署完成后,把安装路径、JDK路径、端口列表、控制台账号、JVM参数和日志路径写进项目交接文档。看起来多花十分钟,但下次不管是环境迁移还是同事接手,都能省下大半天时间。中间件运维这件事,细节记下来比记在脑子里可靠得多。