Java tutorial
/** * 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.pulsar.proxy.server; import static com.google.common.base.Preconditions.checkArgument; import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isEmpty; import static org.slf4j.bridge.SLF4JBridgeHandler.install; import static org.slf4j.bridge.SLF4JBridgeHandler.removeHandlersForRootLogger; import org.apache.pulsar.broker.authentication.AuthenticationService; import org.apache.pulsar.common.configuration.PulsarConfigurationLoader; import org.eclipse.jetty.proxy.ProxyServlet; import org.eclipse.jetty.servlet.ServletHolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import io.prometheus.client.exporter.MetricsServlet; import io.prometheus.client.hotspot.DefaultExports; import org.apache.pulsar.common.configuration.VipStatus; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; /** * Starts an instance of the Pulsar ProxyService * */ public class ProxyServiceStarter { @Parameter(names = { "-c", "--config" }, description = "Configuration file path", required = true) private String configFile; @Parameter(names = { "-zk", "--zookeeper-servers" }, description = "Local zookeeper connection string") private String zookeeperServers = ""; @Deprecated @Parameter(names = { "-gzk", "--global-zookeeper-servers" }, description = "Global zookeeper connection string") private String globalZookeeperServers = ""; @Parameter(names = { "-cs", "--configuration-store-servers" }, description = "Configuration store connection string") private String configurationStoreServers = ""; @Parameter(names = { "-h", "--help" }, description = "Show this help message") private boolean help = false; public ProxyServiceStarter(String[] args) throws Exception { // setup handlers removeHandlersForRootLogger(); install(); DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss,SSS"); Thread.setDefaultUncaughtExceptionHandler((thread, exception) -> { System.out.println(String.format("%s [%s] error Uncaught exception in thread %s: %s", dateFormat.format(new Date()), thread.getContextClassLoader(), thread.getName(), exception.getMessage())); }); JCommander jcommander = new JCommander(); try { jcommander.addObject(this); jcommander.parse(args); if (help || isBlank(configFile)) { jcommander.usage(); return; } } catch (Exception e) { jcommander.usage(); System.exit(-1); } // load config file final ProxyConfiguration config = PulsarConfigurationLoader.create(configFile, ProxyConfiguration.class); if (!isBlank(zookeeperServers)) { // Use zookeeperServers from command line config.setZookeeperServers(zookeeperServers); } if (!isBlank(globalZookeeperServers)) { // Use globalZookeeperServers from command line config.setConfigurationStoreServers(globalZookeeperServers); } if (!isBlank(configurationStoreServers)) { // Use configurationStoreServers from command line config.setConfigurationStoreServers(configurationStoreServers); } if ((isBlank(config.getBrokerServiceURL()) && isBlank(config.getBrokerServiceURLTLS())) || config.isAuthorizationEnabled()) { checkArgument(!isEmpty(config.getZookeeperServers()), "zookeeperServers must be provided"); checkArgument(!isEmpty(config.getConfigurationStoreServers()), "configurationStoreServers must be provided"); } if ((!config.isTlsEnabledWithBroker() && isBlank(config.getBrokerWebServiceURL())) || (config.isTlsEnabledWithBroker() && isBlank(config.getBrokerWebServiceURLTLS()))) { checkArgument(!isEmpty(config.getZookeeperServers()), "zookeeperServers must be provided"); } java.security.Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); AuthenticationService authenticationService = new AuthenticationService( PulsarConfigurationLoader.convertFrom(config)); // create proxy service ProxyService proxyService = new ProxyService(config, authenticationService); // create a web-service final WebServer server = new WebServer(config, authenticationService); Runtime.getRuntime().addShutdownHook(new Thread(() -> { try { proxyService.close(); server.stop(); } catch (Exception e) { log.warn("server couldn't stop gracefully {}", e.getMessage(), e); } })); proxyService.start(); // Setup metrics DefaultExports.initialize(); addWebServerHandlers(server, config, proxyService.getDiscoveryProvider()); // start web-service server.start(); } public static void main(String[] args) throws Exception { new ProxyServiceStarter(args); } static void addWebServerHandlers(WebServer server, ProxyConfiguration config, BrokerDiscoveryProvider discoveryProvider) { server.addServlet("/metrics", new ServletHolder(MetricsServlet.class)); server.addRestResources("/", VipStatus.class.getPackage().getName(), VipStatus.ATTRIBUTE_STATUS_FILE_PATH, config.getStatusFilePath()); AdminProxyHandler adminProxyHandler = new AdminProxyHandler(config, discoveryProvider); ServletHolder servletHolder = new ServletHolder(adminProxyHandler); servletHolder.setInitParameter("preserveHost", "true"); server.addServlet("/admin", servletHolder); server.addServlet("/lookup", servletHolder); for (ProxyConfiguration.HttpReverseProxyConfig revProxy : config.getHttpReverseProxyConfigs()) { log.debug("Adding reverse proxy with config {}", revProxy); ServletHolder proxyHolder = new ServletHolder(ProxyServlet.Transparent.class); proxyHolder.setInitParameter("proxyTo", revProxy.getProxyTo()); proxyHolder.setInitParameter("prefix", "/"); server.addServlet(revProxy.getPath(), proxyHolder); } } private static final Logger log = LoggerFactory.getLogger(ProxyServiceStarter.class); }