一:XXL-JOB任务执行器源码思路
1、首先第一件事不要虚就是干,DOWN下源码之后,发现任务执行器和我们写的项目没有什么太大的区别,也是基于SpringBoot,然后思考一下,万物都有生命周期,那任务执行器创建以及初始化是从哪里开始的呢?
把Module下的文件夹一个个打开,发现就那么几个类。所以XXLJOB的源码相对其他框架来说其实很简单的。
2、这不就发现任务执行器是在这里被创建的吗
3、点开XxlJobSpringExecutor看看
4、通过该类发现核心代码还是super.start()方法里面。继续点进去,发现任务执行的初始化就是在这里面。看作者描述的注释就知道。
初始化log目录 -> 保存任务调度中心的地址与Token -> 开启log定时清除的线程 ->
开启任务回调线程(该线程主要是任务执行器执行完后将结果回调给调度中心)->初始化任务执行器server端(任务执行器核心代码,基于Netty编写Server端,与调度中心进行通信)
5、initEmbedServer(address, ip, port, appname, accessToken);
主要是对参数进行校验,核心代码是 embedServer.start(address, port, appname, accessToken);
private void initEmbedServer(String address, String ip, int port, String appname, String accessToken) throws Exception {
// fill ip port
port = port>0?port: NetUtil.findAvailablePort(9999);
ip = (ip!=null&&ip.trim().length()>0)?ip: IpUtil.getIp();
// generate address
if (address==null || address.trim().length()==0) {
String ip_port_address = IpUtil.getIpPort(ip, port); // registry-address:default use address to registry , otherwise use ip:port if address is null
address = "http://{ip_port}/".replace("{ip_port}", ip_port_address);
}
// accessToken
if (accessToken==null || accessToken.trim().length()==0) {
logger.warn(">>>>>>>>>>> xxl-job accessToken is empty. To ensure system security, please set the accessToken.");
}
// start
embedServer = new EmbedServer();
embedServer.start(address, port, appname, accessToken);
}
6、下面是Netty,Server端的核心代码,都是一些Netty的Api,不要慌看一下Netty文档就知道,主要是将我们配置文件写的端口启动一个Netty进程,然后监听这个端口号,读取调度中心的调度数据,做相应的任务执行。
public void start(final String address, final int port, final String appname, final String accessToken) {
executorBiz = new ExecutorBizImpl();
thread = new Thread(new Runnable() {
@Override
public void run() {
// param
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
ThreadPoolExecutor bizThreadPool = new ThreadPoolExecutor(
0,
200,
60L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(2000),
new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "xxl-rpc, EmbedServer bizThreadPool-" + r.hashCode());
}
},
new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
throw new RuntimeException("xxl-job, EmbedServer bizThreadPool is EXHAUSTED!");
}
});
try {
// start server
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel channel) throws Exception {
channel.pipeline()
.addLast(new IdleStateHandler(0, 0, 30 * 3, TimeUnit.SECONDS)) // beat 3N, close if idle
.addLast(new HttpServerCodec())