Commit c3508b3b by huangfusuper

解决分布式锁失效问题和重构邮箱发送

parent e009fec6
package com.byit.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class IndexController {
@RequestMapping("/")
public String index()
{
return "index";
}
}
...@@ -76,12 +76,14 @@ myth: ...@@ -76,12 +76,14 @@ myth:
# sentinel-addresses: # sentinel-addresses:
# - 127.0.0.1:3306 # - 127.0.0.1:3306
# - 127.7.7.7:6379 # - 127.7.7.7:6379
# timeout: 60000
######################哨兵模式##################### ######################哨兵模式#####################
######################单机环境##################### ######################单机环境#####################
redisson: redisson:
address: redis://10.0.120.208:6379 address: redis://10.0.120.208:6379
database: 3 database: 3
timeout: 60000
######################单机环境##################### ######################单机环境#####################
######################redis分布式锁##################### ######################redis分布式锁#####################
......
...@@ -79,12 +79,14 @@ myth: ...@@ -79,12 +79,14 @@ myth:
# sentinel-addresses: # sentinel-addresses:
# - 127.0.0.1:3306 # - 127.0.0.1:3306
# - 127.7.7.7:6379 # - 127.7.7.7:6379
# timeout: 60000
######################哨兵模式##################### ######################哨兵模式#####################
######################单机环境##################### ######################单机环境#####################
redisson: redisson:
address: redis://10.0.120.208:6379 address: redis://10.0.120.208:6379
database: 3 database: 3
timeout: 60000
######################单机环境##################### ######################单机环境#####################
######################redis分布式锁##################### ######################redis分布式锁#####################
......
...@@ -63,3 +63,37 @@ fdfs: ...@@ -63,3 +63,37 @@ fdfs:
- 10.0.120.216:22122 - 10.0.120.216:22122
- 10.0.120.217:22122 - 10.0.120.217:22122
- 10.0.120.218:22122 - 10.0.120.218:22122
myth:
plugin:
env: ${myth-rpc.registry.env}
biz: ${myth-rpc.registry.biz}
register:
url: ${myth-rpc.registry.address}
######################哨兵模式#####################
#redisson:
# master-name: myMaster
# sentinel-addresses:
# - 127.0.0.1:3306
# - 127.7.7.7:6379
# timeout: 60000
######################哨兵模式#####################
######################单机环境#####################
redisson:
address: redis://10.0.120.208:6379
database: 3
timeout: 60000
######################单机环境#####################
######################redis分布式锁#####################
lock:
type: redis
######################redis分布式锁#####################
######################DB行锁#####################
#lock:
# type: db
######################DB行锁#####################
\ No newline at end of file
...@@ -78,12 +78,14 @@ myth: ...@@ -78,12 +78,14 @@ myth:
# sentinel-addresses: # sentinel-addresses:
# - 127.0.0.1:3306 # - 127.0.0.1:3306
# - 127.7.7.7:6379 # - 127.7.7.7:6379
# timeout: 60000
######################哨兵模式##################### ######################哨兵模式#####################
######################单机环境##################### ######################单机环境#####################
redisson: redisson:
address: redis://10.0.120.208:6379 address: redis://10.0.120.208:6379
database: 3 database: 3
timeout: 60000
######################单机环境##################### ######################单机环境#####################
######################redis分布式锁##################### ######################redis分布式锁#####################
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>Title</title>
</head>
<body>
<h1>遇见事情不要慌qqqqssss</h1>
<script src="/js/jquery.min.js"/>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>工作流执行报告</title>
</head>
<body>
<table border='1' width='80%' align='center' cellspacing='0' cellpadding='6'>
<div style="margin-bottom: 20px">
<h1 style='text-align:center;color:red'>工作流执行报告</h1>
<br/>
<span style="margin-left: 10%;font-size: 16px;color: #646256" th:text="'工作流名称:'+${title}"></span>
<span style="margin-left: 10%;font-size: 16px;color: #646256" th:text="'总耗时:'+${flowConsumeDate}"></span>
<span style="float:right;margin-right: 11%;font-size: 16px;color: #646256" th:text="'环境:'+${env}"></span>
</div>
<thead align='center' style='background: blue;color: #fff'>
<th width = '10%'>节点名称</th>
<th width = '20%'>开始时间</th>
<th width = '20%'>结束时间</th>
<th width = '10%'>耗费时间</th>
<th width = '10%'>运行结果</th>
<th width = '30%'>日志远程路径</th>
</thead>
<tbody>
<tr th:each="email : ${data}">
<th th:text="${email.nodeName}"></th>
<th th:text="${email.startDate}"></th>
<th th:text="${email.endDate}"></th>
<th th:text="${email.consuming}"></th>
<th th:text="${email.runStatus}"></th>
<th>
<dev th:each="logPath : ${email.logPaths}">
<a th:href="@{${logPath}}" th:text="${logPath}"></a><br/>
</dev>
</th>
</tr>
</tbody>
</table>
</body>
</html>
\ No newline at end of file
...@@ -82,6 +82,11 @@ ...@@ -82,6 +82,11 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>myth-job</groupId> <groupId>myth-job</groupId>
<artifactId>plugin-spring-boot-starter</artifactId> <artifactId>plugin-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
......
...@@ -36,9 +36,10 @@ public class RedissonAutoConfiguration { ...@@ -36,9 +36,10 @@ public class RedissonAutoConfiguration {
*/ */
@Bean @Bean
@ConditionalOnProperty(name="redisson.master-name") @ConditionalOnProperty(name="redisson.master-name")
RedissonClient redissonSentinel() { public RedissonClient redissonSentinel() {
Config config = new Config(); Config config = new Config();
SentinelServersConfig serverConfig = config.useSentinelServers().addSentinelAddress(redssionProperties.getSentinelAddresses()) SentinelServersConfig serverConfig = config.useSentinelServers()
.addSentinelAddress(redssionProperties.getSentinelAddresses())
.setMasterName(redssionProperties.getMasterName()) .setMasterName(redssionProperties.getMasterName())
.setTimeout(redssionProperties.getTimeout()) .setTimeout(redssionProperties.getTimeout())
.setMasterConnectionPoolSize(redssionProperties.getMasterConnectionPoolSize()) .setMasterConnectionPoolSize(redssionProperties.getMasterConnectionPoolSize())
...@@ -57,7 +58,7 @@ public class RedissonAutoConfiguration { ...@@ -57,7 +58,7 @@ public class RedissonAutoConfiguration {
*/ */
@Bean @Bean
@ConditionalOnProperty(name="redisson.address") @ConditionalOnProperty(name="redisson.address")
RedissonClient redissonSingle() { public RedissonClient redissonSingle() {
Config config = new Config(); Config config = new Config();
SingleServerConfig serverConfig = config.useSingleServer() SingleServerConfig serverConfig = config.useSingleServer()
.setAddress(redssionProperties.getAddress()) .setAddress(redssionProperties.getAddress())
...@@ -78,7 +79,7 @@ public class RedissonAutoConfiguration { ...@@ -78,7 +79,7 @@ public class RedissonAutoConfiguration {
* @return * @return
*/ */
@Bean @Bean
DistributedLocker distributedLocker(RedissonClient redissonSingle) { public DistributedLocker distributedLocker(RedissonClient redissonSingle) {
RedissonDistributedLocker locker = new RedissonDistributedLocker(); RedissonDistributedLocker locker = new RedissonDistributedLocker();
locker.setRedissonClient(redissonSingle); locker.setRedissonClient(redissonSingle);
log.info("----------redis分布式锁{},被设置加载---------",locker); log.info("----------redis分布式锁{},被设置加载---------",locker);
......
package com.byit.dto;
import lombok.Builder;
import lombok.Data;
import java.util.List;
@Data
public class EmailMappingDto {
private String nodeName;
private String startDate;
private String endDate;
private String consuming;
private String runStatus;
private List<String> logPaths;
}
...@@ -13,4 +13,6 @@ public interface WorkspaceService { ...@@ -13,4 +13,6 @@ public interface WorkspaceService {
* @return 返回全部工作空间 * @return 返回全部工作空间
*/ */
List<Workspace> findAll(); List<Workspace> findAll();
Workspace findOneById(Integer id);
} }
...@@ -22,4 +22,9 @@ public class WorkspaceServiceImpl implements WorkspaceService { ...@@ -22,4 +22,9 @@ public class WorkspaceServiceImpl implements WorkspaceService {
public List<Workspace> findAll() { public List<Workspace> findAll() {
return workspaceMapper.findAll(); return workspaceMapper.findAll();
} }
@Override
public Workspace findOneById(Integer id) {
return workspaceMapper.getById(id);
}
} }
...@@ -2,12 +2,15 @@ package com.byit.service.mapservice.impl; ...@@ -2,12 +2,15 @@ package com.byit.service.mapservice.impl;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import com.byit.dto.EmailMappingDto;
import com.byit.model.EmailAlarm; import com.byit.model.EmailAlarm;
import com.byit.model.JobTaskRunLogWithBLOBs; import com.byit.model.JobTaskRunLogWithBLOBs;
import com.byit.model.RunRecording; import com.byit.model.RunRecording;
import com.byit.model.Workspace;
import com.byit.service.EmailAlarmService; import com.byit.service.EmailAlarmService;
import com.byit.service.JobTaskRunLogService; import com.byit.service.JobTaskRunLogService;
import com.byit.service.RunRecordingService; import com.byit.service.RunRecordingService;
import com.byit.service.WorkspaceService;
import com.byit.service.mapservice.RunRecordingAndEmailService; import com.byit.service.mapservice.RunRecordingAndEmailService;
import com.byit.util.TimeFormatUtil; import com.byit.util.TimeFormatUtil;
import com.github.tobato.fastdfs.conn.TrackerConnectionManager; import com.github.tobato.fastdfs.conn.TrackerConnectionManager;
...@@ -15,10 +18,10 @@ import lombok.extern.slf4j.Slf4j; ...@@ -15,10 +18,10 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import java.util.ArrayList; import java.util.*;
import java.util.Date;
import java.util.List;
/** /**
* @author huangfu * @author huangfu
...@@ -27,6 +30,12 @@ import java.util.List; ...@@ -27,6 +30,12 @@ import java.util.List;
@Slf4j @Slf4j
public class RunRecordingAndEmailServiceImpl implements RunRecordingAndEmailService { public class RunRecordingAndEmailServiceImpl implements RunRecordingAndEmailService {
public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String NODE_RUN_SUCCESS = "1";
public static final String NODE_RE_RUN_SUCCESS = "3";
public static final String NODE_RE_RUN_ERROR = "4";
public static final String NODE_RUN_KILL = "5";
public static final String NODE_UP_RUN_ERROR = "6";
private final TemplateEngine templateEngine;
/** /**
* 邮箱表操作 * 邮箱表操作
*/ */
...@@ -41,15 +50,18 @@ public class RunRecordingAndEmailServiceImpl implements RunRecordingAndEmailServ ...@@ -41,15 +50,18 @@ public class RunRecordingAndEmailServiceImpl implements RunRecordingAndEmailServ
private final RunRecordingService runRecordingService; private final RunRecordingService runRecordingService;
private final TrackerConnectionManager trackerConnectionManager; private final TrackerConnectionManager trackerConnectionManager;
private final WorkspaceService workspaceService;
@Value("${fdfs.http-port}") @Value("${fdfs.http-port}")
private String trackerIpsPort; private String trackerIpsPort;
public RunRecordingAndEmailServiceImpl(EmailAlarmService emailAlarmService, JobTaskRunLogService jobTaskRunLogService, public RunRecordingAndEmailServiceImpl(TemplateEngine templateEngine, EmailAlarmService emailAlarmService, JobTaskRunLogService jobTaskRunLogService,
RunRecordingService runRecordingService, TrackerConnectionManager trackerConnectionManager) { RunRecordingService runRecordingService, TrackerConnectionManager trackerConnectionManager, WorkspaceService workspaceService) {
this.templateEngine = templateEngine;
this.emailAlarmService = emailAlarmService; this.emailAlarmService = emailAlarmService;
this.jobTaskRunLogService = jobTaskRunLogService; this.jobTaskRunLogService = jobTaskRunLogService;
this.runRecordingService = runRecordingService; this.runRecordingService = runRecordingService;
this.trackerConnectionManager = trackerConnectionManager; this.trackerConnectionManager = trackerConnectionManager;
this.workspaceService = workspaceService;
} }
@Override @Override
...@@ -57,7 +69,17 @@ public class RunRecordingAndEmailServiceImpl implements RunRecordingAndEmailServ ...@@ -57,7 +69,17 @@ public class RunRecordingAndEmailServiceImpl implements RunRecordingAndEmailServ
//这一步是根据flowId和RunId查询对应的节点信息 //这一步是根据flowId和RunId查询对应的节点信息
List<JobTaskRunLogWithBLOBs> jobTaskRunLogByFlowIdAndRunId = jobTaskRunLogService.findJobTaskRunLogWithBLOBsByFlowIdAndRunId(runRecording.getFlowId(), runRecording.getRunId()); List<JobTaskRunLogWithBLOBs> jobTaskRunLogByFlowIdAndRunId = jobTaskRunLogService.findJobTaskRunLogWithBLOBsByFlowIdAndRunId(runRecording.getFlowId(), runRecording.getRunId());
String flowName = runRecording.getFlowName(); String flowName = runRecording.getFlowName();
String senContentHtml = runMsgHtml(jobTaskRunLogByFlowIdAndRunId, flowName); //String senContentHtml = runMsgHtml(jobTaskRunLogByFlowIdAndRunId, flowName)
Integer workspaceId = runRecording.getWorkspaceId();
Workspace workspace = workspaceService.findOneById(workspaceId);
String workspaceName = null;
if(workspace != null){
workspaceName = workspace.getWorkspaceName();
}
long flowEndTime = runRecording.getEndTime() == null? System.currentTimeMillis():runRecording.getEndTime().getTime();
long flowStartTime = runRecording.getStartTime() == null? System.currentTimeMillis():runRecording.getStartTime().getTime();
String senContentHtml = buildHtml(flowName,workspaceName,jobTaskRunLogByFlowIdAndRunId,flowEndTime-flowStartTime);
EmailAlarm emailAlarm = EmailAlarm.builder() EmailAlarm emailAlarm = EmailAlarm.builder()
.flowId(runRecording.getFlowId()) .flowId(runRecording.getFlowId())
.flowName(flowName) .flowName(flowName)
...@@ -77,6 +99,85 @@ public class RunRecordingAndEmailServiceImpl implements RunRecordingAndEmailServ ...@@ -77,6 +99,85 @@ public class RunRecordingAndEmailServiceImpl implements RunRecordingAndEmailServ
} }
/** /**
* 根据模板引擎构建html代码
* @param title
* @param env
* @param jobTaskRunLogs
* @param flowConsumeDate
* @return
*/
public String buildHtml(String title,String env, List<JobTaskRunLogWithBLOBs> jobTaskRunLogs,Long flowConsumeDate){
Map<String, Object> data = new HashMap<>(4);
data.put("title",title);
data.put("env",env);
data.put("flowConsumeDate",TimeFormatUtil.timeFormat(flowConsumeDate));
List<EmailMappingDto> emailMappings = new ArrayList<>(8);
if (CollectionUtil.isNotEmpty(jobTaskRunLogs)) {
jobTaskRunLogs.forEach(jobTaskRunLog -> {
EmailMappingDto emailMappingDto = new EmailMappingDto();
//结束时间
Date endTime = jobTaskRunLog.getEndTime() == null ? new Date() : jobTaskRunLog.getEndTime();
String endTimeFormat = com.byit.job.utils.DateUtil.dateFormat(endTime, "yyyy年MM月dd日 HH:mm:ss");
//开始时间
Date startTime = jobTaskRunLog.getStartTime() == null ? new Date() : jobTaskRunLog.getStartTime();
String startTimeFormat = com.byit.job.utils.DateUtil.dateFormat(startTime, "yyyy年MM月dd日 HH:mm:ss");
long timeConsuming = endTime.getTime() - startTime.getTime();
//消耗时间
String consumeDate = TimeFormatUtil.timeFormat(timeConsuming);
String runStatus;
switch (jobTaskRunLog.getRunCode()) {
case NODE_RUN_SUCCESS:
runStatus = "成功";
break;
case NODE_RE_RUN_SUCCESS:
runStatus = "补批成功";
break;
case NODE_RE_RUN_ERROR:
runStatus = "补批失败";
break;
case NODE_RUN_KILL:
runStatus = "kill";
break;
case NODE_UP_RUN_ERROR:
runStatus = "上级节点执行失败";
break;
default:
runStatus = "失败";
break;
}
/**
* 拼接日志远程路径
*/
if(StringUtils.isNotBlank(jobTaskRunLog.getLogRemotelyPath())){
List<String> logPaths = new ArrayList<>(3);
List<String> trackerList = trackerConnectionManager.getTrackerList();
if (CollectionUtil.isNotEmpty(trackerList)) {
for (String ipPort : trackerList) {
String ip = ipPort.split(":")[0];
String baseUrl = "http://"+ip+":"+"8888"+"/";
String hrefUrl = baseUrl + jobTaskRunLog.getLogRemotelyPath();
logPaths.add(hrefUrl);
}
}
emailMappingDto.setLogPaths(logPaths);
}
emailMappingDto.setStartDate(startTimeFormat);
emailMappingDto.setEndDate(endTimeFormat);
emailMappingDto.setConsuming(consumeDate);
emailMappingDto.setRunStatus(runStatus);
emailMappingDto.setNodeName(jobTaskRunLog.getNodeName());
emailMappings.add(emailMappingDto);
});
}
data.put("data",emailMappings);
Context context = new Context();
context.setVariables(data);
return templateEngine.process("/mail/mail", context);
}
/**
* 生成发送邮件的html信息 * 生成发送邮件的html信息
* @param jobTaskRunLogs 节点的运行信息 * @param jobTaskRunLogs 节点的运行信息
* @param title 邮件主题 * @param title 邮件主题
......
package com.byit.util; package com.byit.util;
import org.apache.commons.lang3.StringUtils;
/** /**
* 对于时间的格式化 * 对于时间的格式化
* @author huangfu * @author huangfu
...@@ -37,9 +39,11 @@ public class TimeFormatUtil { ...@@ -37,9 +39,11 @@ public class TimeFormatUtil {
sb.append((int)(time%days%hours%minutes%seconds/millis)+"毫秒"); sb.append((int)(time%days%hours%minutes%seconds/millis)+"毫秒");
} }
return sb.toString(); String consumeDate = sb.toString();
if(StringUtils.isBlank(consumeDate)){
consumeDate = "1毫秒";
} }
return consumeDate;
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment