com.netflix.eureka2.server.service.BridgeChannel Maven / Gradle / Ivy
package com.netflix.eureka2.server.service;
import com.netflix.discovery.DiscoveryClient;
import com.netflix.discovery.shared.Application;
import com.netflix.discovery.shared.Applications;
import com.netflix.eureka2.bridge.InstanceInfoConverter;
import com.netflix.eureka2.bridge.InstanceInfoConverterImpl;
import com.netflix.eureka2.bridge.OperatorInstanceInfoFromV1;
import com.netflix.eureka2.registry.Delta;
import com.netflix.eureka2.registry.InstanceInfo;
import com.netflix.eureka2.server.registry.EurekaServerRegistry;
import com.netflix.eureka2.service.ServiceChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;
import rx.Scheduler;
import rx.Subscriber;
import rx.functions.Action0;
import rx.functions.Func1;
import rx.schedulers.Schedulers;
import rx.subjects.ReplaySubject;
import rx.subjects.Subject;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
/**
* A bridge channel that handles changes between snapshots of v1 instanceInfo
*
* @author David Liu
*/
public class BridgeChannel implements ServiceChannel {
private static final Logger logger = LoggerFactory.getLogger(BridgeChannel.class);
private final EurekaServerRegistry registry;
private final DiscoveryClient discoveryClient;
private final InstanceInfoConverter converter;
private final int refreshRateSec;
private final Scheduler.Worker worker;
private Map currentSnapshot;
private final Subject lifecycle;
public BridgeChannel(EurekaServerRegistry registry,
DiscoveryClient discoveryClient,
int refreshRateSec) {
this.registry = registry;
this.discoveryClient = discoveryClient;
this.refreshRateSec = refreshRateSec;
converter = new InstanceInfoConverterImpl();
worker = Schedulers.computation().createWorker();
currentSnapshot = new HashMap<>();
lifecycle = ReplaySubject.create();
}
public void connect() {
worker.schedulePeriodically(new Action0() {
@Override
public void call() {
logger.info("Starting new round of replication from v1 to v2");
final AtomicLong totalCount = new AtomicLong(0); // TODO: servo-fy
final AtomicLong updateCount = new AtomicLong(0);
final AtomicLong registerCount = new AtomicLong(0);
final AtomicLong unregisterCount = new AtomicLong(0);
final Map newSnapshot = new HashMap<>();
getV1Stream()
.lift(new OperatorInstanceInfoFromV1(converter))
.subscribe(new Subscriber() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
logger.warn("error processing v1 stream", e);
e.printStackTrace();
}
@Override
public void onNext(InstanceInfo instanceInfo) {
totalCount.incrementAndGet();
newSnapshot.put(instanceInfo.getId(), instanceInfo);
if (currentSnapshot.containsKey(instanceInfo.getId())) {
InstanceInfo older = currentSnapshot.get(instanceInfo.getId());
if (!older.equals(instanceInfo)) {
Set> deltas = older.diffNewer(instanceInfo);
registry.update(instanceInfo, deltas);
updateCount.incrementAndGet();
}
} else {
registry.register(instanceInfo);
registerCount.incrementAndGet();
}
}
});
currentSnapshot.keySet().removeAll(newSnapshot.keySet());
Observable.from(currentSnapshot.values())
.subscribe(new Subscriber() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
logger.warn("error unregistering from v1 stream", e);
}
@Override
public void onNext(InstanceInfo instanceInfo) {
registry.unregister(instanceInfo);
unregisterCount.incrementAndGet();
}
});
currentSnapshot = newSnapshot;
logger.info("Finished new round of replication from v1 to v2." +
" Total: {}, registers: {}, updates: {}, unregisters: {}",
totalCount.get(), registerCount.get(), updateCount.get(), unregisterCount.get());
}
}, 0, refreshRateSec, TimeUnit.SECONDS);
}
protected Observable getV1Stream() {
Applications applications =
new Applications(discoveryClient.getApplications().getRegisteredApplications());
return Observable.from(applications.getRegisteredApplications())
.flatMap(new Func1>() {
@Override
public Observable call(Application application) {
return Observable.from(application.getInstances());
}
});
}
@Override
public void close() {
discoveryClient.shutdown();
registry.shutdown();
lifecycle.onCompleted();
}
@Override
public Observable asLifecycleObservable() {
return lifecycle;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy