All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.netflix.eureka2.server.audit.kafka.EurekaSourcedServerList 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.server.audit.kafka;

import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import com.netflix.eureka2.client.Eureka;
import com.netflix.eureka2.client.EurekaClient;
import com.netflix.eureka2.client.resolver.ServerResolver;
import com.netflix.eureka2.interests.ChangeNotification;
import com.netflix.eureka2.registry.InstanceInfo;
import com.netflix.eureka2.registry.NetworkAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Subscriber;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * {@link ServerList} provider for Ribbon {@link ILoadBalancer}. This is utility class
 * that should be shared internally and provided to external users.
 *
 * TODO: move it out to different package
 *
 * @author Tomasz Bak
 */
public class EurekaSourcedServerList implements ServerList {

    private static final Logger logger = LoggerFactory.getLogger(EurekaSourcedServerList.class);

    private final ServerResolver readClusterResolver;
    private final String vip;
    private final int defaultPort;
    private volatile EurekaClient eurekaClient;
    private final ConcurrentHashMap servers = new ConcurrentHashMap<>();

    public EurekaSourcedServerList(ServerResolver readClusterResolver, String vip, int defaultPort) {
        this.readClusterResolver = readClusterResolver;
        this.vip = vip;
        this.defaultPort = defaultPort;
    }

    @PostConstruct
    public void start() {
        eurekaClient = Eureka.newClient(readClusterResolver);
        subscribeToVip();
    }

    protected void subscribeToVip() {
        logger.debug("Starting ServerList subscription to {}", vip);
        eurekaClient.forVips(vip).subscribe(new ServerListUpdater());
    }

    @PreDestroy
    public void stop() {
        if (eurekaClient != null) {
            eurekaClient.close();
            eurekaClient = null;
        }
    }

    @Override
    public List getInitialListOfServers() {
        return getUpdatedListOfServers();
    }

    @Override
    public List getUpdatedListOfServers() {
        return new ArrayList<>(servers.values());
    }

    private class ServerListUpdater extends Subscriber> {
        @Override
        public void onCompleted() {
            // This should only happen when EurekaClient is closed.
            logger.debug("ServerListUpdater completed");
        }

        @Override
        public void onError(Throwable e) {
            if (logger.isDebugEnabled()) {
                logger.debug("Interest channel for " + vip + " completed with error", e);
            }
            // The contract states that we shall subscribe again.
            if (eurekaClient != null) {
                subscribeToVip();
            }
        }

        @Override
        public void onNext(ChangeNotification notification) {
            // TODO: this should be unqiue instanceId, that stays the same even after server restart
            InstanceInfo instanceInfo = notification.getData();
            String instanceId = instanceInfo.getId();
            switch (notification.getKind()) {
                case Add:
                case Modify:
                    NetworkAddress address = instanceInfo.getDataCenterInfo().getDefaultAddress();
                    servers.put(instanceId, new Server(address.getIpAddress(), defaultPort));
                case Delete:
                    servers.remove(instanceId);
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy