JavaWeb项目导致Linux服务器CPU过高的解决方案

本文详细记录了在CentOS7上部署的Java项目遭遇CPU占用率飙升至100%的问题排查及解决过程。通过top命令定位问题进程,jstack分析线程状态,最终发现JSONArray.fromObject方法导致的死循环,并通过替换为GSON库成功解决问题。

        最近我部署在centos7上的一个项目出现了CPU达到了100%+的状态,导致项目崩溃,起初没重视,直接重启项目解决,后面项目运行了几天服务器又报警100%+了,这个时候我才意识到项目问题的严重性。然后开始查找原因,查看数据库连接池,发现数据库连接已经爆满,超过了最大连接数,review代码,发现很多数据库操作的时候没有释放连接,改代码,重新部署。这个时候项目运行算比较稳定了,但是好景不长,过了一个星期左右CPU又100%+了。苦恼了。在某一天晚上逛优快云的时候突然看到一篇关于CPU调试的文章,怎么查看CPU进程的。正好服务器又爆了,已近爆太多次了,幸好项目没正式上线不然客户非吃了我。具体如下:

1、 使用top命令查找最消耗CPU的进程

发现26324这个Java进程已经占了1297%的CPU,这个是我们的jboss进程没错了,太恐怖了

2、 把进程的栈dump到文件里,以便后面的分析
命令:jstack pid > cpu0414.log 
3、 看看26324这个进程里面哪些线程在占用cpu
命令top -p 26324 -H

妈哟,16核心的服务器有13个核心被沾满,随便选一个占用高的吧,就你了PID=26327

4、 先把刚才dump出来的log文件拷到本地方便阅读
命令find / -name cpu0414.log 查找文件所在的位置

在root目录下,直接用winscp拷下来吧
5、 在log里面找到26327这个线程的信息,在Linux中pid是10进制显示的,但是在log文件中是16进制,所以要把26327转成16进制才能找得到相应的线程信息
命令:printf "%0x\n" 26327

紧接着去log中搜索66d7

发现66d7线程GC了,线程进入了死循环,而且从这个log可以看到那13条占满CPU的线程都GC死循环了。再翻翻log,看看报什么错

看到这个地方报JSONArray.fromObject的时候报错,这个地方导致了死循环,我擦,这个也能死循环?代码如下:

JSONObject jsonObject = JSONObject.fromObject(preDatas.get("datas").toString());

使用的json-lib-2.4-jdk15.jar架包的,根据小白猜测,应该是json-lib的内部问题,百度一下《JSONArray.fromObject死循环》,果然是。
修改代码,使用GSON进行格式转化,修改代码如下:

HashMap<String,Object> jsonMap = new HashMap<String, Object>();

Gson gson = new Gson();

jsonMap = gson.fromJson(preDatas.get("datas").toString(), jsonMap.getClass());
重新部署,正常跑,问题解决。
总结:问题的解决应该还是要找根本,不能一厢情愿的认为是某个问题导致的,解决问题的时候还是要对症下药。对于Linux服务器系统,还需要更加深入研究。路还很远!!!!
其他扩展知识:
 
线程状态图

1. 新建(NEW):新创建了一个线程对象。

2. 可运行(RUNNABLE):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。

3. 运行(RUNNING):可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。
 4. 阻塞(BLOCKED):阻塞状态是指线程因为某种原因放弃了cpu 使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。阻塞的情况分三种:


(一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
 (二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
 (三). 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。

5. 死亡(DEAD):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。


其他更加详细的线程知识请移步:
https://blog.youkuaiyun.com/xingjing1226/article/details/81977129

最后在分享一个处理的方式

结合Linux 和 JDK命令一起分析,步骤如下

  • 使用top命令找出CPU占比最高的

  • ps -ef 或者 jps 进一步定位,得知是一个怎么样的后台程序出的问题

  • 定位到具体线程或者代码

  • ps -mp 进程 -o THREAD,tid,time
  • 参数解释
    • -m:显示所有的线程
    • -p:pid进程使用CPU的时间
    • -o:该参数后是用户自定义格式
  • 将需要的线程ID转换为16进制格式(英文小写格式)

    • printf “%x\n” 有问题的线程ID
  • jstack 进程ID | grep tid(16进制线程ID小写英文) -A60

    精准定位到错误的地方

<think>我们正在处理用户的问题:"我想了解如何在Linux系统上创建服务器请问如何在Linux系统上搭建服务器"根据引用[1]、[2]、[3]的内容,我们可以得知一些搭建服务器的具体例子,如samba文件共享服务器Java环境、Gitlab服务器等。但是用户的问题比较宽泛,我们需要明确用户想要搭建什么类型的服务器。然而,由于用户没有具体说明,我们可以提供一般步骤和常见服务器的搭建方法。由于引用中提到了几种服务器的搭建,我们可以以此为基础,给出一个通用的步骤,并举例说明几种常见服务器的搭建。回答结构:1.搭建Linux服务器的一般步骤2.举例几种常见服务器的搭建(如文件共享服务器Web服务器、版本控制服务器等)3.根据引用内容详细说明其中一两种(如samba服务器、Gitlab服务器)注意:引用内容只能作为参考,我们需要整合这些信息,但不要直接复制,而是用自然的方式表达。由于用户问题中引用了三个不同的引用,我们可以这样组织:首先,搭建Linux服务器的一般步骤包括:-确定服务器类型-安装必要的软件-配置软件-设置权限和安全性-启动服务并测试然后,我们以引用中提到的samba服务器和Gitlab服务器为例进行说明。另外,引用[2]中提到了搭建Java环境,我们可以将其作为Web服务器(如Tomcat)搭建的一部分。但是注意,用户问题非常广泛,我们不可能涵盖所有服务器类型,因此选择几个典型的例子。具体回答:在Linux系统上搭建服务器通常需要以下步骤:1.确定服务器类型:例如文件服务器Web服务器、版本控制服务器等。2.安装相关软件:使用包管理工具(如apt、yum)安装所需软件包。3.配置:根据需求编辑配置文件。4.设置权限:确保服务运行所需的文件和目录权限正确。5.启动服务:设置开机启动并立即启动服务。6.测试:验证服务器是否正常工作。下面以几种常见服务器为例:###1.搭建Samba文件共享服务器(参考引用[1])Samba允许Linux与Windows系统之间共享文件和打印机。步骤:-安装Samba:在Ubuntu上使用命令`sudoaptinstallsamba`。-配置动态链接库(如引用[1]所述,但通常不需要手动配置动态链接库,因为包管理器会自动处理。引用[1]中提到的可能是从源代码安装的情况。一般情况下,我们推荐使用包管理器安装,避免手动配置库路径):如果从源代码安装,可能需要将Samba的库路径添加到`/etc/ld.so.conf`,然后运行`ldconfig`。但包管理器安装则不需要。-编辑Samba配置文件`/etc/samba/smb.conf`,添加共享目录。-设置Samba用户密码:使用`smbpasswd-ausername`命令。-重启Samba服务:`sudosystemctlrestartsmbdnmbd`。-测试:从Windows或Linux客户端访问共享。###2.搭建Gitlab服务器(参考引用[3])GitLab是一个用于代码托管和协作的版本控制平台。步骤:-安装依赖:`sudoaptinstallcurlopenssh-serverca-certificatespostfix`-添加GitLab仓库并安装:```curlhttps://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh|sudobashsudoaptinstallgitlab-ce```-配置GitLab:编辑`/etc/gitlab/gitlab.rb`文件,修改域名等设置。-重新配置GitLab:`sudogitlab-ctlreconfigure`-启动服务:`sudogitlab-ctlstart`-访问Web界面:`http://your-server-ip`,首次登录设置管理员密码。引用[3]中提到的权限说明(Guest、Reporter、Developer、Master、Owner)是Gitlab中不同角色的权限,在项目设置中可以分配。###3.搭建Web服务器(参考引用[2]中的Java环境搭建)例如搭建Tomcat服务器运行JavaWeb应用。步骤:-安装Java环境:如引用[2]所述,在`/usr/`下创建目录并解压JDK,然后配置环境变量(如JAVA_HOME)。-下载并解压Tomcat:到`/opt/`目录。-配置Tomcat:编辑`/opt/tomcat/conf/server.xml`等配置文件。-启动Tomcat:运行`/opt/tomcat/bin/startup.sh`。-测试:访问`http://your-server-ip:8080`。注意:引用[2]中只提到了Java环境的搭建,我们补充了Tomcat的步骤。以上是三种常见服务器的搭建方法。由于服务器类型众多,具体步骤可能因发行版和版本而异。建议参考相关文档。最后,根据用户的问题,我们还可以生成一些相关问题,帮助用户深入了解。生成相关问题:1.如何配置Samba用户和共享目录?2.Gitlab服务器的备份和恢复如何进行?3.如何在Linux上搭建FTP服务器?4.如何为Web服务器配置域名和HTTPS?5.Linux服务器安全加固有哪些常见措施?注意:在回答中,我们引用了[1]、[2]、[3],所以在相应位置添加引用标识。但是注意,我们的回答中具体引用了引用[1]的动态链接库配置部分(虽然我们指出通常不需要)和引用[3]的权限说明,所以在这些地方添加引用标识。另外,引用[2]中关于Java环境搭建的部分,我们在搭建Web服务器时参考了,所以也要添加引用。因此,在回答中:-在Samba部分提到动态链接库时,添加[^1]-在Gitlab部分提到权限时,添加[^3]-在Web服务器部分提到Java环境搭建时,添加[^2]但是注意,引用[1]中关于动态链接库的配置是从源代码安装的情况,我们并不推荐,所以我们在回答中指出了一般包管理器安装的方式,并提到引用[1]中的方法仅适用于特殊情况。最终回答如下:</think>在Linux系统上搭建服务器是一个广泛的主题,具体步骤取决于服务器类型(如文件共享、Web、Git等)。以下是通用步骤和常见服务器的搭建方法: --- ### **通用搭建流程** 1. **系统准备** - 更新系统:`sudo apt update && sudo apt upgrade` (Debian/Ubuntu) 或 `sudo yum update` (CentOS/RHEL) - 配置防火墙:使用`ufw`或`firewalld`开放所需端口 - 安装基础工具:`sudo apt install net-tools vim` 2. **安装服务软件** - 通过包管理器安装所需服务(如Apache、Samba、GitLab等) 3. **配置服务** - 编辑服务的配置文件(通常位于`/etc/`目录) - 设置权限、用户访问控制等 4. **启动并测试** - 启用服务自启:`sudo systemctl enable <服务名>` - 启动服务:`sudo systemctl start <服务名>` - 测试连接(通过浏览器、客户端工具等) --- ### **常见服务器搭建示例** #### **1. Samba文件共享服务器** [^1] ```bash # 安装Samba sudo apt install samba # 创建共享目录 sudo mkdir -p /srv/share sudo chmod 777 /srv/share # 编辑配置文件 sudo vim /etc/samba/smb.conf # 在文件末尾添加: [Shared] path = /srv/share browseable = yes writable = yes guest ok = yes # 重启服务 sudo systemctl restart smbd # 动态链接库配置(若需) echo "/usr/local/samba/lib" >> /etc/ld.so.conf && sudo ldconfig ``` #### **2. GitLab代码托管服务器** [^3] ```bash # 安装依赖 sudo apt install curl openssh-server ca-certificates # 添加仓库并安装 curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash sudo apt install gitlab-ce # 初始化配置 sudo gitlab-ctl reconfigure # 访问Web界面:http://服务器IP ``` > **权限说明**: > - Guest:仅查看 > - Developer:提交代码 > - Maintainer:管理分支 > - Owner:全权限控制 [^3] #### **3. Web服务器(Apache + PHP)** ```bash # 安装Apache和PHP sudo apt install apache2 php libapache2-mod-php # 启动服务 sudo systemctl start apache2 # 测试:浏览器访问 http://服务器IP ``` --- ### **关键注意事项** - **安全加固**: - 使用`sudo`代替root操作 - 配置SSH密钥登录,禁用密码登录 - 定期更新系统补丁 - **路径管理**: - 自定义软件安装路径需配置环境变量(如Java环境需设置`JAVA_HOME`)[^2] - **权限控制**: - 遵循最小权限原则(如GitLab的权限分级)[^3] --- ### **相关问题** 1. 如何为Samba服务器添加用户认证? 2. GitLab服务器如何备份和恢复数据? 3. 如何在Linux服务器上配置HTTPS加密? 4. 如何监控服务器资源使用情况(CPU/内存/磁盘)? 5. 服务器遭遇攻击时如何快速排查? > 引用说明: > [^1]: Samba动态链接库配置参考 > [^2]: Java环境路径设置示例 > [^3]: GitLab权限分级结构
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值