alluxio.worker.DefaultAlluxioWorker.java Source code

Java tutorial

Introduction

Here is the source code for alluxio.worker.DefaultAlluxioWorker.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.ServerUtils;
import alluxio.metrics.MetricsSystem;
import alluxio.metrics.sink.MetricsServlet;
import alluxio.security.authentication.TransportProvider;
import alluxio.util.CommonUtils;
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 alluxio.worker.block.DefaultBlockWorker;
import alluxio.worker.file.DefaultFileSystemWorker;
import alluxio.worker.file.FileSystemWorker;

import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
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.atomic.AtomicReference;

import javax.annotation.concurrent.NotThreadSafe;

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

    /** The worker serving blocks. */
    private BlockWorker mBlockWorker;

    /** The worker serving file system operations. */
    private FileSystemWorker mFileSystemWorker;

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

    /** A list of extra workers to launch based on service loader. */
    private List<Worker> mAdditionalWorkers;

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

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

    /** 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 worker ID for this worker. This is set when the block worker is initialized and may be
     * updated by the block sync thread if the master requests re-registration.
     */
    private AtomicReference<Long> mWorkerId;

    /**
     * Creates a new instance of {@link DefaultAlluxioWorker}.
     */
    public DefaultAlluxioWorker() {
        try {
            mWorkerId = new AtomicReference<>();
            mStartTimeMs = System.currentTimeMillis();
            mBlockWorker = new DefaultBlockWorker(mWorkerId);
            mFileSystemWorker = new DefaultFileSystemWorker(mBlockWorker, mWorkerId);

            mAdditionalWorkers = new ArrayList<>();
            List<? extends Worker> workers = Lists.newArrayList(mBlockWorker, mFileSystemWorker);
            for (WorkerFactory factory : ServerUtils.getWorkerServiceLoader()) {
                Worker worker = factory.create(workers);
                if (worker != null) {
                    mAdditionalWorkers.add(worker);
                }
            }

            // Setup web server
            mWebServer = new WorkerWebServer(NetworkAddressUtils.getBindAddress(ServiceType.WORKER_WEB), this,
                    mBlockWorker, 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);
        } catch (Exception e) {
            Throwables.propagate(e);
        }
    }

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

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

    @Override
    public String getDataBindHost() {
        return mDataServer.getBindHost();
    }

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

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

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

    @Override
    public BlockWorker getBlockWorker() {
        return mBlockWorker;
    }

    @Override
    public FileSystemWorker getFileSystemWorker() {
        return mFileSystemWorker;
    }

    @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 Alluxio worker with id {}", mWorkerId.get());

        mIsServingRPC = true;

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

    @Override
    public void stop() throws Exception {
        if (mIsServingRPC) {
            LOG.info("Stopping RPC server on Alluxio worker @ {}", mRpcAddress);
            stopServing();
            stopWorkers();
            mIsServingRPC = false;
        } else {
            LOG.info("Stopping Alluxio worker @ {}", mRpcAddress);
        }
    }

    private void startWorkers() throws Exception {
        mBlockWorker.init(getAddress());
        mBlockWorker.start();
        mFileSystemWorker.start();
        // start additional workers
        for (Worker worker : mAdditionalWorkers) {
            worker.start();
        }
    }

    private void stopWorkers() throws Exception {
        // stop additional workers
        for (Worker worker : mAdditionalWorkers) {
            worker.stop();
        }
        mFileSystemWorker.stop();
        mBlockWorker.stop();
    }

    private void stopServing() throws IOException {
        mDataServer.close();
        mThriftServer.stop();
        mThriftServerSocket.close();
        try {
            mWebServer.stop();
        } catch (Exception e) {
            LOG.error("Failed to stop web server", 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();

        registerServices(processor, mBlockWorker.getServices());
        registerServices(processor, mFileSystemWorker.getServices());
        // register additional workers for RPC service
        for (Worker worker : mAdditionalWorkers) {
            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);
        }
    }

    @Override
    public void waitForReady() {
        while (true) {
            if (mThriftServer.isServing() && mWorkerId.get() != null && mWebServer.getServer().isRunning()) {
                return;
            }
            CommonUtils.sleepMs(10);
        }
    }

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