1
1
/*
2
- * Copyright 2018-2020 the original author or authors.
2
+ * Copyright 2018-2021 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
20
20
import reactor .util .function .Tuple2 ;
21
21
22
22
import java .net .InetSocketAddress ;
23
+ import java .time .Duration ;
23
24
import java .util .ArrayList ;
24
25
import java .util .Collection ;
25
26
import java .util .Collections ;
29
30
import java .util .concurrent .ConcurrentHashMap ;
30
31
import java .util .function .Supplier ;
31
32
33
+ import org .slf4j .Logger ;
34
+ import org .slf4j .LoggerFactory ;
32
35
import org .springframework .data .elasticsearch .client .ElasticsearchHost ;
33
36
import org .springframework .data .elasticsearch .client .ElasticsearchHost .State ;
34
37
import org .springframework .data .elasticsearch .client .NoReachableHostException ;
42
45
*
43
46
* @author Christoph Strobl
44
47
* @author Mark Paluch
48
+ * @author Peter-Josef Meisch
45
49
* @since 3.2
46
50
*/
47
- class MultiNodeHostProvider implements HostProvider {
51
+ class MultiNodeHostProvider implements HostProvider <MultiNodeHostProvider > {
52
+
53
+ private final static Logger LOG = LoggerFactory .getLogger (MultiNodeHostProvider .class );
48
54
49
55
private final WebClientProvider clientProvider ;
50
56
private final Supplier <HttpHeaders > headersSupplier ;
51
57
private final Map <InetSocketAddress , ElasticsearchHost > hosts ;
52
58
53
- MultiNodeHostProvider (WebClientProvider clientProvider , Supplier <HttpHeaders > headersSupplier , InetSocketAddress ... endpoints ) {
59
+ MultiNodeHostProvider (WebClientProvider clientProvider , Supplier <HttpHeaders > headersSupplier ,
60
+ InetSocketAddress ... endpoints ) {
54
61
55
62
this .clientProvider = clientProvider ;
56
63
this .headersSupplier = headersSupplier ;
57
64
this .hosts = new ConcurrentHashMap <>();
58
65
for (InetSocketAddress endpoint : endpoints ) {
59
66
this .hosts .put (endpoint , new ElasticsearchHost (endpoint , State .UNKNOWN ));
60
67
}
68
+
69
+ LOG .debug ("initialized with " + hosts );
61
70
}
62
71
63
72
/*
@@ -66,7 +75,7 @@ class MultiNodeHostProvider implements HostProvider {
66
75
*/
67
76
@ Override
68
77
public Mono <ClusterInformation > clusterInfo () {
69
- return nodes (null ).map (this ::updateNodeState ).buffer (hosts .size ())
78
+ return checkNodes (null ).map (this ::updateNodeState ).buffer (hosts .size ())
70
79
.then (Mono .just (new ClusterInformation (new LinkedHashSet <>(this .hosts .values ()))));
71
80
}
72
81
@@ -86,14 +95,19 @@ public WebClient createWebClient(InetSocketAddress endpoint) {
86
95
@ Override
87
96
public Mono <InetSocketAddress > lookupActiveHost (Verification verification ) {
88
97
98
+ LOG .trace ("lookupActiveHost " + verification + " from " + hosts ());
99
+
89
100
if (Verification .LAZY .equals (verification )) {
90
101
for (ElasticsearchHost entry : hosts ()) {
91
102
if (entry .isOnline ()) {
103
+ LOG .trace ("lookupActiveHost returning " + entry );
92
104
return Mono .just (entry .getEndpoint ());
93
105
}
94
106
}
107
+ LOG .trace ("no online host found with LAZY" );
95
108
}
96
109
110
+ LOG .trace ("searching for active host" );
97
111
return findActiveHostInKnownActives () //
98
112
.switchIfEmpty (findActiveHostInUnresolved ()) //
99
113
.switchIfEmpty (findActiveHostInDead ()) //
@@ -105,20 +119,30 @@ Collection<ElasticsearchHost> getCachedHostState() {
105
119
}
106
120
107
121
private Mono <InetSocketAddress > findActiveHostInKnownActives () {
108
- return findActiveForSate (State .ONLINE );
122
+ return findActiveForState (State .ONLINE );
109
123
}
110
124
111
125
private Mono <InetSocketAddress > findActiveHostInUnresolved () {
112
- return findActiveForSate (State .UNKNOWN );
126
+ return findActiveForState (State .UNKNOWN );
113
127
}
114
128
115
129
private Mono <InetSocketAddress > findActiveHostInDead () {
116
- return findActiveForSate (State .OFFLINE );
130
+ return findActiveForState (State .OFFLINE );
117
131
}
118
132
119
- private Mono <InetSocketAddress > findActiveForSate (State state ) {
120
- return nodes (state ).map (this ::updateNodeState ).filter (ElasticsearchHost ::isOnline )
121
- .map (ElasticsearchHost ::getEndpoint ).next ();
133
+ private Mono <InetSocketAddress > findActiveForState (State state ) {
134
+
135
+ LOG .trace ("findActiveForState state " + state + ", current hosts: " + hosts );
136
+
137
+ return checkNodes (state ) //
138
+ .map (this ::updateNodeState ) //
139
+ .filter (ElasticsearchHost ::isOnline ) //
140
+ .map (elasticsearchHost -> {
141
+ LOG .trace ("findActiveForState returning host " + elasticsearchHost );
142
+ return elasticsearchHost ;
143
+ }).map (ElasticsearchHost ::getEndpoint ) //
144
+ .takeLast (1 ) //
145
+ .next ();
122
146
}
123
147
124
148
private ElasticsearchHost updateNodeState (Tuple2 <InetSocketAddress , State > tuple2 ) {
@@ -129,25 +153,34 @@ private ElasticsearchHost updateNodeState(Tuple2<InetSocketAddress, State> tuple
129
153
return elasticsearchHost ;
130
154
}
131
155
132
- private Flux <Tuple2 <InetSocketAddress , State >> nodes (@ Nullable State state ) {
156
+ private Flux <Tuple2 <InetSocketAddress , State >> checkNodes (@ Nullable State state ) {
157
+
158
+ LOG .trace ("checkNodes() with state " + state );
133
159
134
160
return Flux .fromIterable (hosts ()) //
135
161
.filter (entry -> state == null || entry .getState ().equals (state )) //
136
162
.map (ElasticsearchHost ::getEndpoint ) //
137
- .flatMap (host -> {
163
+ .concatMap (host -> {
164
+
165
+ LOG .trace ("checking host " + host );
138
166
139
167
Mono <ClientResponse > exchange = createWebClient (host ) //
140
168
.head ().uri ("/" ) //
141
169
.headers (httpHeaders -> httpHeaders .addAll (headersSupplier .get ())) //
142
- .exchange ().doOnError (throwable -> {
170
+ .exchange () //
171
+ .timeout (Duration .ofSeconds (1 )) //
172
+ .doOnError (throwable -> {
143
173
hosts .put (host , new ElasticsearchHost (host , State .OFFLINE ));
144
174
clientProvider .getErrorListener ().accept (throwable );
145
175
});
146
176
147
177
return Mono .just (host ).zipWith (exchange
148
178
.flatMap (it -> it .releaseBody ().thenReturn (it .statusCode ().isError () ? State .OFFLINE : State .ONLINE )));
149
179
}) //
150
- .onErrorContinue ((throwable , o ) -> clientProvider .getErrorListener ().accept (throwable ));
180
+ .map (tuple -> {
181
+ LOG .trace ("check result " + tuple );
182
+ return tuple ;
183
+ }).onErrorContinue ((throwable , o ) -> clientProvider .getErrorListener ().accept (throwable ));
151
184
}
152
185
153
186
private List <ElasticsearchHost > hosts () {
0 commit comments