SonarQube6.2源码解析(一)
生活随笔
收集整理的這篇文章主要介紹了
SonarQube6.2源码解析(一)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
首先看sonar后臺的啟動進程:
[root@uranuspreweb34 logs]# ps -ef | grep java root 3169 3167 0 Apr19 ? 00:06:04 java -Dsonar.wrapped=true -Djava.awt.headless=true -Xms8m -Xmx8m -Djava.library.path=./lib -classpath ../../lib/jsw/wrapper-3.2.3.jar:../../lib/sonar-application-6.2.jar -Dwrapper.key=t7uBnfyOYRRUy2un -Dwrapper.port=32000 -Dwrapper.jvm.port.min=31000 -Dwrapper.jvm.port.max=31999 -Dwrapper.pid=3167 -Dwrapper.version=3.2.3 -Dwrapper.native_library=wrapper -Dwrapper.service=TRUE -Dwrapper.cpu.timeout=10 -Dwrapper.jvmid=1 org.tanukisoftware.wrapper.WrapperSimpleApp org.sonar.application.App root 3200 3169 4 Apr19 ? 06:33:32 /usr/java/jdk1.8.0_51/jre/bin/java -Djava.awt.headless=true -Xms4G -Xmx8G -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=7094 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=10.37.124.178 -Djava.io.tmpdir=/opt/CI/sonarqube-6.2/temp -javaagent:/usr/java/jdk1.8.0_51/jre/lib/management-agent.jar -cp ./lib/common/*:./lib/search/* org.sonar.search.SearchServer /opt/CI/sonarqube-6.2/temp/sq-process1495333341950424468properties root 3351 3169 3 Apr19 ? 05:25:40 /usr/java/jdk1.8.0_51/jre/bin/java -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djruby.management.enabled=false -Djruby.compile.invokedynamic=false -Xms4g -Xmx4g -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=7095 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=10.37.124.178 -Djava.io.tmpdir=/opt/CI/sonarqube-6.2/temp -javaagent:/usr/java/jdk1.8.0_51/jre/lib/management-agent.jar -cp ./lib/common/*:./lib/server/*:/opt/CI/sonarqube-6.2/lib/jdbc/mysql/mysql-connector-java-5.1.39.jar org.sonar.server.app.WebServer /opt/CI/sonarqube-6.2/temp/sq-process368230285702864980properties root 3540 3169 41 Apr19 ? 2-10:22:17 /usr/java/jdk1.8.0_51/jre/bin/java -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Xmx8G -Xms4G -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=7093 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=10.37.124.178 -Djava.io.tmpdir=/opt/CI/sonarqube-6.2/temp -javaagent:/usr/java/jdk1.8.0_51/jre/lib/management-agent.jar -cp ./lib/common/*:./lib/server/*:./lib/ce/*:/opt/CI/sonarqube-6.2/lib/jdbc/mysql/mysql-connector-java-5.1.39.jar org.sonar.ce.app.CeServer /opt/CI/sonarqube-6.2/temp/sq-process599434287403847159properties從進程的啟動邏輯看是?WrapperSimpleApp 進程拉起來的 web, search, ce進程
WrapperSimpleApp 對應的是sonar-qube6.2源碼包中的sonar-application這個子工程,這個下面就有
main 入口是App:
/** SonarQube* Copyright (C) 2009-2016 SonarSource SA* mailto:contact AT sonarsource DOT com** This program is free software; you can redistribute it and/or* modify it under the terms of the GNU Lesser General Public* License as published by the Free Software Foundation; either* version 3 of the License, or (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU* Lesser General Public License for more details.** You should have received a copy of the GNU Lesser General Public License* along with this program; if not, write to the Free Software Foundation,* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.*/ package org.sonar.application;import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Properties; import org.apache.commons.io.FilenameUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.process.Lifecycle; import org.sonar.process.ProcessId; import org.sonar.process.ProcessProperties; import org.sonar.process.Props; import org.sonar.process.Stoppable; import org.sonar.process.monitor.JavaCommand; import org.sonar.process.monitor.Monitor;import static org.sonar.process.Lifecycle.State; import static org.sonar.process.ProcessId.APP; import static org.sonar.process.ProcessProperties.HTTPS_PROXY_HOST; import static org.sonar.process.ProcessProperties.HTTPS_PROXY_PORT; import static org.sonar.process.ProcessProperties.HTTP_PROXY_HOST; import static org.sonar.process.ProcessProperties.HTTP_PROXY_PORT;/*** Entry-point of process that starts and monitors ElasticSearch, the Web Server and the Compute Engine.*/ public class App implements Stoppable {/*** Properties about proxy that must be set as system properties*/private static final String[] PROXY_PROPERTY_KEYS = new String[] {HTTP_PROXY_HOST,HTTP_PROXY_PORT,"http.nonProxyHosts",HTTPS_PROXY_HOST,HTTPS_PROXY_PORT,"http.auth.ntlm.domain","socksProxyHost","socksProxyPort"};private final Monitor monitor;public App(AppFileSystem appFileSystem, boolean watchForHardStop) {this(Monitor.create(APP.getIpcIndex(), appFileSystem, watchForHardStop, new AppLifecycleListener()));}App(Monitor monitor) {this.monitor = monitor;}public void start(Props props) throws InterruptedException {monitor.start(createCommands(props));monitor.awaitTermination();}private static List<JavaCommand> createCommands(Props props) {File homeDir = props.nonNullValueAsFile(ProcessProperties.PATH_HOME);List<JavaCommand> commands = new ArrayList<>(3);if (isProcessEnabled(props, ProcessProperties.CLUSTER_SEARCH_DISABLED)) {commands.add(createESCommand(props, homeDir));}if (isProcessEnabled(props, ProcessProperties.CLUSTER_WEB_DISABLED)) {commands.add(createWebServerCommand(props, homeDir));}if (isProcessEnabled(props, ProcessProperties.CLUSTER_CE_DISABLED)) {commands.add(createCeServerCommand(props, homeDir));}return commands;}private static boolean isProcessEnabled(Props props, String disabledPropertyKey) {return !props.valueAsBoolean(ProcessProperties.CLUSTER_ENABLED) ||!props.valueAsBoolean(disabledPropertyKey);}private static JavaCommand createESCommand(Props props, File homeDir) {return newJavaCommand(ProcessId.ELASTICSEARCH, props, homeDir).addJavaOptions("-Djava.awt.headless=true").addJavaOptions(props.nonNullValue(ProcessProperties.SEARCH_JAVA_OPTS)).addJavaOptions(props.nonNullValue(ProcessProperties.SEARCH_JAVA_ADDITIONAL_OPTS)).setClassName("org.sonar.search.SearchServer").addClasspath("./lib/common/*").addClasspath("./lib/search/*");}private static JavaCommand createWebServerCommand(Props props, File homeDir) {JavaCommand command = newJavaCommand(ProcessId.WEB_SERVER, props, homeDir).addJavaOptions(ProcessProperties.WEB_ENFORCED_JVM_ARGS).addJavaOptions(props.nonNullValue(ProcessProperties.WEB_JAVA_OPTS)).addJavaOptions(props.nonNullValue(ProcessProperties.WEB_JAVA_ADDITIONAL_OPTS))// required for logback tomcat valve.setEnvVariable(ProcessProperties.PATH_LOGS, props.nonNullValue(ProcessProperties.PATH_LOGS))// ensure JRuby uses SQ's temp directory as temp directory (eg. for temp files used during HTTP uploads).setEnvVariable("TMPDIR", props.nonNullValue(ProcessProperties.PATH_TEMP)).setClassName("org.sonar.server.app.WebServer").addClasspath("./lib/common/*").addClasspath("./lib/server/*");String driverPath = props.value(ProcessProperties.JDBC_DRIVER_PATH);if (driverPath != null) {command.addClasspath(driverPath);}return command;}private static JavaCommand createCeServerCommand(Props props, File homeDir) {JavaCommand command = newJavaCommand(ProcessId.COMPUTE_ENGINE, props, homeDir).addJavaOptions(ProcessProperties.CE_ENFORCED_JVM_ARGS).addJavaOptions(props.nonNullValue(ProcessProperties.CE_JAVA_OPTS)).addJavaOptions(props.nonNullValue(ProcessProperties.CE_JAVA_ADDITIONAL_OPTS)).setClassName("org.sonar.ce.app.CeServer").addClasspath("./lib/common/*").addClasspath("./lib/server/*").addClasspath("./lib/ce/*");String driverPath = props.value(ProcessProperties.JDBC_DRIVER_PATH);if (driverPath != null) {command.addClasspath(driverPath);}return command;}private static JavaCommand newJavaCommand(ProcessId id, Props props, File homeDir) {JavaCommand command = new JavaCommand(id).setWorkDir(homeDir).setArguments(props.rawProperties());for (String key : PROXY_PROPERTY_KEYS) {if (props.contains(key)) {command.addJavaOption("-D" + key + "=" + props.value(key));}}// defaults of HTTPS are the same than HTTP defaultssetSystemPropertyToDefaultIfNotSet(command, props, HTTPS_PROXY_HOST, HTTP_PROXY_HOST);setSystemPropertyToDefaultIfNotSet(command, props, HTTPS_PROXY_PORT, HTTP_PROXY_PORT);return command;}private static void setSystemPropertyToDefaultIfNotSet(JavaCommand command, Props props, String httpsProperty, String httpProperty) {if (!props.contains(httpsProperty) && props.contains(httpProperty)) {command.addJavaOption("-D" + httpsProperty + "=" + props.value(httpProperty));}}static String starPath(File homeDir, String relativePath) {File dir = new File(homeDir, relativePath);return FilenameUtils.concat(dir.getAbsolutePath(), "*");}public static void main(String[] args) throws InterruptedException {CommandLineParser cli = new CommandLineParser();Properties rawProperties = cli.parseArguments(args);Props props = new PropsBuilder(rawProperties, new JdbcSettings()).build();AppFileSystem appFileSystem = new AppFileSystem(props);appFileSystem.verifyProps();AppLogging logging = new AppLogging();logging.configure(props);// used by orchestratorboolean watchForHardStop = props.valueAsBoolean(ProcessProperties.ENABLE_STOP_COMMAND, false);App app = new App(appFileSystem, watchForHardStop);app.start(props);}@Overridepublic void stopAsync() {monitor.stop();}private static class AppLifecycleListener implements Lifecycle.LifecycleListener {private static final Logger LOGGER = LoggerFactory.getLogger(App.class);@Overridepublic void successfulTransition(State from, State to) {if (to == State.STARTED) {LOGGER.info("SonarQube is up");}}} }main方法中加載properties文件然后調用start方法,(創建ce,es,web進程)然后再次根據properties創建command去啟動jvm,然后再調用minor中start方法。
minor類:minor類是sonar-process-monitor模塊中的類
這個類中最為關鍵的就是startAndMonitorProcesses方法,然后調用JavaProcessLauncher?lauccher方法,同時將對應的command轉換ProcessRef bean對象。
private void startAndMonitorProcesses() throws InterruptedException{File tempDir = fileSystem.getTempDir();this.launcher = new JavaProcessLauncher(TIMEOUTS, tempDir);for (JavaCommand command : javaCommands) {ProcessRef processRef = null;try {processRef = launcher.launch(command);monitor(processRef);} catch (InterruptedException | RuntimeException e) {if (processRef != null) {LOG.error("{} failed to start", processRef);}// fail to start or to monitorstop();throw e;}}} /** SonarQube* Copyright (C) 2009-2016 SonarSource SA* mailto:contact AT sonarsource DOT com** This program is free software; you can redistribute it and/or* modify it under the terms of the GNU Lesser General Public* License as published by the Free Software Foundation; either* version 3 of the License, or (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU* Lesser General Public License for more details.** You should have received a copy of the GNU Lesser General Public License* along with this program; if not, write to the Free Software Foundation,* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.*/ package org.sonar.process.monitor;import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Properties; import org.apache.commons.lang.StringUtils; import org.slf4j.LoggerFactory; import org.sonar.process.AllProcessesCommands; import org.sonar.process.ProcessCommands; import org.sonar.process.ProcessEntryPoint; import org.sonar.process.ProcessUtils;import static org.sonar.process.ProcessEntryPoint.PROPERTY_PROCESS_INDEX; import static org.sonar.process.ProcessEntryPoint.PROPERTY_PROCESS_KEY; import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH; import static org.sonar.process.ProcessEntryPoint.PROPERTY_TERMINATION_TIMEOUT;class JavaProcessLauncher {private final Timeouts timeouts;private final File tempDir;private final AllProcessesCommands allProcessesCommands;JavaProcessLauncher(Timeouts timeouts, File tempDir) {this.timeouts = timeouts;this.tempDir = tempDir;this.allProcessesCommands = new AllProcessesCommands(tempDir);}public void close() {allProcessesCommands.close();}ProcessRef launch(JavaCommand command) {Process process = null;try {ProcessCommands commands = allProcessesCommands.createAfterClean(command.getProcessId().getIpcIndex());ProcessBuilder processBuilder = create(command);LoggerFactory.getLogger(getClass()).info("Launch process[{}]: {}",command.getProcessId().getKey(), StringUtils.join(processBuilder.command(), " "));process = processBuilder.start();StreamGobbler inputGobbler = new StreamGobbler(process.getInputStream(), command.getProcessId().getKey());inputGobbler.start();return new ProcessRef(command.getProcessId().getKey(), commands, process, inputGobbler);} catch (Exception e) {// just in caseProcessUtils.sendKillSignal(process);throw new IllegalStateException("Fail to launch [" + command.getProcessId().getKey() + "]", e);}}private ProcessBuilder create(JavaCommand javaCommand) {List<String> commands = new ArrayList<>();commands.add(buildJavaPath());commands.addAll(javaCommand.getJavaOptions());// TODO warning - does it work if temp dir contains a whitespace ?commands.add(String.format("-Djava.io.tmpdir=%s", tempDir.getAbsolutePath()));commands.add(getJmxAgentCommand());commands.addAll(buildClasspath(javaCommand));commands.add(javaCommand.getClassName());commands.add(buildPropertiesFile(javaCommand).getAbsolutePath());ProcessBuilder processBuilder = new ProcessBuilder();processBuilder.command(commands);processBuilder.directory(javaCommand.getWorkDir());processBuilder.environment().putAll(javaCommand.getEnvVariables());processBuilder.redirectErrorStream(true);return processBuilder;}/*** JVM option to enable the agent that allows inter-process communication through JMX without* opening new ports. The agent is available in JRE of OpenJDK/OracleJDK only.* @see ProcessEntryPoint*/private static String getJmxAgentCommand() {return "-javaagent:" + System.getProperty("java.home") + File.separator + "lib" + File.separator + "management-agent.jar";}private String buildJavaPath() {String separator = System.getProperty("file.separator");return new File(new File(System.getProperty("java.home")), "bin" + separator + "java").getAbsolutePath();}private List<String> buildClasspath(JavaCommand javaCommand) {return Arrays.asList("-cp", StringUtils.join(javaCommand.getClasspath(), System.getProperty("path.separator")));}private File buildPropertiesFile(JavaCommand javaCommand) {File propertiesFile = null;try {propertiesFile = File.createTempFile("sq-process", "properties", tempDir);Properties props = new Properties();props.putAll(javaCommand.getArguments());props.setProperty(PROPERTY_PROCESS_KEY, javaCommand.getProcessId().getKey());props.setProperty(PROPERTY_PROCESS_INDEX, Integer.toString(javaCommand.getProcessId().getIpcIndex()));props.setProperty(PROPERTY_TERMINATION_TIMEOUT, String.valueOf(timeouts.getTerminationTimeout()));props.setProperty(PROPERTY_SHARED_PATH, tempDir.getAbsolutePath());try (OutputStream out = new FileOutputStream(propertiesFile)) {props.store(out, String.format("Temporary properties file for command [%s]", javaCommand.getProcessId().getKey()));}return propertiesFile;} catch (Exception e) {throw new IllegalStateException("Cannot write temporary settings to " + propertiesFile, e);}} }這個類調用jdk中ProcessBuilder拉起的jvm進程。
總結
以上是生活随笔為你收集整理的SonarQube6.2源码解析(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用sonar-ws-client-4.
- 下一篇: 美股周二:三大股指全线下跌,谷歌涨逾2%