电商项目part03 电商支撑服务梳理

分布式任务调度系统

1、contab指令快速实现简单的定时任务

在Linux机器上直接使用crontab -e指令,就可以编辑一个简单的调度任务,适用于请求量不是很大的情况

* * * * * echo "timer">/root/test.out

缺点:只能在本机上执行;只能做到分钟级别的
在这里插入图片描述
在配置每一个部分的表达式时,可以指定具体的数值,比如分钟位设置为0,表示每次第0分钟执行一
次。在这些基础数字之外,还允许几个特殊的字符:

  • 表示所有可能的值。
  • 表示指定范围。例如在day位配置 1-10,表示每个月的第1天到第10天
  • ,表示枚举。例如minute位配置 3,5 表示第3分钟和第5分钟执行。
  • / 表示指定增量。例如在minute位配置0/15表示从0分钟开始,每15分钟执行一次。3/20表示第三分钟开始,每20分钟执行一次。

另外还有几个用得比较少的特殊符号。例如对于day和week位置。为了避免可能的冲突,就可以将其中一个值设为?

xxljob快速实现轻量级分布式任务调度

实现定时任务的框架有很多,目前在国内用得比较多的是elasticjob和xxljob。这两个项目都有非常多的运用场景。其中elasticjob依赖zookeeper进行分布式任务协调,而xxljob则只需要通过数据库进行协调即可。

案例

package com.xxl.job.service.handler;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.IJobHandler;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpJobHandler extends IJobHandler {
    
    
	@Override
	public void execute() throws Exception {
    
    
		String target = XxlJobHelper.getJobParam();
		XxlJobHelper.log("received job target:"+target);
		boolean isPostMethod= false;
		// request
		HttpURLConnection connection = null;
		BufferedReader bufferedReader = null;
		try {
    
    
			// connection
			URL realUrl = new URL(target);
			connection = (HttpURLConnection) realUrl.openConnection();
			connection.setDoOutput(isPostMethod);
			connection.setDoInput(true);
			connection.setUseCaches(false);
			connection.setReadTimeout(5 * 1000);
			connection.setConnectTimeout(3 * 1000);
			connection.setRequestProperty("connection", "Keep-Alive");
			connection.setRequestProperty("Content-Type","application/json;charset=UTF-8");
			connection.setRequestProperty("Accept-Charset","application/json;charset=UTF-8");
			// do connection
			connection.connect();
			// valid StatusCode
			int statusCode = connection.getResponseCode();
			if (statusCode != 200) {
    
    
			throw new RuntimeException("Http Request StatusCode(" +
			statusCode + ") Invalid.");
			}
			// result
			bufferedReader = new BufferedReader(new
			InputStreamReader(connection.getInputStream(), "UTF-8"));
			StringBuilder result = new StringBuilder();
			String line;
			while ((line = bufferedReader.readLine()) != null) {
    
    
				result.append(line);
			}
			String responseMsg = result.toString();
			XxlJobHelper.log(responseMsg);
			return;
		} catch (Exception e) {
    
    
			XxlJobHelper.log(e);
			XxlJobHelper.handleFail();
			return;
		} finally {
    
    
			try {
    
    
				if (bufferedReader != null) {
    
    
					bufferedReader.close();
				}
				if (connection != null) {
    
    
					connection.disconnect();
				}
			} catch (Exception e2) {
    
    
				XxlJobHelper.log(e2);
			}
		}
	}
}

在这个实现中,访问的目标地址target,是作为任务参数传入的。因此,接下来只要在xxljob的任务配置界面将URL以参数形式配置即可。
在这里插入图片描述

定时任务的核心-时间轮算法

时间轮算法可以简单的看成由一个循环数组+双向链表数据结构实现。循环数组构成一个环形结构,指针每隔tickDuration时间就走一步。而数组中每个节点上挂载了一个双向链表结构的定时任务列表。
在这里插入图片描述
双向链表上的任务有个属性为remainingRounds,表示当前任务剩下的轮次是多少。每当指针走到该任务对应的数据节点上时,remainingRounds就减少1,直到remainingRounds为0时,就触发当前定时任务。从这个原理中可以看到,tickDuration越小,定时任务就越精确,但是响应的,系统的计算负担就越重

猜你喜欢

转载自blog.csdn.net/Forbidden_City/article/details/132379714