|
|
|
@ -15,26 +15,26 @@
|
|
|
|
|
*/
|
|
|
|
|
package org.redisson.connection;
|
|
|
|
|
|
|
|
|
|
import java.net.InetSocketAddress;
|
|
|
|
|
import java.util.Collection;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.Map.Entry;
|
|
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
|
|
|
|
|
|
import io.netty.resolver.AddressResolver;
|
|
|
|
|
import io.netty.resolver.AddressResolverGroup;
|
|
|
|
|
import io.netty.util.concurrent.Future;
|
|
|
|
|
import io.netty.util.concurrent.FutureListener;
|
|
|
|
|
import io.netty.util.concurrent.ScheduledFuture;
|
|
|
|
|
import org.redisson.api.RFuture;
|
|
|
|
|
import org.redisson.client.RedisClient;
|
|
|
|
|
import org.redisson.connection.ClientConnectionsEntry.FreezeReason;
|
|
|
|
|
import org.redisson.misc.AsyncCountDownLatch;
|
|
|
|
|
import org.redisson.misc.RedisURI;
|
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
|
|
|
|
import io.netty.resolver.AddressResolver;
|
|
|
|
|
import io.netty.resolver.AddressResolverGroup;
|
|
|
|
|
import io.netty.util.concurrent.Future;
|
|
|
|
|
import io.netty.util.concurrent.FutureListener;
|
|
|
|
|
import io.netty.util.concurrent.ScheduledFuture;
|
|
|
|
|
import java.net.InetSocketAddress;
|
|
|
|
|
import java.util.Collection;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.Map.Entry;
|
|
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* DNS changes monitor.
|
|
|
|
@ -88,105 +88,107 @@ public class DNSMonitor {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AtomicInteger counter = new AtomicInteger(masters.size() + slaves.size());
|
|
|
|
|
monitorMasters(counter);
|
|
|
|
|
monitorSlaves(counter);
|
|
|
|
|
AsyncCountDownLatch latch = new AsyncCountDownLatch();
|
|
|
|
|
latch.latch(() -> {
|
|
|
|
|
monitorDnsChange();
|
|
|
|
|
}, masters.size() + slaves.size());
|
|
|
|
|
monitorMasters(latch);
|
|
|
|
|
monitorSlaves(latch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}, dnsMonitoringInterval, TimeUnit.MILLISECONDS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void monitorMasters(AtomicInteger counter) {
|
|
|
|
|
private void monitorMasters(AsyncCountDownLatch latch) {
|
|
|
|
|
for (Entry<RedisURI, InetSocketAddress> entry : masters.entrySet()) {
|
|
|
|
|
log.debug("Request sent to resolve ip address for master host: {}", entry.getKey().getHost());
|
|
|
|
|
|
|
|
|
|
Future<InetSocketAddress> resolveFuture = resolver.resolve(InetSocketAddress.createUnresolved(entry.getKey().getHost(), entry.getKey().getPort()));
|
|
|
|
|
resolveFuture.addListener(new FutureListener<InetSocketAddress>() {
|
|
|
|
|
@Override
|
|
|
|
|
public void operationComplete(Future<InetSocketAddress> future) throws Exception {
|
|
|
|
|
if (counter.decrementAndGet() == 0) {
|
|
|
|
|
monitorDnsChange();
|
|
|
|
|
}
|
|
|
|
|
resolveFuture.addListener((FutureListener<InetSocketAddress>) future -> {
|
|
|
|
|
if (!future.isSuccess()) {
|
|
|
|
|
log.error("Unable to resolve " + entry.getKey().getHost(), future.cause());
|
|
|
|
|
latch.countDown();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.debug("Resolved ip: {} for master host: {}", future.getNow().getAddress(), entry.getKey().getHost());
|
|
|
|
|
|
|
|
|
|
InetSocketAddress currentMasterAddr = entry.getValue();
|
|
|
|
|
InetSocketAddress newMasterAddr = future.getNow();
|
|
|
|
|
if (!newMasterAddr.getAddress().equals(currentMasterAddr.getAddress())) {
|
|
|
|
|
log.info("Detected DNS change. Master {} has changed ip from {} to {}",
|
|
|
|
|
entry.getKey(), currentMasterAddr.getAddress().getHostAddress(),
|
|
|
|
|
newMasterAddr.getAddress().getHostAddress());
|
|
|
|
|
|
|
|
|
|
if (!future.isSuccess()) {
|
|
|
|
|
log.error("Unable to resolve " + entry.getKey().getHost(), future.cause());
|
|
|
|
|
MasterSlaveEntry masterSlaveEntry = connectionManager.getEntry(currentMasterAddr);
|
|
|
|
|
if (masterSlaveEntry == null) {
|
|
|
|
|
log.error("Unable to find entry for current master {}", currentMasterAddr);
|
|
|
|
|
latch.countDown();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.debug("Resolved ip: {} for master host: {}", future.getNow().getAddress(), entry.getKey().getHost());
|
|
|
|
|
RFuture<RedisClient> changeFuture = masterSlaveEntry.changeMaster(newMasterAddr, entry.getKey());
|
|
|
|
|
changeFuture.onComplete((r, e) -> {
|
|
|
|
|
latch.countDown();
|
|
|
|
|
|
|
|
|
|
InetSocketAddress currentMasterAddr = entry.getValue();
|
|
|
|
|
InetSocketAddress newMasterAddr = future.getNow();
|
|
|
|
|
if (!newMasterAddr.getAddress().equals(currentMasterAddr.getAddress())) {
|
|
|
|
|
log.info("Detected DNS change. Master {} has changed ip from {} to {}",
|
|
|
|
|
entry.getKey(), currentMasterAddr.getAddress().getHostAddress(),
|
|
|
|
|
newMasterAddr.getAddress().getHostAddress());
|
|
|
|
|
|
|
|
|
|
MasterSlaveEntry masterSlaveEntry = connectionManager.getEntry(currentMasterAddr);
|
|
|
|
|
if (masterSlaveEntry == null) {
|
|
|
|
|
log.error("Unable to find entry for current master {}", currentMasterAddr);
|
|
|
|
|
return;
|
|
|
|
|
if (e == null) {
|
|
|
|
|
masters.put(entry.getKey(), newMasterAddr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RFuture<RedisClient> changeFuture = masterSlaveEntry.changeMaster(newMasterAddr, entry.getKey());
|
|
|
|
|
changeFuture.onComplete((r, e) -> {
|
|
|
|
|
if (e == null) {
|
|
|
|
|
masters.put(entry.getKey(), newMasterAddr);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
latch.countDown();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void monitorSlaves(AtomicInteger counter) {
|
|
|
|
|
private void monitorSlaves(AsyncCountDownLatch latch) {
|
|
|
|
|
for (Entry<RedisURI, InetSocketAddress> entry : slaves.entrySet()) {
|
|
|
|
|
log.debug("Request sent to resolve ip address for slave host: {}", entry.getKey().getHost());
|
|
|
|
|
|
|
|
|
|
Future<InetSocketAddress> resolveFuture = resolver.resolve(InetSocketAddress.createUnresolved(entry.getKey().getHost(), entry.getKey().getPort()));
|
|
|
|
|
resolveFuture.addListener(new FutureListener<InetSocketAddress>() {
|
|
|
|
|
@Override
|
|
|
|
|
public void operationComplete(Future<InetSocketAddress> future) throws Exception {
|
|
|
|
|
if (counter.decrementAndGet() == 0) {
|
|
|
|
|
monitorDnsChange();
|
|
|
|
|
}
|
|
|
|
|
resolveFuture.addListener((FutureListener<InetSocketAddress>) future -> {
|
|
|
|
|
if (!future.isSuccess()) {
|
|
|
|
|
log.error("Unable to resolve " + entry.getKey().getHost(), future.cause());
|
|
|
|
|
latch.countDown();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!future.isSuccess()) {
|
|
|
|
|
log.error("Unable to resolve " + entry.getKey().getHost(), future.cause());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
log.debug("Resolved ip: {} for slave host: {}", future.getNow().getAddress(), entry.getKey().getHost());
|
|
|
|
|
|
|
|
|
|
log.debug("Resolved ip: {} for slave host: {}", future.getNow().getAddress(), entry.getKey().getHost());
|
|
|
|
|
InetSocketAddress currentSlaveAddr = entry.getValue();
|
|
|
|
|
InetSocketAddress newSlaveAddr = future.getNow();
|
|
|
|
|
if (!newSlaveAddr.getAddress().equals(currentSlaveAddr.getAddress())) {
|
|
|
|
|
log.info("Detected DNS change. Slave {} has changed ip from {} to {}",
|
|
|
|
|
entry.getKey().getHost(), currentSlaveAddr.getAddress().getHostAddress(), newSlaveAddr.getAddress().getHostAddress());
|
|
|
|
|
for (MasterSlaveEntry masterSlaveEntry : connectionManager.getEntrySet()) {
|
|
|
|
|
if (!masterSlaveEntry.hasSlave(currentSlaveAddr)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InetSocketAddress currentSlaveAddr = entry.getValue();
|
|
|
|
|
InetSocketAddress newSlaveAddr = future.getNow();
|
|
|
|
|
if (!newSlaveAddr.getAddress().equals(currentSlaveAddr.getAddress())) {
|
|
|
|
|
log.info("Detected DNS change. Slave {} has changed ip from {} to {}",
|
|
|
|
|
entry.getKey().getHost(), currentSlaveAddr.getAddress().getHostAddress(), newSlaveAddr.getAddress().getHostAddress());
|
|
|
|
|
for (MasterSlaveEntry masterSlaveEntry : connectionManager.getEntrySet()) {
|
|
|
|
|
if (!masterSlaveEntry.hasSlave(currentSlaveAddr)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (masterSlaveEntry.hasSlave(newSlaveAddr)) {
|
|
|
|
|
masterSlaveEntry.slaveUp(newSlaveAddr, FreezeReason.MANAGER);
|
|
|
|
|
masterSlaveEntry.slaveDown(currentSlaveAddr, FreezeReason.MANAGER);
|
|
|
|
|
slaves.put(entry.getKey(), newSlaveAddr);
|
|
|
|
|
latch.countDown();
|
|
|
|
|
} else {
|
|
|
|
|
RFuture<Void> addFuture = masterSlaveEntry.addSlave(newSlaveAddr, entry.getKey());
|
|
|
|
|
addFuture.onComplete((res, e) -> {
|
|
|
|
|
latch.countDown();
|
|
|
|
|
|
|
|
|
|
if (e != null) {
|
|
|
|
|
log.error("Can't add slave: " + newSlaveAddr, e);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (masterSlaveEntry.hasSlave(newSlaveAddr)) {
|
|
|
|
|
masterSlaveEntry.slaveUp(newSlaveAddr, FreezeReason.MANAGER);
|
|
|
|
|
masterSlaveEntry.slaveDown(currentSlaveAddr, FreezeReason.MANAGER);
|
|
|
|
|
} else {
|
|
|
|
|
RFuture<Void> addFuture = masterSlaveEntry.addSlave(newSlaveAddr, entry.getKey());
|
|
|
|
|
addFuture.onComplete((res, e) -> {
|
|
|
|
|
if (e != null) {
|
|
|
|
|
log.error("Can't add slave: " + newSlaveAddr, e);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
masterSlaveEntry.slaveDown(currentSlaveAddr, FreezeReason.MANAGER);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
slaves.put(entry.getKey(), newSlaveAddr);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
slaves.put(entry.getKey(), newSlaveAddr);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
latch.countDown();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|