一次解决因GRPC导致的cpu占用率异常的经历

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/XingYuan8023/article/details/88658350

背景:

本人负责的一个数据转换项目(java)中用到了google的grpc远程调用框架,在移交测试后发现,程序持续运行一段时间后cpu占用率总会在一个时间点由<5%突变到>20%并且再也不会下降到原来的水平。经过一系列排查最终确定,是由于所使用的grpc(1.13.1)版本中包含了一个有bug的netty(4.1.25.Final)版本导致的。

解决过程:

    由于并未及时博客记录所以没用详细的截图,只能凭记忆大致写出解决过程以及所以用到的工具。

1、起初怀疑是由内存泄漏导致jvm在频繁的gc使cpu占用率升高,于是使用jdk自带工具jvisiualvm和jstat监测分析进程运行情况。发现gc发生的频率并不高并且,发生gc时cpu占用率比问题复现且未发生gc时还低。

2、在使用jvisiualvm和jstat对进程长时间的监测分析后发现每次突发cpu异常飙高的时候都恰好有一个新线程产生,于是立马用jstack命令查看此线程的详细信息,发现这个线程是在netty框架用于回收资源的线程ObjectCleanerThread。翻阅netty和grpc-java的官方github->ISSUES得知是由于netty框架未正确关闭ObjectCleanerThread导致的cpu占用异常。

3升级grpc版本至1.17.1->问题解决!

 

 

 

 

展开阅读全文

请教问题:MERGE INTO导致CPU占用率非常高

09-27

服务器搭在虚拟机上:rnCPU: 2 * 4核rn内存: 16GBrn硬盘: 60GBrnrn操作系统: RHEL 6.4 x86-64rn数据库: ORACLE 11.2rnrnrn该服务器当作数据库服务器+WEB服务器(TOMCAT)使用,设计ORACLE分配8GB内存,TOMCAT分配4.5GB内存。rnrnrnORACLE内存设置:rn[code=sql]alter system set memory_target=6g;rnalter system set memory_max_target=8g;rnalter system set db_keep_cache_size=384m;rnalter system set sga_target=4g;rnalter system set sga_max_size=6g;rnalter system set pga_aggregate_target=2g;[/code]rnrnrn主要有一个记录表(设计预计每月记录约1亿条,该表需保存5年以上数据):rn[code=sql]CREATE TABLE Recordsrn(rn Record_Id NUMBER CONSTRAINT PK_RECORDS PRIMARY KEY,rn Record_Terminal NUMBER NOT NULL,rn Record_Window NUMBER(4) NOT NULL,rn Record_Employee NVARCHAR2(50) ,rn Record_Number NVARCHAR2(50) NOT NULL,rn Record_Business NUMBER NOT NULL,rn Record_Status NUMBER(4) NOT NULL,rn Record_Evaluation NUMBER(4) NOT NULL,rn Record_TicketTime DATE NOT NULL,rn Record_AcceptTime DATE ,rn Record_FinishTime DATE ,rn Record_VIP NUMBER NOT NULL,rn Record_BookChannel NUMBER NOT NULL,rn Record_Description1 NVARCHAR2(255) ,rn Record_Description2 NVARCHAR2(1024) ,rn -- 仅 11g以上支持虚拟列rn Record_PartitionField NUMBER(3) GENERATED ALWAYS AS (MOD(TO_NUMBER(TO_CHAR(Record_TicketTime,'y')),2)*100+TO_NUMBER(TO_CHAR(Record_TicketTime,'mm'))) VIRTUALrn)PCTFREE 10,PCTUSED 75rnPARTITION BY LIST (Record_PartitionField)rn(rn PARTITION P01 VALUES (1) TABLESPACE qms_records_01,rn PARTITION P02 VALUES (2) TABLESPACE qms_records_02,rn PARTITION P03 VALUES (3) TABLESPACE qms_records_03,rn PARTITION P04 VALUES (4) TABLESPACE qms_records_04,rn PARTITION P05 VALUES (5) TABLESPACE qms_records_05,rn PARTITION P06 VALUES (6) TABLESPACE qms_records_06,rn PARTITION P07 VALUES (7) TABLESPACE qms_records_07,rn PARTITION P08 VALUES (8) TABLESPACE qms_records_08,rn PARTITION P09 VALUES (9) TABLESPACE qms_records_09,rn PARTITION P10 VALUES (10) TABLESPACE qms_records_10,rn PARTITION P11 VALUES (11) TABLESPACE qms_records_11,rn PARTITION P12 VALUES (12) TABLESPACE qms_records_12,rn PARTITION P13 VALUES (101) TABLESPACE qms_records_13,rn PARTITION P14 VALUES (102) TABLESPACE qms_records_14,rn PARTITION P15 VALUES (103) TABLESPACE qms_records_15,rn PARTITION P16 VALUES (104) TABLESPACE qms_records_16,rn PARTITION P17 VALUES (105) TABLESPACE qms_records_17,rn PARTITION P18 VALUES (106) TABLESPACE qms_records_18,rn PARTITION P19 VALUES (107) TABLESPACE qms_records_19,rn PARTITION P20 VALUES (108) TABLESPACE qms_records_20,rn PARTITION P21 VALUES (109) TABLESPACE qms_records_21,rn PARTITION P22 VALUES (110) TABLESPACE qms_records_22,rn PARTITION P23 VALUES (111) TABLESPACE qms_records_23,rn PARTITION P24 VALUES (112) TABLESPACE qms_records_24rn);rn[/code]rnrnWEB端定期会有一批数据需MERGE INTO到RECORDS表里(约15000条/分钟),大部分是需要UPDATE的,小部分使用INSERT。rn实际测试时,发现[color=#FF0000]ORACLE进程占用CPU相当高,Load Average都在8.0以上,MERGE INTO的操作速度很慢[/color];同时,查看[color=#FF0000]内存还有很大空余(8GB以上),Oracle只占用了4.0GB内存(相当于我为SGA_TARGET指定的值)[/color]。rnWEB端使用一个CONNECTION或多个CONNECTION进行操作,效果都差不多。rnrnWEB端JAVA使用prepareStatement进行SQL预编译,然后传入参数,通过addBatch批量传入待更新记录(批量大小各种值都测试过,不理想),最后executeBatch进行执行并commit。rnrnMERGE INTO的语句如下:rn[code=sql]MERGE INTO Records r1rn USING (SELECT 1 FROM DUAL) r2rn ON(rn r1.record_tickettime BETWEEN TO_DATE('2014-09-25','yyyy-mm-dd') AND TO_DATE('2014-09-25 23:59:59','yyyy-mm-dd hh24:mi:ss')rn AND r1.record_terminal=1rn AND r1.record_business=1rn AND r1.record_number='VIP1000'rn )rnWHEN MATCHED THENrn UPDATE SET r1.record_window=1,rn r1.record_employee='100001',rn r1.record_status=80,rn r1.record_evaluation=80,rn r1.record_vip=0,rn r1.record_bookchannel=2,rn r1.record_description1='这里是客户信息,是调用ESB服务获取到的'rnWHEN NOT MATCHED THENrn INSERT(record_id,record_terminal,record_window,record_employee,rn record_number,record_business,record_status,record_evaluation,rn record_tickettime,record_vip,record_bookchannel)rn VALUES(seq_record_id.NEXTVAL,1,1,'100002','VIP1000',1,1,2,rn TO_DATE('2014-09-25 12:34:56','yyyy-mm-dd hh24:mi:ss'),1,2);[/code]rn 论坛

关于多线程导致CPU占用率的问题

10-31

[code=java]public void run() rn // List vos = assess.get();rn if (assess.size() == 0) rn return;rn rn SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");rn while (!isInterrupted()) rn for (AccessVo acs : assess) rn if (sdf.format(new Date()).equals(sdf.format(acs.getAccessTime()))) rn //通过Spring工具类,注入Servicern managementService = (ManagementService) SpringApplicationContextHolderrn .getSpringBean("managementService");rn HttpTookit.doGet(acs.getUrl(), managementService);rn rn rn try rn Thread.sleep(900);rn catch (InterruptedException e) rn Thread.currentThread().interrupt();rn rn rn [/code]rnrnrnrn[code=java]threadName = "monit" + targetId;rn // 获取当前JVM所有线程rn int flag = 0;rn for (Thread thread : allThreads) rn // 如果存在就中断,重新创建一个线程rn if (threadName.equals(thread.getName())) rn// thread.stop();// 中断此线程rn// thread.join();rn thread.interrupt();rn DoAccessing newThread = new DoAccessing();rn newThread.setAssess(vos);rn Thread t = new Thread(newThread);rn t.setName(threadName);rn t.start();rn flag++;rn break;rn rn rn if (flag == 0) rn // 没有则创建rn DoAccessing newThread = new DoAccessing();rn newThread.setAssess(vos);rn Thread t = new Thread(newThread);rn t.setName(threadName);rn t.start();rn rn catch (Exception e) rn e.printStackTrace();rn [/code]rnrn[img=https://img-bbs.csdn.net/upload/201610/31/1477899324_707587.png][/img]rnrn按照如上情况,我的程序最多会启动[color=#FF0000] 7个线程[/color],可是为什么会导致CPU占用率达到 50%上下呢 论坛

没有更多推荐了,返回首页