悟空,拿我的打狗棒来

一个服务假死问题

Elasticsearch | 作者 code4j | 发布于2017年12月31日 | 阅读数:4680

我写了一个服务调用es做增删改查的,结果前些天有一起假死事件,现象是服务全都没流量了,请求进不来,rpc服务队列里面堆积了好多请求都超时了。过了十几分钟后这个现象自己就缓解了。
当时rpc服务的状态是这样的:

1590537962-5a329fe8a1db8.png

这个代表流量,中间一段时间没流量了,请求进不来,但是我的服务没有死进程还在,所以我才说是假死。

由于当时电脑不在边上让同事帮忙看的,很多问题没法复现,我只知道几个数据:
通过我自己记录的超时日志发现那一瞬间很多请求耗时非常高(es查询返回的took 以及调用actionGet方法消耗的时间都比较长),一段时间很多操作能花几十秒甚至一两分钟。 
当时的GC频率不高都是年轻带GC,老年代GC也有但是只有十来次,也没有出现concurrent mode failure,qps也属于正常的范围,日志记录的耗时较长的查询或修改 但是我再拿去执行的时候发现其实耗时并不长,也许是因为请求超时了所以才会统计到耗时较长吧,感觉这个线索不具备可靠性。
 
还有一种可能,就是服务层和es集群的连接数满了,导致那一会儿请求es集群的任务都阻塞了?我的客户端是这么写的:
public class ClientManager {
private static Logger logger = LogManager.getLogger(ClientManager.class.getName());

private static final String CLUSTER_NAME = "cluster.name";
private static final String ES_SERVICES = "es.services";

private Client client;

private static class ClientManagerHolder {
private ClientManagerHolder() {
}

private static final ClientManager INSTANCE = new ClientManager();
}

public static Client getClient() {
return ClientManagerHolder.INSTANCE.client;
}

private ClientManager() {
if (client == null) {
createClient();
}
}

private void createClient() {
// init

String configPath = Path.getCurrentPath() + "/../config/app.properties";
logger.info("######## appConfig配置文件路径 " + configPath);
AppConfig.init(configPath);

try {
String clusterName = AppConfig.getProperty(CLUSTER_NAME);
String services = AppConfig.getProperty(ES_SERVICES);
logger.debug("es.services:" + services);
logger.debug("clusterName:" + clusterName);
Settings settings = Settings.settingsBuilder().put("cluster.name", clusterName)
.put("client.transport.sniff", true).put("client.transport.ignore_cluster_name", true)
.put("client.transport.ping_timeout", "1s").put("client.transport.nodes_sampler_interval", "1s")
.build();
// add delete-by-query plugin
TransportClient c = TransportClient.builder().settings(settings).addPlugin(DeleteByQueryPlugin.class)
.build();
String servicesArray;
if (StringUtils.isNotBlank(services)) {
servicesArray = services.split(",");
for (String service : servicesArray) {
String serviceInfo = service.split(":");
if (serviceInfo.length > 1) {
c = c.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(serviceInfo[0]),
Integer.valueOf(serviceInfo[1])));
}
}
client = c;
logger.info("connect to es cluster success.");
} else {
logger.error(" has no services info.");
}

} catch (Exception e) {
logger.error("create es client failed.", e);
}
}

}
大致就是做了个单例,但是我不太清楚esclient 有没有做连接池 或者请求关闭等操作?总之我是没有手动调用过close方法的,不知道是不是这块导致连接池资源都释放不掉了。
 
 
es有关连接池部分的配置我也发一下吧:
 threadpool:
        index:
                type: fixed
                size: 24
                queue_size: 500
        bulk:
                type: fixed
                size: 24
                queue_size: 500
 action.write_consistency: one
 index.store.type: mmapfs
 indices.memory.index_buffer_size: 10%
 index.translog.flush_threshold_ops: 50000
 index.translog.flush_threshold_size: 500mb
 index.translog.flush_threshold_period: 10m
 indices.memory.min_translog_buffer_size: 512m
 indices.memory.max_translog_buffer_size: 512m
 indices.queries.cache.size: 512m
 indices.queries.cache.count: 5000
 
求大神帮忙分析
 
 
然后顺带再问一个问题,这个TransportClient 默认是连接池的吗?这样做成单例了我就不能close了 不会有问题么?
然后近期发现haoxiang官方还有一个RestClient,据说tcp的方式已经不推荐了,不知道大家现在流行用哪种。
已邀请:

rockybean - Elastic Certified Engineer, ElasticStack Fans,公众号:ElasticTalk

赞同来自: fishyou

少年,赶紧把 es 的监控加进来吧,讨论这个问题的时候,你贴的数据应该都是那个时刻的 node 的 heap 占用情况、gc 的次数、时长等,你贴一个客户端的代码意义不大哈,如果担心是连接数问题,es 也有相关的监控数据可以看的。
 
https://www.datadoghq.com/blog ... rics/

novia - 1&0

赞同来自:

TransportClient 这个应该是没有问题的,单例完全没有问题,而且是线程安全的。建议从其他方面继续分析吧

kennywu76 - Wood

赞同来自:

ES服务端需要有监控数据帮助排查问题, 基本的cpu,load average,磁盘IO, JVM内部的GC情况, slow log等等。 

fishyou

赞同来自:

出问题的时间也就20分钟吧,老年代的GC有十来次,这不明显老年代GC过于频繁了。
 
话说,es的这个配置,你是如何查看到的呢?用的什么命令
 threadpool:
        index:
                type: fixed
                size: 24
                queue_size: 500
        bulk:
                type: fixed
                size: 24
                queue_size: 500
 action.write_consistency: one
 index.store.type: mmapfs
 indices.memory.index_buffer_size: 10%
 index.translog.flush_threshold_ops: 50000
 index.translog.flush_threshold_size: 500mb
 index.translog.flush_threshold_period: 10m
 indices.memory.min_translog_buffer_size: 512m
 indices.memory.max_translog_buffer_size: 512m
 indices.queries.cache.size: 512m
 indices.queries.cache.count: 5000

medcl - 今晚打老虎。

赞同来自:

安装一个 xpack 也可以的,monitoring 反正是免费的。
在卡的时候看一下接口http://localhost:9200/_nodes/hot_threads都返回哪些信息。

cyberdak

赞同来自:

看截图很像是58的同事  :)
没有xpack的话,装个bigdesk看起来也挺方便

bytedance

赞同来自:

hi 您好 请问问题有解决吗 目前我也遇到类似的问题

要回复问题请先登录注册