橡皮、老虎皮、狮子皮哪一个最不好?

本来集群好好的,突然连接master失败,有大神能给指点一下方向吗?

etoak 回复了问题 • 4 人关注 • 3 个回复 • 7782 次浏览 • 2020-05-19 10:09 • 来自相关话题

jest client 作为客户端连接es出现的问题

trycatchfinal 回复了问题 • 2 人关注 • 2 个回复 • 3208 次浏览 • 2020-05-19 10:08 • 来自相关话题

使用term聚合,然后排序的时候 聚合数量的值+自定义的count字段 组合 降序排序

tacsklet 回复了问题 • 2 人关注 • 1 个回复 • 1298 次浏览 • 2020-05-18 15:27 • 来自相关话题

创建Elastic alerts - 7.7 发行版

回复

liuxg 发起了问题 • 1 人关注 • 0 个回复 • 1145 次浏览 • 2020-05-18 12:21 • 来自相关话题

Elasticesearch add host blacklist

trycatchfinal 回复了问题 • 2 人关注 • 1 个回复 • 1852 次浏览 • 2020-05-18 11:56 • 来自相关话题

解决Elasticsearch HTTP方式查询报SocketTimeoutException的问题(待验证)

trycatchfinal 发表了文章 • 3 个评论 • 12076 次浏览 • 2020-05-18 11:47 • 来自相关话题

注意: 此解决方案,短时间内没有复现,还需要长时间验证是否有效。

现象

在使用HTTP方式,Elasticsearch 长时间不查询后,再次查询会出现抛出SocketTimeoutException的问题。

原因

基本逻辑

Elasticsearch 客户端会根据服务器返回的HTTP报文内容,来决定客户端保持HTTP连接Keep-Alive状态的策略。
如果结果如下,那么保持HTTP连接 Keep-Alive状态为120s
<br /> Connection: Keep-Alive<br /> Keep-Alive: max=5, timeout = 120<br />
如果不包含上述内容,那么客户端将保持Keep-Alive状态的时间为永久。
事实上,Elasticsearch服务器返回的报文,并没有上述HTTP头内容,所以客户端所有的HTTP连接都为永久保持Keep-Alive。
如果客户端长时间没有发送请求,服务器或者防火墙已经close了HTTP底层的TCP链接,但是此时客户端并不知道,由于Keep Alive是无限期,那么并不会重新建立连接,而是直接发送请求,此时就会得到SocketTimeout异常。

阅读源码

我使用的Elasticsearch的客户端下面的版本
```


org.elasticsearch.client
rest
5.4.1

```
其HTTP的发送依赖Maven包`httpasyncclient`.

这个包中的接口ConnectionKeepAliveStrategy,抽象了处理 HTTP Keepalive 的策略,其默认实现为:
```
@Contract(threading = ThreadingBehavior.IMMUTABLE)
public class DefaultConnectionKeepAliveStrategy implements ConnectionKeepAliveStrategy {


public static final DefaultConnectionKeepAliveStrategy INSTANCE = new DefaultConnectionKeepAliveStrategy();

@Override
public long getKeepAliveDuration(final HttpResponse response, final HttpContext context) {
Args.notNull(response, "HTTP response");
final HeaderElementIterator it = new BasicHeaderElementIterator(
response.headerIterator(HTTP.CONN_KEEP_ALIVE));
while (it.hasNext()) {
final HeaderElement he = it.nextElement();
final String param = he.getName();
final String value = he.getValue();
if (value != null && param.equalsIgnoreCase("timeout")) {
try {
return Long.parseLong(value) * 1000;
} catch(final NumberFormatException ignore) {
}
}
}
return -1;
}
}
```
`-1`代表多长时间,接口说明不是很清楚。
PoolingNHttpClientConnectionManager 类中的代码,实现了上述对待KeepAlive的逻辑,可以看到`-1`表示为:无限期
```
@Override
public void releaseConnection(
final NHttpClientConnection managedConn,
final Object state,
final long keepalive,
final TimeUnit tunit) {
Args.notNull(managedConn, "Managed connection");
synchronized (managedConn) {
final CPoolEntry entry = CPoolProxy.detach(managedConn);
if (entry == null) {
return;
}
if (this.log.isDebugEnabled()) {
this.log.debug("Releasing connection: " + format(entry) + formatStats(entry.getRoute()));
}
final NHttpClientConnection conn = entry.getConnection();
try {
if (conn.isOpen()) {
entry.setState(state);
entry.updateExpiry(keepalive, tunit != null ? tunit : TimeUnit.MILLISECONDS);
if (this.log.isDebugEnabled()) {
final String s;
// keepalive 就是上面接口 ConnectionKeepAliveStrategy.getKeepAliveDuration()的返回值
if (keepalive > 0) {
s = "for " + (double) keepalive / 1000 + " seconds";
} else {
// 如果小于0 ,那么策略为indefinitely:无限期。
s = "indefinitely";
}
this.log.debug("Connection " + format(entry) + " can be kept alive " + s);
}
}
} finally {
this.pool.release(entry, conn.isOpen() && entry.isRouteComplete());
if (this.log.isDebugEnabled()) {
this.log.debug("Connection released: " + format(entry) + formatStats(entry.getRoute()));
}
}
}
}
```

## 解决方式
自定义类实现`ConnectionKeepAliveStrategy `接口:
```
public class CustomConnectionKeepAliveStrategy extends DefaultConnectionKeepAliveStrategy {


public static final CustomConnectionKeepAliveStrategy INSTANCE = new CustomConnectionKeepAliveStrategy();


private CustomConnectionKeepAliveStrategy() {
super();
}


/**
* 最大keep alive的时间(分钟)
* 这里默认为10分钟,可以根据实际情况设置。可以观察客户端机器状态为TIME_WAIT的TCP连接数,如果太多,可以增大此值。
*/
private final long MAX_KEEP_ALIVE_MINUTES = 10;


@Override
public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
long keepAliveDuration = super.getKeepAliveDuration(response, context);
// <0 为无限期keepalive
// 将无限期替换成一个默认的时间
if(keepAliveDuration < 0){
return TimeUnit.MINUTES.toMillis(MAX_KEEP_ALIVE_MINUTES);
}
return keepAliveDuration;
}
}
```
在创建Elasticserach Client时,配置
```
RestClientBuilder builder = RestClient.builder(hosts);
builder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
httpClientBuilder.setKeepAliveStrategy(CustomConnectionKeepAliveStrategy.INSTANCE);
return httpClientBuilder;
}
});
```

es客户端io.netty.buffer.PoolArena$HeapArena内存占用高

han_001 回复了问题 • 9 人关注 • 5 个回复 • 8901 次浏览 • 2020-05-18 10:32 • 来自相关话题

python 连接es sniff_on_start 问题

回复

jimi 发起了问题 • 1 人关注 • 0 个回复 • 1424 次浏览 • 2020-05-18 10:15 • 来自相关话题

es 6.3.2 时间戳查询的问题

回复

Pantheon 发起了问题 • 1 人关注 • 0 个回复 • 2717 次浏览 • 2020-05-16 19:45 • 来自相关话题

ES 搜索建议 Suggester 的问题

kazaff 回复了问题 • 7 人关注 • 3 个回复 • 12330 次浏览 • 2020-05-16 09:57 • 来自相关话题

ES集群配置中,如果设置了协调节点,还需要再设置nginx反代处理吗

byx313 回复了问题 • 2 人关注 • 1 个回复 • 1775 次浏览 • 2020-05-15 17:56 • 来自相关话题

大佬们,如何解决es的时区问题

caizhongao 回复了问题 • 3 人关注 • 2 个回复 • 4956 次浏览 • 2020-05-15 16:59 • 来自相关话题

Elastic:创建一个Elastic alert - 7.7 发布版

回复

liuxg 发起了问题 • 1 人关注 • 0 个回复 • 2596 次浏览 • 2020-05-15 16:53 • 来自相关话题

springboot整合es 使用Repository.search报错

回复

leeq 发起了问题 • 1 人关注 • 0 个回复 • 2990 次浏览 • 2020-05-15 15:47 • 来自相关话题

自定义id带来的问题

liutianhao 回复了问题 • 6 人关注 • 3 个回复 • 3111 次浏览 • 2020-05-14 21:04 • 来自相关话题