From 3ccfbaea904de643b57cfef2faf550f2673ade75 Mon Sep 17 00:00:00 2001 From: 王彬 Date: Thu, 24 Jun 2021 19:29:59 +0800 Subject: [PATCH] module heartbeat --- build.gradle | 16 +++++----------- deployment-rollback.txt | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ deployment.txt | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/StartUp.java | 2 ++ src/main/java/com/taover/bazhuayun/analysis/web/controller/ExportCenterController.java | 99 --------------------------------------------------------------------------------------------------- src/main/java/com/taover/bazhuayun/analysis/web/controller/api/HeartBeatController.java | 23 +++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/controller/data/ExportCenterController.java | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/form/BaseCreateForm.java | 25 +++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/form/BaseForm.java | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/form/BaseSearchForm.java | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/form/BaseUpdateForm.java | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/form/HeartbeatInstanceCreateForm.java | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/form/HeartbeatInstanceUpdateForm.java | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/HeartbeatManager.java | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/HeartbeatManagerImpl.java | 329 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ClientInstance.java | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ClientRequest.java | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/Instance.java | 37 +++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ServerInstance.java | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ServerResponse.java | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ClientHolder.java | 21 +++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ClientHolderImpl.java | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ServerHolder.java | 16 ++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ServerHolderImpl.java | 34 ++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatDeployService.java | 7 +++++++ src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatDeployServiceImpl.java | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatReformService.java | 11 +++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatReformServiceImpl.java | 264 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatInstanceEntity.java | 236 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatInstanceRepository.java | 25 +++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatLogEntity.java | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatLogRepository.java | 19 +++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatReformEntity.java | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatReformRepository.java | 24 ++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/scafford/CodeGeneraterWB.java | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/bazhuayun/analysis/web/schedule/HttpHeartbeat.java | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ src/main/resources/application-local.properties | 108 ++++-------------------------------------------------------------------------------------------------------- src/main/resources/application-production.properties | 61 +++++++++++-------------------------------------------------- test/main/java/com/taover/bazhuayun/analysis/test/SemilarClient.java | 25 +++++++++++++++++++++++++ 39 files changed, 2820 insertions(+), 264 deletions(-) create mode 100644 deployment-rollback.txt create mode 100644 deployment.txt delete mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/controller/ExportCenterController.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/controller/api/HeartBeatController.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/controller/data/ExportCenterController.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/form/BaseCreateForm.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/form/BaseForm.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/form/BaseSearchForm.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/form/BaseUpdateForm.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/form/HeartbeatInstanceCreateForm.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/form/HeartbeatInstanceUpdateForm.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/HeartbeatManager.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/HeartbeatManagerImpl.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ClientInstance.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ClientRequest.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/Instance.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ServerInstance.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ServerResponse.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ClientHolder.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ClientHolderImpl.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ServerHolder.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ServerHolderImpl.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatDeployService.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatDeployServiceImpl.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatReformService.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatReformServiceImpl.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatInstanceEntity.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatInstanceRepository.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatLogEntity.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatLogRepository.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatReformEntity.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatReformRepository.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/scafford/CodeGeneraterWB.java create mode 100644 src/main/java/com/taover/bazhuayun/analysis/web/schedule/HttpHeartbeat.java create mode 100644 test/main/java/com/taover/bazhuayun/analysis/test/SemilarClient.java diff --git a/build.gradle b/build.gradle index 61bdc17..f620f02 100644 --- a/build.gradle +++ b/build.gradle @@ -35,21 +35,15 @@ dependencies { "org.springframework.boot:spring-boot-starter-data-jpa", "org.springframework.boot:spring-boot-starter-mail", - "mysql:mysql-connector-java", - - "com.hankcs:hanlp:portable-1.7.5", - - "com.aliyun.oss:aliyun-sdk-oss:2.0.7", "com.alibaba:fastjson:1.2.72", - "com.alibaba:druid-spring-boot-starter:1.1.10", + "mysql:mysql-connector-java:8.0.11", - "com.xuxueli:xxl-job-core:2.1.0", - "com.taover:com-taover-repository:2.1.22", + "com.taover:com-taover-repository-starter:2.3.8", "com.taover:com-taover-easyexcel:2.2.16", - "com.taover:com-taover-util:1.1.112", + "com.taover:com-taover-util:1.2.2", + "com.taover:com-taover-codegenerate:1.2.28", "cn.hutool:hutool-all:5.2.4", - "com.taover:com-taover-codegenerate:1.2.11", "com.auth0:java-jwt:3.4.0", - "io.jsonwebtoken:jjwt:0.6.0" + "io.jsonwebtoken:jjwt:0.6.0" ) } diff --git a/deployment-rollback.txt b/deployment-rollback.txt new file mode 100644 index 0000000..27e4b12 --- /dev/null +++ b/deployment-rollback.txt @@ -0,0 +1,91 @@ +#!/bin/bash + +. ~/.bash_profile + +#出现异常则退出 +set -e + +#获取输入的GIT_BRANCH +GIT_BRANCH="$1" + +#验证GIT_BRANCH +if [ ! ${GIT_BRANCH} ]; then + echo "fail: please input git branch name" + exit 2 +fi + +#获取输入的commit id +ROLLBACK_COMMIT_ID="$2" + +#验证commitID +if [ ! ${ROLLBACK_COMMIT_ID} ]; then + echo "fail: please input commit id" + exit 2 +fi + +#定义常量 +GIT_URL=git@gitlab.taover.com:taov-erp/8zyun-data-analysis.git +GIT_PROJECT_NAME=8zyun-data-analysis +MAIN_DIR=$(cd `dirname $0`; pwd) +WEBAPP_DIR_NAME=webapp +WEBAPP_BAK_DIR_NAME=webapp-bak +LOG_DIR_NAME=log + +cd ${MAIN_DIR} + +#克隆项目 +if [ ! -d "${MAIN_DIR}/${GIT_PROJECT_NAME}" ]; then + cd ${MAIN_DIR} + git clone ${GIT_URL} + echo "git clone success" +fi + +#创建基础目录 +if [ ! -d "${MAIN_DIR}/${WEBAPP_DIR_NAME}" ]; then + mkdir ${MAIN_DIR}/${WEBAPP_DIR_NAME} + echo "mkdir webapp success" +fi +if [ ! -d "${MAIN_DIR}/${WEBAPP_BAK_DIR_NAME}" ]; then + mkdir ${MAIN_DIR}/${WEBAPP_BAK_DIR_NAME} + echo "mkdir webapp bak success" +fi +if [ ! -d "${MAIN_DIR}/${LOG_DIR_NAME}" ]; then + mkdir ${MAIN_DIR}/${LOG_DIR_NAME} + echo "mkdir log success" +fi + +#备份上一JAR +#cp -rf ${MAIN_DIR}/${WEBAPP_DIR_NAME}/ ${MAIN_DIR}/${WEBAPP_BAK_DIR_NAME}/ +#echo "bak webapp dir success" + +#备份日志文件 +bakLogFilePreffix=`date '+%Y%m%d_%H%M'` +if [ -f ${MAIN_DIR}/${LOG_DIR_NAME}/log_std.out ]; then + cp -f ${MAIN_DIR}/${LOG_DIR_NAME}/log_std.out ${MAIN_DIR}/${LOG_DIR_NAME}/${bakLogFilePreffix}_log_std.out +fi +if [ -f ${MAIN_DIR}/${LOG_DIR_NAME}/log_error.out ]; then + cp -f ${MAIN_DIR}/${LOG_DIR_NAME}/log_error.out ${MAIN_DIR}/${LOG_DIR_NAME}/${bakLogFilePreffix}_log_error.out +fi + +#拉取线上production代码并编译发布 +cd ${MAIN_DIR}/${GIT_PROJECT_NAME}/ +git checkout ${GIT_BRANCH} +git reset --hard ${ROLLBACK_COMMIT_ID} +gradle build +echo "pull ${GIT_BRANCH} ${ROLLBACK_COMMIT_ID} and build success" + +#终止线程并移除文件 +pid=`ps -ef | grep "$GIT_PROJECT_NAME".jar | grep -v grep | awk '{print $2}'` +if [ -n "$pid" ] +then + kill $pid +fi +rm -rf ${MAIN_DIR}/${WEBAPP_DIR_NAME}/* +echo "end process and rm success" + +#移动TAR文件、解压、启动 +cd ${MAIN_DIR}/${WEBAPP_DIR_NAME}/ +mv ${MAIN_DIR}/${GIT_PROJECT_NAME}/build/distributions/${GIT_PROJECT_NAME}-boot.tar ${MAIN_DIR}/${WEBAPP_DIR_NAME}/ +tar -xvf ${GIT_PROJECT_NAME}-boot.tar +nohup java -Xmx8192m -jar ${GIT_PROJECT_NAME}-boot/lib/${GIT_PROJECT_NAME}.jar --spring.profiles.active=production 2>${MAIN_DIR}/${LOG_DIR_NAME}/log_error.out 1>${MAIN_DIR}/${LOG_DIR_NAME}/log_std.out & +echo "start up success" \ No newline at end of file diff --git a/deployment.txt b/deployment.txt new file mode 100644 index 0000000..0a565b0 --- /dev/null +++ b/deployment.txt @@ -0,0 +1,86 @@ +#!/bin/bash + +. ~/.bash_profile + +#出现异常则退出 +set -e + +#获取输入的GIT_BRANCH +GIT_BRANCH="$1" + +#验证GIT_BRANCH +if [ ! ${GIT_BRANCH} ]; then + echo "fail: please input git branch name" + exit 2 +fi + +#定义常量 +GIT_URL=git@gitlab.taover.com:taov-erp/8zyun-data-analysis.git +GIT_PROJECT_NAME=8zyun-data-analysis +MAIN_DIR=$(cd `dirname $0`; pwd) +WEBAPP_DIR_NAME=webapp +WEBAPP_BAK_DIR_NAME=webapp-bak +LOG_DIR_NAME=log + +cd ${MAIN_DIR} + +#克隆项目 +if [ ! -d "${MAIN_DIR}/${GIT_PROJECT_NAME}" ]; then + cd ${MAIN_DIR} + git clone ${GIT_URL} + echo "git clone success" +fi + +#创建基础目录 +if [ ! -d "${MAIN_DIR}/${WEBAPP_DIR_NAME}" ]; then + mkdir ${MAIN_DIR}/${WEBAPP_DIR_NAME} + echo "mkdir webapp success" +fi +if [ ! -d "${MAIN_DIR}/${WEBAPP_BAK_DIR_NAME}" ]; then + mkdir ${MAIN_DIR}/${WEBAPP_BAK_DIR_NAME} + echo "mkdir webapp bak success" +fi +if [ ! -d "${MAIN_DIR}/${LOG_DIR_NAME}" ]; then + mkdir ${MAIN_DIR}/${LOG_DIR_NAME} + echo "mkdir log success" +fi + +#备份上一JAR +cp -rf ${MAIN_DIR}/${WEBAPP_DIR_NAME}/ ${MAIN_DIR}/${WEBAPP_BAK_DIR_NAME}/ +echo "bak webapp dir success" + +#备份日志文件 +bakLogFilePreffix=`date '+%Y%m%d_%H%M'` +if [ -f ${MAIN_DIR}/${LOG_DIR_NAME}/log_std.out ]; then + cp -f ${MAIN_DIR}/${LOG_DIR_NAME}/log_std.out ${MAIN_DIR}/${LOG_DIR_NAME}/${bakLogFilePreffix}_log_std.out +fi +if [ -f ${MAIN_DIR}/${LOG_DIR_NAME}/log_error.out ]; then + cp -f ${MAIN_DIR}/${LOG_DIR_NAME}/log_error.out ${MAIN_DIR}/${LOG_DIR_NAME}/${bakLogFilePreffix}_log_error.out +fi + +#拉取线上production代码并编译发布 +tagNamePreffix=`date '+%Y%m%d'` +cd ${MAIN_DIR}/${GIT_PROJECT_NAME}/ +git checkout ${GIT_BRANCH} +git pull origin ${GIT_BRANCH} +headCommit=`git rev-parse HEAD` +git tag -a v.${GIT_BRANCH}.${tagNamePreffix}.${headCommit} -m "COMMIT ID : ${headCommit}" || echo "git tag fail" +git push origin v.${GIT_BRANCH}.${tagNamePreffix}.${headCommit} +gradle build +echo "pull ${GIT_BRANCH} and build success" + +#终止线程并移除文件 +pid=`ps -ef | grep "$GIT_PROJECT_NAME".jar | grep -v grep | awk '{print $2}'` +if [ -n "$pid" ] +then + kill $pid +fi +rm -rf ${MAIN_DIR}/${WEBAPP_DIR_NAME}/* +echo "end process and rm success" + +#移动TAR文件、解压、启动 +cd ${MAIN_DIR}/${WEBAPP_DIR_NAME}/ +mv ${MAIN_DIR}/${GIT_PROJECT_NAME}/build/distributions/${GIT_PROJECT_NAME}-boot.tar ${MAIN_DIR}/${WEBAPP_DIR_NAME}/ +tar -xvf ${GIT_PROJECT_NAME}-boot.tar +nohup java -Xmx8192m -jar ${GIT_PROJECT_NAME}-boot/lib/${GIT_PROJECT_NAME}.jar --spring.profiles.active=${GIT_BRANCH} 2>${MAIN_DIR}/${LOG_DIR_NAME}/log_error.out 1>${MAIN_DIR}/${LOG_DIR_NAME}/log_std.out & +echo "start up success" \ No newline at end of file diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/StartUp.java b/src/main/java/com/taover/bazhuayun/analysis/web/StartUp.java index 4a7cebc..e36d84e 100644 --- a/src/main/java/com/taover/bazhuayun/analysis/web/StartUp.java +++ b/src/main/java/com/taover/bazhuayun/analysis/web/StartUp.java @@ -3,9 +3,11 @@ package com.taover.bazhuayun.analysis.web; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableAspectJAutoProxy(exposeProxy=true, proxyTargetClass=true) +@EnableScheduling public class StartUp { public static void main(String[] args) { SpringApplication.run(StartUp.class, args); diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/controller/ExportCenterController.java b/src/main/java/com/taover/bazhuayun/analysis/web/controller/ExportCenterController.java deleted file mode 100644 index 199129f..0000000 --- a/src/main/java/com/taover/bazhuayun/analysis/web/controller/ExportCenterController.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.taover.bazhuayun.analysis.web.controller; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang.StringUtils; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import com.taover.bazhuayun.analysis.util.FileContentTypeUtils; -import com.taover.bazhuayun.analysis.web.service.ExportCenterService; -import com.taover.util.UtilLog; - -@RestController("exportcenter") -@RequestMapping("/exportcenter") -public class ExportCenterController { - @Resource - private ExportCenterService exportCenterService; - - @GetMapping("/wareorderfile") - public void wareOrderFile(@RequestParam(name="tenantId", required=true) Integer tenantId, - @RequestParam(name="startDate", defaultValue = "") String startDateStr, - @RequestParam(name="endDate", defaultValue = "") String endDateStr, - @RequestParam(name="wareCreateStartDate", defaultValue = "") String wareCreateStartDateStr, - @RequestParam(name="wareCreateEndDate", defaultValue = "") String wareCreateEndDateStr, - HttpServletResponse response) { - Date startDate = new Date(); - Date endDate = new Date(); - Date wareCreateStartDate = null; - Date wareCreateEndDate = null; - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - if(StringUtils.isNotBlank(startDateStr)) { - try { - startDate = sdf.parse(startDateStr.substring(0, 10)); - } catch (ParseException e) { - e.printStackTrace(); - } - } - if(StringUtils.isNotBlank(endDateStr)) { - try { - endDate = sdf.parse(endDateStr.substring(0, 10)); - } catch (ParseException e) { - e.printStackTrace(); - } - } - if(StringUtils.isNotBlank(wareCreateStartDateStr)) { - try { - wareCreateStartDate = sdf.parse(wareCreateStartDateStr.substring(0, 10)); - } catch (ParseException e) { - e.printStackTrace(); - } - } - if(StringUtils.isNotBlank(wareCreateEndDateStr)) { - try { - wareCreateEndDate = sdf.parse(wareCreateEndDateStr.substring(0, 10)); - } catch (ParseException e) { - e.printStackTrace(); - } - } - - File orderFile = null; - try { - orderFile = this.exportCenterService.wareOrderFile(tenantId, startDate, endDate, wareCreateStartDate, wareCreateEndDate); - } catch (IOException e1) { - UtilLog.errorForException(e1, this.getClass()); - return; - } - try { - this.writeFielToResponse(response, orderFile); - } catch (IOException e) { - UtilLog.errorForException(e, this.getClass()); - } - } - - private void writeFielToResponse(HttpServletResponse response, File file) throws IOException { - OutputStream stream = response.getOutputStream(); - FileInputStream reader = new FileInputStream(file); - byte[] data= new byte[(int)file.length()]; - reader.read(data); - reader.close(); - - //记得设置ContentType - String fileName = file.getName(); - response.setContentType(FileContentTypeUtils.contentType(fileName.substring(fileName.lastIndexOf(".")))); - response.setHeader("Content-Dis", "filename="+file.getName()); - stream.write(data); - stream.flush(); - } -} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/controller/api/HeartBeatController.java b/src/main/java/com/taover/bazhuayun/analysis/web/controller/api/HeartBeatController.java new file mode 100644 index 0000000..11c5dc0 --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/controller/api/HeartBeatController.java @@ -0,0 +1,23 @@ +package com.taover.bazhuayun.analysis.web.controller.api; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.taover.bazhuayun.analysis.web.module.heartbeat.HeartbeatManager; +import com.taover.util.bean.ResultInfo; + +@RestController("api.heartbeat") +@RequestMapping("/api/heartbeat") +public class HeartBeatController { + @Resource + private HeartbeatManager heartbeatManager; + + @GetMapping + public ResultInfo get(HttpServletRequest request) { + return this.heartbeatManager.dealClientRequest(request); + } +} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/controller/data/ExportCenterController.java b/src/main/java/com/taover/bazhuayun/analysis/web/controller/data/ExportCenterController.java new file mode 100644 index 0000000..87cb27d --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/controller/data/ExportCenterController.java @@ -0,0 +1,99 @@ +package com.taover.bazhuayun.analysis.web.controller.data; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.taover.bazhuayun.analysis.util.FileContentTypeUtils; +import com.taover.bazhuayun.analysis.web.service.ExportCenterService; +import com.taover.util.UtilLog; + +@RestController("exportcenter") +@RequestMapping("/exportcenter") +public class ExportCenterController { + @Resource + private ExportCenterService exportCenterService; + + @GetMapping("/wareorderfile") + public void wareOrderFile(@RequestParam(name="tenantId", required=true) Integer tenantId, + @RequestParam(name="startDate", defaultValue = "") String startDateStr, + @RequestParam(name="endDate", defaultValue = "") String endDateStr, + @RequestParam(name="wareCreateStartDate", defaultValue = "") String wareCreateStartDateStr, + @RequestParam(name="wareCreateEndDate", defaultValue = "") String wareCreateEndDateStr, + HttpServletResponse response) { + Date startDate = new Date(); + Date endDate = new Date(); + Date wareCreateStartDate = null; + Date wareCreateEndDate = null; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + if(StringUtils.isNotBlank(startDateStr)) { + try { + startDate = sdf.parse(startDateStr.substring(0, 10)); + } catch (ParseException e) { + e.printStackTrace(); + } + } + if(StringUtils.isNotBlank(endDateStr)) { + try { + endDate = sdf.parse(endDateStr.substring(0, 10)); + } catch (ParseException e) { + e.printStackTrace(); + } + } + if(StringUtils.isNotBlank(wareCreateStartDateStr)) { + try { + wareCreateStartDate = sdf.parse(wareCreateStartDateStr.substring(0, 10)); + } catch (ParseException e) { + e.printStackTrace(); + } + } + if(StringUtils.isNotBlank(wareCreateEndDateStr)) { + try { + wareCreateEndDate = sdf.parse(wareCreateEndDateStr.substring(0, 10)); + } catch (ParseException e) { + e.printStackTrace(); + } + } + + File orderFile = null; + try { + orderFile = this.exportCenterService.wareOrderFile(tenantId, startDate, endDate, wareCreateStartDate, wareCreateEndDate); + } catch (IOException e1) { + UtilLog.errorForException(e1, this.getClass()); + return; + } + try { + this.writeFielToResponse(response, orderFile); + } catch (IOException e) { + UtilLog.errorForException(e, this.getClass()); + } + } + + private void writeFielToResponse(HttpServletResponse response, File file) throws IOException { + OutputStream stream = response.getOutputStream(); + FileInputStream reader = new FileInputStream(file); + byte[] data= new byte[(int)file.length()]; + reader.read(data); + reader.close(); + + //记得设置ContentType + String fileName = file.getName(); + response.setContentType(FileContentTypeUtils.contentType(fileName.substring(fileName.lastIndexOf(".")))); + response.setHeader("Content-Dis", "filename="+file.getName()); + stream.write(data); + stream.flush(); + } +} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/form/BaseCreateForm.java b/src/main/java/com/taover/bazhuayun/analysis/web/form/BaseCreateForm.java new file mode 100644 index 0000000..4364330 --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/form/BaseCreateForm.java @@ -0,0 +1,25 @@ +package com.taover.bazhuayun.analysis.web.form; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.validation.BindingResult; +import org.springframework.validation.ObjectError; + +public abstract class BaseCreateForm extends BaseForm{ + /** + * 获取验证异常消息列表 + * @param bindingResult + * @return + */ + public List getErrorMessageList(BindingResult bindingResult){ + List errorMessageList = new ArrayList(); + if(bindingResult.hasErrors()){ + List errorList = bindingResult.getAllErrors(); + for(int i=0; i, Field[]> CACHE_FIELDS_BY_CLASS = new HashMap, Field[]>(); + + /** + * 通过正则表达式去除所有字符串左右空白字符 + */ + public void trimByRegexS(){ + Class thisClass = this.getClass(); + Field[] fieldArr = CACHE_FIELDS_BY_CLASS.get(thisClass); + if(fieldArr == null) { + fieldArr = thisClass.getDeclaredFields(); + CACHE_FIELDS_BY_CLASS.put(thisClass, fieldArr); + } + for(int i=0; i thisClass = this.getClass(); + Field[] fieldArr = CACHE_FIELDS_BY_CLASS.get(thisClass); + if(fieldArr == null) { + fieldArr = thisClass.getDeclaredFields(); + CACHE_FIELDS_BY_CLASS.put(thisClass, fieldArr); + } + StringBuffer result = new StringBuffer(); + for(int i=0; i='" + DateUtil.formatDateTime(startDate) +"' "; + } + + public String createDateEndSql(Date endDate, String columnSql){ + return " AND " + columnSql + "<='" + DateUtil.formatDateTime(endDate) + "' "; + } + + public String createGreaterEqualSql(Object value, String columnSql){ + if(value == null) { + return ""; + } + return " AND " + columnSql + ">=" + value.toString(); + } + + public String createLessEqualSql(Object value, String columnSql){ + if(value == null) { + return ""; + } + return " AND " + columnSql + "<=" + value.toString(); + } + + public String createLikeSql(String likeStr, String columnSql){ + if(likeStr == null) { + return ""; + } + return " AND "+columnSql+" like '%"+this.preDealSqlKeyword(likeStr)+"%'"; + } + + public String createRightLikeSql(String likeStr, String columnSql){ + if(likeStr == null) { + return ""; + } + return " AND "+columnSql+" like '"+this.preDealSqlKeyword(likeStr)+"%'"; + } + + public String createEqualsSql(Object value, String columnSql){ + if(value == null) { + return ""; + } + return " AND "+columnSql+"='"+this.preDealSqlKeyword(value.toString())+"'"; + } + + public String createInSql(String[] inArray, String columnSql){ + return " AND "+columnSql+" IN('"+StringUtils.join(inArray, "','")+"')"; + } + + public String createInSql(Integer[] inArray, String columnSql){ + return " AND "+columnSql+" IN("+StringUtils.join(inArray, ",")+")"; + } + + public String createInSql(Long[] inArray, String columnSql){ + return " AND "+columnSql+" IN("+StringUtils.join(inArray, ",")+")"; + } + + public String getOrderBySql(String defaultOrderBySql) { + if(StringUtils.isNotBlank(this.getOriginOrderBySql())) { + return " ORDER BY "+this.getOriginOrderBySql(); + }else if(StringUtils.isNotBlank(this.getSortBy()) && StringUtils.isNotBlank(this.getSortOrder())) { + return " ORDER BY "+UtilString.underscoreName(this.getSortBy()).toLowerCase()+" "+this.getSortOrder(); + } + return defaultOrderBySql; + } + + public String preDealSqlKeyword(String value) { + if(value == null) { + return ""; + } + return value.replaceAll("\\\\", "\\\\\\\\\\\\\\\\").replaceAll("'", "\\\\'"); + } +} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/form/BaseUpdateForm.java b/src/main/java/com/taover/bazhuayun/analysis/web/form/BaseUpdateForm.java new file mode 100644 index 0000000..0fe206a --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/form/BaseUpdateForm.java @@ -0,0 +1,44 @@ +package com.taover.bazhuayun.analysis.web.form; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.Column; +import javax.persistence.Id; + +public abstract class BaseUpdateForm extends BaseForm{ + + /** + * 转换为数据库字段更新数组 + * @return + */ + public List getSQLUpdateList(){ + List result = new ArrayList(); + Field[] fieldArr = this.getClass().getDeclaredFields(); + for(int i=0; i servers) throws Exception; + + /** + * 创建监控实例 + * @param form + */ + void createInstance(HeartbeatInstanceCreateForm form); + + /** + * 修改监控实例 + * @param form + */ + void updateInstance(HeartbeatInstanceUpdateForm form); + + /** + * 停用监控实例 + * @param code + */ + void disableInstanceByCode(String code); + + /** + * 启用监控实例 + * @param code + */ + void enableInstanceByCode(String code); + + /** + * 处理客户端心跳请求 + * @param clientRequest + * @return + */ + ResultInfo dealClientRequest(HttpServletRequest request); + + /** + * 刷新客户端状态 + */ + void flushClientStatus(); + + /** + * 向服务器发送心跳 + */ + void sendServerHeartbeat(); +} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/HeartbeatManagerImpl.java b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/HeartbeatManagerImpl.java new file mode 100644 index 0000000..1df29c7 --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/HeartbeatManagerImpl.java @@ -0,0 +1,329 @@ +package com.taover.bazhuayun.analysis.web.module.heartbeat; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; + +import org.springframework.stereotype.Service; + +import com.alibaba.fastjson.JSONObject; +import com.taover.bazhuayun.analysis.web.form.HeartbeatInstanceCreateForm; +import com.taover.bazhuayun.analysis.web.form.HeartbeatInstanceUpdateForm; +import com.taover.bazhuayun.analysis.web.module.heartbeat.bean.ClientInstance; +import com.taover.bazhuayun.analysis.web.module.heartbeat.bean.ClientRequest; +import com.taover.bazhuayun.analysis.web.module.heartbeat.bean.Instance; +import com.taover.bazhuayun.analysis.web.module.heartbeat.bean.ServerInstance; +import com.taover.bazhuayun.analysis.web.module.heartbeat.holder.ClientHolder; +import com.taover.bazhuayun.analysis.web.module.heartbeat.holder.ClientHolderImpl; +import com.taover.bazhuayun.analysis.web.module.heartbeat.holder.ServerHolder; +import com.taover.bazhuayun.analysis.web.module.heartbeat.holder.ServerHolderImpl; +import com.taover.bazhuayun.analysis.web.module.heartbeat.service.HeartbeatDeployService; +import com.taover.bazhuayun.analysis.web.module.heartbeat.service.HeartbeatReformService; +import com.taover.bazhuayun.analysis.web.repository.AnalysisHeartbeatInstanceEntity; +import com.taover.bazhuayun.analysis.web.repository.AnalysisHeartbeatInstanceRepository; +import com.taover.bazhuayun.analysis.web.repository.AnalysisHeartbeatLogEntity; +import com.taover.bazhuayun.analysis.web.repository.AnalysisHeartbeatLogRepository; +import com.taover.repository.exception.MultiRowException; +import com.taover.repository.exception.NotFoundException; +import com.taover.util.UtilLog; +import com.taover.util.bean.ResultInfo; +import com.taover.util.bean.UtilResultInfo; + +@Service +public class HeartbeatManagerImpl implements HeartbeatManager { + //客户端holder + private static ClientHolder clientHolder = new ClientHolderImpl(); + //服务端holder + private static ServerHolder serverHolder = new ServerHolderImpl(); + + @Resource + private HeartbeatReformService heartbeatReformService; + @Resource + private HeartbeatDeployService heartbeatDeployService; + @Resource + private AnalysisHeartbeatInstanceRepository analysisHeartbeatInstanceRepository; + @Resource + private AnalysisHeartbeatLogRepository analysisHeartbeatLogRepository; + + /** + * 处理客户端心跳请求 + * @param clientRequest + * @return + * @throws + */ + @Override + public ResultInfo dealClientRequest(HttpServletRequest request) { + ClientRequest cRequest = ClientRequest.createClientRequest(request); + if(!clientHolder.containInstanceCode(cRequest.getCode())) { + return UtilResultInfo.getFailure("code="+cRequest.getCode()+"找不到对应的监控实例"); + } + + try { + AnalysisHeartbeatInstanceEntity instance = this.analysisHeartbeatInstanceRepository.findEntityBySql("code='"+cRequest.getCode()+"' and role_type="+AnalysisHeartbeatInstanceRepository.ROLE_TYPE_CLIENT+" and status="+AnalysisHeartbeatInstanceRepository.STATUS_ENABLE, null); + ResultInfo result = null; + try { + //刷新client信息 + clientHolder.dealClientRequest(cRequest, instance); + result = UtilResultInfo.getSuccess(""); + }catch (Exception e) { + result = UtilResultInfo.getFailure(e.getMessage()); + } + + //记录请求日志 + this.createLog(cRequest, request.getParameterMap(), result); + + return result; + }catch (NotFoundException | MultiRowException e) { + return UtilResultInfo.getFailure("查找code="+cRequest.getCode()+"对应的监控实例异常,异常信息:"+e.getMessage()); + } + } + + private void createLog(ClientRequest cRequest, Map data, ResultInfo response) { + try { + AnalysisHeartbeatLogEntity log = new AnalysisHeartbeatLogEntity(); + log.setClientIp(cRequest.getIp()); + log.setInstanceCode(cRequest.getCode()); + log.setResponse(JSONObject.toJSONString(response)); + log.setRequest(JSONObject.toJSONString(data)); + this.analysisHeartbeatLogRepository.addEntity(log, null); + }catch (Exception e) { + UtilLog.error("数据库异常:客户端心跳请求,日志记录出现异常", e, HeartbeatManagerImpl.class); + } + } + + /** + * 刷新客户端状态 + */ + @Override + public void flushClientStatus() { + List instances = clientHolder.getClientInstanceList(); + for(ClientInstance item: instances) { + try { + item.flush(); + if(item.needReform()) { + this.heartbeatReformService.sendReform(item); + } + if(item.needDeploy()) { + this.heartbeatDeployService.sendDeploy(item); + } + }catch (Exception e) { + UtilLog.error("刷新客户端状态出现异常,code["+item.getIdentity()+"]", e, this.getClass()); + } + } + } + + /** + * 向服务器发送心跳 + */ + @Override + public void sendServerHeartbeat() { + List instances = serverHolder.getServerInstanceList(); + for(ServerInstance item: instances) { + try { + item.flush(); + if(item.isSendNewHeartbeat()) { + this.createLog(item); + } + if(item.needReform()) { + this.heartbeatReformService.sendReform(item); + } + if(item.needDeploy()) { + this.heartbeatDeployService.sendDeploy(item); + } + }catch (Exception e) { + UtilLog.error("向服务器发送心跳出现异常,code["+item.getIdentity()+"]", e, this.getClass()); + } + } + } + + private void createLog(ServerInstance item) { + try { + AnalysisHeartbeatLogEntity log = new AnalysisHeartbeatLogEntity(); + log.setServerUrl(item.getLatestUrlWithParam()); + log.setInstanceCode(item.getIdentity()); + if(item.getLatestServerResponse() == null) { + log.setResponse("null"); + }else { + log.setResponse(item.getLatestServerResponse().toString()); + } + this.analysisHeartbeatLogRepository.addEntity(log, null); + }catch (Exception e) { + UtilLog.error("数据库异常:向服务器发送心跳,日志记录出现异常", e, HeartbeatManagerImpl.class); + } + } + + @Override + public void loadInstance(List instanceList) throws Exception{ + if(instanceList == null || instanceList.isEmpty()) { + return; + } + for(AnalysisHeartbeatInstanceEntity serverItem: instanceList) { + if(serverItem.getCode() == null || serverItem.getCode().trim().equals("")) { + continue; + } + if(serverItem.getFixRateSec() == null) { + serverItem.setFixRateSec(Instance.DEFAULT_FIX_RATE_SEC); + } + if(serverItem.getMaxWaitSec() == null) { + serverItem.setMaxWaitSec(Instance.DEFAULT_MAX_WAIT_SEC); + } + + try { + this.registryRuntimeInstance(serverItem); + }catch (Exception e) { + UtilLog.error("注册监控实例出现异常,code["+serverItem.getCode()+"]", e, this.getClass()); + } + } + } + + private void registryRuntimeInstance(AnalysisHeartbeatInstanceEntity serverItem) throws Exception { + if(AnalysisHeartbeatInstanceRepository.ROLE_TYPE_SERVER == serverItem.getRoleType().intValue()) { + serverHolder.registryServer(serverItem); + }else if(AnalysisHeartbeatInstanceRepository.ROLE_TYPE_CLIENT == serverItem.getRoleType().intValue()) { + clientHolder.registryClient(serverItem); + }else { + throw new RuntimeException("不支持的实例角色,INSTANCE:"+JSONObject.toJSONString(serverItem)); + } + } + + private void unregistryRuntimeInstance(AnalysisHeartbeatInstanceEntity serverItem) throws Exception { + if(AnalysisHeartbeatInstanceRepository.ROLE_TYPE_SERVER == serverItem.getRoleType().intValue()) { + serverHolder.unregistryServer(serverItem.getCode()); + }else if(AnalysisHeartbeatInstanceRepository.ROLE_TYPE_CLIENT == serverItem.getRoleType().intValue()) { + clientHolder.unregistryClient(serverItem.getCode()); + }else { + throw new RuntimeException("不支持的实例角色,INSTANCE:"+JSONObject.toJSONString(serverItem)); + } + } + + @Override + public void createInstance(HeartbeatInstanceCreateForm form) { + form.trimByRegexS(); + this.checkCreateForm(form); + AnalysisHeartbeatInstanceEntity instance = this.constructInstance(form); + Number id = this.analysisHeartbeatInstanceRepository.addEntity(instance, null); + try { + this.registryRuntimeInstance(this.analysisHeartbeatInstanceRepository.findEntityByID(id.longValue(), null)); + }catch (Exception e) { + UtilLog.error("注册监控实例出现异常,code["+instance.getCode()+"]", e, this.getClass()); + } + } + + private void checkCreateForm(HeartbeatInstanceCreateForm form) { + if(form.getCode() == null) { + throw new RuntimeException("未传入code"); + } + if(form.getFixRateSec() == null) { + throw new RuntimeException("未传入检查间隔(秒)"); + } + if(form.getMaxWaitSec() == null) { + throw new RuntimeException("未传入最大等待时间(秒)"); + } + if(form.getRoleType() == null) { + throw new RuntimeException("未传入实例类型"); + } + + } + + private AnalysisHeartbeatInstanceEntity constructInstance(HeartbeatInstanceCreateForm form) { + AnalysisHeartbeatInstanceEntity instance = new AnalysisHeartbeatInstanceEntity(); + instance.setCode(form.getCode()); + if(form.getDeployAtLostNum() != null) { + instance.setDeployAtLostNum(form.getDeployAtLostNum()); + } + if(form.getDeployUrl() != null) { + instance.setDeployUrl(form.getDeployUrl()); + } + if(form.getFixRateSec() != null) { + instance.setFixRateSec(form.getFixRateSec()); + } + if(form.getMaxWaitSec() != null) { + instance.setMaxWaitSec(form.getMaxWaitSec()); + } + if(form.getReformEmail() != null) { + instance.setReformEmail(form.getReformEmail()); + } + if(form.getReformMaxTime() != null) { + instance.setReformMaxTime(form.getReformMaxTime()); + } + if(form.getReformPhone() != null) { + instance.setReformPhone(form.getReformPhone()); + } + if(form.getReformWxid() != null) { + instance.setReformWxid(form.getReformWxid()); + } + if(form.getRoleType() != null) { + instance.setRoleType(form.getRoleType()); + } + if(form.getStatus() != null) { + instance.setStatus(form.getStatus()); + } + if(form.getUrl() != null) { + instance.setUrl(form.getUrl()); + } + if(form.getToken() != null) { + instance.setToken(form.getToken()); + } + return instance; + } + + @Override + public void updateInstance(HeartbeatInstanceUpdateForm form) { + form.trimByRegexS(); + AnalysisHeartbeatInstanceEntity instance = null; + try { + instance = this.analysisHeartbeatInstanceRepository.findEntityBySql("code='"+form.getCode()+"'", null); + } catch (NotFoundException | MultiRowException e1) { + throw new RuntimeException("code="+form.getCode()+"对应的实例数据异常(未找到或存在多条重复记录),请技术人员核实"); + } + this.analysisHeartbeatInstanceRepository.updateEntityById(form.getSQLUpdateList(), instance.getId(), null); + try { + if(AnalysisHeartbeatInstanceRepository.STATUS_DISABLE == instance.getStatus().intValue()) { + this.unregistryRuntimeInstance(instance); + }else { + this.registryRuntimeInstance(instance); + } + }catch (Exception e) { + UtilLog.error("注销监控实例出现异常,code["+instance.getCode()+"]", e, this.getClass()); + } + } + + @Override + public void disableInstanceByCode(String code) { + AnalysisHeartbeatInstanceEntity instance = null; + try { + instance = this.analysisHeartbeatInstanceRepository.findEntityBySql("code='"+code+"'", null); + } catch (NotFoundException | MultiRowException e1) { + throw new RuntimeException("code="+code+"对应的实例数据异常(未找到或存在多条重复记录),请技术人员核实"); + } + List updateList = new ArrayList(1); + updateList.add(new Object[] {"status", AnalysisHeartbeatInstanceRepository.STATUS_DISABLE}); + this.analysisHeartbeatInstanceRepository.updateEntityById(updateList, instance.getId(), null); + try { + this.unregistryRuntimeInstance(instance); + }catch (Exception e) { + UtilLog.error("注销监控实例出现异常,code["+instance.getCode()+"]", e, this.getClass()); + } + } + + @Override + public void enableInstanceByCode(String code) { + AnalysisHeartbeatInstanceEntity instance = null; + try { + instance = this.analysisHeartbeatInstanceRepository.findEntityBySql("code='"+code+"'", null); + } catch (NotFoundException | MultiRowException e1) { + throw new RuntimeException("code="+code+"对应的实例数据异常(未找到或存在多条重复记录),请技术人员核实"); + } + List updateList = new ArrayList(1); + updateList.add(new Object[] {"status", AnalysisHeartbeatInstanceRepository.STATUS_ENABLE}); + this.analysisHeartbeatInstanceRepository.updateEntityById(updateList, instance.getId(), null); + try { + this.registryRuntimeInstance(instance); + }catch (Exception e) { + UtilLog.error("注销监控实例出现异常,code["+instance.getCode()+"]", e, this.getClass()); + } + } +} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ClientInstance.java b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ClientInstance.java new file mode 100644 index 0000000..85aac75 --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ClientInstance.java @@ -0,0 +1,90 @@ +package com.taover.bazhuayun.analysis.web.module.heartbeat.bean; + +import com.taover.bazhuayun.analysis.web.repository.AnalysisHeartbeatInstanceEntity; +import com.taover.util.UtilLog; + +public class ClientInstance implements Instance{ + private AnalysisHeartbeatInstanceEntity instance; + private ClientRequest lastestClientRequest; + private long lastestServerUnixtime = System.currentTimeMillis()/1000; + private long currFlushServerUnixtimeBaseline = 0L; + private int lostClientRequestCount = 0; + private boolean detectNewLost = false; + + public ClientInstance(AnalysisHeartbeatInstanceEntity instance) { + this.instance = instance; + } + + @Override + public void flush() { + //还未收到请求,则无需刷新失败次数 + if(lastestClientRequest == null) { + return; + } + + this.detectNewLost = false; + this.currFlushServerUnixtimeBaseline = System.currentTimeMillis()/1000; + //通过服务器时间,判断是否超时未收到客户端请求 + if(isNewLoopForFixRateSec()) { + ++this.lostClientRequestCount; + this.detectNewLost = true; + + UtilLog.infoForMessage("检测到超时未收到请求,code["+this.getIdentity()+"],丢包统计["+this.lostClientRequestCount+"]", ServerInstance.class); + } + } + + private boolean isNewLoopForFixRateSec() { + return ((this.currFlushServerUnixtimeBaseline-this.lastestServerUnixtime) / this.instance.getFixRateSec()) > this.lostClientRequestCount; + } + + @Override + public boolean needReform() { + return this.detectNewLost && this.lostClientRequestCount>=1 && this.lostClientRequestCount<=this.instance.getReformMaxTime(); + } + + @Override + public boolean needDeploy() { + return this.detectNewLost && this.lostClientRequestCount == this.instance.getDeployAtLostNum(); + } + + public long getLastestServerUnixtime() { + return lastestServerUnixtime; + } + + public int getLostClientRequestCount() { + return lostClientRequestCount; + } + + public ClientRequest getLastestClientRequest() { + return lastestClientRequest; + } + + public AnalysisHeartbeatInstanceEntity getInstance() { + return instance; + } + + public void dealClientRequest(ClientRequest clientRequest) { + if(this.instance.getFixRateSec() == null) { + this.instance.setFixRateSec(Instance.DEFAULT_FIX_RATE_SEC); + } + if(this.instance.getMaxWaitSec() == null) { + this.instance.setMaxWaitSec(Instance.DEFAULT_MAX_WAIT_SEC); + } + this.lastestClientRequest = clientRequest; + this.lastestServerUnixtime = System.currentTimeMillis()/1000; + this.lostClientRequestCount = 0; + } + + @Override + public String getIdentity() { + return this.instance.getCode(); + } + + public long getUnixtime() { + if(this.lastestClientRequest == null) { + return this.lastestServerUnixtime; + }else { + return this.lastestClientRequest.getUnixtime(); + } + } +} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ClientRequest.java b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ClientRequest.java new file mode 100644 index 0000000..748c27f --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ClientRequest.java @@ -0,0 +1,63 @@ +package com.taover.bazhuayun.analysis.web.module.heartbeat.bean; + +import javax.servlet.http.HttpServletRequest; + +public class ClientRequest { + private String code = ""; + private String ip = ""; + private long unixtime; + private String seckey = ""; + + public String getCode() { + return code; + } + public void setCode(String code) { + this.code = code; + } + public String getIp() { + return ip; + } + public void setIp(String ip) { + this.ip = ip; + } + public long getUnixtime() { + return unixtime; + } + public void setUnixtime(long unixtime) { + this.unixtime = unixtime; + } + public String getSeckey() { + return seckey; + } + public void setSeckey(String seckey) { + this.seckey = seckey; + } + + public ClientRequest(String code, String ip, long unixtime, String seckey) { + this.code = code; + this.ip = ip; + this.unixtime = unixtime; + this.seckey = seckey; + } + + public ClientRequest(ClientRequest clientRequest) { + this.code = clientRequest.getCode(); + this.ip = clientRequest.getIp(); + this.unixtime = clientRequest.getUnixtime(); + this.seckey = clientRequest.getSeckey(); + } + + public static ClientRequest createClientRequest(HttpServletRequest request) { + String code = request.getParameter("code"); + String unixtime = request.getParameter("unixtime"); + String seckey = request.getParameter("seckey"); + String ip = request.getRemoteHost(); + return new ClientRequest(code, ip, + unixtime==null?0L:Long.valueOf(unixtime), + seckey); + } + + public String getIdentity() { + return this.code; + } +} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/Instance.java b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/Instance.java new file mode 100644 index 0000000..e17cfae --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/Instance.java @@ -0,0 +1,37 @@ +package com.taover.bazhuayun.analysis.web.module.heartbeat.bean; + +import com.taover.bazhuayun.analysis.web.repository.AnalysisHeartbeatInstanceEntity; + +public interface Instance { + public static final int DEFAULT_MAX_WAIT_SEC = -1; + public static final int DEFAULT_FIX_RATE_SEC = -1; + + /** + * 实例 + * @return + */ + AnalysisHeartbeatInstanceEntity getInstance(); + + /** + * 获取id字符串 + * @return + */ + String getIdentity(); + + /** + * 是否需要发送通知 + * @return + */ + boolean needReform(); + + /** + * 是否需要发布 + * @return + */ + boolean needDeploy(); + + /** + * 刷新状态 + */ + void flush(); +} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ServerInstance.java b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ServerInstance.java new file mode 100644 index 0000000..6f88952 --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ServerInstance.java @@ -0,0 +1,119 @@ +package com.taover.bazhuayun.analysis.web.module.heartbeat.bean; + +import java.net.SocketTimeoutException; + +import com.taover.bazhuayun.analysis.web.repository.AnalysisHeartbeatInstanceEntity; +import com.taover.util.UtilEncrypt; +import com.taover.util.UtilHttpByOkHttp; +import com.taover.util.UtilLog; + +public class ServerInstance implements Instance { + private AnalysisHeartbeatInstanceEntity instance; + private ServerResponse latestServerResponse; + private long latestRequestUnixtime = -1; + private long serverUnixtimeBaseline = 0L; + private int errorServerResponseCount = 0; + private boolean detectNewErrorServerResponse; + private boolean isSendNewHeartbeat; + private String latestUrlWithParam; + + public ServerInstance(AnalysisHeartbeatInstanceEntity instance) throws Exception { + super(); + if(!instance.getUrl().toLowerCase().startsWith("http")) { + throw new Exception("目前只支持http协议的URL"); + } + if(instance.getFixRateSec() < 60) { + throw new Exception("固定时间间隔不允许小于60s"); + } + this.instance = instance; + } + + @Override + public void flush() { + this.serverUnixtimeBaseline = System.currentTimeMillis()/1000; + this.detectNewErrorServerResponse = false; + this.isSendNewHeartbeat = false; + + //如果小于设置的发送时间间隔,则不发送请求 + if(!this.isNewLoopForFixRateSec()) { + return; + } + + this.latestRequestUnixtime = this.serverUnixtimeBaseline; + try { + this.isSendNewHeartbeat = true; + this.latestUrlWithParam = this.instance.getUrl() + this.getUrlParams(); + UtilLog.infoForMessage("向code["+this.getIdentity()+"],url["+this.latestUrlWithParam+"]发送心跳请求", ServerInstance.class); + + this.latestServerResponse = ServerResponse.createByJSONString(UtilHttpByOkHttp.sendGet(this.latestUrlWithParam, null, this.instance.getMaxWaitSec())); + if(this.latestServerResponse.isCodeOk()) { + this.errorServerResponseCount = 0; + } + } catch(SocketTimeoutException timeError) { + this.latestServerResponse = ServerResponse.createOverdue(); + } catch (Exception e) { + this.latestServerResponse = ServerResponse.createException(e); + } + + //判断响应是否正常 + if(this.latestServerResponse.isOverdue() || !this.latestServerResponse.isCodeOk()) { + ++this.errorServerResponseCount; + this.detectNewErrorServerResponse = true; + } + } + + private String getUrlParams() { + long time = this.serverUnixtimeBaseline; + String seckey = UtilEncrypt.MD5Lower32(this.instance.getCode()+time+this.instance.getToken()); + return "?code="+this.instance.getCode()+"&fixRateSec="+this.instance.getFixRateSec()+"&maxWaitSec="+this.instance.getMaxWaitSec()+"&unixtime="+time+"&seckey="+seckey; + } + + private boolean isNewLoopForFixRateSec() { + return ((this.serverUnixtimeBaseline-this.latestRequestUnixtime)/this.instance.getFixRateSec()) > this.errorServerResponseCount; + } + + public AnalysisHeartbeatInstanceEntity getInstance() { + return instance; + } + + @Override + public String getIdentity() { + return this.instance.getCode(); + } + + @Override + public boolean needDeploy() { + return this.detectNewErrorServerResponse && this.errorServerResponseCount == this.instance.getDeployAtLostNum(); + } + + @Override + public boolean needReform() { + return this.detectNewErrorServerResponse + && this.errorServerResponseCount>=1 + && this.errorServerResponseCount<=this.instance.getReformMaxTime(); + } + + public long getLatestRequestUnixtime() { + return latestRequestUnixtime; + } + + public ServerResponse getLatestServerResponse() { + return latestServerResponse; + } + + public int getErrorServerResponseCount() { + return errorServerResponseCount; + } + + public boolean isIncrErrorServerResponseCount() { + return detectNewErrorServerResponse; + } + + public boolean isSendNewHeartbeat() { + return isSendNewHeartbeat; + } + + public String getLatestUrlWithParam() { + return latestUrlWithParam; + } +} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ServerResponse.java b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ServerResponse.java new file mode 100644 index 0000000..757de7d --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/bean/ServerResponse.java @@ -0,0 +1,79 @@ +package com.taover.bazhuayun.analysis.web.module.heartbeat.bean; + +import org.apache.commons.lang.StringUtils; + +import com.alibaba.fastjson.JSONObject; + +public class ServerResponse { + public static String RESPONSE_CODE_OK = "ok"; + + private boolean isOverdue; + private boolean isCodeOk; + private String responseContent; + private Exception exception; + + private ServerResponse(boolean isOverdue, boolean isCodeOk, String responseContent, Exception e) { + super(); + this.isOverdue = isOverdue; + this.isCodeOk = isCodeOk; + this.responseContent = responseContent; + this.exception = e; + } + + public boolean isOverdue() { + return isOverdue; + } + public void setOverdue(boolean isOverdue) { + this.isOverdue = isOverdue; + } + public boolean isCodeOk() { + return isCodeOk; + } + public void setCodeOk(boolean isCodeOk) { + this.isCodeOk = isCodeOk; + } + public String getResponseContent() { + return responseContent; + } + public void setResponseContent(String responseContent) { + this.responseContent = responseContent; + } + public Exception getException() { + return exception; + } + public void setException(Exception exception) { + this.exception = exception; + } + + public static ServerResponse createByJSONString(String response) { + if(StringUtils.isBlank(response)) { + return new ServerResponse(false, false, response, null); + }else { + try { + JSONObject data = JSONObject.parseObject(response); + String code = data.getString("code"); + if(RESPONSE_CODE_OK.equals(code.toLowerCase())) { + return new ServerResponse(false, true, response, null); + }else { + return new ServerResponse(false, false, response, null); + } + }catch (Exception e) { + return new ServerResponse(false, false, response, e); + } + } + } + + public static ServerResponse createOverdue() { + return new ServerResponse(false, false, "", null); + } + + public static ServerResponse createException(Exception e) { + return new ServerResponse(false, false, "", e); + } + + @Override + public String toString() { + return "ServerResponse [isOverdue=" + isOverdue + ", isCodeOk=" + isCodeOk + ", responseContent=" + + responseContent + ", exception=" + (exception==null?"":exception.getMessage()) + "]"; + } +} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ClientHolder.java b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ClientHolder.java new file mode 100644 index 0000000..fa14e4e --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ClientHolder.java @@ -0,0 +1,21 @@ +package com.taover.bazhuayun.analysis.web.module.heartbeat.holder; + +import java.util.List; + +import com.taover.bazhuayun.analysis.web.module.heartbeat.bean.ClientInstance; +import com.taover.bazhuayun.analysis.web.module.heartbeat.bean.ClientRequest; +import com.taover.bazhuayun.analysis.web.repository.AnalysisHeartbeatInstanceEntity; + +public interface ClientHolder { + void dealClientRequest(ClientRequest clientRequest, AnalysisHeartbeatInstanceEntity instance); + + void registryClient(AnalysisHeartbeatInstanceEntity instance); + + List getClientInstanceList(); + + void flushClientStatus(ClientInstance clientInstance); + + void unregistryClient(String code); + + boolean containInstanceCode(String code); +} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ClientHolderImpl.java b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ClientHolderImpl.java new file mode 100644 index 0000000..899d1df --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ClientHolderImpl.java @@ -0,0 +1,71 @@ +package com.taover.bazhuayun.analysis.web.module.heartbeat.holder; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.commons.lang.StringUtils; + +import com.taover.bazhuayun.analysis.web.module.heartbeat.bean.ClientInstance; +import com.taover.bazhuayun.analysis.web.module.heartbeat.bean.ClientRequest; +import com.taover.bazhuayun.analysis.web.repository.AnalysisHeartbeatInstanceEntity; +import com.taover.util.UtilEncrypt; + +public class ClientHolderImpl implements ClientHolder{ + Map clientMap = new ConcurrentHashMap(); + + @Override + public List getClientInstanceList() { + return new ArrayList(clientMap.values()); + } + + @Override + public void flushClientStatus(ClientInstance clientInstance) { + clientInstance.flush(); + } + + @Override + public void dealClientRequest(ClientRequest clientRequest, AnalysisHeartbeatInstanceEntity instance) { + this.validClientRequest(clientRequest, instance.getToken()); + synchronized (this.clientMap) { + ClientInstance client = null; + if(clientMap.containsKey(clientRequest.getIdentity())) { + client = clientMap.get(clientRequest.getIdentity()); + clientMap.put(client.getIdentity(), client); + }else { + throw new RuntimeException("找不到code="+clientRequest.getIdentity()+"的监控实例"); + } + client.dealClientRequest(clientRequest); + } + } + + private void validClientRequest(ClientRequest clientRequest, String token) { + long time = clientRequest.getUnixtime(); + String seckey = UtilEncrypt.MD5Lower32(clientRequest.getCode()+time+token); + if(StringUtils.isBlank(clientRequest.getCode())) { + throw new RuntimeException("未传入code信息"); + } + if(!seckey.equals(clientRequest.getSeckey())) { + throw new RuntimeException("秘钥信息检查失败"); + } + } + + @Override + public void registryClient(AnalysisHeartbeatInstanceEntity instance) { + synchronized (this.clientMap) { + ClientInstance client = new ClientInstance(instance); + clientMap.put(client.getIdentity(), client); + } + } + + @Override + public void unregistryClient(String code) { + clientMap.remove(code); + } + + @Override + public boolean containInstanceCode(String code) { + return clientMap.containsKey(code); + } +} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ServerHolder.java b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ServerHolder.java new file mode 100644 index 0000000..567d4a8 --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ServerHolder.java @@ -0,0 +1,16 @@ +package com.taover.bazhuayun.analysis.web.module.heartbeat.holder; + +import java.util.List; + +import com.taover.bazhuayun.analysis.web.module.heartbeat.bean.ServerInstance; +import com.taover.bazhuayun.analysis.web.repository.AnalysisHeartbeatInstanceEntity; + +public interface ServerHolder { + List getServerInstanceList(); + + void registryServer(AnalysisHeartbeatInstanceEntity instance) throws Exception; + + void flushServerStatus(ServerInstance serverInstance); + + void unregistryServer(String code); +} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ServerHolderImpl.java b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ServerHolderImpl.java new file mode 100644 index 0000000..8e8114e --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/holder/ServerHolderImpl.java @@ -0,0 +1,34 @@ +package com.taover.bazhuayun.analysis.web.module.heartbeat.holder; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.taover.bazhuayun.analysis.web.module.heartbeat.bean.ServerInstance; +import com.taover.bazhuayun.analysis.web.repository.AnalysisHeartbeatInstanceEntity; + +public class ServerHolderImpl implements ServerHolder { + Map serverMap = new ConcurrentHashMap(); + + @Override + public List getServerInstanceList() { + return new ArrayList(serverMap.values()); + } + + @Override + public void registryServer(AnalysisHeartbeatInstanceEntity instance) throws Exception { + ServerInstance server = new ServerInstance(instance); + serverMap.put(server.getIdentity(), server); + } + + @Override + public void flushServerStatus(ServerInstance serverInstance) { + serverInstance.flush(); + } + + @Override + public void unregistryServer(String code) { + serverMap.remove(code); + } +} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatDeployService.java b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatDeployService.java new file mode 100644 index 0000000..9dfad9d --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatDeployService.java @@ -0,0 +1,7 @@ +package com.taover.bazhuayun.analysis.web.module.heartbeat.service; + +import com.taover.bazhuayun.analysis.web.module.heartbeat.bean.Instance; + +public interface HeartbeatDeployService { + void sendDeploy(Instance item); +} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatDeployServiceImpl.java b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatDeployServiceImpl.java new file mode 100644 index 0000000..a032386 --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatDeployServiceImpl.java @@ -0,0 +1,46 @@ +package com.taover.bazhuayun.analysis.web.module.heartbeat.service; + +import javax.annotation.Resource; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import com.taover.bazhuayun.analysis.web.module.heartbeat.bean.Instance; +import com.taover.bazhuayun.analysis.web.repository.AnalysisHeartbeatReformEntity; +import com.taover.bazhuayun.analysis.web.repository.AnalysisHeartbeatReformRepository; +import com.taover.util.UtilHttpByOkHttp; +import com.taover.util.UtilLog; + +@Service +public class HeartbeatDeployServiceImpl implements HeartbeatDeployService { + @Resource + private AnalysisHeartbeatReformRepository analysisHeartbeatReformRepository; + @Resource + private HeartbeatReformService heartbeatReformService; + + private void createDeployLog(Instance instance, String response) { + AnalysisHeartbeatReformEntity reform = new AnalysisHeartbeatReformEntity(); + reform.setInstanceCode(instance.getIdentity()); + reform.setReformContent(response); + reform.setReformInfo("调用发布URL"); + reform.setReformType(AnalysisHeartbeatReformRepository.REFORM_TYPE_WEIXIN); + this.analysisHeartbeatReformRepository.addEntity(reform, null); + } + + @Override + public void sendDeploy(Instance item) { + if(item.getInstance() == null || StringUtils.isBlank(item.getInstance().getDeployUrl())) { + return; + } + String response = null; + try { + response = UtilHttpByOkHttp.sendGet(item.getInstance().getDeployUrl(), null); + this.heartbeatReformService.sendReformDeploy(item); + } catch (Exception e) { + UtilLog.error("调用自动发布URL发生异常,发布URL["+item.getInstance().getDeployUrl()+"]", e, HeartbeatDeployServiceImpl.class); + response = e.getMessage(); + this.heartbeatReformService.sendErrorMsg(item, response); + } + this.createDeployLog(item, response); + } +} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatReformService.java b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatReformService.java new file mode 100644 index 0000000..fd9534d --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatReformService.java @@ -0,0 +1,11 @@ +package com.taover.bazhuayun.analysis.web.module.heartbeat.service; + +import com.taover.bazhuayun.analysis.web.module.heartbeat.bean.Instance; + +public interface HeartbeatReformService { + void sendReform(Instance item); + + void sendReformDeploy(Instance item); + + void sendErrorMsg(Instance item, String response); +} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatReformServiceImpl.java b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatReformServiceImpl.java new file mode 100644 index 0000000..0c99485 --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/module/heartbeat/service/HeartbeatReformServiceImpl.java @@ -0,0 +1,264 @@ +package com.taover.bazhuayun.analysis.web.module.heartbeat.service; + +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; + +import javax.annotation.Resource; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.taover.bazhuayun.analysis.web.module.heartbeat.bean.ClientInstance; +import com.taover.bazhuayun.analysis.web.module.heartbeat.bean.Instance; +import com.taover.bazhuayun.analysis.web.module.heartbeat.bean.ServerInstance; +import com.taover.bazhuayun.analysis.web.repository.AnalysisHeartbeatInstanceEntity; +import com.taover.bazhuayun.analysis.web.repository.AnalysisHeartbeatReformEntity; +import com.taover.bazhuayun.analysis.web.repository.AnalysisHeartbeatReformRepository; +import com.taover.util.UtilEmail; +import com.taover.util.UtilLog; +import com.taover.util.UtilWeixinMsg; + +@Service +public class HeartbeatReformServiceImpl implements HeartbeatReformService { + @Resource + private AnalysisHeartbeatReformRepository analysisHeartbeatReformRepository; + + private void sendWarnWeixin(Instance instance, String weixinContent) { + if(StringUtils.isBlank(instance.getInstance().getReformWxid())) { + return; + } + try { + String[] wxidArr = instance.getInstance().getReformWxid().split(","); + for(String weixinWxid: wxidArr) { + if(weixinWxid != null && !weixinWxid.trim().equals("")) { + UtilWeixinMsg.sendTextMessage(weixinWxid, weixinContent); + this.createWeixinReformLog(instance, weixinWxid, weixinContent); + } + } + } catch (Exception e) { + UtilLog.infoForMessage("发送微信消息失败,消息内容:"+weixinContent, this.getClass()); + UtilLog.errorForException(e, this.getClass()); + } + } + + private void createWeixinReformLog(Instance instance, String weixinWxid, String weixinContent) { + AnalysisHeartbeatReformEntity reform = new AnalysisHeartbeatReformEntity(); + reform.setInstanceCode(instance.getIdentity()); + reform.setReformContent(weixinContent); + reform.setReformInfo(weixinWxid); + reform.setReformType(AnalysisHeartbeatReformRepository.REFORM_TYPE_WEIXIN); + this.analysisHeartbeatReformRepository.addEntity(reform, null); + } + + private String formatWeixin(ServerInstance instance) { + String htmlContent = ""; + AnalysisHeartbeatInstanceEntity entity = instance.getInstance(); + if(instance.getLatestServerResponse() == null) { + htmlContent += " 未收到服务器响应\n"; + }else { + if(instance.getLatestServerResponse().isOverdue()) { + htmlContent += " 向接口["+entity.getUrl()+"]发送请求,响应超时["+entity.getMaxWaitSec()+"s],请及时确认服务是否正常运行\n"; + }else if(!instance.getLatestServerResponse().isCodeOk()) { + htmlContent += " 向接口["+entity.getUrl()+"]发送请求,响应数据不正常(详细请查看邮件),请及时确认服务是否正常运行\n"; + }else { + htmlContent += " 向接口["+entity.getUrl()+"]发送请求,未知异常,请及时确认服务是否正常运行\n"; + } + } + htmlContent += " 最后一次请求时间: "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(instance.getLatestRequestUnixtime()*1000)); + return htmlContent; + } + + private String formatWeixin(ClientInstance instance) { + String htmlContent = " 超过"+instance.getInstance().getFixRateSec()+"秒未收到请求,请确认CODE["+instance.getIdentity()+"]对应的服务是否运行正常\n"; + htmlContent += " 客户端最后一次请求时间: "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(instance.getLastestClientRequest().getUnixtime()*1000))+"\n"; + htmlContent += " 累计次数("+instance.getInstance().getReformMaxTime()+"次后不再报警):"+instance.getLostClientRequestCount(); + return htmlContent; + } + + private void sendWarnEmail(Instance instance, String subject, String htmlContent) { + if(StringUtils.isBlank(instance.getInstance().getReformEmail())) { + return; + } + try { + String[] emailArr = instance.getInstance().getReformEmail().split(","); + if(emailArr.length == 0) { + return; + } + UtilEmail.sendHtmlMail(Arrays.asList(emailArr), subject, htmlContent); + this.createHtmlReformLog(instance, emailArr, subject, htmlContent); + } catch (Exception e) { + UtilLog.infoForMessage("发送邮件失败,消息内容:[标题:"+subject+"],[正文:"+htmlContent+"]", this.getClass()); + UtilLog.errorForException(e, this.getClass()); + } + } + + private void createHtmlReformLog(Instance instance, String[] emailArr, String subject, String htmlContent) { + AnalysisHeartbeatReformEntity reform = new AnalysisHeartbeatReformEntity(); + reform.setInstanceCode(instance.getIdentity()); + JSONObject data = new JSONObject(); + data.put("subject", subject); + data.put("content", htmlContent); + reform.setReformContent(data.toJSONString()); + reform.setReformInfo(StringUtils.join(emailArr, ",")); + reform.setReformType(AnalysisHeartbeatReformRepository.REFORM_TYPE_EMAIL); + this.analysisHeartbeatReformRepository.addEntity(reform, null); + } + + private String formatHtml(ServerInstance instance) { + String htmlContent = ""; + htmlContent += "

"; + AnalysisHeartbeatInstanceEntity entity = instance.getInstance(); + if(instance.getLatestServerResponse() != null) { + if(instance.getLatestServerResponse().isOverdue()) { + htmlContent += " 向接口["+entity.getUrl()+"]发送请求,响应超时["+entity.getMaxWaitSec()+"s],请及时确认服务是否正常运行"; + }else if(!instance.getLatestServerResponse().isCodeOk()) { + htmlContent += " 向接口["+entity.getUrl()+"]发送请求,响应数据不正常(详细请查看邮件),请及时确认服务是否正常运行"; + }else { + htmlContent += "未知异常"; + } + }else { + htmlContent += "未记录最后一次响应记录"; + } + htmlContent += "

"; + htmlContent += "
    "; + htmlContent += "
  • CODE: "+instance.getIdentity()+"
  • "; + htmlContent += "
  • URL: "+entity.getUrl()+"
  • "; + htmlContent += "
  • 请求频率: "+entity.getFixRateSec()+"秒/次
  • "; + htmlContent += "
  • 请求最大等待时间: "+entity.getMaxWaitSec()+"秒
  • "; + htmlContent += "
  • 客户端请求时间戳: "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(instance.getLatestRequestUnixtime()*1000))+"
  • "; + htmlContent += "
  • 最后一次收到的响应包: "+JSON.toJSONString(instance.getLatestServerResponse())+"
  • "; + htmlContent += "
"; + return htmlContent; + } + + private String formatHtml(ClientInstance instance) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + AnalysisHeartbeatInstanceEntity entity = instance.getInstance(); + String htmlContent = ""; + htmlContent += "

"; + htmlContent += "超过"+entity.getFixRateSec()+"秒未收到请求,请确认CODE["+instance.getIdentity()+"]对应的客户端是否运行正常
"; + htmlContent += "客户端最后一次请求时间: "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(instance.getUnixtime()*1000)); + htmlContent += "

"; + htmlContent += "
    "; + htmlContent += "
  • CODE: "+instance.getIdentity()+"
  • "; + //htmlContent += "
  • IP: "+instance.getIp()+"
  • "; + htmlContent += "
  • 请求频率: "+entity.getFixRateSec()+"秒/次
  • "; + htmlContent += "
  • 请求最大等待时间: "+entity.getMaxWaitSec()+"秒
  • "; + htmlContent += "
  • 客户端请求时间戳: "+sdf.format(new Date(instance.getUnixtime()*1000))+"
  • "; + htmlContent += "
  • 服务器接收时间: "+sdf.format(new Date(instance.getLastestServerUnixtime()*1000))+"
  • "; + htmlContent += "
  • 最后一次收到的请求包: "+JSON.toJSONString(instance.getLastestClientRequest())+"
  • "; + htmlContent += "
  • 累计次数("+entity.getReformMaxTime()+"次后不再报警):"+instance.getLostClientRequestCount()+"
  • "; + htmlContent += "
"; + return htmlContent; + } + + private String[] formatNormalEmailInfo(Instance instance) { + String subject = "报警-项目可用性监控--监控ID["+instance.getIdentity()+"]"; + String htmlContent = "

监控ID:"+instance.getIdentity()+"

"; + if(instance instanceof ClientInstance) { + htmlContent += this.formatHtml((ClientInstance)instance); + }else if(instance instanceof ServerInstance) { + htmlContent += this.formatHtml((ServerInstance)instance); + }else { + try { + htmlContent += "

"+JSONObject.toJSONString(instance)+"

"; + }catch (Exception e) { + htmlContent += "对象无法序列化打印,instance.toString() ==>> "+instance.toString()+""; + } + } + return new String[] {subject, htmlContent}; + } + + @Override + public void sendReform(Instance item) { + String[] emailData = this.formatNormalEmailInfo(item); + this.sendWarnEmail(item, emailData[0], emailData[1]); + + String weixinContent = this.formatNormalWeixinContent(item); + this.sendWarnWeixin(item, weixinContent); + } + + private String formatNormalWeixinContent(Instance instance) { + String weixinContent = "报警-项目可用性监控\n"; + if(instance instanceof ClientInstance) { + weixinContent += this.formatWeixin((ClientInstance)instance); + }else if(instance instanceof ServerInstance) { + weixinContent += this.formatWeixin((ServerInstance)instance); + }else { + try { + weixinContent += " JSON序列化:"+JSONObject.toJSONString(instance); + }catch (Exception e) { + weixinContent += " 对象无法序列化打印,instance.toString() ==>> "+instance.toString(); + } + } + return weixinContent; + } + + @Override + public void sendReformDeploy(Instance item) { + String[] emailData = this.formatDeployEmailInfo(item); + this.sendWarnEmail(item, emailData[0], emailData[1]); + + String weixinContent = this.formatDelayWeixin(item); + this.sendWarnWeixin(item, weixinContent); + } + + private String formatDelayWeixin(Instance instance) { + return "通知-项目可用性监控--自动发布任务\n" + + " CODE["+instance.getIdentity()+"]对应的服务多次检查失败\n" + + " 系统自动调度执行发布任务,服务怠机原因,请及时核实解决~"; + } + + private String[] formatDeployEmailInfo(Instance instance) { + String subject = "通知-项目可用性监控--执行发布任务["+instance.getIdentity()+"]"; + String htmlContent = "

监控ID:"+instance.getIdentity()+"

"; + if(instance instanceof ClientInstance) { + htmlContent += this.formatHtml((ClientInstance)instance); + }else if(instance instanceof ServerInstance) { + htmlContent += this.formatHtml((ServerInstance)instance); + }else { + try { + htmlContent += "

"+JSONObject.toJSONString(instance)+"

"; + }catch (Exception e) { + htmlContent += "对象无法序列化打印,instance.toString() ==>> "+instance.toString()+""; + } + } + return new String[] {subject, htmlContent}; + } + + @Override + public void sendErrorMsg(Instance item, String response) { + String[] emailData = this.formatErrorEmailInfo(item, response); + this.sendWarnEmail(item, emailData[0], emailData[1]); + + String weixinContent = this.formatErrorWeixinContent(item, response); + this.sendWarnWeixin(item, weixinContent); + } + + private String[] formatErrorEmailInfo(Instance instance, String response) { + String subject = "异常-项目可用监控--异常通知["+instance.getIdentity()+"]"; + String htmlContent = "

监控ID:"+instance.getIdentity()+"

" + + "

异常内容:"+response+"

"; + if(instance instanceof ClientInstance) { + htmlContent += this.formatHtml((ClientInstance)instance); + }else if(instance instanceof ServerInstance) { + htmlContent += this.formatHtml((ServerInstance)instance); + }else { + try { + htmlContent += "

"+JSONObject.toJSONString(instance)+"

"; + }catch (Exception e) { + htmlContent += "对象无法序列化打印,instance.toString() ==>> "+instance.toString()+""; + } + } + return new String[] {subject, htmlContent}; + } + + private String formatErrorWeixinContent(Instance instance, String response) { + return "异常-项目可用监控\n" + + " CODE["+instance.getIdentity()+"]对应的服务出现异常\n" + + " 异常内容:"+response; + } +} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatInstanceEntity.java b/src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatInstanceEntity.java new file mode 100644 index 0000000..73f07f0 --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatInstanceEntity.java @@ -0,0 +1,236 @@ +package com.taover.bazhuayun.analysis.web.repository; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.sql.Timestamp; +import java.util.Date; + +import javax.persistence.Entity; +import javax.persistence.Table; +import javax.persistence.Id; +import javax.persistence.Column; + +/** + * @version 1.0.0 + */ +@Entity +@Table(name="analysis_heartbeat_instance", catalog="") +public class AnalysisHeartbeatInstanceEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + + /** + * + */ + @Id + @Column(name="id") + private java.lang.Long id; + + public java.lang.Long getId(){ + return id; + } + public void setId(java.lang.Long id){ + this.id = id; + } + + /** + * 实例类型:0-请求端,1-服务端 + */ + @Column(name="role_type") + private java.lang.Integer roleType; + + public java.lang.Integer getRoleType(){ + return roleType; + } + public void setRoleType(java.lang.Integer roleType){ + this.roleType = roleType; + } + + /** + * + */ + @Column(name="url") + private java.lang.String url; + + public java.lang.String getUrl(){ + return url; + } + public void setUrl(java.lang.String url){ + this.url = url; + } + + /** + * + */ + @Column(name="code") + private java.lang.String code; + + public java.lang.String getCode(){ + return code; + } + public void setCode(java.lang.String code){ + this.code = code; + } + + /** + * + */ + @Column(name="fix_rate_sec") + private java.lang.Integer fixRateSec; + + public java.lang.Integer getFixRateSec(){ + return fixRateSec; + } + public void setFixRateSec(java.lang.Integer fixRateSec){ + this.fixRateSec = fixRateSec; + } + + /** + * + */ + @Column(name="max_wait_sec") + private java.lang.Integer maxWaitSec; + + public java.lang.Integer getMaxWaitSec(){ + return maxWaitSec; + } + public void setMaxWaitSec(java.lang.Integer maxWaitSec){ + this.maxWaitSec = maxWaitSec; + } + + /** + * + */ + @Column(name="token") + private java.lang.String token; + + public java.lang.String getToken(){ + return token; + } + public void setToken(java.lang.String token){ + this.token = token; + } + + /** + * + */ + @Column(name="reform_email") + private java.lang.String reformEmail; + + public java.lang.String getReformEmail(){ + return reformEmail; + } + public void setReformEmail(java.lang.String reformEmail){ + this.reformEmail = reformEmail; + } + + /** + * + */ + @Column(name="reform_wxid") + private java.lang.String reformWxid; + + public java.lang.String getReformWxid(){ + return reformWxid; + } + public void setReformWxid(java.lang.String reformWxid){ + this.reformWxid = reformWxid; + } + + /** + * + */ + @Column(name="reform_phone") + private java.lang.String reformPhone; + + public java.lang.String getReformPhone(){ + return reformPhone; + } + public void setReformPhone(java.lang.String reformPhone){ + this.reformPhone = reformPhone; + } + + /** + * 可用状态:0-注销,1-使用中 + */ + @Column(name="status") + private java.lang.Integer status; + + public java.lang.Integer getStatus(){ + return status; + } + public void setStatus(java.lang.Integer status){ + this.status = status; + } + + /** + * + */ + @Column(name="create_time") + private java.sql.Timestamp createTime; + + public java.sql.Timestamp getCreateTime(){ + return createTime; + } + public void setCreateTime(java.sql.Timestamp createTime){ + this.createTime = createTime; + } + + /** + * + */ + @Column(name="update_time") + private java.sql.Timestamp updateTime; + + public java.sql.Timestamp getUpdateTime(){ + return updateTime; + } + public void setUpdateTime(java.sql.Timestamp updateTime){ + this.updateTime = updateTime; + } + + /** + * + */ + @Column(name="reform_max_time") + private java.lang.Integer reformMaxTime; + + public java.lang.Integer getReformMaxTime(){ + return reformMaxTime; + } + public void setReformMaxTime(java.lang.Integer reformMaxTime){ + this.reformMaxTime = reformMaxTime; + } + + /** + * + */ + @Column(name="deploy_url") + private java.lang.String deployUrl; + + public java.lang.String getDeployUrl(){ + return deployUrl; + } + public void setDeployUrl(java.lang.String deployUrl){ + this.deployUrl = deployUrl; + } + + /** + * 丢包满足多少次,则调用发布 + */ + @Column(name="deploy_at_lost_num") + private java.lang.Integer deployAtLostNum; + + public java.lang.Integer getDeployAtLostNum(){ + return deployAtLostNum; + } + public void setDeployAtLostNum(java.lang.Integer deployAtLostNum){ + this.deployAtLostNum = deployAtLostNum; + } + + @Override + public String toString() { + return "AnalysisHeartbeatInstanceEntity: [id="+id+",roleType="+roleType+",url="+url+",code="+code+",fixRateSec="+fixRateSec+",maxWaitSec="+maxWaitSec+",token="+token+",reformEmail="+reformEmail+",reformWxid="+reformWxid+",reformPhone="+reformPhone+",status="+status+",createTime="+createTime+",updateTime="+updateTime+",reformMaxTime="+reformMaxTime+",deployUrl="+deployUrl+",deployAtLostNum="+deployAtLostNum+"]"; + } + } diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatInstanceRepository.java b/src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatInstanceRepository.java new file mode 100644 index 0000000..138e8c2 --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatInstanceRepository.java @@ -0,0 +1,25 @@ +package com.taover.bazhuayun.analysis.web.repository; + +import org.springframework.stereotype.Repository; + +import com.taover.repository.CustomJdbcTemplateWrapperTenant; +import com.taover.repository.jdbctemplate.JdbcTemplateWrapperTenant; + +@Repository +public class AnalysisHeartbeatInstanceRepository extends CustomJdbcTemplateWrapperTenant{ + + public static final int STATUS_ENABLE = 1; + public static final int STATUS_DISABLE = 0; + public static final int ROLE_TYPE_CLIENT = 0; + public static final int ROLE_TYPE_SERVER = 1; + + public AnalysisHeartbeatInstanceRepository() throws Exception { + super(); + } + + public AnalysisHeartbeatInstanceRepository(JdbcTemplateWrapperTenant jdbcTemplate) throws Exception { + super(jdbcTemplate); + } + +} + diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatLogEntity.java b/src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatLogEntity.java new file mode 100644 index 0000000..d8c010e --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatLogEntity.java @@ -0,0 +1,132 @@ +package com.taover.bazhuayun.analysis.web.repository; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.sql.Timestamp; +import java.util.Date; + +import javax.persistence.Entity; +import javax.persistence.Table; +import javax.persistence.Id; +import javax.persistence.Column; + +/** + * @version 1.0.0 + */ +@Entity +@Table(name="analysis_heartbeat_log", catalog="") +public class AnalysisHeartbeatLogEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + + /** + * + */ + @Id + @Column(name="id") + private java.lang.Long id; + + public java.lang.Long getId(){ + return id; + } + public void setId(java.lang.Long id){ + this.id = id; + } + + /** + * + */ + @Column(name="instance_code") + private java.lang.String instanceCode; + + public java.lang.String getInstanceCode(){ + return instanceCode; + } + public void setInstanceCode(java.lang.String instanceCode){ + this.instanceCode = instanceCode; + } + + /** + * + */ + @Column(name="client_ip") + private java.lang.String clientIp; + + public java.lang.String getClientIp(){ + return clientIp; + } + public void setClientIp(java.lang.String clientIp){ + this.clientIp = clientIp; + } + + /** + * + */ + @Column(name="server_url") + private java.lang.String serverUrl; + + public java.lang.String getServerUrl(){ + return serverUrl; + } + public void setServerUrl(java.lang.String serverUrl){ + this.serverUrl = serverUrl; + } + + /** + * + */ + @Column(name="response") + private java.lang.String response; + + public java.lang.String getResponse(){ + return response; + } + public void setResponse(java.lang.String response){ + this.response = response; + } + + /** + * + */ + @Column(name="create_time") + private java.sql.Timestamp createTime; + + public java.sql.Timestamp getCreateTime(){ + return createTime; + } + public void setCreateTime(java.sql.Timestamp createTime){ + this.createTime = createTime; + } + + /** + * + */ + @Column(name="update_time") + private java.sql.Timestamp updateTime; + + public java.sql.Timestamp getUpdateTime(){ + return updateTime; + } + public void setUpdateTime(java.sql.Timestamp updateTime){ + this.updateTime = updateTime; + } + + /** + * + */ + @Column(name="request") + private java.lang.String request; + + public java.lang.String getRequest(){ + return request; + } + public void setRequest(java.lang.String request){ + this.request = request; + } + + @Override + public String toString() { + return "AnalysisHeartbeatLogEntity: [id="+id+",instanceCode="+instanceCode+",clientIp="+clientIp+",serverUrl="+serverUrl+",response="+response+",createTime="+createTime+",updateTime="+updateTime+",request="+request+"]"; + } + } diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatLogRepository.java b/src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatLogRepository.java new file mode 100644 index 0000000..7853396 --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatLogRepository.java @@ -0,0 +1,19 @@ +package com.taover.bazhuayun.analysis.web.repository; + +import org.springframework.stereotype.Repository; + +import com.taover.repository.CustomJdbcTemplateWrapperTenant; +import com.taover.repository.jdbctemplate.JdbcTemplateWrapperTenant; + +@Repository +public class AnalysisHeartbeatLogRepository extends CustomJdbcTemplateWrapperTenant{ + public AnalysisHeartbeatLogRepository() throws Exception { + super(); + } + + public AnalysisHeartbeatLogRepository(JdbcTemplateWrapperTenant jdbcTemplate) throws Exception { + super(jdbcTemplate); + } + +} + diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatReformEntity.java b/src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatReformEntity.java new file mode 100644 index 0000000..39e2766 --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatReformEntity.java @@ -0,0 +1,119 @@ +package com.taover.bazhuayun.analysis.web.repository; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.sql.Timestamp; +import java.util.Date; + +import javax.persistence.Entity; +import javax.persistence.Table; +import javax.persistence.Id; +import javax.persistence.Column; + +/** + * @version 1.0.0 + */ +@Entity +@Table(name="analysis_heartbeat_reform", catalog="") +public class AnalysisHeartbeatReformEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + + /** + * + */ + @Id + @Column(name="id") + private java.lang.Long id; + + public java.lang.Long getId(){ + return id; + } + public void setId(java.lang.Long id){ + this.id = id; + } + + /** + * + */ + @Column(name="instance_code") + private java.lang.String instanceCode; + + public java.lang.String getInstanceCode(){ + return instanceCode; + } + public void setInstanceCode(java.lang.String instanceCode){ + this.instanceCode = instanceCode; + } + + /** + * 通知类型:0-邮件,1-微信,2-短信 + */ + @Column(name="reform_type") + private java.lang.Integer reformType; + + public java.lang.Integer getReformType(){ + return reformType; + } + public void setReformType(java.lang.Integer reformType){ + this.reformType = reformType; + } + + /** + * + */ + @Column(name="reform_info") + private java.lang.String reformInfo; + + public java.lang.String getReformInfo(){ + return reformInfo; + } + public void setReformInfo(java.lang.String reformInfo){ + this.reformInfo = reformInfo; + } + + /** + * + */ + @Column(name="reform_content") + private java.lang.String reformContent; + + public java.lang.String getReformContent(){ + return reformContent; + } + public void setReformContent(java.lang.String reformContent){ + this.reformContent = reformContent; + } + + /** + * + */ + @Column(name="create_time") + private java.sql.Timestamp createTime; + + public java.sql.Timestamp getCreateTime(){ + return createTime; + } + public void setCreateTime(java.sql.Timestamp createTime){ + this.createTime = createTime; + } + + /** + * + */ + @Column(name="update_time") + private java.sql.Timestamp updateTime; + + public java.sql.Timestamp getUpdateTime(){ + return updateTime; + } + public void setUpdateTime(java.sql.Timestamp updateTime){ + this.updateTime = updateTime; + } + + @Override + public String toString() { + return "AnalysisHeartbeatReformEntity: [id="+id+",instanceCode="+instanceCode+",reformType="+reformType+",reformInfo="+reformInfo+",reformContent="+reformContent+",createTime="+createTime+",updateTime="+updateTime+"]"; + } + } diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatReformRepository.java b/src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatReformRepository.java new file mode 100644 index 0000000..b4766b1 --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/repository/AnalysisHeartbeatReformRepository.java @@ -0,0 +1,24 @@ +package com.taover.bazhuayun.analysis.web.repository; + +import org.springframework.stereotype.Repository; + +import com.taover.repository.CustomJdbcTemplateWrapperTenant; +import com.taover.repository.jdbctemplate.JdbcTemplateWrapperTenant; + +@Repository +public class AnalysisHeartbeatReformRepository extends CustomJdbcTemplateWrapperTenant{ + + public static final int REFORM_TYPE_EMAIL = 0; + public static final int REFORM_TYPE_WEIXIN = 1; + public static final int REFORM_TYPE_DEPLOY = 2; + + public AnalysisHeartbeatReformRepository() throws Exception { + super(); + } + + public AnalysisHeartbeatReformRepository(JdbcTemplateWrapperTenant jdbcTemplate) throws Exception { + super(jdbcTemplate); + } + +} + diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/scafford/CodeGeneraterWB.java b/src/main/java/com/taover/bazhuayun/analysis/web/scafford/CodeGeneraterWB.java new file mode 100644 index 0000000..2dd806b --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/scafford/CodeGeneraterWB.java @@ -0,0 +1,67 @@ +package com.taover.bazhuayun.analysis.web.scafford; + +import com.taover.codegenerate.bazhuayun.GenerateCode; + +public class CodeGeneraterWB { + public static void main(String args[]){ + generateEntity("analysis_heartbeat_log"); + //generateRepository("analysis_heartbeat_log"); + } + + public static void generateEntity(String tableName){ + try { + GenerateCode.generateEntity("com.taover.bazhuayun.analysis.web", + tableName, + "D:\\workproject\\8zyun-data-analysis\\src\\main\\java", + "rdsifmezqifmezqo.mysql.rds.aliyuncs.com", "3306", "tylife", "lexi365", "bzyun_wxorder", true); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static void generateRepository(String tableName){ + try { + GenerateCode.generateRepository("com.taover.bazhuayun.analysis.web", + tableName, + "D:\\workproject\\8zyun-data-analysis\\src\\main\\java", + "rdsifmezqifmezqo.mysql.rds.aliyuncs.com", "3306", "tylife", "lexi365", "bzyun_wxorder", true); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static void generateAll(String tableName){ + try { + GenerateCode.generate("com.taover.bazhuayun.wxorder", + tableName, + "D:\\workproject\\8zyun-wxorder-api\\src\\main\\java", + "121.42.142.102", "3306", "dev", "taover02", "bzyun_wxorder"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * API 调用示例 + */ + public static void generateCodeExample(){ + try { + //基础包名:"com.taover.bazhuayun.wxorder" + //表名:"wxorder_agent_ssy_contact",多个表名用逗号分隔,全部表"ALL" + //数据库连接信息:"127.0.0.1", "3306", "tylife", "lexi365" + //数据库名称:"8zyun_wxorder" + /*GenerateCode.generate("com.taover.bazhuayun.wxorder", + "wxorder_goods_base_sku", + "D:\\workproject\\8zyun-wxorder-api\\src\\main\\java", + "127.0.0.1", "3306", "tylife", "lexi365", "8zyun_wxorder");*/ + + //gaoming + GenerateCode.generate("com.taover.bazhuayun.wxorder", + "wxorder_goods_map", + "C:\\springboot\\8zyun-wxorder-api\\src\\main\\java", + "192.168.3.2", "3306", "tylife", "lexi365", "8zyun_wxorder"); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/taover/bazhuayun/analysis/web/schedule/HttpHeartbeat.java b/src/main/java/com/taover/bazhuayun/analysis/web/schedule/HttpHeartbeat.java new file mode 100644 index 0000000..5596e6f --- /dev/null +++ b/src/main/java/com/taover/bazhuayun/analysis/web/schedule/HttpHeartbeat.java @@ -0,0 +1,48 @@ +package com.taover.bazhuayun.analysis.web.schedule; + +import java.util.List; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; + +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import com.taover.bazhuayun.analysis.web.module.heartbeat.HeartbeatManager; +import com.taover.bazhuayun.analysis.web.repository.AnalysisHeartbeatInstanceEntity; +import com.taover.bazhuayun.analysis.web.repository.AnalysisHeartbeatInstanceRepository; +import com.taover.util.UtilLog; + +@Component +public class HttpHeartbeat { + @Resource + private HeartbeatManager heartbeatManager; + @Resource + private AnalysisHeartbeatInstanceRepository analysisHeartbeatInstanceRepository; + + /** + * 注册心跳实例 + */ + @PostConstruct + public void initHeartbeat() { + //注册实例 + List instanceList = this.analysisHeartbeatInstanceRepository.findListBySql("status="+AnalysisHeartbeatInstanceRepository.STATUS_ENABLE, null); + try { + this.heartbeatManager.loadInstance(instanceList); + } catch (Exception e) { + UtilLog.error("心跳监控--server注册失败", e, this.getClass()); + } + } + + /** + * 每秒执行一次 + */ + @Scheduled(fixedDelay=1000) + public void flushHeartbeat() { + //刷新注册客户端状态 + this.heartbeatManager.flushClientStatus(); + + //发送服务端心跳包 + this.heartbeatManager.sendServerHeartbeat(); + } +} diff --git a/src/main/resources/application-local.properties b/src/main/resources/application-local.properties index e47c289..ec5bed9 100644 --- a/src/main/resources/application-local.properties +++ b/src/main/resources/application-local.properties @@ -29,111 +29,11 @@ spring.mvc.dispatch-options-request=true #spring.datasource.password=root -spring.datasource.url=jdbc\:mysql\://121.42.142.102\:3306/bzyun_wxorder?useUnicode\=true&characterEncoding\=UTF-8&autoReconnect\=true&zeroDateTimeBehavior\=convertToNull&transformedBitIsBoolean\=true -spring.datasource.username=dev -spring.datasource.password=taover02 -spring.datasource.driver-class-name=com.mysql.jdbc.Driver +spring.datasource.url=jdbc:mysql://rdsifmezqifmezqo.mysql.rds.aliyuncs.com:3306/bzyun_wxorder?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai +spring.datasource.username=tylife +spring.datasource.password=lexi365 +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.max-idle=10 spring.datasource.max-wait=10000 spring.datasource.min-idle=5 spring.datasource.initial-size=5 - -#zto analysis address url -#zto.analysisAddress.url=https://localhost/Word_AnalysisAddress -zto.analysisAddress.url=https://hdgateway.zto.com/Word_AnalysisAddress -#taover analysis address url -taover.analysisAddress.url=http://address.taover.com/ -#kuaibao -kuaibao.analysisAddress.url=https://kop.kuaidihelp.com/api -kuaibao.analysisAddress.appId=105128 -kuaibao.analysisAddress.appKey=3310236ba4d6296e6e2346a7d9c824662510ff87 -kuaibao.analysisAddress.method=cloud.address.resolve -kuaibao.analysisAddress.methodSimple=cloud.address.cleanse - -#aliyun oss -accessKeyId=H4fIVB56iHjR6zQw -accessKeySecret=7bA395UltFp16kWPJT7Pfz0XYXCk4Q -endpoint=oss-cn-beijing.aliyuncs.com -bucket_contact=8zyun-oss -aliyun.mnsEndpoint=http://1225610490807748.mns.cn-hangzhou.aliyuncs.com -#https://8zyun-oss.oss-cn-beijing.aliyuncs.com -#mobile message url -wwltData=sname=dlmzty00&spwd=A6cU4Tyx&scorpid=&sprdid=1012888 -wwltUrl=https://seccf.51welink.com/submitdata/service.asmx/g_Submit - -#root ssy callcenter api config -ssy.callcenter.appid=c2MkSTjT8ghM -ssy.callcenter.seckey=7105ec065b8bb30fa6e3f13fccf92d0f - -pc.callcenter.appid=c2MkSTjT8ghZ -pc.callcenter.seckey=7105ec065b8bb30fa6e3f13fccf92d0G - -ssy.callcenter.subscribePreffixUrl=http://localhost/api/ -ssy.callcenter.subscribeSuffixUrl=/wxagentssymessagesubscribe - - -ssy.callcenter.url.openapiSurrogacyAgent=/api/v2/openapi/surrogacy/agent -ssy.callcenter.url.openapiSurrogacyQuerycontacts=/api/v2/openapi/surrogacy/querycontacts -ssy.callcenter.url.openapiSurrogacySendmessage=/api/v2/openapi/surrogacy/sendmessage -ssy.callcenter.url.openapiSurrogacyRegisteropenapi=/api/v2/openapi/surrogacy/registeropenapi -ssy.callcenter.url.openapiSurrogacyUnregisteropenapi=/api/v2/openapi/surrogacy/unregisteropenapi -ssy.callcenter.url.openapiCallcenterapibridgeService=/api/v2/openapi/callcenterapibridge/service -ssy.callcenter.url.openapiCallGroupMember=/api/v2/openapi/surrogacy/querygroupmember - - - - -ssy.upload.url=https://ssep.umsapi.com/api/v1/upload - -ssy.callcenter.sendMessage.preffixUrl=https://ssep.umsapi.com - -#weixin group text order confirm url -wxorder.url.grouptextorder.confirm=http://localhost:8100/confirm/ -wxorder.url.express.search=http://localhost:8100/confirm/query-logistics/ - -#ssy file server domain -ssy.fileserver.urlpreffix=https://ss0.umsapi.com - -wxorder.front.url.host=http://localhost:8100 - -platform.shop.registerUrl=http://localhost/common/authorization/index - -wxorder.platformgoods.matchurl=http://localhost/goods/channelgoods -wxorder.platformgoods.errororderurl=https://localhost/ordererror/index -wxorder.url.excellist=http://localhost/groupexcel/index - -#pc api -pc.callcenter.url.openapiSurrogacyRegisteropenapi=http://192.168.3.236:18308/v1/agent -pc.callcenter.url.openapiSurrogacyQuerycontacts=http://192.168.3.236:18308/v1/contacts/ -pc.callcenter.url.openapiCallGroupMember=http://192.168.3.236:18308/v1/contact/group_members/ -pc.callcenter.url.openapiSurrogacyAgent=http://192.168.3.236:18308/v1/agent -pc.callcenter.url.openapiSurrogacySendmessage=http://192.168.3.236:18308/v1/message_task -pc.callcenter.subscribeUrl=http://192.168.3.146/api/wxagentpcmessagesubscribe -pc.callcenter.url.sendMessageQueueName=oms-pc-msg -pc.callcenter.url.openapiContactsFeaturesgroup=http://192.168.3.236:18308/v1/contacts/ - -pc.message.url.messageTaskListUrl=http://192.168.3.236:18308/v1/message_task_list -pc.message.url.agentMessageTask=http://192.168.3.236:18308/v1/agent_message_task - -#cainiao param -cainiao.link.url=http://link.cainiao.com/gateway/link.do -cainiao.link.paramFormat=json -cainiao.link.appKey=650167 -cainiao.link.secretKey=lDO6y26nBJ6b5K96lnA1an447H1L0XK3 -cainiao.link.auth.grantpage=http://lcp.cloud.cainiao.com/permission/isv/grantpage.do -cainiao.link.auth.tokenUrl=http://lcp.cloud.cainiao.com/api/permission/exchangeToken.do -cainiao.link.auth.callbackUrl=https://api.oms.8zyun.cn/api/expressprint/auth/cainiao - -#fa wang -fineex.method.addOrder=fineex.wms.trades.add -fineex.method.cancelOrder=fineex.wms.trade.cancel -fineex.method.orderProcess=fineex.wms.trade.orderprocess.get -fineex.apiAddress=http://apicloud.fineex.net/Interface/InterfaceWeb/InterfaceFwWMS.ashx -fineex.method.goodsInventory=fineex.wms.product.inventory.get -fineex.method.orderConfirm=fineex.wms.trade.orderdetail.confirm -fineex.method.returnorderAdd=fineex.wms.trade.returnorder.add - - -qimen.api.appKey=30303007 -qimen.api.appSecret=80c63d1d8cf36a4c68b2df25fb93f703 -qimen.api.url=https://qimen.api.taobao.com/router/qmtest diff --git a/src/main/resources/application-production.properties b/src/main/resources/application-production.properties index 59dd423..24871cc 100644 --- a/src/main/resources/application-production.properties +++ b/src/main/resources/application-production.properties @@ -1,14 +1,11 @@ server.port=8200 -server.session.timeout=10 +server.session.timeout=3600 server.connection-timeout=120000 -spring.servlet.multipart.max-file-size=10MB -spring.servlet.multipart.max-request-size=20MB - spring.jackson.time-zone=GMT+8 spring.jackson.date-format=yyyy-MM-dd HH:mm:ss -spring.mvc.dateFormat = yyyy-MM-dd HH:mm:ss +spring.mvc.dateFormat=yyyy-MM-dd HH:mm:ss spring.gson.serialize-nulls=true #email config @@ -27,48 +24,12 @@ spring.mvc.dispatch-options-request=true spring.mvc.async.request-timeout=200000 #DB info -spring.datasource.url=jdbc:mysql://rdsifmezqifmezqo.mysql.rds.aliyuncs.com:3306/bzyun_wxorder_prd?useUnicode=true&characterEncoding=UTF8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true -spring.datasource.username=tylife -spring.datasource.password=lexi365 -spring.datasource.driver-class-name=com.mysql.jdbc.Driver -spring.datasource.max-idle=10 -spring.datasource.max-wait=10000 -spring.datasource.min-idle=5 -spring.datasource.initial-size=5 - -#zto analysis address url -zto.analysisAddress.url=https://hdgateway.zto.com/Word_AnalysisAddress -#taover analysis address url -taover.analysisAddress.url=http://address.taover.com/ -#kuaibao -kuaibao.analysisAddress.url=https://kop.kuaidihelp.com/api -kuaibao.analysisAddress.appId=105128 -kuaibao.analysisAddress.appKey=3310236ba4d6296e6e2346a7d9c824662510ff87 -kuaibao.analysisAddress.method=cloud.address.resolve -kuaibao.analysisAddress.methodSimple=cloud.address.cleanse - -#aliyun oss address -accessKeyId=H4fIVB56iHjR6zQw -accessKeySecret=7bA395UltFp16kWPJT7Pfz0XYXCk4Q -endpoint=oss-cn-beijing.aliyuncs.com -bucket_contact=8zyun-oss -aliyun.mnsEndpoint=http://1225610490807748.mns.cn-hangzhou.aliyuncs.com -#mobile message url -wwltData=sname=dlmzty00&spwd=A6cU4Tyx&scorpid=&sprdid=1012888 -wwltUrl=https://seccf.51welink.com/submitdata/service.asmx/g_Submit - -#pc api -pc.callcenter.url.openapiSurrogacyRegisteropenapi=https://ws.8zyun.cn:8080/v1/agent -pc.callcenter.url.openapiSurrogacyQuerycontacts=https://ws.8zyun.cn:8080/v1/contacts/ -pc.callcenter.url.openapiCallGroupMember=https://ws.8zyun.cn:8080/v1/contact/group_members/ -pc.callcenter.url.openapiSurrogacyAgent=https://ws.8zyun.cn:8080/v1/agent -pc.callcenter.url.openapiSurrogacySendmessage=https://ws.8zyun.cn:8080/v1/message_task -pc.callcenter.url.openapiContactsFeaturesgroup=https://ws.8zyun.cn:8080/v1/contactsMessageCount - -pc.callcenter.appid=c2MkSTjT8ghZ -pc.callcenter.seckey=7105ec065b8bb30fa6e3f13fccf92d0G -pc.callcenter.subscribeUrl=https://api.oms.8zyun.cn/api/wxagentpcmessagesubscribe -pc.callcenter.url.sendMessageQueueName=oms-pc-msg-production - -pc.message.url.messageTaskListUrl=https://ws.8zyun.cn:8080/v1/message_task_list -pc.message.url.agentMessageTask=https://ws.8zyun.cn:8080/v1/agent_message_task +spring.datasource.druid.url=jdbc:mysql://pxc-hzryz5s6f2lq4b.polarx.rds.aliyuncs.com:3306/bzyun_wxorder_prd?characterEncoding=UTF8&serverTimezone=Asia/Shanghai +spring.datasource.druid.username=pj_analysis +spring.datasource.druid.password=p67r0H@y8BLYNhCx +spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver + +spring.datasource.druid.initial-size=5 +spring.datasource.druid.max-active=10 +spring.datasource.druid.min-idle=5 +spring.datasource.druid.max-wait=60000 diff --git a/test/main/java/com/taover/bazhuayun/analysis/test/SemilarClient.java b/test/main/java/com/taover/bazhuayun/analysis/test/SemilarClient.java new file mode 100644 index 0000000..ac5bcf1 --- /dev/null +++ b/test/main/java/com/taover/bazhuayun/analysis/test/SemilarClient.java @@ -0,0 +1,25 @@ +package com.taover.bazhuayun.analysis.test; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import com.taover.util.UtilEncrypt; +import com.taover.util.UtilHttpByOkHttp; + +public class SemilarClient { + public static void main(String[] args) { + while(true) { + String code = "xxljob"; + long time = System.currentTimeMillis()/1000; + String token = ""; + try { + System.out.println("=======send heartbeat["+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"]======="); + System.out.println("response:"+UtilHttpByOkHttp.sendGet("http://localhost/api/heartbeat?code="+code+"&unixtime="+time+"&seckey="+UtilEncrypt.MD5Lower32(code+time+token), null)); + + Thread.sleep(1000*60); + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} -- libgit2 0.21.2