1
This commit is contained in:
@@ -29,10 +29,12 @@ public class LogisticsServiceImpl implements ILogisticsService {
|
||||
|
||||
private static final String REDIS_WAYBILL_KEY_PREFIX = "logistics:waybill:order:";
|
||||
private static final String REDIS_LOCK_KEY_PREFIX = "logistics:lock:order:";
|
||||
private static final String REDIS_HEALTH_CHECK_ALERT_KEY = "logistics:health:alert:";
|
||||
private static final String PUSH_URL = "https://wxts.van333.cn/wx/send/pdd";
|
||||
private static final String PUSH_TOKEN = "super_token_b62190c26";
|
||||
private static final String CONFIG_KEY_PREFIX = "logistics.push.touser.";
|
||||
private static final long LOCK_EXPIRE_SECONDS = 300; // 锁过期时间5分钟,防止死锁
|
||||
private static final long HEALTH_CHECK_ALERT_INTERVAL_MINUTES = 30; // 健康检查失败提醒间隔30分钟,避免频繁推送
|
||||
|
||||
@Value("${jarvis.server.logistics.base-url:http://127.0.0.1:5001}")
|
||||
private String logisticsBaseUrl;
|
||||
@@ -40,7 +42,11 @@ public class LogisticsServiceImpl implements ILogisticsService {
|
||||
@Value("${jarvis.server.logistics.fetch-path:/fetch_logistics}")
|
||||
private String logisticsFetchPath;
|
||||
|
||||
@Value("${jarvis.server.logistics.health-path:/health}")
|
||||
private String logisticsHealthPath;
|
||||
|
||||
private String externalApiUrlTemplate;
|
||||
private String healthCheckUrl;
|
||||
|
||||
@Resource
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
@@ -51,7 +57,9 @@ public class LogisticsServiceImpl implements ILogisticsService {
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
externalApiUrlTemplate = logisticsBaseUrl + logisticsFetchPath + "?tracking_url=";
|
||||
healthCheckUrl = logisticsBaseUrl + logisticsHealthPath;
|
||||
logger.info("物流服务地址已初始化: {}", externalApiUrlTemplate);
|
||||
logger.info("物流服务健康检查地址已初始化: {}", healthCheckUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,6 +71,114 @@ public class LogisticsServiceImpl implements ILogisticsService {
|
||||
return stringRedisTemplate.hasKey(redisKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查物流服务健康状态
|
||||
* @return 是否健康
|
||||
*/
|
||||
private boolean checkLogisticsServiceHealth() {
|
||||
try {
|
||||
logger.debug("开始检查物流服务健康状态 - URL: {}", healthCheckUrl);
|
||||
String healthResult = HttpUtils.sendGet(healthCheckUrl);
|
||||
|
||||
if (healthResult == null || healthResult.trim().isEmpty()) {
|
||||
logger.warn("物流服务健康检查返回空结果");
|
||||
handleHealthCheckFailure("健康检查返回空结果");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 尝试解析JSON响应
|
||||
try {
|
||||
JSONObject response = JSON.parseObject(healthResult);
|
||||
if (response != null) {
|
||||
// 检查常见的健康状态字段
|
||||
String status = response.getString("status");
|
||||
Boolean healthy = response.getBoolean("healthy");
|
||||
Integer code = response.getInteger("code");
|
||||
|
||||
if ("ok".equalsIgnoreCase(status) || "healthy".equalsIgnoreCase(status) ||
|
||||
Boolean.TRUE.equals(healthy) || (code != null && code == 200)) {
|
||||
logger.debug("物流服务健康检查通过");
|
||||
// 清除健康检查失败标记
|
||||
stringRedisTemplate.delete(REDIS_HEALTH_CHECK_ALERT_KEY);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 如果不是JSON格式,检查是否包含成功标识
|
||||
String lowerResult = healthResult.toLowerCase();
|
||||
if (lowerResult.contains("ok") || lowerResult.contains("healthy") || lowerResult.contains("success")) {
|
||||
logger.debug("物流服务健康检查通过(非JSON格式)");
|
||||
stringRedisTemplate.delete(REDIS_HEALTH_CHECK_ALERT_KEY);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
logger.warn("物流服务健康检查失败 - 响应: {}", healthResult);
|
||||
handleHealthCheckFailure("健康检查返回异常状态: " + healthResult);
|
||||
return false;
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("物流服务健康检查异常 - URL: {}, 错误: {}", healthCheckUrl, e.getMessage(), e);
|
||||
handleHealthCheckFailure("健康检查异常: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理健康检查失败,推送提醒消息
|
||||
* @param reason 失败原因
|
||||
*/
|
||||
private void handleHealthCheckFailure(String reason) {
|
||||
try {
|
||||
// 检查是否在提醒间隔内已经推送过
|
||||
String alertKey = REDIS_HEALTH_CHECK_ALERT_KEY;
|
||||
String lastAlertTime = stringRedisTemplate.opsForValue().get(alertKey);
|
||||
|
||||
if (lastAlertTime != null) {
|
||||
// 如果30分钟内已经推送过,不再重复推送
|
||||
logger.debug("健康检查失败提醒已在30分钟内推送过,跳过本次推送");
|
||||
return;
|
||||
}
|
||||
|
||||
// 构建推送消息
|
||||
StringBuilder pushContent = new StringBuilder();
|
||||
pushContent.append("【物流服务异常提醒】\n");
|
||||
pushContent.append("服务地址:").append(healthCheckUrl).append("\n");
|
||||
pushContent.append("失败原因:").append(reason).append("\n");
|
||||
pushContent.append("时间:").append(new Date()).append("\n");
|
||||
pushContent.append("请及时检查服务状态!");
|
||||
|
||||
JSONObject pushParam = new JSONObject();
|
||||
pushParam.put("title", "物流服务健康检查失败");
|
||||
pushParam.put("text", pushContent.toString());
|
||||
|
||||
// 尝试获取系统管理员接收人配置,如果没有则使用默认接收人
|
||||
String adminTouser = sysConfigService.selectConfigByKey("logistics.push.touser.ADMIN");
|
||||
if (StringUtils.hasText(adminTouser)) {
|
||||
pushParam.put("touser", adminTouser.trim());
|
||||
logger.info("使用管理员接收人配置推送健康检查失败提醒");
|
||||
} else {
|
||||
logger.info("未配置管理员接收人,将使用远程接口默认接收人推送健康检查失败提醒");
|
||||
}
|
||||
|
||||
String jsonBody = pushParam.toJSONString();
|
||||
String pushResult = sendPostWithHeaders(PUSH_URL, jsonBody, PUSH_TOKEN);
|
||||
|
||||
if (pushResult != null && !pushResult.trim().isEmpty()) {
|
||||
logger.info("健康检查失败提醒已推送 - 响应: {}", pushResult);
|
||||
// 记录推送时间,30分钟内不再重复推送
|
||||
Long currentTime = System.currentTimeMillis();
|
||||
stringRedisTemplate.opsForValue().set(alertKey, currentTime.toString(),
|
||||
HEALTH_CHECK_ALERT_INTERVAL_MINUTES, TimeUnit.MINUTES);
|
||||
} else {
|
||||
logger.warn("健康检查失败提醒推送失败 - 响应为空");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("推送健康检查失败提醒异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fetchLogisticsAndPush(JDOrder order) {
|
||||
if (order == null || order.getId() == null) {
|
||||
@@ -100,6 +216,14 @@ public class LogisticsServiceImpl implements ILogisticsService {
|
||||
logger.info("订单暂无物流链接,跳过处理 - 订单ID: {}", orderId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 先进行健康检查
|
||||
boolean healthCheckPassed = checkLogisticsServiceHealth();
|
||||
if (!healthCheckPassed) {
|
||||
logger.error("物流服务健康检查失败,跳过处理订单 - 订单ID: {}", orderId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 构建外部接口URL
|
||||
String externalUrl = externalApiUrlTemplate + URLEncoder.encode(logisticsLink, "UTF-8");
|
||||
logger.info("调用外部接口获取物流信息 - 订单ID: {}, URL: {}", orderId, externalUrl);
|
||||
|
||||
Reference in New Issue
Block a user