com.netflix.eureka2.client.resolver.EurekaServerResolver Maven / Gradle / Ivy
/*
* Copyright 2014 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.netflix.eureka2.client.resolver;
import com.netflix.eureka2.Names;
import com.netflix.eureka2.client.Eureka;
import com.netflix.eureka2.client.EurekaClient;
import com.netflix.eureka2.interests.ChangeNotification;
import com.netflix.eureka2.interests.Interests;
import com.netflix.eureka2.registry.InstanceInfo;
import com.netflix.eureka2.registry.ServiceSelector;
import rx.Observable;
import rx.Subscriber;
import rx.functions.Func1;
import rx.subjects.BehaviorSubject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
/**
* A resolver fetching server list from the Eureka cluster. Eureka client uses
* this resolver to load read cluster server list from the write cluster, after the
* registration process.
*
* @author Tomasz Bak
*/
public class EurekaServerResolver implements ServerResolver {
private final ServiceSelector addressQuery;
private final BehaviorSubject serverListSubject;
private final AtomicReference currentServerList = new AtomicReference<>(new ServerList());
private final EurekaClient eurekaClient;
protected EurekaServerResolver(ServerResolver bootstrapResolver, String readServerVip) {
this(bootstrapResolver, readServerVip, ServiceSelector.selectBy().serviceLabel(Names.DISCOVERY).publicIp(true)
.or()
.serviceLabel(Names.DISCOVERY));
}
protected EurekaServerResolver(ServerResolver bootstrapResolver, String readServerVip, ServiceSelector serviceSelector) {
this.addressQuery = serviceSelector;
serverListSubject = BehaviorSubject.create();
eurekaClient = Eureka.newClient(bootstrapResolver);
eurekaClient.forInterest(Interests.forVips(readServerVip))
.subscribe(new Subscriber>() {
@Override
public void onCompleted() {
eurekaClient.close();
}
@Override
public void onError(Throwable e) {
// TODO: Re-subscribe
}
@Override
public void onNext(ChangeNotification changeNotification) {
InstanceInfo instanceInfo = changeNotification.getData();
InstanceInfo.ServiceEndpoint endpoint = addressQuery.returnServiceEndpoint(instanceInfo);
final Server server = new Server(endpoint.getAddress().getIpAddress(),
endpoint.getServicePort().getPort());
final ServerList serverList = currentServerList.get();
// This should always be a single threaded invocation, so we do not need CAS
switch (changeNotification.getKind()) {
case Add:
overwriteServerList(serverList.add(instanceInfo.getId(), server));
case Delete:
overwriteServerList(serverList.remove(instanceInfo.getId()));
case Modify:
overwriteServerList(serverList.update(instanceInfo.getId(), server));
}
}
});
}
private void overwriteServerList(final ServerList serverList) {
currentServerList.set(serverList);
serverListSubject.onNext(serverList);
}
@Override
public Observable resolve() {
return serverListSubject
.filter(new Func1() {
@Override
public Boolean call(ServerList serverList) {
return !serverList.servers.isEmpty();
}
})
.take(1)
.flatMap(new Func1>() {
@Override
public Observable call(ServerList serverList) {
return Observable.from(serverList.servers);
}
});
}
protected class ServerList {
private final Map idVsServers;
private final ArrayList servers;
private final int size;
private final AtomicInteger currentIndex = new AtomicInteger();
public ServerList(Map servers) {
this.idVsServers = servers;
this.servers = new ArrayList<>(this.idVsServers.values());
this.size = this.servers.size();
}
public ServerList() {
this(new HashMap());
}
public Server getNextServer() {
final int nextIndex = Math.abs(currentIndex.incrementAndGet()) % size;
return servers.get(nextIndex);
}
public ServerList add(String id, Server server) {
final HashMap idVsServers = new HashMap<>(this.idVsServers); // Copy existing
return idVsServers.put(id, server) == null ? this : new ServerList(idVsServers);
}
public ServerList remove(String id) {
if (!idVsServers.containsKey(id)) {
return this;
}
final HashMap idVsServers = new HashMap<>(this.idVsServers); // Copy existing
idVsServers.remove(id);
return new ServerList(idVsServers);
}
public ServerList update(String id, Server server) {
if (!idVsServers.containsKey(id)) {
return this;
}
final HashMap idVsServers = new HashMap<>(this.idVsServers); // Copy existing
idVsServers.put(id, server);
return new ServerList(idVsServers);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy