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