I. 개요
타이밍 작업은 무엇입니까
- 특정 기간, 일부 작업의 조작에 대응 작업 스케줄링 (개발) 타이밍. 타이밍 (2 점에서의 동작을위한 시간주기가 가정된다) 태스크 (주문형) 스케줄 (트리거)
- 케이스 : 타이밍 작업 예약의 경우는, 매일 아침 내가 활성 일 어제 사용자의 양을 알 필요가, UI 사용자는 우편으로 내 사서함으로 보내 매달 양을 사는 어제 일반 작업, 9시 매일 아침, 하루에 문의를 기록합니다.
- 타이밍 작업 시나리오 : 데이터 동기화, 거래 정보, 명확한 사용자 정보는 정기적으로 이벤트를 밀어 보고서 데이터를 전송
- 문제로 리드 : 분산의 분야에서 분산 작업 스케줄링 플랫폼 서버 클러스터는 다음, 어떻게 보장하기 위해 그 작업 멱등의 타이밍
타이밍 작업을 달성하기 위해 두 자바 방법
2.1 스레드
public class Demo01 {
static long count = 0;
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
count++;
System.out.println(count);
} catch (Exception e) {
// TODO: handle exception
}
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
}
2.2의 TimerTask
/**
* 使用TimerTask类实现定时任务
*/
public class Demo02 {
static long count = 0;
public static void main(String[] args) {
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
count++;
System.out.println(count);
}
};
Timer timer = new Timer();
// 天数
long delay = 0;
// 秒数
long period = 1000;
timer.scheduleAtFixedRate(timerTask, delay, period);
}
}
2.3 ScheduledExecutorService를
자바 사용에서 ScheduledExecutorService를
하고있는 java.util.concurrent의 JavaSE5는 도구 도입으로 복잡,이 예약 된 작업을 달성 할 수있는 이상적인 방법이 될 수 있습니다.
public class Demo003 {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
public void run() {
// task to run goes here
System.out.println("Hello !!");
}
};
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
service.scheduleAtFixedRate(runnable, 1, 1, TimeUnit.SECONDS);
}
}
2.4 석영
도입 받는다는 의존
<dependencies>
<!-- quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.1</version>
</dependency>
</dependencies>
작업 예약 클래스
public class MyJob implements Job {
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("quartz MyJob date:" + new Date().getTime());
}
}
시작 클래스
//1.创建Scheduler的工厂
SchedulerFactory sf = new StdSchedulerFactory();
//2.从工厂中获取调度器实例
Scheduler scheduler = sf.getScheduler();
//3.创建JobDetail
JobDetail jb = JobBuilder.newJob(MyJob.class)
.withDescription("this is a ram job") //job的描述
.withIdentity("ramJob", "ramGroup") //job 的name和group
.build();
//任务运行的时间,SimpleSchedle类型触发器有效
long time= System.currentTimeMillis() + 3*1000L; //3秒后启动任务
Date statTime = new Date(time);
//4.创建Trigger
//使用SimpleScheduleBuilder或者CronScheduleBuilder
Trigger t = TriggerBuilder.newTrigger()
.withDescription("")
.withIdentity("ramTrigger", "ramTriggerGroup")
//.withSchedule(SimpleScheduleBuilder.simpleSchedule())
.startAt(statTime) //默认当前时间启动
.withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?")) //两秒执行一次
.build();
//5.注册任务和定时器
scheduler.scheduleJob(jb, t);
//6.启动 调度器
scheduler.start();
석영 식
http://cron.qqe2.com/
셋째, 어떤 문제가 될 것입니다 일반 작업 상황을 분산?
분산 된 클러스터의 경우, 어떻게 예약 된 작업의 실행이 반복되지 않습니다 보장하기 위해
- 같은 JVM에 저장 정기적 인 작업 및 비즈니스 코드 (작은 프로젝트)
- 대형 인터넷 회사는 태스크 코드의 실행을 스케줄 및 서버 작업이 분리 된 코드는, 독립적 인 JVM 있습니다 실행합니다.
- 일반 작업은 고도의 동시성 서버로 간주 할 필요가 있는지? 간격 장면이 필요하지 않습니다 동시에 여러 작업을 수행 할 포인트, 높은 동시성 시나리오가 발생할 수 있습니다
- 높은 동시성의 경우 어떻게 다음, 일반 다운 타임 코드를 실행할 때 오류의 중간에 갑자기 (작은 마크를 만들기 위해 각 작업을) 심장 박동이, 보상 메커니즘을 자동으로 모니터링 다시 시작 일반 작업을 사용하여 (단일 노드)? 작업을 처리한다 오류 로깅의 사용은 보상하는 타이밍 에러 검사 작업 로그 레코드 정보를 이용하여 계속 스킵. 실행시 타이밍] 산부인과는 작업의 결과로하면 운영 및 유지 보수 인력에 송신 전자 메일 알림을 중단
![](https://img2018.cnblogs.com/blog/1710915/201909/1710915-20190918124535956-40632188.jpg)
전통적인 분산 태스크와 태스크 타이밍 간의 타이밍 차이
종래의 예약 된 작업 특성 : 단일 (NO 클러스터)
넷째, 정기적 인 작업 분산 솔루션
- 분산 잠금 단점을 구현 사육사를 사용 (임시 노드를 작성해야하고, 이벤트 알림 확장하는 것은 쉽지 않다)
- 단점의 출시가 작업 스위치가 켜져 설정, 다시 부팅해야 후 서버 중 하나가 개방 작업 대신에, true로 설정되어있을 것입니다, 스위치를 만들기 위해 구성 파일을 사용하여 false로 설정 다른 서버는,이 방법은 서버가 true로 설정되어있는 경우에 아래 작업이 비효율적이된다. (권장하지 않음)
- 유일한 제약 조건 데이터베이스, 낮은 효율의 단점은 (권장하지 않음)
- 분산 작업 스케줄링 플랫폼 XXLJOB를 사용 Elastric-작업, TBSchedule
다섯, XXLJOB 소개
5.1 분산 스케줄링 플랫폼은 우리가 그 일을 달성 할 수
- 지원 작업 클러스터 (보장 멱등 문제의 전제) 회전 메커니즘을 균형 작업 부하
- 그것은 반복적으로 다시 시작하거나 운영 및 유지 보수 담당자에게 전자 메일 알림을 보내도록 실패 할 경우 지원 작업 작업 실행 보상이 실패하면, 그것은 자동 메커니즘을 다시 시도합니다.
- 지원 작업 로깅
- 전통적인 시간 초과 작업 트리거 규칙의 규칙 타이밍 동적 구성은 죽은 동적 구성 작업 규칙을 작성됩니다
5.2 XXLJOB GitHub의
![XX-JOB](https://img2018.cnblogs.com/blog/1710915/201909/1710915-20190918124536070-1734703316.jpg)
5.3 원리
- XXL-작업 원칙 : 실행, 작업 관리자
- 일반 서비스 작업의 실제 구현을 주소 : 의미 액추에이터 표현
- 의미 작업 세관 : 타이밍 작업 구성 규칙, 라우팅 정책, 사용 권한 모드 등이있다.
단계
- ① 배포 : 등록 센터로 XXL - 직업 - 관리자
- ② 생성 액추에이터 (특정 주소를 스케줄링) 클러스터를 지원
- ③ 프로파일은 XXL-작업 레지스트리 주소를 입력해야
- ④ 각각의 특정 작업 실행 서버는 연결 포트 번호에게 그물코를 확립
- ⑤ 작업의 작업 클래스를 수행 할 필요, 작업 컨테이너에 IJobHandler 추상 클래스 등록을 통합
- 특정 작업의 작업을 준비하는 방법을 실행 ⑥
5.4 SpringBoot 통합 XXLJob
프로필 정보
application.properties
# web port
server.port=8081
# log config
logging.config=classpath:logback.xml
### xxl-job admin address list, such as "http://address" or "http://address01,http://address02"
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
### xxl-job executor address
xxl.job.executor.appname=text-job
xxl.job.executor.ip=
xxl.job.executor.port=9999
### xxl-job, access token
xxl.job.accessToken=
### xxl-job log path
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### xxl-job log retention days
xxl.job.executor.logretentiondays=-1
구성 XxlJobConfig
@Configuration
@ComponentScan(basePackages = "com.xxl.job.executor.service.jobhandler")
public class XxlJobConfig {
private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;
@Value("${xxl.job.executor.appname}")
private String appName;
@Value("${xxl.job.executor.ip}")
private String ip;
@Value("${xxl.job.executor.port}")
private int port;
@Value("${xxl.job.accessToken}")
private String accessToken;
@Value("${xxl.job.executor.logpath}")
private String logPath;
@Value("${xxl.job.executor.logretentiondays}")
private int logRetentionDays;
@Bean(initMethod = "start", destroyMethod = "destroy")
public XxlJobExecutor xxlJobExecutor() {
logger.info(">>>>>>>>>>> xxl-job config init.");
XxlJobExecutor xxlJobExecutor = new XxlJobExecutor();
xxlJobExecutor.setAdminAddresses(adminAddresses);
xxlJobExecutor.setAppName(appName);
xxlJobExecutor.setIp(ip);
xxlJobExecutor.setPort(port);
xxlJobExecutor.setAccessToken(accessToken);
xxlJobExecutor.setLogPath(logPath);
xxlJobExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobExecutor;
}
}
핸들러 인터페이스를 만들기
@JobHandler("demoJobHandler")
@Component
public class DemoHandler extends IJobHandler {
@Value("${server.port}")
private String serverPort;
@Override
public ReturnT<String> execute(String param) throws Exception {
System.out.println("######端口号:serverPort" + serverPort + "###定时Job开始执行啦!!!!######");
return SUCCESS;
}
}
5.5 파견 센터 클러스터
XX-작업 관리 플랫폼을 끊고 경우, 파견 센터는 또한 클러스터 파견 센터를 구축 할 필요가 있으므로, 클러스터의 배포를 지원, 작업을 수행 할 수 없습니다 이어질 예약 시스템 재해 복구 및 가용성이 향상됩니다. 때 파견 센터 클러스터 구축, 몇 가지 요구 사항 및 권장 사항 :
- DB 구성 일치;
- 로그인 계정 구성의 일관성;
- 일관성 그룹의 기계 시계 (단일 클러스터 방치);
- 권장 사항 : Nginx에 의해로드 밸런싱 클러스터 파견 센터, 도메인 이름의 할당을 수행하는 것이 좋습니다. 파견 센터 액세스, 콜백을 구성 액추에이터는 API 서비스 및 기타 작업은 도메인 이름에 의해 수행되는 호출.
![XXL-작업 클러스터 원칙](https://img2018.cnblogs.com/blog/1710915/201909/1710915-20190918124536012-1113553231.png)
Nginx의 구성 정보
upstream backServer{
server 127.0.0.1:8080 weight=1;
server 127.0.0.1:8081 weight=1;
}
server {
listen 80;
server_name 127.0.0.1 ;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://backServer;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}