Back to home page

OSCL-LXR

 
 

    


0001 /**
0002  * Licensed to the Apache Software Foundation (ASF) under one
0003  * or more contributor license agreements.  See the NOTICE file
0004  * distributed with this work for additional information
0005  * regarding copyright ownership.  The ASF licenses this file
0006  * to you under the Apache License, Version 2.0 (the
0007  * "License"); you may not use this file except in compliance
0008  * with the License.  You may obtain a copy of the License at
0009  *
0010  *     http://www.apache.org/licenses/LICENSE-2.0
0011  *
0012  * Unless required by applicable law or agreed to in writing, software
0013  * distributed under the License is distributed on an "AS IS" BASIS,
0014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0015  * See the License for the specific language governing permissions and
0016  * limitations under the License.
0017  */
0018 
0019 package org.apache.hive.service.cli.thrift;
0020 
0021 import java.util.Arrays;
0022 import java.util.concurrent.SynchronousQueue;
0023 import java.util.concurrent.ThreadPoolExecutor;
0024 import java.util.concurrent.TimeUnit;
0025 
0026 import org.apache.hadoop.hive.conf.HiveConf;
0027 import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
0028 import org.apache.hadoop.hive.shims.ShimLoader;
0029 import org.apache.hadoop.security.UserGroupInformation;
0030 import org.apache.hadoop.util.Shell;
0031 import org.apache.hive.service.auth.HiveAuthFactory;
0032 import org.apache.hive.service.cli.CLIService;
0033 import org.apache.hive.service.cli.thrift.TCLIService.Iface;
0034 import org.apache.hive.service.server.ThreadFactoryWithGarbageCleanup;
0035 import org.apache.thrift.TProcessor;
0036 import org.apache.thrift.protocol.TBinaryProtocol;
0037 import org.apache.thrift.protocol.TProtocolFactory;
0038 import org.apache.thrift.server.TServlet;
0039 import org.eclipse.jetty.server.AbstractConnectionFactory;
0040 import org.eclipse.jetty.server.ConnectionFactory;
0041 import org.eclipse.jetty.server.HttpConnectionFactory;
0042 import org.eclipse.jetty.server.ServerConnector;
0043 import org.eclipse.jetty.servlet.ServletContextHandler;
0044 import org.eclipse.jetty.servlet.ServletHolder;
0045 import org.eclipse.jetty.util.ssl.SslContextFactory;
0046 import org.eclipse.jetty.util.thread.ExecutorThreadPool;
0047 import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
0048 
0049 
0050 public class ThriftHttpCLIService extends ThriftCLIService {
0051 
0052   public ThriftHttpCLIService(CLIService cliService) {
0053     super(cliService, ThriftHttpCLIService.class.getSimpleName());
0054   }
0055 
0056   /**
0057    * Configure Jetty to serve http requests. Example of a client connection URL:
0058    * http://localhost:10000/servlets/thrifths2/ A gateway may cause actual target URL to differ,
0059    * e.g. http://gateway:port/hive2/servlets/thrifths2/
0060    */
0061   @Override
0062   public void run() {
0063     try {
0064       // Server thread pool
0065       // Start with minWorkerThreads, expand till maxWorkerThreads and reject subsequent requests
0066       String threadPoolName = "HiveServer2-HttpHandler-Pool";
0067       ThreadPoolExecutor executorService = new ThreadPoolExecutor(minWorkerThreads, maxWorkerThreads,
0068           workerKeepAliveTime, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),
0069           new ThreadFactoryWithGarbageCleanup(threadPoolName));
0070       ExecutorThreadPool threadPool = new ExecutorThreadPool(executorService);
0071 
0072       // HTTP Server
0073       httpServer = new org.eclipse.jetty.server.Server(threadPool);
0074 
0075       // Connector configs
0076 
0077       ConnectionFactory[] connectionFactories;
0078       boolean useSsl = hiveConf.getBoolVar(ConfVars.HIVE_SERVER2_USE_SSL);
0079       String schemeName = useSsl ? "https" : "http";
0080       // Change connector if SSL is used
0081       if (useSsl) {
0082         String keyStorePath = hiveConf.getVar(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PATH).trim();
0083         String keyStorePassword = ShimLoader.getHadoopShims().getPassword(hiveConf,
0084             HiveConf.ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PASSWORD.varname);
0085         if (keyStorePath.isEmpty()) {
0086           throw new IllegalArgumentException(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PATH.varname
0087               + " Not configured for SSL connection");
0088         }
0089         SslContextFactory sslContextFactory = new SslContextFactory.Server();
0090         String[] excludedProtocols = hiveConf.getVar(ConfVars.HIVE_SSL_PROTOCOL_BLACKLIST).split(",");
0091         LOG.info("HTTP Server SSL: adding excluded protocols: " + Arrays.toString(excludedProtocols));
0092         sslContextFactory.addExcludeProtocols(excludedProtocols);
0093         LOG.info("HTTP Server SSL: SslContextFactory.getExcludeProtocols = " +
0094           Arrays.toString(sslContextFactory.getExcludeProtocols()));
0095         sslContextFactory.setKeyStorePath(keyStorePath);
0096         sslContextFactory.setKeyStorePassword(keyStorePassword);
0097         connectionFactories = AbstractConnectionFactory.getFactories(
0098             sslContextFactory, new HttpConnectionFactory());
0099       } else {
0100         connectionFactories = new ConnectionFactory[] { new HttpConnectionFactory() };
0101       }
0102       ServerConnector connector = new ServerConnector(
0103           httpServer,
0104           null,
0105           // Call this full constructor to set this, which forces daemon threads:
0106           new ScheduledExecutorScheduler("HiveServer2-HttpHandler-JettyScheduler", true),
0107           null,
0108           -1,
0109           -1,
0110           connectionFactories);
0111 
0112       connector.setPort(portNum);
0113       // Linux:yes, Windows:no
0114       connector.setReuseAddress(!Shell.WINDOWS);
0115       int maxIdleTime = (int) hiveConf.getTimeVar(ConfVars.HIVE_SERVER2_THRIFT_HTTP_MAX_IDLE_TIME,
0116           TimeUnit.MILLISECONDS);
0117       connector.setIdleTimeout(maxIdleTime);
0118 
0119       httpServer.addConnector(connector);
0120 
0121       // Thrift configs
0122       hiveAuthFactory = new HiveAuthFactory(hiveConf);
0123       TProcessor processor = new TCLIService.Processor<Iface>(this);
0124       TProtocolFactory protocolFactory = new TBinaryProtocol.Factory();
0125       // Set during the init phase of HiveServer2 if auth mode is kerberos
0126       // UGI for the hive/_HOST (kerberos) principal
0127       UserGroupInformation serviceUGI = cliService.getServiceUGI();
0128       // UGI for the http/_HOST (SPNego) principal
0129       UserGroupInformation httpUGI = cliService.getHttpUGI();
0130       String authType = hiveConf.getVar(ConfVars.HIVE_SERVER2_AUTHENTICATION);
0131       TServlet thriftHttpServlet = new ThriftHttpServlet(processor, protocolFactory, authType,
0132           serviceUGI, httpUGI);
0133 
0134       // Context handler
0135       final ServletContextHandler context = new ServletContextHandler(
0136           ServletContextHandler.SESSIONS);
0137       context.setContextPath("/");
0138       String httpPath = getHttpPath(hiveConf
0139           .getVar(HiveConf.ConfVars.HIVE_SERVER2_THRIFT_HTTP_PATH));
0140       httpServer.setHandler(context);
0141       context.addServlet(new ServletHolder(thriftHttpServlet), httpPath);
0142 
0143       // TODO: check defaults: maxTimeout, keepalive, maxBodySize, bodyRecieveDuration, etc.
0144       // Finally, start the server
0145       httpServer.start();
0146       // In case HIVE_SERVER2_THRIFT_HTTP_PORT or hive.server2.thrift.http.port is configured with
0147       // 0 which represents any free port, we should set it to the actual one
0148       portNum = connector.getLocalPort();
0149       String msg = "Started " + ThriftHttpCLIService.class.getSimpleName() + " in " + schemeName
0150           + " mode on port " + connector.getLocalPort()+ " path=" + httpPath + " with " + minWorkerThreads + "..."
0151           + maxWorkerThreads + " worker threads";
0152       LOG.info(msg);
0153       httpServer.join();
0154     } catch (Throwable t) {
0155       LOG.fatal(
0156           "Error starting HiveServer2: could not start "
0157               + ThriftHttpCLIService.class.getSimpleName(), t);
0158       System.exit(-1);
0159     }
0160   }
0161 
0162   /**
0163    * The config parameter can be like "path", "/path", "/path/", "path/*", "/path1/path2/*" and so on.
0164    * httpPath should end up as "/*", "/path/*" or "/path1/../pathN/*"
0165    * @param httpPath
0166    * @return
0167    */
0168   private String getHttpPath(String httpPath) {
0169     if(httpPath == null || httpPath.equals("")) {
0170       httpPath = "/*";
0171     }
0172     else {
0173       if(!httpPath.startsWith("/")) {
0174         httpPath = "/" + httpPath;
0175       }
0176       if(httpPath.endsWith("/")) {
0177         httpPath = httpPath + "*";
0178       }
0179       if(!httpPath.endsWith("/*")) {
0180         httpPath = httpPath + "/*";
0181       }
0182     }
0183     return httpPath;
0184   }
0185 }