Package com.netflix.discovery

Source Code of com.netflix.discovery.MockRemoteEurekaServer$AppsResourceHandler

package com.netflix.discovery;

import com.netflix.appinfo.AbstractEurekaIdentity;
import com.netflix.appinfo.EurekaClientIdentity;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.converters.XmlXStream;
import com.netflix.discovery.shared.Application;
import com.netflix.discovery.shared.Applications;

import org.junit.Assert;
import org.junit.rules.ExternalResource;
import org.mortbay.jetty.Request;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.handler.AbstractHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

/**
* @author Nitesh Kant
*/
public class MockRemoteEurekaServer extends ExternalResource {

    public static final String EUREKA_API_BASE_PATH = "/eureka/v2/";

    private int port;
    private final Map<String, Application> applicationMap        = new HashMap<String, Application>();
    private final Map<String, Application> remoteRegionApps      = new HashMap<String, Application>();
    private final Map<String, Application> remoteRegionAppsDelta = new HashMap<String, Application>();
    private final Map<String, Application> applicationDeltaMap   = new HashMap<String, Application>();
    private Server server;
    private final AtomicBoolean sentDelta = new AtomicBoolean();
    private final AtomicBoolean sentRegistry = new AtomicBoolean();

    public AtomicLong heartbeatCount = new AtomicLong(0);
    public AtomicLong getFullRegistryCount = new AtomicLong(0);
    public AtomicLong getSingleVipCount = new AtomicLong(0);
    public AtomicLong getDeltaCount = new AtomicLong(0);

    @Override
    protected void before() throws Throwable {
        start();
    }

    @Override
    protected void after() {
        try {
            stop();
        } catch (Exception e) {
            Assert.fail(e.getMessage());
        }
    }

    public void start() throws Exception {
        server = new Server(port);
        server.setHandler(new AppsResourceHandler());
        server.start();
        port = server.getConnectors()[0].getLocalPort();
    }

    public int getPort() {
        return port;
    }
   
    public void stop() throws Exception {
        server.stop();
        server = null;
        port = 0;
       
        applicationMap.clear();
        remoteRegionApps.clear();
        remoteRegionAppsDelta.clear();
        applicationDeltaMap.clear();
    }

    public boolean isSentDelta() {
        return sentDelta.get();
    }

    public boolean isSentRegistry() {
        return sentRegistry.get();
    }

    public void addRemoteRegionApps(String appName, Application app) {
        remoteRegionApps.put(appName, app);
    }

    public void addRemoteRegionAppsDelta(String appName, Application app) {
        remoteRegionAppsDelta.put(appName, app);
    }

    public void addLocalRegionApps(String appName, Application app) {
        applicationMap.put(appName, app);
    }

    public void addLocalRegionAppsDelta(String appName, Application app) {
        applicationDeltaMap.put(appName, app);
    }

    public void waitForDeltaToBeRetrieved(int refreshRate) throws InterruptedException {
        int count = 0;
        while (count++ < 3 && !isSentDelta()) {
            System.out.println("Sleeping for " + refreshRate + " seconds to let the remote registry fetch delta. Attempt: " + count);
            Thread.sleep( 3 * refreshRate * 1000);
            System.out.println("Done sleeping for 10 seconds to let the remote registry fetch delta. Delta fetched: " + isSentDelta());
        }

        System.out.println("Sleeping for extra " + refreshRate + " seconds for the client to update delta in memory.");
    }

    //
    // A base default resource handler for the mock server
    //
    private class AppsResourceHandler extends AbstractHandler {

        @Override
        public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch)
                throws IOException, ServletException {
            String authName = request.getHeader(AbstractEurekaIdentity.AUTH_NAME_HEADER_KEY);
            String authVersion = request.getHeader(AbstractEurekaIdentity.AUTH_VERSION_HEADER_KEY);
            String authId = request.getHeader(AbstractEurekaIdentity.AUTH_ID_HEADER_KEY);

            Assert.assertEquals(EurekaClientIdentity.DEFAULT_CLIENT_NAME, authName);
            Assert.assertNotNull(authVersion);
            Assert.assertNotNull(authId);

            String pathInfo = request.getPathInfo();
            System.out.println("Eureka port: " + port + ". " + System.currentTimeMillis() +
                    ". Eureka resource mock, received request on path: " + pathInfo + ". HTTP method: |"
                    + request.getMethod() + '|' + ", query string: " + request.getQueryString());
            boolean handled = false;
            if (null != pathInfo && pathInfo.startsWith("")) {
                pathInfo = pathInfo.substring(EUREKA_API_BASE_PATH.length());
                boolean includeRemote = isRemoteRequest(request);

                if (pathInfo.startsWith("apps/delta")) {
                    getDeltaCount.getAndIncrement();

                    Applications apps = new Applications();
                    apps.setVersion(100L);
                    if (sentDelta.compareAndSet(false, true)) {
                        addDeltaApps(includeRemote, apps);
                    } else {
                        System.out.println("Eureka port: " +  port + ". " + System.currentTimeMillis() +". Not including delta as it has already been sent.");
                    }
                    apps.setAppsHashCode(getDeltaAppsHashCode(includeRemote));
                    sendOkResponseWithContent((Request) request, response, apps);
                    handled = true;
                } else if(pathInfo.equals("apps/")) {
                    getFullRegistryCount.getAndIncrement();

                    Applications apps = new Applications();
                    apps.setVersion(100L);
                    for (Application application : applicationMap.values()) {
                        apps.addApplication(application);
                    }
                    if (includeRemote) {
                        for (Application application : remoteRegionApps.values()) {
                            apps.addApplication(application);
                        }
                    }

                    if (sentDelta.get()) {
                        addDeltaApps(includeRemote, apps);
                    } else {
                        System.out.println("Eureka port: " + port + ". " + System.currentTimeMillis() +". Not including delta apps in /apps response, as delta has not been sent.");
                    }
                    apps.setAppsHashCode(apps.getReconcileHashCode());
                    sendOkResponseWithContent((Request) request, response, apps);
                    sentRegistry.set(true);
                    handled = true;
                } else if (pathInfo.startsWith("vips/")) {
                    getSingleVipCount.getAndIncrement();

                    String vipAddress = pathInfo.substring("vips/".length());
                    Applications apps = new Applications();
                    apps.setVersion(-1l);
                    for (Application application : applicationMap.values()) {
                        Application retApp = new Application(application.getName());
                        for (InstanceInfo instance : application.getInstances()) {
                            if (vipAddress.equals(instance.getVIPAddress())) {
                                retApp.addInstance(instance);
                            }
                        }

                        if (retApp.getInstances().size() > 0) {
                            apps.addApplication(retApp);
                        }
                    }

                    apps.setAppsHashCode(apps.getReconcileHashCode());
                    sendOkResponseWithContent((Request) request, response, apps);
                    handled = true;
                } else if (pathInfo.startsWith("apps")) {  // assume this is the renewal heartbeat
                    heartbeatCount.getAndIncrement();

                    sendOkResponseWithContent((Request) request, response, new Applications());
                } else {
                    System.out.println("Not handling request: " + pathInfo);
                }
            }

            if(!handled) {
                response.sendError(HttpServletResponse.SC_NOT_FOUND,
                        "Request path: " + pathInfo + " not supported by eureka resource mock.");
            }
        }

        protected void addDeltaApps(boolean includeRemote, Applications apps) {
            for (Application application : applicationDeltaMap.values()) {
                apps.addApplication(application);
            }
            if (includeRemote) {
                for (Application application : remoteRegionAppsDelta.values()) {
                    apps.addApplication(application);
                }
            }
        }

        protected String getDeltaAppsHashCode(boolean includeRemote) {
            Applications allApps = new Applications();
            for (Application application : applicationMap.values()) {
                allApps.addApplication(application);
            }

            if (includeRemote) {
                for (Application application : remoteRegionApps.values()) {
                    allApps.addApplication(application);
                }
            }
            addDeltaApps(includeRemote, allApps);
            return allApps.getReconcileHashCode();
        }

        protected boolean isRemoteRequest(HttpServletRequest request) {
            String queryString = request.getQueryString();
            if (queryString == null) {
                return false;
            }
            return queryString.contains("regions=");
        }

        protected void sendOkResponseWithContent(Request request, HttpServletResponse response, Applications apps)
                throws IOException {
            String content = XmlXStream.getInstance().toXML(apps);
            response.setContentType("application/xml");
            response.setStatus(HttpServletResponse.SC_OK);
            response.getWriter().println(content);
            response.getWriter().flush();
            request.setHandled(true);
            System.out.println("Eureka port: " + port + ". " + System.currentTimeMillis() +
                    ". Eureka resource mock, sent response for request path: " + request.getPathInfo() +
                    ", apps count: " + apps.getRegisteredApplications().size());
        }

        protected void sleep(int seconds) {
            try {
                Thread.sleep(seconds);
            } catch (InterruptedException e) {
                System.out.println("Interrupted: " + e);
            }
        }
    }
}
TOP

Related Classes of com.netflix.discovery.MockRemoteEurekaServer$AppsResourceHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.