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

org.apache.thrift.server.THsHaServer Maven / Gradle / Ivy

Go to download

Thrift is a software framework for scalable cross-language services development.

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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 org.apache.thrift.server;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.thrift.TProcessor;
import org.apache.thrift.TProcessorFactory;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocolFactory;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TNonblockingServerTransport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * An extension of the TNonblockingServer to a Half-Sync/Half-Async server.
 * Like TNonblockingServer, it relies on the use of TFramedTransport.
 */
public class THsHaServer extends TNonblockingServer {
  private static final Logger LOGGER =
    LoggerFactory.getLogger(THsHaServer.class.getName());

  // This wraps all the functionality of queueing and thread pool management
  // for the passing of Invocations from the Selector to workers.
  private ExecutorService invoker;

  /**
   * Create server with given processor, and server transport. Default server
   * options, TBinaryProtocol for the protocol, and TFramedTransport.Factory on
   * both input and output transports. A TProcessorFactory will be created that
   * always returns the specified processor.
   */
  public THsHaServer( TProcessor processor,
                      TNonblockingServerTransport serverTransport) {
    this(processor, serverTransport, new Options());
  }

  /**
   * Create server with given processor, server transport, and server options
   * using TBinaryProtocol for the protocol, and TFramedTransport.Factory on
   * both input and output transports. A TProcessorFactory will be created that
   * always returns the specified processor.
   */
  public THsHaServer( TProcessor processor,
                      TNonblockingServerTransport serverTransport,
                      Options options) {
    this(new TProcessorFactory(processor), serverTransport, options);
  }

  /**
   * Create server with specified processor factory and server transport. Uses
   * default options. TBinaryProtocol is assumed. TFramedTransport.Factory is
   * used on both input and output transports.
   */
  public THsHaServer( TProcessorFactory processorFactory,
                      TNonblockingServerTransport serverTransport) {
    this(processorFactory, serverTransport, new Options());
  }

  /**
   * Create server with specified processor factory, server transport, and server
   * options. TBinaryProtocol is assumed. TFramedTransport.Factory is used on
   * both input and output transports.
   */
  public THsHaServer( TProcessorFactory processorFactory,
                      TNonblockingServerTransport serverTransport,
                      Options options) {
    this(processorFactory, serverTransport, new TFramedTransport.Factory(),
      new TBinaryProtocol.Factory(), options);
  }

  /**
   * Server with specified processor, server transport, and in/out protocol
   * factory. Defaults will be used for in/out transport factory and server
   * options.
   */
  public THsHaServer( TProcessor processor,
                      TNonblockingServerTransport serverTransport,
                      TProtocolFactory protocolFactory) {
    this(processor, serverTransport, protocolFactory, new Options());
  }

  /**
   * Server with specified processor, server transport, and in/out protocol
   * factory. Defaults will be used for in/out transport factory and server
   * options.
   */
  public THsHaServer( TProcessor processor,
                      TNonblockingServerTransport serverTransport,
                      TProtocolFactory protocolFactory,
                      Options options) {
    this(new TProcessorFactory(processor), serverTransport,
      new TFramedTransport.Factory(),
      protocolFactory, protocolFactory, 
      options);
  }

  /**
   * Create server with specified processor, server transport, in/out
   * transport factory, in/out protocol factory, and default server options. A
   * processor factory will be created that always returns the specified
   * processor.
   */
  public THsHaServer( TProcessor processor,
                      TNonblockingServerTransport serverTransport,
                      TFramedTransport.Factory transportFactory,
                      TProtocolFactory protocolFactory) {
    this(new TProcessorFactory(processor), serverTransport,
      transportFactory, protocolFactory);
  }

  /**
   * Create server with specified processor factory, server transport, in/out
   * transport factory, in/out protocol factory, and default server options.
   */
  public THsHaServer( TProcessorFactory processorFactory,
                      TNonblockingServerTransport serverTransport,
                      TFramedTransport.Factory transportFactory,
                      TProtocolFactory protocolFactory) {
    this(processorFactory, serverTransport,
      transportFactory,
      protocolFactory, protocolFactory, new Options());
  }

  /**
   * Create server with specified processor factory, server transport, in/out
   * transport factory, in/out protocol factory, and server options.
   */
  public THsHaServer( TProcessorFactory processorFactory,
                      TNonblockingServerTransport serverTransport,
                      TFramedTransport.Factory transportFactory,
                      TProtocolFactory protocolFactory,
                      Options options) {
    this(processorFactory, serverTransport,
      transportFactory,
      protocolFactory, protocolFactory,
      options);
  }

  /**
   * Create server with everything specified, except use default server options.
   */
  public THsHaServer( TProcessor processor,
                      TNonblockingServerTransport serverTransport,
                      TFramedTransport.Factory outputTransportFactory,
                      TProtocolFactory inputProtocolFactory,
                      TProtocolFactory outputProtocolFactory) {
    this(new TProcessorFactory(processor), serverTransport,
      outputTransportFactory,
      inputProtocolFactory, outputProtocolFactory);
  }

  /**
   * Create server with everything specified, except use default server options.
   */
  public THsHaServer( TProcessorFactory processorFactory,
                      TNonblockingServerTransport serverTransport,
                      TFramedTransport.Factory outputTransportFactory,
                      TProtocolFactory inputProtocolFactory,
                      TProtocolFactory outputProtocolFactory)
  {
    this(processorFactory, serverTransport,
      outputTransportFactory,
      inputProtocolFactory, outputProtocolFactory, new Options());
  }

  /**
   * Create server with every option fully specified, with an internally managed
   * ExecutorService
   */
  public THsHaServer( TProcessorFactory processorFactory,
                      TNonblockingServerTransport serverTransport,
                      TFramedTransport.Factory outputTransportFactory,
                      TProtocolFactory inputProtocolFactory,
                      TProtocolFactory outputProtocolFactory,
                      Options options)
  {
    this(processorFactory, serverTransport,
      outputTransportFactory,
      inputProtocolFactory, outputProtocolFactory,
      createInvokerPool(options),
      options);
  }

  /**
   * Create server with every option fully specified, and with an injected
   * ExecutorService
   */
  public THsHaServer( TProcessorFactory processorFactory,
                      TNonblockingServerTransport serverTransport,
                      TFramedTransport.Factory outputTransportFactory,
                      TProtocolFactory inputProtocolFactory,
                      TProtocolFactory outputProtocolFactory,
                      ExecutorService executor,
                      TNonblockingServer.Options options) {
    super(processorFactory, serverTransport,
      outputTransportFactory,
      inputProtocolFactory, outputProtocolFactory,
      options);

    invoker = executor;
  }

  /** @inheritDoc */
  @Override
  public void serve() {
    // start listening, or exit
    if (!startListening()) {
      return;
    }

    // start the selector, or exit
    if (!startSelectorThread()) {
      return;
    }

    // this will block while we serve
    joinSelector();

    gracefullyShutdownInvokerPool();

    // do a little cleanup
    stopListening();

    // ungracefully shut down the invoker pool?
  }

  /**
   * Helper to create an invoker pool
   */
  protected static ExecutorService createInvokerPool(Options options) {
    int workerThreads = options.workerThreads;
    int stopTimeoutVal = options.stopTimeoutVal;
    TimeUnit stopTimeoutUnit = options.stopTimeoutUnit;

    LinkedBlockingQueue queue = new LinkedBlockingQueue();
    ExecutorService invoker = new ThreadPoolExecutor(workerThreads, workerThreads,
      stopTimeoutVal, stopTimeoutUnit, queue);

    return invoker;
  }

  protected void gracefullyShutdownInvokerPool() {
    // try to gracefully shut down the executor service
    invoker.shutdown();

    // Loop until awaitTermination finally does return without a interrupted
    // exception. If we don't do this, then we'll shut down prematurely. We want
    // to let the executorService clear it's task queue, closing client sockets
    // appropriately.
    long timeoutMS = 10000;
    long now = System.currentTimeMillis();
    while (timeoutMS >= 0) {
      try {
        invoker.awaitTermination(timeoutMS, TimeUnit.MILLISECONDS);
        break;
      } catch (InterruptedException ix) {
        long newnow = System.currentTimeMillis();
        timeoutMS -= (newnow - now);
        now = newnow;
      }
    }
  }

  /**
   * We override the standard invoke method here to queue the invocation for
   * invoker service instead of immediately invoking. The thread pool takes care of the rest.
   */
  @Override
  protected boolean requestInvoke(FrameBuffer frameBuffer) {
    try {
      invoker.execute(new Invocation(frameBuffer));
      return true;
    } catch (RejectedExecutionException rx) {
      LOGGER.warn("ExecutorService rejected execution!", rx);
      return false;
    }
  }

  /**
   * An Invocation represents a method call that is prepared to execute, given
   * an idle worker thread. It contains the input and output protocols the
   * thread's processor should use to perform the usual Thrift invocation.
   */
  private class Invocation implements Runnable {

    private final FrameBuffer frameBuffer;

    public Invocation(final FrameBuffer frameBuffer) {
      this.frameBuffer = frameBuffer;
    }

    public void run() {
      frameBuffer.invoke();
    }
  }

  public static class Options extends TNonblockingServer.Options {
    public int workerThreads = 5;
    public int stopTimeoutVal = 60;
    public TimeUnit stopTimeoutUnit = TimeUnit.SECONDS;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy