change judge dispather

This commit is contained in:
Himit_ZH 2021-12-22 13:12:42 +08:00
parent 6844f5e712
commit cd90da2b5a
8 changed files with 115 additions and 49 deletions

View File

@ -32,7 +32,7 @@
**注意:**
**1. 正式部署请自行修改配置,不要使用默认配置例如mysql或redis的密码**
**1. 正式部署请自行修改配置,不要使用默认配置的密码例如mysql、redis、nacos的密码**
**2. 如果已经为了测试而使用默认配置启动来部署,建议删掉当前文件夹,重新执行以下部署流程,修改默认配置**

View File

@ -2,6 +2,8 @@
> 前提已经在上一步准备好docker与docker-compose
**注意如果正式部署运用HOJ请修改默认配置的密码例如Redis、MySQL、Nacos的密码**
## 一、单机部署
1. 选择好需要安装的位置,运行下面命令
@ -106,7 +108,7 @@ vim docker-compose.yml
如果不改动,则以默认参数启动
如果不改动,则以默认参数启动**测试可以不改,但正式部署请修改默认配置的密码!**
```shell
docker-compose up -d
@ -125,9 +127,9 @@ docker ps -a
> 以下默认参数说明
- 默认超级管理员账号与密码root / hoj123456
- 默认redis密码hoj123456
- 默认mysql账号与密码root / hoj123456
- 默认nacos管理员账号与密码root / hoj123456
- 默认redis密码hoj123456**正式部署请修改**
- 默认mysql账号与密码root / hoj123456**正式部署请修改**
- 默认nacos管理员账号与密码root / hoj123456**正式部署请修改**
- 默认不开启https开启需修改文件同时提供证书文件
- 判题并发数默认cpu核心数+1
- 默认开启vj判题需要手动修改添加账号与密码如果不添加不能vj判题

View File

@ -0,0 +1,23 @@
package top.hcode.hoj.judge;
/**
* @Author: Himit_ZH
* @Date: 2021/12/22 12:40
* @Description:
*/
public abstract class AbstractReceiver {
public void handleWaitingTask(String... queues) {
for (String queue : queues) {
String taskJsonStr = getTaskByRedis(queue);
if (taskJsonStr != null) {
handleJudgeMsg(taskJsonStr);
}
}
}
public abstract String getTaskByRedis(String queue);
public abstract void handleJudgeMsg(String taskJsonStr);
}

View File

@ -35,7 +35,12 @@ public class RemoteJudgeDispatcher {
task.set("tryAgainNum", tryAgainNum);
task.set("isHasSubmitIdRemoteReJudge", isHasSubmitIdRemoteReJudge);
try {
boolean isOk = redisUtils.llPush(Constants.Judge.STATUS_REMOTE_JUDGE_WAITING_HANDLE.getName(), JSONUtil.toJsonStr(task));
boolean isOk;
if (isContest){
isOk = redisUtils.llPush(Constants.Queue.CONTEST_REMOTE_JUDGE_WAITING_HANDLE.getName(), JSONUtil.toJsonStr(task));
}else{
isOk = redisUtils.llPush(Constants.Queue.GENERAL_REMOTE_JUDGE_WAITING_HANDLE.getName(), JSONUtil.toJsonStr(task));
}
if (!isOk) {
judgeService.updateById(new Judge()
.setSubmitId(judge.getSubmitId())

View File

@ -8,6 +8,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import top.hcode.hoj.judge.AbstractReceiver;
import top.hcode.hoj.judge.ChooseUtils;
import top.hcode.hoj.judge.Dispatcher;
import top.hcode.hoj.pojo.entity.judge.Judge;
@ -25,7 +26,7 @@ import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
@Component
public class RemoteJudgeReceiver {
public class RemoteJudgeReceiver extends AbstractReceiver {
@Autowired
private JudgeServiceImpl judgeService;
@ -48,37 +49,43 @@ public class RemoteJudgeReceiver {
@Async("judgeTaskAsyncPool")
public void processWaitingTask() {
// 如果队列中还有任务则继续处理
if (redisUtils.lGetListSize(Constants.Judge.STATUS_REMOTE_JUDGE_WAITING_HANDLE.getName()) > 0) {
String taskJsonStr = (String) redisUtils.lrPop(Constants.Judge.STATUS_REMOTE_JUDGE_WAITING_HANDLE.getName());
// 再次检查
if (taskJsonStr != null) {
// 优先处理比赛的提交
// 其次处理普通提交的提交
handleWaitingTask(Constants.Queue.CONTEST_REMOTE_JUDGE_WAITING_HANDLE.getName(),
Constants.Queue.GENERAL_REMOTE_JUDGE_WAITING_HANDLE.getName());
}
JSONObject task = JSONUtil.parseObj(taskJsonStr);
Judge judge = task.get("judge", Judge.class);
String token = task.getStr("token");
String remoteJudgeProblem = task.getStr("remoteJudgeProblem");
Boolean isContest = task.getBool("isContest");
Integer tryAgainNum = task.getInt("tryAgainNum");
Boolean isHasSubmitIdRemoteReJudge = task.getBool("isHasSubmitIdRemoteReJudge");
String remoteOJName = remoteJudgeProblem.split("-")[0].toUpperCase();
handleJudgeMsg(judge,
token,
remoteJudgeProblem,
isContest,
tryAgainNum,
isHasSubmitIdRemoteReJudge,
remoteOJName);
}
@Override
public String getTaskByRedis(String queue) {
if (redisUtils.lGetListSize(queue) > 0) {
return (String) redisUtils.lrPop(queue);
} else {
return null;
}
}
public void handleJudgeMsg(Judge judge, String token, String remoteJudgeProblem, Boolean isContest,
Integer tryAgainNum,
Boolean isHasSubmitIdRemoteReJudge, String remoteOJName) {
@Override
public void handleJudgeMsg(String taskJsonStr) {
JSONObject task = JSONUtil.parseObj(taskJsonStr);
Judge judge = task.get("judge", Judge.class);
String token = task.getStr("token");
String remoteJudgeProblem = task.getStr("remoteJudgeProblem");
Integer tryAgainNum = task.getInt("tryAgainNum");
Boolean isHasSubmitIdRemoteReJudge = task.getBool("isHasSubmitIdRemoteReJudge");
String remoteOJName = remoteJudgeProblem.split("-")[0].toUpperCase();
dispatchRemoteJudge(judge,
token,
remoteJudgeProblem,
tryAgainNum,
isHasSubmitIdRemoteReJudge,
remoteOJName);
}
private void dispatchRemoteJudge(Judge judge, String token, String remoteJudgeProblem,
Integer tryAgainNum,
Boolean isHasSubmitIdRemoteReJudge, String remoteOJName) {
ToJudge toJudge = new ToJudge();
toJudge.setJudge(judge)

View File

@ -14,7 +14,7 @@ import top.hcode.hoj.utils.RedisUtils;
/**
* @Author: Himit_ZH
* @Date: 2021/2/5 16:44
* @Description: 判题信息的发布者通过主题发布到特定频道内
* @Description:
*/
@Component
@Slf4j(topic = "hoj")
@ -36,7 +36,12 @@ public class JudgeDispatcher {
task.set("isContest", isContest);
task.set("tryAgainNum", tryAgainNum);
try {
boolean isOk = redisUtils.llPush(Constants.Judge.STATUS_JUDGE_WAITING.getName(), JSONUtil.toJsonStr(task));
boolean isOk;
if (isContest){
isOk = redisUtils.llPush(Constants.Queue.CONTEST_JUDGE_WAITING.getName(), JSONUtil.toJsonStr(task));
}else{
isOk = redisUtils.llPush(Constants.Queue.GENERAL_JUDGE_WAITING.getName(), JSONUtil.toJsonStr(task));
}
if (!isOk) {
judgeService.updateById(new Judge()
.setSubmitId(judge.getSubmitId())

View File

@ -6,6 +6,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import top.hcode.hoj.judge.AbstractReceiver;
import top.hcode.hoj.judge.Dispatcher;
import top.hcode.hoj.pojo.entity.judge.Judge;
import top.hcode.hoj.pojo.entity.judge.ToJudge;
@ -15,13 +16,11 @@ import top.hcode.hoj.utils.RedisUtils;
/**
* @Author: Himit_ZH
* @Date: 2021/2/5 16:43
* @Description: 1. 判题信息的接受者调用判题服务对提交代码进行判断
* 2. 若无空闲判题服务器会自动进入熔断机制重新将该判题信息发布到频道内
* 3. 再次接受到信息再次查询是否有空闲判题服务器若有则进行判题否则回到2
* @Description:
*/
@Component
@Slf4j(topic = "hoj")
public class JudgeReceiver {
public class JudgeReceiver extends AbstractReceiver {
@Autowired
private Dispatcher dispatcher;
@ -31,16 +30,23 @@ public class JudgeReceiver {
@Async("judgeTaskAsyncPool")
public void processWaitingTask() {
// 如果队列中还有任务则继续处理
if (redisUtils.lGetListSize(Constants.Judge.STATUS_JUDGE_WAITING.getName()) > 0) {
String taskJsonStr = (String) redisUtils.lrPop(Constants.Judge.STATUS_JUDGE_WAITING.getName());
// 再次检查
if (taskJsonStr != null) {
handleJudgeMsg(taskJsonStr);
}
// 优先处理比赛的提交
// 其次处理普通提交的提交
handleWaitingTask(Constants.Queue.CONTEST_JUDGE_WAITING.getName(),
Constants.Queue.GENERAL_JUDGE_WAITING.getName());
}
@Override
public String getTaskByRedis(String queue) {
if (redisUtils.lGetListSize(queue) > 0) {
return (String) redisUtils.lrPop(queue);
} else {
return null;
}
}
@Override
public void handleJudgeMsg(String taskJsonStr) {
JSONObject task = JSONUtil.parseObj(taskJsonStr);

View File

@ -29,8 +29,6 @@ public class Constants {
STATUS_SUBMITTING(9, "Submitting", null),
STATUS_SUBMITTED_FAILED(10, "Submitted Failed", null),
STATUS_NULL(15, "No Status", null),
STATUS_JUDGE_WAITING(-100, "Waiting Queue", null),
STATUS_REMOTE_JUDGE_WAITING_HANDLE(-200, "Remote Waiting Handle Queue", null),
JUDGE_SERVER_SUBMIT_PREFIX(-1002, "Judge SubmitId-ServerId:", null);
private Judge(Integer status, String name, String columnName) {
@ -56,6 +54,26 @@ public class Constants {
}
}
/**
* 等待判题的redis队列
* @Since 2021/12/22
*/
public enum Queue{
CONTEST_JUDGE_WAITING("Contest_Waiting_Handle_Queue"),
GENERAL_JUDGE_WAITING("General_Waiting_Handle_Queue"),
CONTEST_REMOTE_JUDGE_WAITING_HANDLE("Contest_Remote_Waiting_Handle_Queue"),
GENERAL_REMOTE_JUDGE_WAITING_HANDLE("General_Remote_Waiting_Handle_Queue");
private Queue(String name) {
this.name = name;
}
private final String name;
public String getName() {
return name;
}
}
public enum RemoteOJ {
HDU("HDU"),
CODEFORCES("CF"),