Commit c4be98576a91211532ddb6710849a17f17661374

Authored by Igor Kulikov
1 parent 5206a0e4

Improve zookeeper client reconnect logic. UI: Flot widget - Fixed incorrect indi…

…vidual tooltip content.
@@ -52,6 +52,8 @@ import javax.annotation.PostConstruct; @@ -52,6 +52,8 @@ import javax.annotation.PostConstruct;
52 import javax.annotation.PreDestroy; 52 import javax.annotation.PreDestroy;
53 import java.util.List; 53 import java.util.List;
54 import java.util.NoSuchElementException; 54 import java.util.NoSuchElementException;
  55 +import java.util.concurrent.ExecutorService;
  56 +import java.util.concurrent.Executors;
55 import java.util.stream.Collectors; 57 import java.util.stream.Collectors;
56 58
57 import static org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent.Type.CHILD_REMOVED; 59 import static org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent.Type.CHILD_REMOVED;
@@ -96,11 +98,13 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi @@ -96,11 +98,13 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi
96 @Lazy 98 @Lazy
97 private ClusterRoutingService routingService; 99 private ClusterRoutingService routingService;
98 100
  101 + private ExecutorService reconnectExecutorService;
  102 +
99 private CuratorFramework client; 103 private CuratorFramework client;
100 private PathChildrenCache cache; 104 private PathChildrenCache cache;
101 private String nodePath; 105 private String nodePath;
102 106
103 - private volatile boolean stopped = false; 107 + private volatile boolean stopped = true;
104 108
105 @PostConstruct 109 @PostConstruct
106 public void init() { 110 public void init() {
@@ -110,9 +114,15 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi @@ -110,9 +114,15 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi
110 Assert.notNull(zkConnectionTimeout, MiscUtils.missingProperty("zk.connection_timeout_ms")); 114 Assert.notNull(zkConnectionTimeout, MiscUtils.missingProperty("zk.connection_timeout_ms"));
111 Assert.notNull(zkSessionTimeout, MiscUtils.missingProperty("zk.session_timeout_ms")); 115 Assert.notNull(zkSessionTimeout, MiscUtils.missingProperty("zk.session_timeout_ms"));
112 116
  117 + reconnectExecutorService = Executors.newSingleThreadExecutor();
  118 +
113 log.info("Initializing discovery service using ZK connect string: {}", zkUrl); 119 log.info("Initializing discovery service using ZK connect string: {}", zkUrl);
114 120
115 zkNodesDir = zkDir + "/nodes"; 121 zkNodesDir = zkDir + "/nodes";
  122 + initZkClient();
  123 + }
  124 +
  125 + private void initZkClient() {
116 try { 126 try {
117 client = CuratorFrameworkFactory.newClient(zkUrl, zkSessionTimeout, zkConnectionTimeout, new RetryForever(zkRetryInterval)); 127 client = CuratorFrameworkFactory.newClient(zkUrl, zkSessionTimeout, zkConnectionTimeout, new RetryForever(zkRetryInterval));
118 client.start(); 128 client.start();
@@ -120,6 +130,8 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi @@ -120,6 +130,8 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi
120 cache = new PathChildrenCache(client, zkNodesDir, true); 130 cache = new PathChildrenCache(client, zkNodesDir, true);
121 cache.getListenable().addListener(this); 131 cache.getListenable().addListener(this);
122 cache.start(); 132 cache.start();
  133 + stopped = false;
  134 + log.info("ZK client connected");
123 } catch (Exception e) { 135 } catch (Exception e) {
124 log.error("Failed to connect to ZK: {}", e.getMessage(), e); 136 log.error("Failed to connect to ZK: {}", e.getMessage(), e);
125 CloseableUtils.closeQuietly(cache); 137 CloseableUtils.closeQuietly(cache);
@@ -128,12 +140,20 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi @@ -128,12 +140,20 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi
128 } 140 }
129 } 141 }
130 142
131 - @PreDestroy  
132 - public void destroy() { 143 + private void destroyZkClient() {
133 stopped = true; 144 stopped = true;
134 - unpublishCurrentServer(); 145 + try {
  146 + unpublishCurrentServer();
  147 + } catch (Exception e) {}
135 CloseableUtils.closeQuietly(cache); 148 CloseableUtils.closeQuietly(cache);
136 CloseableUtils.closeQuietly(client); 149 CloseableUtils.closeQuietly(client);
  150 + log.info("ZK client disconnected");
  151 + }
  152 +
  153 + @PreDestroy
  154 + public void destroy() {
  155 + destroyZkClient();
  156 + reconnectExecutorService.shutdownNow();
137 log.info("Stopped discovery service"); 157 log.info("Stopped discovery service");
138 } 158 }
139 159
@@ -180,20 +200,21 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi @@ -180,20 +200,21 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi
180 return (client, newState) -> { 200 return (client, newState) -> {
181 log.info("[{}:{}] ZK state changed: {}", self.getHost(), self.getPort(), newState); 201 log.info("[{}:{}] ZK state changed: {}", self.getHost(), self.getPort(), newState);
182 if (newState == ConnectionState.LOST) { 202 if (newState == ConnectionState.LOST) {
183 - reconnect(); 203 + reconnectExecutorService.submit(this::reconnect);
184 } 204 }
185 }; 205 };
186 } 206 }
187 207
188 - private boolean reconnectInProgress = false; 208 + private volatile boolean reconnectInProgress = false;
189 209
190 private synchronized void reconnect() { 210 private synchronized void reconnect() {
191 if (!reconnectInProgress) { 211 if (!reconnectInProgress) {
192 reconnectInProgress = true; 212 reconnectInProgress = true;
193 try { 213 try {
194 - client.blockUntilConnected(); 214 + destroyZkClient();
  215 + initZkClient();
195 publishCurrentServer(); 216 publishCurrentServer();
196 - } catch (InterruptedException e) { 217 + } catch (Exception e) {
197 log.error("Failed to reconnect to ZK: {}", e.getMessage(), e); 218 log.error("Failed to reconnect to ZK: {}", e.getMessage(), e);
198 } finally { 219 } finally {
199 reconnectInProgress = false; 220 reconnectInProgress = false;
@@ -50,7 +50,7 @@ @@ -50,7 +50,7 @@
50 <commons-validator.version>1.5.0</commons-validator.version> 50 <commons-validator.version>1.5.0</commons-validator.version>
51 <commons-io.version>2.5</commons-io.version> 51 <commons-io.version>2.5</commons-io.version>
52 <commons-csv.version>1.4</commons-csv.version> 52 <commons-csv.version>1.4</commons-csv.version>
53 - <jackson.version>2.9.7</jackson.version> 53 + <jackson.version>2.9.8</jackson.version>
54 <json-schema-validator.version>2.2.6</json-schema-validator.version> 54 <json-schema-validator.version>2.2.6</json-schema-validator.version>
55 <scala.version>2.11</scala.version> 55 <scala.version>2.11</scala.version>
56 <akka.version>2.4.2</akka.version> 56 <akka.version>2.4.2</akka.version>
@@ -59,7 +59,7 @@ @@ -59,7 +59,7 @@
59 <velocity.version>1.7</velocity.version> 59 <velocity.version>1.7</velocity.version>
60 <velocity-tools.version>2.0</velocity-tools.version> 60 <velocity-tools.version>2.0</velocity-tools.version>
61 <mail.version>1.4.3</mail.version> 61 <mail.version>1.4.3</mail.version>
62 - <curator.version>4.0.1</curator.version> 62 + <curator.version>4.2.0</curator.version>
63 <protobuf.version>3.6.1</protobuf.version> 63 <protobuf.version>3.6.1</protobuf.version>
64 <grpc.version>1.16.1</grpc.version> 64 <grpc.version>1.16.1</grpc.version>
65 <lombok.version>1.16.18</lombok.version> 65 <lombok.version>1.16.18</lombok.version>
@@ -137,9 +137,11 @@ export default class TbFlot { @@ -137,9 +137,11 @@ export default class TbFlot {
137 }); 137 });
138 content += dateDiv.prop('outerHTML'); 138 content += dateDiv.prop('outerHTML');
139 if (tbFlot.ctx.tooltipIndividual) { 139 if (tbFlot.ctx.tooltipIndividual) {
140 - var seriesHoverInfo = hoverInfo.seriesHover[seriesIndex];  
141 - if (seriesHoverInfo) {  
142 - content += seriesInfoDivFromInfo(seriesHoverInfo, seriesIndex); 140 + var found = hoverInfo.seriesHover.filter((seriesHover) => {
  141 + return seriesHover.index === seriesIndex;
  142 + });
  143 + if (found && found.length) {
  144 + content += seriesInfoDivFromInfo(found[0], seriesIndex);
143 } 145 }
144 } else { 146 } else {
145 var seriesDiv = $('<div></div>'); 147 var seriesDiv = $('<div></div>');
@@ -161,7 +163,7 @@ export default class TbFlot { @@ -161,7 +163,7 @@ export default class TbFlot {
161 if (i == hoverInfo.seriesHover.length) { 163 if (i == hoverInfo.seriesHover.length) {
162 break; 164 break;
163 } 165 }
164 - seriesHoverInfo = hoverInfo.seriesHover[i]; 166 + var seriesHoverInfo = hoverInfo.seriesHover[i];
165 columnContent += seriesInfoDivFromInfo(seriesHoverInfo, seriesIndex); 167 columnContent += seriesInfoDivFromInfo(seriesHoverInfo, seriesIndex);
166 } 168 }
167 columnDiv.html(columnContent); 169 columnDiv.html(columnContent);