[关闭]
@aloxc 2017-12-05T06:35:03.000000Z 字数 11716 阅读 1216

我们一起学ignite之启动脚本

ignite 一起学 源码分析


ignite的启动脚本bin/ignite.sh,该脚本包含了其它几个脚本,

  • bin/include/functions.sh 定义了若干函数
  • bin/include/parseargs.sh 解析参数
  • bin/include/setenv.sh 设置一些环境变量

里面定义了如何启动ignite服务器、如何设置堆内存、如何设置jmx信息等等,这些信息可以直接从ignite启动后的进程看到,
在终端中输入ps aux|grep java,找到ignite进程后可以看到类似如下的进程信息。

root 23190 115 6.6 4764008 258988 pts/0 Sl+ 10:17 0:05 /usr/java/jdk1.8.0_111/bin/java -Xms1g -Xmx1g -server -XX:+AggressiveOpts -XX:MaxMetaspaceSize=256m -XX:+PrintGCDetails -Xloggc:/usr/java/ignite/gc.log -XX:+PrintGCTimeStamps -DIGNITE_QUIET=true -DIGNITE_SUCCESS_FILE=/usr/java/ignite/work/ignite_success_fbff5113-ff60-435d-8ec8-7a1563ba12e2 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=49288 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -DIGNITE_HOME=/usr/java/ignite -DIGNITE_PROG_NAME=bin/ignite.sh -cp /usr/java/ignite/libs/:/usr/java/ignite/libs/ignite-indexing/:/usr/java/ignite/libs/ignite-spring/:/usr/java/ignite/libs/licenses/ org.apache.ignite.startup.cmdline.CommandLineStartup config/default-config.xml

1 这些参数信息的功能有

1.1. xmx1g

设置ignite进程使用最大的堆内存1g

1.2. IGNITE_SUCCESS_FILE

ignite服务成功启动后的一个文件,注意此文件不存在的,只是设置的一个系统属性,本属性的属性配置在IgniteSystemProperties.java中做了定义,并且在IgniteKernal.java做了引用,

  1. @Override public boolean isRestartEnabled() {
  2. return System.getProperty(IGNITE_SUCCESS_FILE) != null;
  3. }

注意该方法上的注释
Whether or not node restart is enabled. Node restart us supported when this node was started with {@code bin/ignite.{sh|bat}} script using {@code -r} argument. Node can be programmatically restarted using {@link Ignition#restart(boolean)}} method. @return {@code True} if restart mode is enabled, {@code false} otherwise. @see Ignition#restart(boolean)

是否启用节点重启功能,节点重启支持是使用bin/ignite.sh -r,加上-r参数。假如允许重启节点的话可使用编程方式来重启,使用Ignition.restart(boolean)

另外还在IgniteEx.java中有引用

  1. public static void restart(boolean cancel) {
  2. String file = System.getProperty(IGNITE_SUCCESS_FILE);
  3. if (file == null)
  4. U.warn(null, "Cannot restart node when restart not enabled.");
  5. else {
  6. try {
  7. new File(file).createNewFile();
  8. }
  9. catch (IOException e) {
  10. U.error(null, "Failed to create restart marker file (restart aborted): " + e.getMessage());
  11. return;
  12. }
  13. U.log(null, "Restarting node. Will exit (" + Ignition.RESTART_EXIT_CODE + ").");
  14. // Set the exit code so that shell process can recognize it and loop
  15. // the start up sequence again.
  16. System.setProperty(IGNITE_RESTART_CODE, Integer.toString(Ignition.RESTART_EXIT_CODE));
  17. stopAll(cancel);
  18. // This basically leaves loaders hang - we accept it.
  19. System.exit(Ignition.RESTART_EXIT_CODE);
  20. }
  21. }

1.3. org.apache.ignite.startup.cmdline.CommandLineStartup.java

ignite服务器的启动类,其实启动ignite服务就是执行该类中的main方法,

1.4. ignite服务对应的配置文件 config/default-config.xml

1.5. jmx服务相关信息

-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=49288 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false

1.6. IGNITE_HOME

ignite安装路径

2. 从以上这些信息看,ignite预定义了一些东西,如要要调整如何调整?

2.1. 每次启动后查看进程信息,每次都会有不同的jmx端口,为什么每次有不同的端口?如何使用固定的jmx端口?

bin/ignite.sh中有如下代码

  1. if [ "${NOJMX}" == "0" ] ; then
  2. findAvailableJmxPort
  3. fi

通过执行findAvailableJmxPort方法去查找jmx端口,该方法在bin/include/functions.sh定义好了,

  1. findAvailableJmxPort() {
  2. JMX_PORT=`"$JAVA" -cp "${IGNITE_LIBS}" org.apache.ignite.internal.util.portscanner.GridJmxPortFinder`
  3. #
  4. # This variable defines necessary parameters for JMX
  5. # monitoring and management.
  6. #
  7. # This enables remote unsecure access to JConsole or VisualVM.
  8. #
  9. # ADD YOUR ADDITIONAL PARAMETERS/OPTIONS HERE
  10. #
  11. if [ -n "$JMX_PORT" ]; then
  12. JMX_MON="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=${JMX_PORT} \
  13. -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"
  14. else
  15. # If JMX port wasn't found do not initialize JMX.
  16. echo "$0, WARN: Failed to resolve JMX host (JMX will be disabled): $HOSTNAME"
  17. JMX_MON=""
  18. fi
  19. }

代码中已经写明是通过执行org.apache.ignite.internal.util.portscanner.GridJmxPortFinder.java类的main方法来查找端口,我们通过分析GridJmxPortFinder.java的代码发现,是通过读取系统变量java.io.tmpdir目录(一般是/tmp)下的ignite.lastport.tmp文件来读取上次的jmx端口的,读取后加一就是这次的jmx端口(保证该端口没有被占用,占用就再加一,一直找到可用的端口),如果端口加一后大于65535就使用49112.如果jmx端口保存文件不存在就用49112(保证该端口没有被占用,占用就再加一,一直找到可用的端口)。找到可用的端口后写入系统变量java.io.tmpdir目录下的ignite.lastport.tmp文件中。

代码分析完了,如果我们想用一个固定的端口(一般公司为了方便和约定俗成都是使用固定的端口),那我们只要调整下bin/include/funtions.sh中关于JMX_PORT的地方,例如JMX_PORT=19988,而不再使用org.apache.ignite.internal.util.portscanner.GridJmxPortFinder.java来定义jmx端口。

还有一个问题,当服务有多张网卡,绑定了多ip后,通过jmx查看ignite的时候可能会无法连接上,这个时候只要加上一个jvm参数,-Djava.rmi.server.hostname=xxx,xxx为ip地址,该地址指明了需要连接本机的jmx服务,需要通过这个xxxip地址,我们可以通过写死一个ip或者使用其他方式获取一个ip,比如说通过java代码获取一个ip,可参考GridJmxPortFinder.java是如何定义jmx端口,照葫芦画瓢取出一个ip来。我们可以直接修改bin/include/functions.sh的findAvailableJmxPort(),在JMX_MON后面添加-Djava.rmi.server.hostname=你定义的ip

2.2.

3.执行具体的启动代码IgnitionEx

  1. private void start0(GridStartContext startCtx) throws IgniteCheckedException {
  2. System.out.println("执行启动代码");
  3. IgniteConfiguration cfg = startCtx.config() != null ? startCtx.config() : new IgniteConfiguration();
  4. IgniteConfiguration myCfg = initializeConfiguration(cfg);
  5. // Set configuration URL, if any, into system property.
  6. if (startCtx.configUrl() != null)
  7. System.setProperty(IGNITE_CONFIG_URL, startCtx.configUrl().toString());
  8. execSvc = new IgniteThreadPoolExecutor(
  9. "pub",
  10. cfg.getGridName(),
  11. cfg.getPublicThreadPoolSize(),
  12. cfg.getPublicThreadPoolSize(),
  13. DFLT_PUBLIC_KEEP_ALIVE_TIME,
  14. new LinkedBlockingQueue<Runnable>(DFLT_PUBLIC_THREADPOOL_QUEUE_CAP));
  15. if (!myCfg.isClientMode())
  16. // Pre-start all threads as they are guaranteed to be needed.
  17. ((ThreadPoolExecutor)execSvc).prestartAllCoreThreads();
  18. // Note that since we use 'LinkedBlockingQueue', number of
  19. // maximum threads has no effect.
  20. sysExecSvc = new IgniteThreadPoolExecutor(
  21. "sys",
  22. cfg.getGridName(),
  23. cfg.getSystemThreadPoolSize(),
  24. cfg.getSystemThreadPoolSize(),
  25. DFLT_SYSTEM_KEEP_ALIVE_TIME,
  26. new LinkedBlockingQueue<Runnable>(DFLT_SYSTEM_THREADPOOL_QUEUE_CAP));
  27. // Pre-start all threads as they are guaranteed to be needed.
  28. ((ThreadPoolExecutor)sysExecSvc).prestartAllCoreThreads();
  29. // Note that since we use 'LinkedBlockingQueue', number of
  30. // maximum threads has no effect.
  31. // Note, that we do not pre-start threads here as management pool may
  32. // not be needed.
  33. mgmtExecSvc = new IgniteThreadPoolExecutor(
  34. "mgmt",
  35. cfg.getGridName(),
  36. cfg.getManagementThreadPoolSize(),
  37. cfg.getManagementThreadPoolSize(),
  38. 0,
  39. new LinkedBlockingQueue<Runnable>());
  40. // Note that since we use 'LinkedBlockingQueue', number of
  41. // maximum threads has no effect.
  42. // Note, that we do not pre-start threads here as class loading pool may
  43. // not be needed.
  44. p2pExecSvc = new IgniteThreadPoolExecutor(
  45. "p2p",
  46. cfg.getGridName(),
  47. cfg.getPeerClassLoadingThreadPoolSize(),
  48. cfg.getPeerClassLoadingThreadPoolSize(),
  49. 0,
  50. new LinkedBlockingQueue<Runnable>());
  51. // Note that we do not pre-start threads here as this pool may not be needed.
  52. callbackExecSvc = new IgniteStripedThreadPoolExecutor(
  53. cfg.getAsyncCallbackPoolSize(),
  54. cfg.getGridName(),
  55. "callback");
  56. utilityCacheExecSvc = new IgniteThreadPoolExecutor(
  57. "utility",
  58. cfg.getGridName(),
  59. myCfg.getUtilityCacheThreadPoolSize(),
  60. myCfg.getUtilityCacheThreadPoolSize(),
  61. myCfg.getUtilityCacheKeepAliveTime(),
  62. new LinkedBlockingQueue<Runnable>(DFLT_SYSTEM_THREADPOOL_QUEUE_CAP));
  63. marshCacheExecSvc = new IgniteThreadPoolExecutor(
  64. "marshaller-cache",
  65. cfg.getGridName(),
  66. myCfg.getMarshallerCacheThreadPoolSize(),
  67. myCfg.getMarshallerCacheThreadPoolSize(),
  68. myCfg.getMarshallerCacheKeepAliveTime(),
  69. new LinkedBlockingQueue<Runnable>(DFLT_SYSTEM_THREADPOOL_QUEUE_CAP));
  70. boolean started = false;
  71. try {
  72. IgniteKernal grid0 = new IgniteKernal(startCtx.springContext());
  73. // Init here to make grid available to lifecycle listeners.
  74. grid = grid0;
  75. grid0.start(myCfg, utilityCacheExecSvc, marshCacheExecSvc, execSvc, sysExecSvc, p2pExecSvc, mgmtExecSvc,
  76. callbackExecSvc,
  77. new GridAbsClosure() {
  78. public void apply() {
  79. startLatch.countDown();
  80. }
  81. });
  82. state = STARTED;
  83. if (log.isDebugEnabled())
  84. log.debug("Grid factory started ok: " + name);
  85. started = true;
  86. }
  87. catch (IgniteCheckedException e) {
  88. throw e;
  89. }
  90. // Catch Throwable to protect against any possible failure.
  91. catch (Throwable e) {
  92. if (e instanceof Error)
  93. throw e;
  94. throw new IgniteCheckedException("Unexpected exception when starting grid.", e);
  95. }
  96. finally {
  97. if (!started)
  98. // Grid was not started.
  99. grid = null;
  100. }
  101. // Do NOT set it up only if IGNITE_NO_SHUTDOWN_HOOK=TRUE is provided.
  102. if (!IgniteSystemProperties.getBoolean(IGNITE_NO_SHUTDOWN_HOOK, false)) {
  103. try {
  104. Runtime.getRuntime().addShutdownHook(shutdownHook = new Thread() {
  105. public void run() {
  106. if (log.isInfoEnabled())
  107. log.info("Invoking shutdown hook...");
  108. IgniteNamedInstance.this.stop(true);
  109. }
  110. });
  111. if (log.isDebugEnabled())
  112. log.debug("Shutdown hook is installed.");
  113. }
  114. catch (IllegalStateException e) {
  115. stop(true);
  116. throw new IgniteCheckedException("Failed to install shutdown hook.", e);
  117. }
  118. }
  119. else {
  120. if (log.isDebugEnabled())
  121. log.debug("Shutdown hook has not been installed because environment " +
  122. "or system property " + IGNITE_NO_SHUTDOWN_HOOK + " is set.");
  123. }
  124. }

[2017-03-24]发现ignite启动类CommandLineStartup中的一个小bug,

  1. public static void main(String[] args) {
  2. if (!QUITE) {
  3. X.println("Ignite Command Line Startup, ver. " + ACK_VER_STR);
  4. X.println(COPYRIGHT);
  5. X.println();
  6. }
  7. if (args.length > 1)
  8. exit("Too many arguments.", true, -1);
  9. if (args.length > 0 && isHelp(args[0]))
  10. exit(null, true, 0);
  11. if (args.length > 0 && args[0].isEmpty())
  12. exit("Empty argument.", true, 1);
  13. if (args.length > 0 && args[0].charAt(0) == '-')
  14. exit("Invalid arguments: " + args[0], true, -1);
  15. String cfg = null;
  16. if (args.length > 0)
  17. cfg = args[0];
  18. else {
  19. try {
  20. cfg = askConfigFile();
  21. if (cfg == null)
  22. exit(null, false, 0);
  23. }
  24. catch (IOException e) {
  25. exit("Failed to run interactive mode: " + e.getMessage(), false, -1);
  26. }
  27. }
  28. // Name of the grid loaded from the command line (unique in JVM).
  29. final String gridName;
  30. try {
  31. gridName = G.start(cfg).name();
  32. }
  33. catch (Throwable e) {
  34. e.printStackTrace();
  35. String note = "";
  36. if (X.hasCause(e, ClassNotFoundException.class))
  37. note = "\nNote! You may use 'USER_LIBS' environment variable to specify your classpath.";
  38. exit("Failed to start grid: " + e.getMessage() + note, false, -1);
  39. if (e instanceof Error)
  40. throw e;
  41. return;
  42. }
  43. // Exit latch for the grid loaded from the command line.
  44. final CountDownLatch latch = new CountDownLatch(1);
  45. G.addListener(new IgnitionListener() {
  46. @Override public void onStateChange(String name, IgniteState state) {
  47. // Skip all grids except loaded from the command line.
  48. if (!F.eq(gridName, name))
  49. return;
  50. if (state == STOPPED || state == STOPPED_ON_SEGMENTATION)
  51. latch.countDown();
  52. }
  53. });
  54. try {
  55. latch.await();
  56. }
  57. catch (InterruptedException e) {
  58. X.error("Start was interrupted (exiting): " + e.getMessage());
  59. }
  60. String code = System.getProperty(IGNITE_RESTART_CODE);
  61. if (code != null)
  62. try {
  63. System.exit(Integer.parseInt(code));
  64. }
  65. catch (NumberFormatException ignore) {
  66. System.exit(0);
  67. }
  68. else
  69. System.exit(0);
  70. }

main方法中是先启动ignite网格,后添加匿名状态监听器,顺序执行的代码,当ignite启动完毕后才添加状态监听器,是不会执行这个监听器中的代码的,可以调整下,

  1. public static void main(String[] args) {
  2. if (args.length > 1)
  3. exit("Too many arguments.", true, -1);
  4. if (args.length > 0 && isHelp(args[0]))
  5. exit(null, true, 0);
  6. if (args.length > 0 && args[0].isEmpty())
  7. exit("Empty argument.", true, 1);
  8. if (args.length > 0 && args[0].charAt(0) == '-')
  9. exit("Invalid arguments: " + args[0], true, -1);
  10. String cfg = null;
  11. if (args.length > 0)
  12. cfg = args[0];
  13. else {
  14. try {
  15. cfg = askConfigFile();
  16. if (cfg == null)
  17. exit(null, false, 0);
  18. }
  19. catch (IOException e) {
  20. exit("Failed to run interactive mode: " + e.getMessage(), false, -1);
  21. }
  22. }
  23. // Name of the grid loaded from the command line (unique in JVM).
  24. final String gridName;
  25. Ignition.addListener(new IgnitionListener() {
  26. public void onStateChange(String name, IgniteState state) {
  27. System.out.println("状态改变" + name + "\t" + state.name());
  28. }
  29. });
  30. try {
  31. gridName = Ignition.start(cfg).name();
  32. }
  33. catch (Throwable e) {
  34. e.printStackTrace();
  35. String note = "";
  36. if (X.hasCause(e, ClassNotFoundException.class))
  37. note = "\nNote! You may use 'USER_LIBS' environment variable to specify your classpath.";
  38. exit("Failed to start grid: " + e.getMessage() + note, false, -1);
  39. if (e instanceof Error)
  40. throw e;
  41. return;
  42. }
  43. String code = System.getProperty(IGNITE_RESTART_CODE);
  44. if (code != null)
  45. try {
  46. System.exit(Integer.parseInt(code));
  47. }
  48. catch (NumberFormatException ignore) {
  49. System.exit(0);
  50. }
  51. else
  52. System.exit(0);
  53. }

最终这个状态监听器会在IgnitionEx.java中的notifyStateChange方法中执行,

  1. private static void notifyStateChange(@Nullable String gridName, IgniteState state) {
  2. if (gridName != null)
  3. gridStates.put(gridName, state);
  4. else
  5. dfltGridState = state;
  6. for (IgnitionListener lsnr : lsnrs)
  7. lsnr.onStateChange(gridName, state);
  8. }

x

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注