Seata的服务端启动过程分析
程序员文章站
2022-05-07 18:46:13
...
下载Seata服务端源代码
这样用的是Seata的最新版本V1.0
解压源代码文件, 导入源代码到IDEA当中
Seata服务端源代码是一个标准的Maven工程,很容易很入到IDEA工具当中,最后源代码工程文件目录如下:
查看Seata的启动脚本
#!/bin/sh
# resolve links - $0 may be a softlink
PRG="$0"
while [ -h "$PRG" ]; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`/"$link"
fi
done
PRGDIR=`dirname "$PRG"`
BASEDIR=`cd "$PRGDIR/.." >/dev/null; pwd`
# Reset the REPO variable. If you need to influence this use the environment setup file.
REPO=
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
case "`uname`" in
CYGWIN*) cygwin=true ;;
Darwin*) darwin=true
if [ -z "$JAVA_VERSION" ] ; then
JAVA_VERSION="CurrentJDK"
else
echo "Using Java version: $JAVA_VERSION"
fi
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
JAVA_HOME=`/usr/libexec/java_home`
else
JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/${JAVA_VERSION}/Home
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] && CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# If a specific java binary isn't specified search for the standard 'java' binary
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD=`which java`
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." 1>&2
echo " We cannot execute $JAVACMD" 1>&2
exit 1
fi
if [ -z "$REPO" ]
then
REPO="$BASEDIR"/lib
fi
CLASSPATH="$BASEDIR"/conf:"$REPO"/*
ENDORSED_DIR=
if [ -n "$ENDORSED_DIR" ] ; then
CLASSPATH=$BASEDIR/$ENDORSED_DIR/*:$CLASSPATH
fi
if [ -n "$CLASSPATH_PREFIX" ] ; then
CLASSPATH=$CLASSPATH_PREFIX:$CLASSPATH
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$CLASSPATH" ] && CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$HOME" ] && HOME=`cygpath --path --windows "$HOME"`
[ -n "$BASEDIR" ] && BASEDIR=`cygpath --path --windows "$BASEDIR"`
[ -n "$REPO" ] && REPO=`cygpath --path --windows "$REPO"`
fi
exec "$JAVACMD" $JAVA_OPTS -server -Xmx2048m -Xms2048m -Xmn1024m -Xss512k -XX:SurvivorRatio=10 -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:MaxDirectMemorySize=1024m -XX:-OmitStackTraceInFastThrow -XX:-UseAdaptiveSizePolicy -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath="$BASEDIR"/logs/java_heapdump.hprof -XX:+DisableExplicitGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=75 -Xloggc:"$BASEDIR"/logs/seata_gc.log -verbose:gc -Dio.netty.leakDetectionLevel=advanced \
-classpath "$CLASSPATH" \
-Dapp.name="seata-server" \
-Dapp.pid="$$" \
-Dapp.repo="$REPO" \
-Dapp.home="$BASEDIR" \
-Dbasedir="$BASEDIR" \
io.seata.server.Server \
"aaa@qq.com"
启动脚本分析
从脚本当中可以看到启动的类入口为io.seata.server.Server,从源代码当中可以明显的看出Seata的底层通信框架使用的是Netty
Seata服务端启动类
/**
* The type Server.
* 服务器端启动
* @author slievrly
*/
public class Server {
private static final Logger LOGGER = LoggerFactory.getLogger(Server.class);
private static final int MIN_SERVER_POOL_SIZE = 100;
private static final int MAX_SERVER_POOL_SIZE = 500;
private static final int MAX_TASK_QUEUE_SIZE = 20000;
private static final int KEEP_ALIVE_TIME = 500;
private static final ThreadPoolExecutor WORKING_THREADS = new ThreadPoolExecutor(
MIN_SERVER_POOL_SIZE,
MAX_SERVER_POOL_SIZE,
KEEP_ALIVE_TIME,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(MAX_TASK_QUEUE_SIZE),//阻塞队列
new NamedThreadFactory("ServerHandlerThread", MAX_SERVER_POOL_SIZE),
new ThreadPoolExecutor.CallerRunsPolicy());
/**
* 整个seata服务的入口应用
*/
public static void main(String[] args) throws IOException {
//获取所有传的参数
ParameterParser parameterParser = new ParameterParser(args);
//初始化监听指标组件
MetricsManager.get().init();
System.setProperty(ConfigurationKeys.STORE_MODE, parameterParser.getStoreMode());
RpcServer rpcServer = new RpcServer(WORKING_THREADS);
//server port
rpcServer.setListenPort(parameterParser.getPort());
UUIDGenerator.init(parameterParser.getServerNode());
//log store mode : file, db
SessionHolder.init(parameterParser.getStoreMode());
DefaultCoordinator coordinator = new DefaultCoordinator(rpcServer);
coordinator.init();
rpcServer.setHandler(coordinator);
//注册关闭注销执行方法
ShutdownHook.getInstance().addDisposable(coordinator);
//127.0.0.1 and 0.0.0.0 are not valid here.
if (NetUtil.isValidIp(parameterParser.getHost(), false)) {
XID.setIpAddress(parameterParser.getHost());
} else {
XID.setIpAddress(NetUtil.getLocalIp());
}
XID.setPort(rpcServer.getListenPort());
try {
//服务端启动
rpcServer.init();
} catch (Throwable e) {
LOGGER.error("rpcServer init error:{}", e.getMessage(), e);
System.exit(-1);
}
System.exit(0);
}
}
RpcServer#init方法
/**
* Init.
* 服务端启动接口
*/
@Override
public void init() {
super.init();
setChannelHandlers(RpcServer.this);
DefaultServerMessageListenerImpl defaultServerMessageListenerImpl = new DefaultServerMessageListenerImpl(
transactionMessageHandler);
defaultServerMessageListenerImpl.init();
defaultServerMessageListenerImpl.setServerMessageSender(this);
//进行监听客户发布的消息
this.setServerMessageListener(defaultServerMessageListenerImpl);
//开启服务端
super.start();
}
就先分析到到这里吧
上一篇: exec和system函数