为了同学们看起来一目了,特按如下思路进行讲解。

1.出现的场景

    2.分析及解决的过程

    3.总结

  最近公司要使用zookeeper做配置管理(后面简称ZK),然后自己就提前用虚拟机进行了ZK三台集群的搭建。之后开始选择使用zookeeper的java client工具,google了半天,发现了一个很名强大的Apache的Curator工具,很多底层的东西都已经给你封装好了,所以用起来很方便,因为我使用的场景是做配置管理,所以使用Curator的Framework就够了。Curator相对于zookeeper,就相当于Guava之于Java.

  因为每天的访问量上亿级的,所以考虑的因素还是很多,因此从网上找了一些demo,然后自己就开始写一些测试的类,下边的这个方法是用于获取客户端,并且加入了一些监听和输出:

private static CuratorFramework getClient(String namespace) throws Exception{

        ACLProvider aclProvider = new ACLProvider() {
private List<ACL> acl ;
@Override
public List<ACL> getDefaultAcl() {
if(acl ==null){
ArrayList<ACL> acl = ZooDefs.Ids.CREATOR_ALL_ACL;
acl.clear();
acl.add(new ACL(Perms.ALL, new Id("auth", "admin:admin") ));
this.acl = acl;
}
return acl;
}
@Override
public List<ACL> getAclForPath(String path) {
return acl;
}
};
String scheme = "digest";
byte[] auth = "admin:admin".getBytes();
int connectionTimeoutMs = 1000;
String connectString = "127.0.0.1:2181";
CuratorFramework client = CuratorFrameworkFactory.builder().
aclProvider(aclProvider).
authorization(scheme, auth).
connectionTimeoutMs(1).
connectString(connectString).sessionTimeoutMs(50).
namespace(namespace).
retryPolicy(new RetryOneTime(1)).build();
client.getConnectionStateListenable().addListener(new ConnectionStateListener() {
@Override
public void stateChanged(CuratorFramework client, ConnectionState newState) {
System.out.println("** STATE CHANGED TO : " + newState);
}
});
client.start();
client.getZookeeperClient().internalBlockUntilConnectedOrTimedOut(); // client.getZookeeperClient().blockUntilConnectedOrTimedOut();
System.out.println(client.getZookeeperClient().isConnected());
System.out.println(client.getState());
return client;
}

  获取客户端之后就可以启动(client.start())客户端并且创建相当的Node以及它的payload. 感觉写的已经可以了,而且经过简单的测试,觉得可以了,然后就上到测试环境上了,测试环境的访问量并不是很大,所以也没有什么特别异常,之后就放到线上了。

  当把程序放到线上去之后,系统的JVM监控系统就开始报警,线程数由几百迅速增加到了3、4千个,直接超过了我们设置的报警阈值,所以感觉使用jstack命令 jstack -l pid > threadDump,找一个 stack analyzer online的一个网站 fastthread.io, upload做好的threadDump文件,上边有很多汇总,然后基本上一目了然:

  1700多个TIMED_WATING,还有1700多个TIMED_WATING,这里边肯定有问题,然后继续往下拉,会按线程分组进行展示:

  会发现有大概有77%的线程和Curator有关系,这个应该就是它的问题了,那么点开里边的内容,就能看到线程的明细了,继续:

  里边有Curator Framework的代码了,找到相当的行907,发现只要Client一启动的话就会使得BlockingQueue会有一个take()的动作,这个take的含义是将head取到,如果没有的话就等待,这就是线程WAITING的状态,然后继续看是在什么地方调用的它。

找到了,原来是客户端启动(client.start())的时候进行的调用,因为我在网上看到很多地方说build模式拿到的Client是线程安全的,所以我就每次拿一次client,然后调用其start()。这样每个不同的线程就会都等待在那个位置上。我没有在Finally调用 CloseableUtils.closeQuietly(client); 因为请求量太大,如果频繁的调用关闭客户端会造成性能下降,必须保持一个长连接。

  打开Curator的官网上,里边也进行了说明,创建采用build的方式是线程安全的,但是要保持单例。

  这样问题找到了,下边开始想着如果修复和优化,首先让它实现单例,同时还不能用完之后就直接关闭。同时要保持长连接,在特定情况下进行连接关闭,那就如果出现异常为

KeeperException.ConnectionLossException时需要捕获并且进行计数和关闭。同时也为了效率考虑,再获取Node的payload时将payload进行缓存,这样再次减少了对zk的大量访问。同时可以根据自己的实际情况去考虑缓存的时间。
if(client == null || client.getState().equals(CuratorFrameworkState.STOPPED) || !client.getNamespace().equals(namespace)) {
synchronized (ZookeeperUtil.class) {
if(client == null || client.getState().equals(CuratorFrameworkState.STOPPED) || !client.getNamespace().equals(namespace)) {
               CloseableUtils.closeQuietly(client);  
client = getClient(namespace);
}
}
}

  同时在网上找到zookeeper集群上从3.4开始,从客户端连接数maxClientCnxns(配置在zoo.cfg)默认连接数为60,改为0时不限制。

  总结:

  1. 当遇到线程数增加或CPU过高时需要使用jstack将JVM的线程数据导出到文件,然后通过在线工具或自己下载的工具进行分析,我还是比较喜欢这个在线的分析工具,它能分析出总的线程数中按状态进行分析,还可以按线程类型进行分组,很强大。

  2. 遇到问题要冷静思考,然后多写几个小的demo进行测试。我其实在写这个问题的过程中我是写了测试类进行模拟的,然后通过本机的jvisualvm查看栈的情况,根我推断的一致的,所以就会找到解决的方法。

  3.有些技术知识还是从官方网站学习,而且如果看书的话,需要从头看到尾,这样的话基本上能了解事务的全部内容,否则只看到部分内容。

  如果有写的不对的地方,欢迎同学们来拍砖~

记一次线上Curator使用过程JVM栈溢出解决的更多相关文章

  1. 记一次线上bug排查-quartz线程调度相关

    记一次线上bug排查,与各位共同探讨. 概述:使用quartz做的定时任务,正式生产环境有个任务延迟了1小时之久才触发.在这一小时里各种排查找不出问题,直到延迟时间结束了,该任务才珊珊触发.原因主要就 ...

  2. 解Bug之路-记一次线上请求偶尔变慢的排查

    解Bug之路-记一次线上请求偶尔变慢的排查 前言 最近解决了个比较棘手的问题,由于排查过程挺有意思,于是就以此为素材写出了本篇文章. Bug现场 这是一个偶发的性能问题.在每天几百万比交易请求中,平均 ...

  3. 记一次线上gc调优的过程

           近期公司运营同学经常表示线上我们一个后台管理系统运行特别慢,而且经常出现504超时的情况.对于这种情况我们本能的认为可能是代码有性能问题,可能有死循环或者是数据库调用次数过多导致接口运行 ...

  4. 记一次线上服务CPU 100%的处理过程

    告警 正在开会,突然钉钉告警声响个不停,同时市场人员反馈客户在投诉系统登不进了,报504错误.查看钉钉上的告警信息,几台业务服务器节点全部报CPU超过告警阈值,达100%. 赶紧从会上下来,SSH登录 ...

  5. 记一次排查线上MySQL死锁过程,不能只会curd,还要知道加锁原理

    昨晚我正在床上睡得着着的,突然来了一条短信. 啥,线上MySQL死锁了,我赶紧登录线上系统,查看业务日志. 能清楚看到是这条insert语句发生了死锁. MySQL如果检测到两个事务发生了死锁,会回滚 ...

  6. 记一次线上Kafka消息堆积踩坑总结

    2018年05月31日 13:26:59 xiaoguozi0218 阅读数:2018更多 个人分类: 大数据   年后上线的系统,与其他业务系统的通信方式采用了第三代消息系统中间件Kafka.由于是 ...

  7. 记一次线上由nginx upstream keepalive与http协议"协作"引起的接口报错率飙高事件

    年前接到个任务,说要解决线上一些手机客户端接口报错率很高的问题.拿到了监控邮件,粗略一看,各种50%+的错误率,简直触目惊心.这种疑难杂症解决起来还是挺好玩的,于是撸起袖子action. 最终的结果虽 ...

  8. 【MySQL】记一次线上重大事故:二狗子竟然把线上数据库删了!!

    写在前面 估计二狗子这几天是大姨夫来了,心情很郁闷,情绪也很低落,工作的时候也有点心不在焉.让他发个版本,结果,一行命令下去把线上的数据库删了!你没听错:是删掉了线上的数据库!运营那边顿时炸了锅:怎么 ...

  9. 线上问题debug过程(cat,grep,tr,awk,sort,uniq,comm等工具的综合使用)

    问题:发现线上到货单的数量,小于实际到货的数量. 怀疑一些隐藏的条件,将部分唯一码进行了过滤,导致数量变少. 开展了如下的跟踪流程: 1.找到其中一个明细的唯一码 grep 6180e-4b09f p ...

随机推荐

  1. 终极解决方案:java.security.cert.CertificateException: Certificates does not conform to algorithm constraints

    报错信息 javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: Certificates does ...

  2. mac中配置jdk环境

  3. 危化品速查APP--Android Project

    开发环境 Android studio 2.3.1 功能描述 集成多种查询方式,查看本地数据库中危险化学品的信息: 按照中文拼音和英文首字母,对化学品进行查询: 按照UN号或者CAS号查询相应的化学品 ...

  4. 在SpringBoot中存放session到Redis

    前言 今天你们将再一次领略到SpringBoot的开发到底有多快,以及SpringBoot的思想(默认配置) 我们将使用redis存放用户的session,用户session存放策略有很多,有存放到内 ...

  5. ANTD mobile源码分析 -- popover

    最近的开发中要用到很多的各式各样的组件.但是发现ant design mobile(后面简称ANTDM)里很多的资源.于是就分析一下,学习学习. ANTDM直接使用了typescript,没有用ES2 ...

  6. duilib界面库学习(仿PC微信界面,有服务器,有数据库,可以网络通信)

    客户端代码:https://github.com/TTGuoying/duilib_ChatClient 服务器代码:https://github.com/TTGuoying/duilib_ChatS ...

  7. OSQA的配置

    1.安装Python,我安装的是python 2.7.3 2.安装setuptools 下载setuptools,并安装 安装好以后,在pyton2.7/scripts的路径下将会有easy_inst ...

  8. session 与 coolie 的区别与联系

    cookie 和session 的区别: session 在服务器端,cookie 在客户端(浏览器) cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗考虑到安全应当 ...

  9. XAF_GS_02_创建第一个XAF项目

    上一节我们讲解了如何安装XAF环境,这次我们要开始创建一个自己的XAF项目. Setp 1 第一步打开你的Visual Studio,新建项目,如下图所示,选择DevExpress XAF,选择好你的 ...

  10. 【DDD】领域驱动设计实践 —— 一些问题及想法

    在社区系统的DDD实践过程中,将遇到一些问题和产生的想法记录下来,共讨论. 本文为[DDD]系列文章中的其中一篇,其他内容可参考:使用领域驱动设计思想实现业务系统. 1.dto.model和entit ...