@aloxc
2017-12-05T06:35:03.000000Z
字数 11716
阅读 1216
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
设置ignite进程使用最大的堆内存1g
ignite服务成功启动后的一个文件,注意此文件不存在的,只是设置的一个系统属性,本属性的属性配置在IgniteSystemProperties.java中做了定义,并且在IgniteKernal.java做了引用,
@Override public boolean isRestartEnabled() {
return System.getProperty(IGNITE_SUCCESS_FILE) != null;
}
注意该方法上的注释
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中有引用
public static void restart(boolean cancel) {
String file = System.getProperty(IGNITE_SUCCESS_FILE);
if (file == null)
U.warn(null, "Cannot restart node when restart not enabled.");
else {
try {
new File(file).createNewFile();
}
catch (IOException e) {
U.error(null, "Failed to create restart marker file (restart aborted): " + e.getMessage());
return;
}
U.log(null, "Restarting node. Will exit (" + Ignition.RESTART_EXIT_CODE + ").");
// Set the exit code so that shell process can recognize it and loop
// the start up sequence again.
System.setProperty(IGNITE_RESTART_CODE, Integer.toString(Ignition.RESTART_EXIT_CODE));
stopAll(cancel);
// This basically leaves loaders hang - we accept it.
System.exit(Ignition.RESTART_EXIT_CODE);
}
}
ignite服务器的启动类,其实启动ignite服务就是执行该类中的main方法,
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=49288 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
ignite安装路径
bin/ignite.sh中有如下代码
if [ "${NOJMX}" == "0" ] ; then
findAvailableJmxPort
fi
通过执行findAvailableJmxPort方法去查找jmx端口,该方法在bin/include/functions.sh定义好了,
findAvailableJmxPort() {
JMX_PORT=`"$JAVA" -cp "${IGNITE_LIBS}" org.apache.ignite.internal.util.portscanner.GridJmxPortFinder`
#
# This variable defines necessary parameters for JMX
# monitoring and management.
#
# This enables remote unsecure access to JConsole or VisualVM.
#
# ADD YOUR ADDITIONAL PARAMETERS/OPTIONS HERE
#
if [ -n "$JMX_PORT" ]; then
JMX_MON="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=${JMX_PORT} \
-Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"
else
# If JMX port wasn't found do not initialize JMX.
echo "$0, WARN: Failed to resolve JMX host (JMX will be disabled): $HOSTNAME"
JMX_MON=""
fi
}
代码中已经写明是通过执行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
private void start0(GridStartContext startCtx) throws IgniteCheckedException {
System.out.println("执行启动代码");
IgniteConfiguration cfg = startCtx.config() != null ? startCtx.config() : new IgniteConfiguration();
IgniteConfiguration myCfg = initializeConfiguration(cfg);
// Set configuration URL, if any, into system property.
if (startCtx.configUrl() != null)
System.setProperty(IGNITE_CONFIG_URL, startCtx.configUrl().toString());
execSvc = new IgniteThreadPoolExecutor(
"pub",
cfg.getGridName(),
cfg.getPublicThreadPoolSize(),
cfg.getPublicThreadPoolSize(),
DFLT_PUBLIC_KEEP_ALIVE_TIME,
new LinkedBlockingQueue<Runnable>(DFLT_PUBLIC_THREADPOOL_QUEUE_CAP));
if (!myCfg.isClientMode())
// Pre-start all threads as they are guaranteed to be needed.
((ThreadPoolExecutor)execSvc).prestartAllCoreThreads();
// Note that since we use 'LinkedBlockingQueue', number of
// maximum threads has no effect.
sysExecSvc = new IgniteThreadPoolExecutor(
"sys",
cfg.getGridName(),
cfg.getSystemThreadPoolSize(),
cfg.getSystemThreadPoolSize(),
DFLT_SYSTEM_KEEP_ALIVE_TIME,
new LinkedBlockingQueue<Runnable>(DFLT_SYSTEM_THREADPOOL_QUEUE_CAP));
// Pre-start all threads as they are guaranteed to be needed.
((ThreadPoolExecutor)sysExecSvc).prestartAllCoreThreads();
// Note that since we use 'LinkedBlockingQueue', number of
// maximum threads has no effect.
// Note, that we do not pre-start threads here as management pool may
// not be needed.
mgmtExecSvc = new IgniteThreadPoolExecutor(
"mgmt",
cfg.getGridName(),
cfg.getManagementThreadPoolSize(),
cfg.getManagementThreadPoolSize(),
0,
new LinkedBlockingQueue<Runnable>());
// Note that since we use 'LinkedBlockingQueue', number of
// maximum threads has no effect.
// Note, that we do not pre-start threads here as class loading pool may
// not be needed.
p2pExecSvc = new IgniteThreadPoolExecutor(
"p2p",
cfg.getGridName(),
cfg.getPeerClassLoadingThreadPoolSize(),
cfg.getPeerClassLoadingThreadPoolSize(),
0,
new LinkedBlockingQueue<Runnable>());
// Note that we do not pre-start threads here as this pool may not be needed.
callbackExecSvc = new IgniteStripedThreadPoolExecutor(
cfg.getAsyncCallbackPoolSize(),
cfg.getGridName(),
"callback");
utilityCacheExecSvc = new IgniteThreadPoolExecutor(
"utility",
cfg.getGridName(),
myCfg.getUtilityCacheThreadPoolSize(),
myCfg.getUtilityCacheThreadPoolSize(),
myCfg.getUtilityCacheKeepAliveTime(),
new LinkedBlockingQueue<Runnable>(DFLT_SYSTEM_THREADPOOL_QUEUE_CAP));
marshCacheExecSvc = new IgniteThreadPoolExecutor(
"marshaller-cache",
cfg.getGridName(),
myCfg.getMarshallerCacheThreadPoolSize(),
myCfg.getMarshallerCacheThreadPoolSize(),
myCfg.getMarshallerCacheKeepAliveTime(),
new LinkedBlockingQueue<Runnable>(DFLT_SYSTEM_THREADPOOL_QUEUE_CAP));
boolean started = false;
try {
IgniteKernal grid0 = new IgniteKernal(startCtx.springContext());
// Init here to make grid available to lifecycle listeners.
grid = grid0;
grid0.start(myCfg, utilityCacheExecSvc, marshCacheExecSvc, execSvc, sysExecSvc, p2pExecSvc, mgmtExecSvc,
callbackExecSvc,
new GridAbsClosure() {
public void apply() {
startLatch.countDown();
}
});
state = STARTED;
if (log.isDebugEnabled())
log.debug("Grid factory started ok: " + name);
started = true;
}
catch (IgniteCheckedException e) {
throw e;
}
// Catch Throwable to protect against any possible failure.
catch (Throwable e) {
if (e instanceof Error)
throw e;
throw new IgniteCheckedException("Unexpected exception when starting grid.", e);
}
finally {
if (!started)
// Grid was not started.
grid = null;
}
// Do NOT set it up only if IGNITE_NO_SHUTDOWN_HOOK=TRUE is provided.
if (!IgniteSystemProperties.getBoolean(IGNITE_NO_SHUTDOWN_HOOK, false)) {
try {
Runtime.getRuntime().addShutdownHook(shutdownHook = new Thread() {
public void run() {
if (log.isInfoEnabled())
log.info("Invoking shutdown hook...");
IgniteNamedInstance.this.stop(true);
}
});
if (log.isDebugEnabled())
log.debug("Shutdown hook is installed.");
}
catch (IllegalStateException e) {
stop(true);
throw new IgniteCheckedException("Failed to install shutdown hook.", e);
}
}
else {
if (log.isDebugEnabled())
log.debug("Shutdown hook has not been installed because environment " +
"or system property " + IGNITE_NO_SHUTDOWN_HOOK + " is set.");
}
}
[2017-03-24]发现ignite启动类CommandLineStartup中的一个小bug,
public static void main(String[] args) {
if (!QUITE) {
X.println("Ignite Command Line Startup, ver. " + ACK_VER_STR);
X.println(COPYRIGHT);
X.println();
}
if (args.length > 1)
exit("Too many arguments.", true, -1);
if (args.length > 0 && isHelp(args[0]))
exit(null, true, 0);
if (args.length > 0 && args[0].isEmpty())
exit("Empty argument.", true, 1);
if (args.length > 0 && args[0].charAt(0) == '-')
exit("Invalid arguments: " + args[0], true, -1);
String cfg = null;
if (args.length > 0)
cfg = args[0];
else {
try {
cfg = askConfigFile();
if (cfg == null)
exit(null, false, 0);
}
catch (IOException e) {
exit("Failed to run interactive mode: " + e.getMessage(), false, -1);
}
}
// Name of the grid loaded from the command line (unique in JVM).
final String gridName;
try {
gridName = G.start(cfg).name();
}
catch (Throwable e) {
e.printStackTrace();
String note = "";
if (X.hasCause(e, ClassNotFoundException.class))
note = "\nNote! You may use 'USER_LIBS' environment variable to specify your classpath.";
exit("Failed to start grid: " + e.getMessage() + note, false, -1);
if (e instanceof Error)
throw e;
return;
}
// Exit latch for the grid loaded from the command line.
final CountDownLatch latch = new CountDownLatch(1);
G.addListener(new IgnitionListener() {
@Override public void onStateChange(String name, IgniteState state) {
// Skip all grids except loaded from the command line.
if (!F.eq(gridName, name))
return;
if (state == STOPPED || state == STOPPED_ON_SEGMENTATION)
latch.countDown();
}
});
try {
latch.await();
}
catch (InterruptedException e) {
X.error("Start was interrupted (exiting): " + e.getMessage());
}
String code = System.getProperty(IGNITE_RESTART_CODE);
if (code != null)
try {
System.exit(Integer.parseInt(code));
}
catch (NumberFormatException ignore) {
System.exit(0);
}
else
System.exit(0);
}
main方法中是先启动ignite网格,后添加匿名状态监听器,顺序执行的代码,当ignite启动完毕后才添加状态监听器,是不会执行这个监听器中的代码的,可以调整下,
public static void main(String[] args) {
if (args.length > 1)
exit("Too many arguments.", true, -1);
if (args.length > 0 && isHelp(args[0]))
exit(null, true, 0);
if (args.length > 0 && args[0].isEmpty())
exit("Empty argument.", true, 1);
if (args.length > 0 && args[0].charAt(0) == '-')
exit("Invalid arguments: " + args[0], true, -1);
String cfg = null;
if (args.length > 0)
cfg = args[0];
else {
try {
cfg = askConfigFile();
if (cfg == null)
exit(null, false, 0);
}
catch (IOException e) {
exit("Failed to run interactive mode: " + e.getMessage(), false, -1);
}
}
// Name of the grid loaded from the command line (unique in JVM).
final String gridName;
Ignition.addListener(new IgnitionListener() {
public void onStateChange(String name, IgniteState state) {
System.out.println("状态改变" + name + "\t" + state.name());
}
});
try {
gridName = Ignition.start(cfg).name();
}
catch (Throwable e) {
e.printStackTrace();
String note = "";
if (X.hasCause(e, ClassNotFoundException.class))
note = "\nNote! You may use 'USER_LIBS' environment variable to specify your classpath.";
exit("Failed to start grid: " + e.getMessage() + note, false, -1);
if (e instanceof Error)
throw e;
return;
}
String code = System.getProperty(IGNITE_RESTART_CODE);
if (code != null)
try {
System.exit(Integer.parseInt(code));
}
catch (NumberFormatException ignore) {
System.exit(0);
}
else
System.exit(0);
}
最终这个状态监听器会在IgnitionEx.java中的notifyStateChange方法中执行,
private static void notifyStateChange(@Nullable String gridName, IgniteState state) {
if (gridName != null)
gridStates.put(gridName, state);
else
dfltGridState = state;
for (IgnitionListener lsnr : lsnrs)
lsnr.onStateChange(gridName, state);
}