alluxio.worker.AlluxioWorkerProcess.java Source code

Java tutorial

Introduction

Here is the source code for alluxio.worker.AlluxioWorkerProcess.java

Source

/*
 * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
 * (the "License"). You may not use this work except in compliance with the License, which is
 * available at www.apache.org/licenses/LICENSE-2.0
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied, as more fully set forth in the License.
 *
 * See the NOTICE file distributed with this work for information regarding copyright ownership.
 */

package alluxio.worker;

import alluxio.Configuration;
import alluxio.Constants;
import alluxio.PropertyKey;
import alluxio.RuntimeConstants;
import alluxio.ServiceUtils;
import alluxio.metrics.MetricsSystem;
import alluxio.metrics.sink.MetricsServlet;
import alluxio.network.ChannelType;
import alluxio.security.authentication.TransportProvider;
import alluxio.underfs.UfsManager;
import alluxio.underfs.WorkerUfsManager;
import alluxio.util.CommonUtils;
import alluxio.util.WaitForOptions;
import alluxio.util.network.NetworkAddressUtils;
import alluxio.util.network.NetworkAddressUtils.ServiceType;
import alluxio.web.WebServer;
import alluxio.web.WorkerWebServer;
import alluxio.wire.WorkerNetAddress;
import alluxio.worker.block.BlockWorker;

import com.google.common.base.Function;
import com.google.common.base.Throwables;
import io.netty.channel.unix.DomainSocketAddress;
import org.apache.thrift.TMultiplexedProcessor;
import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TTransportException;
import org.apache.thrift.transport.TTransportFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

import javax.annotation.concurrent.NotThreadSafe;

/**
 * This class encapsulates the different worker services that are configured to run.
 */
@NotThreadSafe
public final class AlluxioWorkerProcess implements WorkerProcess {
    private static final Logger LOG = LoggerFactory.getLogger(AlluxioWorkerProcess.class);

    /** Server for data requests and responses. */
    private DataServer mDataServer;

    /** If started (i.e. not null), this server is used to serve local data transfer. */
    private DataServer mDomainSocketDataServer;

    /** Whether the worker is serving the RPC server. */
    private boolean mIsServingRPC = false;

    private final MetricsServlet mMetricsServlet = new MetricsServlet(MetricsSystem.METRIC_REGISTRY);

    /** The worker registry. */
    private WorkerRegistry mRegistry;

    /** Worker Web UI server. */
    private WebServer mWebServer;

    /** The transport provider to create thrift server transport. */
    private TransportProvider mTransportProvider;

    /** Thread pool for thrift. */
    private TThreadPoolServer mThriftServer;

    /** Server socket for thrift. */
    private TServerSocket mThriftServerSocket;

    /** The address for the rpc server. */
    private InetSocketAddress mRpcAddress;

    /** Worker start time in milliseconds. */
    private long mStartTimeMs;

    /** The manager for all ufs. */
    private UfsManager mUfsManager;

    /**
     * Creates a new instance of {@link AlluxioWorkerProcess}.
     */
    AlluxioWorkerProcess() {
        try {
            mStartTimeMs = System.currentTimeMillis();
            mUfsManager = new WorkerUfsManager();
            mRegistry = new WorkerRegistry();
            List<Callable<Void>> callables = new ArrayList<>();
            for (final WorkerFactory factory : ServiceUtils.getWorkerServiceLoader()) {
                callables.add(new Callable<Void>() {
                    @Override
                    public Void call() throws Exception {
                        if (factory.isEnabled()) {
                            factory.create(mRegistry, mUfsManager);
                        }
                        return null;
                    }
                });
            }
            CommonUtils.invokeAll(callables);

            // Setup web server
            mWebServer = new WorkerWebServer(NetworkAddressUtils.getBindAddress(ServiceType.WORKER_WEB), this,
                    mRegistry.get(BlockWorker.class), NetworkAddressUtils.getConnectHost(ServiceType.WORKER_RPC),
                    mStartTimeMs);

            // Setup Thrift server
            mTransportProvider = TransportProvider.Factory.create();
            mThriftServerSocket = createThriftServerSocket();
            int rpcPort = NetworkAddressUtils.getThriftPort(mThriftServerSocket);
            String rpcHost = NetworkAddressUtils.getThriftSocket(mThriftServerSocket).getInetAddress()
                    .getHostAddress();
            mRpcAddress = new InetSocketAddress(rpcHost, rpcPort);
            mThriftServer = createThriftServer();

            // Setup Data server
            mDataServer = DataServer.Factory.create(NetworkAddressUtils.getBindAddress(ServiceType.WORKER_DATA),
                    this);

            if (isDomainSocketEnabled()) {
                String domainSocketPath = Configuration.get(PropertyKey.WORKER_DATA_SERVER_DOMAIN_SOCKET_ADDRESS);
                LOG.info("Domain socket data server is enabled at {}.", domainSocketPath);
                mDomainSocketDataServer = DataServer.Factory.create(new DomainSocketAddress(domainSocketPath),
                        this);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public long getStartTimeMs() {
        return mStartTimeMs;
    }

    @Override
    public long getUptimeMs() {
        return System.currentTimeMillis() - mStartTimeMs;
    }

    @Override
    public String getDataBindHost() {
        return ((InetSocketAddress) mDataServer.getBindAddress()).getHostString();
    }

    @Override
    public int getDataLocalPort() {
        return ((InetSocketAddress) mDataServer.getBindAddress()).getPort();
    }

    @Override
    public String getDataDomainSocketPath() {
        if (mDomainSocketDataServer != null) {
            return ((DomainSocketAddress) mDomainSocketDataServer.getBindAddress()).path();
        }
        return "";
    }

    @Override
    public String getWebBindHost() {
        return mWebServer.getBindHost();
    }

    @Override
    public int getWebLocalPort() {
        return mWebServer.getLocalPort();
    }

    @Override
    public <T extends Worker> T getWorker(Class<T> clazz) {
        return mRegistry.get(clazz);
    }

    @Override
    public UfsManager getUfsManager() {
        return mUfsManager;
    }

    @Override
    public InetSocketAddress getRpcAddress() {
        return mRpcAddress;
    }

    @Override
    public void start() throws Exception {
        // NOTE: the order to start different services is sensitive. If you change it, do it cautiously.

        // Start serving metrics system, this will not block
        MetricsSystem.startSinks();

        // Start serving the web server, this will not block.
        mWebServer.addHandler(mMetricsServlet.getHandler());
        mWebServer.start();

        // Start each worker
        // Requirement: NetAddress set in WorkerContext, so block worker can initialize BlockMasterSync
        // Consequence: worker id is granted
        startWorkers();
        LOG.info("Started {} with id {}", this, mRegistry.get(BlockWorker.class).getWorkerId());

        mIsServingRPC = true;

        // Start serving RPC, this will block
        LOG.info("{} version {} started @ {}", this, RuntimeConstants.VERSION, mRpcAddress);
        mThriftServer.serve();
        LOG.info("{} version {} ended @ {}", this, RuntimeConstants.VERSION, mRpcAddress);
    }

    @Override
    public void stop() throws Exception {
        if (mIsServingRPC) {
            stopServing();
            stopWorkers();
            mIsServingRPC = false;
        }
    }

    private void startWorkers() throws Exception {
        mRegistry.start(getAddress());
    }

    private void stopWorkers() throws Exception {
        mRegistry.stop();
    }

    private void stopServing() throws IOException {
        mDataServer.close();
        if (mDomainSocketDataServer != null) {
            mDomainSocketDataServer.close();
            mDomainSocketDataServer = null;
        }
        mThriftServer.stop();
        mThriftServerSocket.close();
        mUfsManager.close();
        try {
            mWebServer.stop();
        } catch (Exception e) {
            LOG.error("Failed to stop {} web server", this, e);
        }
        MetricsSystem.stopSinks();
    }

    private void registerServices(TMultiplexedProcessor processor, Map<String, TProcessor> services) {
        for (Map.Entry<String, TProcessor> service : services.entrySet()) {
            processor.registerProcessor(service.getKey(), service.getValue());
        }
    }

    /**
     * Helper method to create a {@link org.apache.thrift.server.TThreadPoolServer} for handling
     * incoming RPC requests.
     *
     * @return a thrift server
     */
    private TThreadPoolServer createThriftServer() {
        int minWorkerThreads = Configuration.getInt(PropertyKey.WORKER_BLOCK_THREADS_MIN);
        int maxWorkerThreads = Configuration.getInt(PropertyKey.WORKER_BLOCK_THREADS_MAX);
        TMultiplexedProcessor processor = new TMultiplexedProcessor();

        for (Worker worker : mRegistry.getServers()) {
            registerServices(processor, worker.getServices());
        }

        // Return a TTransportFactory based on the authentication type
        TTransportFactory tTransportFactory;
        try {
            tTransportFactory = mTransportProvider.getServerTransportFactory();
        } catch (IOException e) {
            throw Throwables.propagate(e);
        }
        TThreadPoolServer.Args args = new TThreadPoolServer.Args(mThriftServerSocket)
                .minWorkerThreads(minWorkerThreads).maxWorkerThreads(maxWorkerThreads).processor(processor)
                .transportFactory(tTransportFactory).protocolFactory(new TBinaryProtocol.Factory(true, true));
        if (Configuration.getBoolean(PropertyKey.TEST_MODE)) {
            args.stopTimeoutVal = 0;
        } else {
            args.stopTimeoutVal = Constants.THRIFT_STOP_TIMEOUT_SECONDS;
        }
        return new TThreadPoolServer(args);
    }

    /**
     * Helper method to create a {@link org.apache.thrift.transport.TServerSocket} for the RPC server.
     *
     * @return a thrift server socket
     */
    private TServerSocket createThriftServerSocket() {
        try {
            return new TServerSocket(NetworkAddressUtils.getBindAddress(ServiceType.WORKER_RPC));
        } catch (TTransportException e) {
            throw Throwables.propagate(e);
        }
    }

    /**
     * @return true if domain socket is enabled
     */
    private boolean isDomainSocketEnabled() {
        return Configuration.getEnum(PropertyKey.WORKER_NETWORK_NETTY_CHANNEL,
                ChannelType.class) == ChannelType.EPOLL
                && !Configuration.get(PropertyKey.WORKER_DATA_SERVER_DOMAIN_SOCKET_ADDRESS).isEmpty();
    }

    @Override
    public void waitForReady() {
        CommonUtils.waitFor(this + " to start", new Function<Void, Boolean>() {
            @Override
            public Boolean apply(Void input) {
                return mThriftServer.isServing() && mRegistry.get(BlockWorker.class).getWorkerId() != null
                        && mWebServer.getServer().isRunning();
            }
        }, WaitForOptions.defaults().setTimeout(10000));
    }

    @Override
    public WorkerNetAddress getAddress() {
        return new WorkerNetAddress().setHost(NetworkAddressUtils.getConnectHost(ServiceType.WORKER_RPC))
                .setRpcPort(mRpcAddress.getPort()).setDataPort(getDataLocalPort())
                .setDomainSocketPath(getDataDomainSocketPath()).setWebPort(mWebServer.getLocalPort());
    }

    @Override
    public String toString() {
        return "Alluxio worker";
    }
}