Commit 7c217d06380b469d80474501ce3b6706215e0803
0 parents
Exists in
master
first commit
Showing
22 changed files
with
1234 additions
and
0 deletions
Show diff stats
1 | +++ a/build.gradle | ||
@@ -0,0 +1,66 @@ | @@ -0,0 +1,66 @@ | ||
1 | +/* | ||
2 | + * This file was generated by the Gradle 'init' task. | ||
3 | + * | ||
4 | + * This generated file contains a sample Java Library project to get you started. | ||
5 | + * For more details take a look at the Java Libraries chapter in the Gradle | ||
6 | + * user guide available at https://docs.gradle.org/4.5.1/userguide/java_library_plugin.html | ||
7 | + */ | ||
8 | + | ||
9 | +plugins { | ||
10 | + // Apply the java-library plugin to add support for Java Library | ||
11 | + id 'java' | ||
12 | + id 'eclipse' | ||
13 | + id 'application' | ||
14 | + id 'maven' | ||
15 | +} | ||
16 | + | ||
17 | +jar.enabled = true | ||
18 | +group = 'com.taover.heartbeat' | ||
19 | +mainClassName = 'com.taover.heartbeat.HeartbeatManager' | ||
20 | + | ||
21 | +dependencies { | ||
22 | + compile( | ||
23 | + "com.taover:com-taover-util:1.1.116", | ||
24 | + "javax.servlet:javax.servlet-api:4.0.1" | ||
25 | + ) | ||
26 | +} | ||
27 | + | ||
28 | +repositories { | ||
29 | + jcenter() | ||
30 | + maven{ url 'http://repository.sonatype.org/content/groups/public/' } | ||
31 | + maven{ url 'https://repository.jboss.org/nexus/content/groups/public/' } | ||
32 | + maven{ url 'http://nexus.taover.com:9001/repository/maven-releases/' } | ||
33 | +} | ||
34 | +task sourcesJar(type: Jar, dependsOn: classes) { | ||
35 | + classifier = 'sources' | ||
36 | + from sourceSets.main.allSource | ||
37 | +} | ||
38 | + | ||
39 | +tasks.withType(JavaCompile) { | ||
40 | + options.encoding = "UTF-8" | ||
41 | +} | ||
42 | + | ||
43 | +artifacts { | ||
44 | + archives sourcesJar | ||
45 | +} | ||
46 | + | ||
47 | +uploadArchives { | ||
48 | + configuration = configurations.archives | ||
49 | + repositories { | ||
50 | + mavenDeployer { | ||
51 | + snapshotRepository(url: MAVEN_REPO_SNAPSHOT_URL) { | ||
52 | + authentication(userName: NEXUS_USERNAME, password: NEXUS_PASSWORD) | ||
53 | + } | ||
54 | + repository(url: MAVEN_REPO_RELEASE_URL) { | ||
55 | + authentication(userName: NEXUS_USERNAME, password: NEXUS_PASSWORD) | ||
56 | + } | ||
57 | + pom.project { | ||
58 | + version '1.1.1' | ||
59 | + artifactId ARTIFACT_Id | ||
60 | + groupId GROUP_ID | ||
61 | + packaging TYPE | ||
62 | + description DESCRIPTION | ||
63 | + } | ||
64 | + } | ||
65 | + } | ||
66 | +} |
1 | +++ a/gradle.properties | ||
@@ -0,0 +1,21 @@ | @@ -0,0 +1,21 @@ | ||
1 | +#Maven Repo URL | ||
2 | +MAVEN_REPO_RELEASE_URL=http://nexus.taover.com:9001/repository/maven-releases/ | ||
3 | +MAVEN_REPO_SNAPSHOT_URL=http://nexus.taover.com:9001/repository/maven-snapshots/ | ||
4 | + | ||
5 | +#maven GroupId | ||
6 | +GROUP=com.taover | ||
7 | +#nexus ossde | ||
8 | +NEXUS_USERNAME=dev | ||
9 | +#nexus oss | ||
10 | +NEXUS_PASSWORD=Nexus@dev | ||
11 | + | ||
12 | +# groupid | ||
13 | +GROUP_ID=com.taover | ||
14 | + | ||
15 | +ARTIFACT_Id=com-taover-heartbeat | ||
16 | + | ||
17 | +# type | ||
18 | +TYPE=jar | ||
19 | + | ||
20 | +# description | ||
21 | +DESCRIPTION=heartbeat package | ||
0 | \ No newline at end of file | 22 | \ No newline at end of file |
No preview for this file type
1 | +++ a/gradlew | ||
@@ -0,0 +1,172 @@ | @@ -0,0 +1,172 @@ | ||
1 | +#!/usr/bin/env sh | ||
2 | + | ||
3 | +############################################################################## | ||
4 | +## | ||
5 | +## Gradle start up script for UN*X | ||
6 | +## | ||
7 | +############################################################################## | ||
8 | + | ||
9 | +# Attempt to set APP_HOME | ||
10 | +# Resolve links: $0 may be a link | ||
11 | +PRG="$0" | ||
12 | +# Need this for relative symlinks. | ||
13 | +while [ -h "$PRG" ] ; do | ||
14 | + ls=`ls -ld "$PRG"` | ||
15 | + link=`expr "$ls" : '.*-> \(.*\)$'` | ||
16 | + if expr "$link" : '/.*' > /dev/null; then | ||
17 | + PRG="$link" | ||
18 | + else | ||
19 | + PRG=`dirname "$PRG"`"/$link" | ||
20 | + fi | ||
21 | +done | ||
22 | +SAVED="`pwd`" | ||
23 | +cd "`dirname \"$PRG\"`/" >/dev/null | ||
24 | +APP_HOME="`pwd -P`" | ||
25 | +cd "$SAVED" >/dev/null | ||
26 | + | ||
27 | +APP_NAME="Gradle" | ||
28 | +APP_BASE_NAME=`basename "$0"` | ||
29 | + | ||
30 | +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | ||
31 | +DEFAULT_JVM_OPTS="" | ||
32 | + | ||
33 | +# Use the maximum available, or set MAX_FD != -1 to use that value. | ||
34 | +MAX_FD="maximum" | ||
35 | + | ||
36 | +warn () { | ||
37 | + echo "$*" | ||
38 | +} | ||
39 | + | ||
40 | +die () { | ||
41 | + echo | ||
42 | + echo "$*" | ||
43 | + echo | ||
44 | + exit 1 | ||
45 | +} | ||
46 | + | ||
47 | +# OS specific support (must be 'true' or 'false'). | ||
48 | +cygwin=false | ||
49 | +msys=false | ||
50 | +darwin=false | ||
51 | +nonstop=false | ||
52 | +case "`uname`" in | ||
53 | + CYGWIN* ) | ||
54 | + cygwin=true | ||
55 | + ;; | ||
56 | + Darwin* ) | ||
57 | + darwin=true | ||
58 | + ;; | ||
59 | + MINGW* ) | ||
60 | + msys=true | ||
61 | + ;; | ||
62 | + NONSTOP* ) | ||
63 | + nonstop=true | ||
64 | + ;; | ||
65 | +esac | ||
66 | + | ||
67 | +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar | ||
68 | + | ||
69 | +# Determine the Java command to use to start the JVM. | ||
70 | +if [ -n "$JAVA_HOME" ] ; then | ||
71 | + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then | ||
72 | + # IBM's JDK on AIX uses strange locations for the executables | ||
73 | + JAVACMD="$JAVA_HOME/jre/sh/java" | ||
74 | + else | ||
75 | + JAVACMD="$JAVA_HOME/bin/java" | ||
76 | + fi | ||
77 | + if [ ! -x "$JAVACMD" ] ; then | ||
78 | + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME | ||
79 | + | ||
80 | +Please set the JAVA_HOME variable in your environment to match the | ||
81 | +location of your Java installation." | ||
82 | + fi | ||
83 | +else | ||
84 | + JAVACMD="java" | ||
85 | + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | ||
86 | + | ||
87 | +Please set the JAVA_HOME variable in your environment to match the | ||
88 | +location of your Java installation." | ||
89 | +fi | ||
90 | + | ||
91 | +# Increase the maximum file descriptors if we can. | ||
92 | +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then | ||
93 | + MAX_FD_LIMIT=`ulimit -H -n` | ||
94 | + if [ $? -eq 0 ] ; then | ||
95 | + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then | ||
96 | + MAX_FD="$MAX_FD_LIMIT" | ||
97 | + fi | ||
98 | + ulimit -n $MAX_FD | ||
99 | + if [ $? -ne 0 ] ; then | ||
100 | + warn "Could not set maximum file descriptor limit: $MAX_FD" | ||
101 | + fi | ||
102 | + else | ||
103 | + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" | ||
104 | + fi | ||
105 | +fi | ||
106 | + | ||
107 | +# For Darwin, add options to specify how the application appears in the dock | ||
108 | +if $darwin; then | ||
109 | + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" | ||
110 | +fi | ||
111 | + | ||
112 | +# For Cygwin, switch paths to Windows format before running java | ||
113 | +if $cygwin ; then | ||
114 | + APP_HOME=`cygpath --path --mixed "$APP_HOME"` | ||
115 | + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` | ||
116 | + JAVACMD=`cygpath --unix "$JAVACMD"` | ||
117 | + | ||
118 | + # We build the pattern for arguments to be converted via cygpath | ||
119 | + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` | ||
120 | + SEP="" | ||
121 | + for dir in $ROOTDIRSRAW ; do | ||
122 | + ROOTDIRS="$ROOTDIRS$SEP$dir" | ||
123 | + SEP="|" | ||
124 | + done | ||
125 | + OURCYGPATTERN="(^($ROOTDIRS))" | ||
126 | + # Add a user-defined pattern to the cygpath arguments | ||
127 | + if [ "$GRADLE_CYGPATTERN" != "" ] ; then | ||
128 | + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" | ||
129 | + fi | ||
130 | + # Now convert the arguments - kludge to limit ourselves to /bin/sh | ||
131 | + i=0 | ||
132 | + for arg in "$@" ; do | ||
133 | + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` | ||
134 | + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option | ||
135 | + | ||
136 | + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition | ||
137 | + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` | ||
138 | + else | ||
139 | + eval `echo args$i`="\"$arg\"" | ||
140 | + fi | ||
141 | + i=$((i+1)) | ||
142 | + done | ||
143 | + case $i in | ||
144 | + (0) set -- ;; | ||
145 | + (1) set -- "$args0" ;; | ||
146 | + (2) set -- "$args0" "$args1" ;; | ||
147 | + (3) set -- "$args0" "$args1" "$args2" ;; | ||
148 | + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; | ||
149 | + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; | ||
150 | + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; | ||
151 | + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; | ||
152 | + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; | ||
153 | + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; | ||
154 | + esac | ||
155 | +fi | ||
156 | + | ||
157 | +# Escape application args | ||
158 | +save () { | ||
159 | + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done | ||
160 | + echo " " | ||
161 | +} | ||
162 | +APP_ARGS=$(save "$@") | ||
163 | + | ||
164 | +# Collect all arguments for the java command, following the shell quoting and substitution rules | ||
165 | +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" | ||
166 | + | ||
167 | +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong | ||
168 | +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then | ||
169 | + cd "$(dirname "$0")" | ||
170 | +fi | ||
171 | + | ||
172 | +exec "$JAVACMD" "$@" |
1 | +++ a/gradlew.bat | ||
@@ -0,0 +1,84 @@ | @@ -0,0 +1,84 @@ | ||
1 | +@if "%DEBUG%" == "" @echo off | ||
2 | +@rem ########################################################################## | ||
3 | +@rem | ||
4 | +@rem Gradle startup script for Windows | ||
5 | +@rem | ||
6 | +@rem ########################################################################## | ||
7 | + | ||
8 | +@rem Set local scope for the variables with windows NT shell | ||
9 | +if "%OS%"=="Windows_NT" setlocal | ||
10 | + | ||
11 | +set DIRNAME=%~dp0 | ||
12 | +if "%DIRNAME%" == "" set DIRNAME=. | ||
13 | +set APP_BASE_NAME=%~n0 | ||
14 | +set APP_HOME=%DIRNAME% | ||
15 | + | ||
16 | +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | ||
17 | +set DEFAULT_JVM_OPTS= | ||
18 | + | ||
19 | +@rem Find java.exe | ||
20 | +if defined JAVA_HOME goto findJavaFromJavaHome | ||
21 | + | ||
22 | +set JAVA_EXE=java.exe | ||
23 | +%JAVA_EXE% -version >NUL 2>&1 | ||
24 | +if "%ERRORLEVEL%" == "0" goto init | ||
25 | + | ||
26 | +echo. | ||
27 | +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | ||
28 | +echo. | ||
29 | +echo Please set the JAVA_HOME variable in your environment to match the | ||
30 | +echo location of your Java installation. | ||
31 | + | ||
32 | +goto fail | ||
33 | + | ||
34 | +:findJavaFromJavaHome | ||
35 | +set JAVA_HOME=%JAVA_HOME:"=% | ||
36 | +set JAVA_EXE=%JAVA_HOME%/bin/java.exe | ||
37 | + | ||
38 | +if exist "%JAVA_EXE%" goto init | ||
39 | + | ||
40 | +echo. | ||
41 | +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% | ||
42 | +echo. | ||
43 | +echo Please set the JAVA_HOME variable in your environment to match the | ||
44 | +echo location of your Java installation. | ||
45 | + | ||
46 | +goto fail | ||
47 | + | ||
48 | +:init | ||
49 | +@rem Get command-line arguments, handling Windows variants | ||
50 | + | ||
51 | +if not "%OS%" == "Windows_NT" goto win9xME_args | ||
52 | + | ||
53 | +:win9xME_args | ||
54 | +@rem Slurp the command line arguments. | ||
55 | +set CMD_LINE_ARGS= | ||
56 | +set _SKIP=2 | ||
57 | + | ||
58 | +:win9xME_args_slurp | ||
59 | +if "x%~1" == "x" goto execute | ||
60 | + | ||
61 | +set CMD_LINE_ARGS=%* | ||
62 | + | ||
63 | +:execute | ||
64 | +@rem Setup the command line | ||
65 | + | ||
66 | +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar | ||
67 | + | ||
68 | +@rem Execute Gradle | ||
69 | +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% | ||
70 | + | ||
71 | +:end | ||
72 | +@rem End local scope for the variables with windows NT shell | ||
73 | +if "%ERRORLEVEL%"=="0" goto mainEnd | ||
74 | + | ||
75 | +:fail | ||
76 | +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of | ||
77 | +rem the _cmd.exe /c_ return code! | ||
78 | +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 | ||
79 | +exit /b 1 | ||
80 | + | ||
81 | +:mainEnd | ||
82 | +if "%OS%"=="Windows_NT" endlocal | ||
83 | + | ||
84 | +:omega |
1 | +++ a/settings.gradle | ||
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +/* | ||
2 | + * This file was generated by the Gradle 'init' task. | ||
3 | + * | ||
4 | + * The settings file is used to specify which projects to include in your build. | ||
5 | + * | ||
6 | + * Detailed information about configuring a multi-project build in Gradle can be found | ||
7 | + * in the user guide at https://docs.gradle.org/4.9/userguide/multi_project_builds.html | ||
8 | + */ | ||
9 | + | ||
10 | +rootProject.name = 'com-taover-heartbeat' |
1 | +++ a/src/main/java/com/taover/heartbeat/ClientHolder.java | ||
@@ -0,0 +1,14 @@ | @@ -0,0 +1,14 @@ | ||
1 | +package com.taover.heartbeat; | ||
2 | + | ||
3 | +import java.util.List; | ||
4 | + | ||
5 | +import com.taover.heartbeat.bean.ClientInstance; | ||
6 | +import com.taover.heartbeat.bean.ClientRequest; | ||
7 | + | ||
8 | +interface ClientHolder { | ||
9 | + void registryClientInstance(ClientRequest clientRequest); | ||
10 | + | ||
11 | + List<ClientInstance> getClientInstanceList(); | ||
12 | + | ||
13 | + void flushClientStatus(ClientInstance clientInstance); | ||
14 | +} |
src/main/java/com/taover/heartbeat/ClientHolderImpl.java
0 → 100644
1 | +++ a/src/main/java/com/taover/heartbeat/ClientHolderImpl.java | ||
@@ -0,0 +1,38 @@ | @@ -0,0 +1,38 @@ | ||
1 | +package com.taover.heartbeat; | ||
2 | + | ||
3 | +import java.util.ArrayList; | ||
4 | +import java.util.HashMap; | ||
5 | +import java.util.List; | ||
6 | +import java.util.Map; | ||
7 | + | ||
8 | +import com.taover.heartbeat.bean.ClientInstance; | ||
9 | +import com.taover.heartbeat.bean.ClientRequest; | ||
10 | + | ||
11 | +public class ClientHolderImpl implements ClientHolder{ | ||
12 | + Map<String, ClientInstance> clientMap = new HashMap<String, ClientInstance>(); | ||
13 | + | ||
14 | + @Override | ||
15 | + public List<ClientInstance> getClientInstanceList() { | ||
16 | + return new ArrayList<ClientInstance>(clientMap.values()); | ||
17 | + } | ||
18 | + | ||
19 | + @Override | ||
20 | + public void flushClientStatus(ClientInstance clientInstance) { | ||
21 | + clientInstance.flush(); | ||
22 | + } | ||
23 | + | ||
24 | + @Override | ||
25 | + public void registryClientInstance(ClientRequest clientRequest) { | ||
26 | + synchronized (this.clientMap) { | ||
27 | + ClientInstance client = null; | ||
28 | + if(clientMap.containsKey(clientRequest.getIdentity())) { | ||
29 | + client = clientMap.get(clientRequest.getIdentity()); | ||
30 | + clientMap.put(client.getIdentity(), client); | ||
31 | + }else { | ||
32 | + client = new ClientInstance(clientRequest); | ||
33 | + clientMap.put(client.getIdentity(), client); | ||
34 | + } | ||
35 | + client.dealClientRequest(clientRequest); | ||
36 | + } | ||
37 | + } | ||
38 | +} |
src/main/java/com/taover/heartbeat/HeartbeatManager.java
0 → 100644
1 | +++ a/src/main/java/com/taover/heartbeat/HeartbeatManager.java | ||
@@ -0,0 +1,57 @@ | @@ -0,0 +1,57 @@ | ||
1 | +package com.taover.heartbeat; | ||
2 | + | ||
3 | +import java.util.List; | ||
4 | + | ||
5 | +import com.taover.heartbeat.bean.ClientInstance; | ||
6 | +import com.taover.heartbeat.bean.ClientRequest; | ||
7 | +import com.taover.heartbeat.bean.Instance; | ||
8 | +import com.taover.heartbeat.bean.ReformInstance; | ||
9 | +import com.taover.heartbeat.bean.ServerInstance; | ||
10 | + | ||
11 | +public class HeartbeatManager { | ||
12 | + //客户端holder | ||
13 | + private static ClientHolder clientHolder = new ClientHolderImpl(); | ||
14 | + //服务端holder | ||
15 | + private static ServerHolder serverHolder = new ServerHolderImpl(); | ||
16 | + //通知对象 | ||
17 | + private static ReformInstance reformData = new ReformInstance(); | ||
18 | + | ||
19 | + public static void registryClient(ClientRequest clientRequest) { | ||
20 | + clientHolder.registryClientInstance(clientRequest); | ||
21 | + } | ||
22 | + | ||
23 | + /** | ||
24 | + * 刷新客户端信息 | ||
25 | + */ | ||
26 | + public static void flushClientStatus() { | ||
27 | + List<ClientInstance> instances = clientHolder.getClientInstanceList(); | ||
28 | + for(ClientInstance item: instances) { | ||
29 | + item.flush(); | ||
30 | + if(item.needReform()) { | ||
31 | + HeartbeatManager.sendReform(item); | ||
32 | + } | ||
33 | + } | ||
34 | + } | ||
35 | + | ||
36 | + public static void sendReform(Instance instance) { | ||
37 | + reformData.doReform(instance); | ||
38 | + } | ||
39 | + | ||
40 | + public static void sendServerHeartbeat() { | ||
41 | + List<ServerInstance> instances = serverHolder.getServerInstanceList(); | ||
42 | + for(ServerInstance item: instances) { | ||
43 | + item.flush(); | ||
44 | + if(item.needReform()) { | ||
45 | + HeartbeatManager.sendReform(item); | ||
46 | + } | ||
47 | + } | ||
48 | + } | ||
49 | + | ||
50 | + public static void registryServers(String code, String url, int fixRateSec, int maxWaitSec) throws Exception{ | ||
51 | + serverHolder.registeServer(code, url, fixRateSec, maxWaitSec); | ||
52 | + } | ||
53 | + | ||
54 | + public static void setReformData(String emailTo, String weixinWxid, String mobile) { | ||
55 | + HeartbeatManager.reformData.loadConfig(emailTo, weixinWxid, mobile); | ||
56 | + } | ||
57 | +} |
1 | +++ a/src/main/java/com/taover/heartbeat/ServerHolder.java | ||
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +package com.taover.heartbeat; | ||
2 | + | ||
3 | +import java.util.List; | ||
4 | + | ||
5 | +import com.taover.heartbeat.bean.ServerInstance; | ||
6 | + | ||
7 | +interface ServerHolder { | ||
8 | + List<ServerInstance> getServerInstanceList(); | ||
9 | + | ||
10 | + void registeServer(String code, String url, int fixRateSec, int maxWaitSec) throws Exception; | ||
11 | + | ||
12 | + void flushServerStatus(ServerInstance serverInstance); | ||
13 | +} |
src/main/java/com/taover/heartbeat/ServerHolderImpl.java
0 → 100644
1 | +++ a/src/main/java/com/taover/heartbeat/ServerHolderImpl.java | ||
@@ -0,0 +1,35 @@ | @@ -0,0 +1,35 @@ | ||
1 | +package com.taover.heartbeat; | ||
2 | + | ||
3 | +import java.util.ArrayList; | ||
4 | +import java.util.HashMap; | ||
5 | +import java.util.List; | ||
6 | +import java.util.Map; | ||
7 | + | ||
8 | +import com.taover.heartbeat.bean.ServerInstance; | ||
9 | + | ||
10 | +public class ServerHolderImpl implements ServerHolder { | ||
11 | + Map<String, ServerInstance> serverMap = new HashMap<String, ServerInstance>(); | ||
12 | + | ||
13 | + @Override | ||
14 | + public List<ServerInstance> getServerInstanceList() { | ||
15 | + return new ArrayList<ServerInstance>(serverMap.values()); | ||
16 | + } | ||
17 | + | ||
18 | + @Override | ||
19 | + public void registeServer(String code, String url, int fixRateSec, int maxWaitSec) throws Exception { | ||
20 | + ServerInstance server = new ServerInstance(code, url, fixRateSec, maxWaitSec); | ||
21 | + synchronized (this.serverMap) { | ||
22 | + if(serverMap.containsKey(server.getIdentity())) { | ||
23 | + server = serverMap.get(server.getIdentity()); | ||
24 | + }else { | ||
25 | + serverMap.put(server.getIdentity(), server); | ||
26 | + } | ||
27 | + } | ||
28 | + server.flush(); | ||
29 | + } | ||
30 | + | ||
31 | + @Override | ||
32 | + public void flushServerStatus(ServerInstance serverInstance) { | ||
33 | + serverInstance.flush(); | ||
34 | + } | ||
35 | +} |
src/main/java/com/taover/heartbeat/adaptor/HttpHeartbeatService.java
0 → 100644
1 | +++ a/src/main/java/com/taover/heartbeat/adaptor/HttpHeartbeatService.java | ||
@@ -0,0 +1,40 @@ | @@ -0,0 +1,40 @@ | ||
1 | +package com.taover.heartbeat.adaptor; | ||
2 | + | ||
3 | +import javax.servlet.http.HttpServletRequest; | ||
4 | + | ||
5 | +import com.taover.util.bean.ResultInfo; | ||
6 | + | ||
7 | +public interface HttpHeartbeatService { | ||
8 | + | ||
9 | + /** | ||
10 | + * 处理客户端心跳请求 | ||
11 | + * @param clientRequest | ||
12 | + * @return | ||
13 | + */ | ||
14 | + ResultInfo registryClient(HttpServletRequest request); | ||
15 | + | ||
16 | + /** | ||
17 | + * 注册服务端 | ||
18 | + * @param servers | ||
19 | + * @param reformData | ||
20 | + * @param fixRateSec | ||
21 | + * @param maxWait | ||
22 | + */ | ||
23 | + void registryServers(String code, String servers, Integer fixRateSec, Integer maxWaitSec) throws Exception; | ||
24 | + | ||
25 | + /** | ||
26 | + * 刷新客户端状态 | ||
27 | + */ | ||
28 | + void flushClientStatus(); | ||
29 | + | ||
30 | + /** | ||
31 | + * 向服务器发送心跳 | ||
32 | + */ | ||
33 | + void sendServerHeartbeat(); | ||
34 | + | ||
35 | + /** | ||
36 | + * 设置通知信息 | ||
37 | + * @param reformData | ||
38 | + */ | ||
39 | + void setReformData(String emailTo, String weixinWxid, String mobile); | ||
40 | +} |
src/main/java/com/taover/heartbeat/adaptor/HttpHeartbeatServiceImpl.java
0 → 100644
1 | +++ a/src/main/java/com/taover/heartbeat/adaptor/HttpHeartbeatServiceImpl.java | ||
@@ -0,0 +1,89 @@ | @@ -0,0 +1,89 @@ | ||
1 | +package com.taover.heartbeat.adaptor; | ||
2 | + | ||
3 | +import javax.servlet.http.HttpServletRequest; | ||
4 | + | ||
5 | +import com.taover.heartbeat.HeartbeatManager; | ||
6 | +import com.taover.heartbeat.bean.ClientRequest; | ||
7 | +import com.taover.heartbeat.bean.Instance; | ||
8 | +import com.taover.util.UtilLog; | ||
9 | +import com.taover.util.bean.ResultInfo; | ||
10 | +import com.taover.util.bean.UtilResultInfo; | ||
11 | + | ||
12 | +public class HttpHeartbeatServiceImpl implements HttpHeartbeatService { | ||
13 | + public HttpHeartbeatServiceImpl() {} | ||
14 | + | ||
15 | + /** | ||
16 | + * 处理客户端心跳请求 | ||
17 | + * @param clientRequest | ||
18 | + * @return | ||
19 | + */ | ||
20 | + @Override | ||
21 | + public ResultInfo registryClient(HttpServletRequest request) { | ||
22 | + try { | ||
23 | + HeartbeatManager.registryClient(ClientRequest.createClientRequest(request)); | ||
24 | + return UtilResultInfo.getSuccess(""); | ||
25 | + }catch (Exception e) { | ||
26 | + return UtilResultInfo.getFailure(e.getMessage()); | ||
27 | + } | ||
28 | + } | ||
29 | + | ||
30 | + /** | ||
31 | + * 刷新客户端状态 | ||
32 | + */ | ||
33 | + @Override | ||
34 | + public void flushClientStatus() { | ||
35 | + try { | ||
36 | + HeartbeatManager.flushClientStatus(); | ||
37 | + }catch (Exception e) { | ||
38 | + UtilLog.errorForException(e, this.getClass()); | ||
39 | + } | ||
40 | + } | ||
41 | + | ||
42 | + /** | ||
43 | + * 向服务器发送心跳 | ||
44 | + */ | ||
45 | + @Override | ||
46 | + public void sendServerHeartbeat() { | ||
47 | + try { | ||
48 | + HeartbeatManager.sendServerHeartbeat(); | ||
49 | + }catch (Exception e) { | ||
50 | + UtilLog.errorForException(e, this.getClass()); | ||
51 | + } | ||
52 | + } | ||
53 | + | ||
54 | + @Override | ||
55 | + public void registryServers(String code, String servers, Integer fixRateSec, Integer maxWaitSec) throws Exception{ | ||
56 | + if(servers == null || servers.trim().equals("")) { | ||
57 | + return; | ||
58 | + } | ||
59 | + String[] serverSplit = servers.split(","); | ||
60 | + if(code == null || code.trim().equals("")) { | ||
61 | + throw new Exception("property[heartbeat.clientCode] is blank"); | ||
62 | + } | ||
63 | + if(fixRateSec == null) { | ||
64 | + fixRateSec = Instance.DEFAULT_FIX_RATE_SEC; | ||
65 | + } | ||
66 | + if(maxWaitSec == null) { | ||
67 | + maxWaitSec = Instance.DEFAULT_MAX_WAIT_SEC; | ||
68 | + } | ||
69 | + for(String serverItem: serverSplit) { | ||
70 | + if(code == null || code.trim().equals("") || !serverItem.toLowerCase().startsWith("http")) { | ||
71 | + continue; | ||
72 | + } | ||
73 | + try { | ||
74 | + HeartbeatManager.registryServers(code, serverItem, fixRateSec, maxWaitSec); | ||
75 | + }catch (Exception e) { | ||
76 | + UtilLog.errorForException(e, this.getClass()); | ||
77 | + } | ||
78 | + } | ||
79 | + } | ||
80 | + | ||
81 | + @Override | ||
82 | + public void setReformData(String emailTo, String weixinWxid, String mobile) { | ||
83 | + try { | ||
84 | + HeartbeatManager.setReformData(emailTo, weixinWxid, mobile); | ||
85 | + }catch (Exception e) { | ||
86 | + UtilLog.errorForException(e, this.getClass()); | ||
87 | + } | ||
88 | + } | ||
89 | +} |
src/main/java/com/taover/heartbeat/bean/ClientInstance.java
0 → 100644
1 | +++ a/src/main/java/com/taover/heartbeat/bean/ClientInstance.java | ||
@@ -0,0 +1,73 @@ | @@ -0,0 +1,73 @@ | ||
1 | +package com.taover.heartbeat.bean; | ||
2 | + | ||
3 | +public class ClientInstance extends ClientRequest implements Instance{ | ||
4 | + public int DEFAULT_REFORM_MIN_ERROR_COUNT = 1; | ||
5 | + public int DEFAULT_REFORM_MAX_ERROR_COUNT = 3; | ||
6 | + | ||
7 | + private long lastestServerUnixtime = System.currentTimeMillis()/1000; | ||
8 | + private int lostClientRequestCount = 0; | ||
9 | + private ClientRequest lastestClientRequest; | ||
10 | + | ||
11 | + public ClientInstance(ClientRequest clientRequest) { | ||
12 | + super(clientRequest); | ||
13 | + this.lastestClientRequest = clientRequest; | ||
14 | + } | ||
15 | + | ||
16 | + @Override | ||
17 | + public void flush() { | ||
18 | + //还未收到请求,则无需刷新失败次数 | ||
19 | + if(lastestClientRequest == null) { | ||
20 | + return; | ||
21 | + } | ||
22 | + | ||
23 | + //通过服务器时间,判断是否超时未收到客户端请求 | ||
24 | + if(isLatestRequestGreateEqualFixRateSec()) { | ||
25 | + ++this.lostClientRequestCount; | ||
26 | + } | ||
27 | + } | ||
28 | + | ||
29 | + private boolean isLatestRequestGreateEqualFixRateSec() { | ||
30 | + return (System.currentTimeMillis()/1000 - this.lastestServerUnixtime) > this.getFixRateSec(); | ||
31 | + } | ||
32 | + | ||
33 | + @Override | ||
34 | + public boolean needReform() { | ||
35 | + return isLatestRequestGreateEqualFixRateSec() && this.lostClientRequestCount>=DEFAULT_REFORM_MIN_ERROR_COUNT && this.lostClientRequestCount<=DEFAULT_REFORM_MAX_ERROR_COUNT; | ||
36 | + } | ||
37 | + | ||
38 | + public long getLastestServerUnixtime() { | ||
39 | + return lastestServerUnixtime; | ||
40 | + } | ||
41 | + | ||
42 | + public void setLastestServerUnixtime(long lastestServerUnixtime) { | ||
43 | + this.lastestServerUnixtime = lastestServerUnixtime; | ||
44 | + } | ||
45 | + | ||
46 | + public int getLostClientRequestCount() { | ||
47 | + return lostClientRequestCount; | ||
48 | + } | ||
49 | + | ||
50 | + public void setLostClientRequestCount(int lostClientRequestCount) { | ||
51 | + this.lostClientRequestCount = lostClientRequestCount; | ||
52 | + } | ||
53 | + | ||
54 | + public ClientRequest getLastestClientRequest() { | ||
55 | + return lastestClientRequest; | ||
56 | + } | ||
57 | + | ||
58 | + public void setLastestClientRequest(ClientRequest lastestClientRequest) { | ||
59 | + this.lastestClientRequest = lastestClientRequest; | ||
60 | + } | ||
61 | + | ||
62 | + public void dealClientRequest(ClientRequest clientRequest) { | ||
63 | + if(this.getFixRateSec() != clientRequest.getFixRateSec()) { | ||
64 | + this.setFixRateSec(clientRequest.getFixRateSec()); | ||
65 | + } | ||
66 | + if(this.getMaxWaitSec() != clientRequest.getMaxWaitSec()) { | ||
67 | + this.setMaxWaitSec(clientRequest.getMaxWaitSec()); | ||
68 | + } | ||
69 | + this.setLastestClientRequest(clientRequest); | ||
70 | + this.lastestServerUnixtime = System.currentTimeMillis()/1000; | ||
71 | + this.lostClientRequestCount = 0; | ||
72 | + } | ||
73 | +} |
src/main/java/com/taover/heartbeat/bean/ClientRequest.java
0 → 100644
1 | +++ a/src/main/java/com/taover/heartbeat/bean/ClientRequest.java | ||
@@ -0,0 +1,74 @@ | @@ -0,0 +1,74 @@ | ||
1 | +package com.taover.heartbeat.bean; | ||
2 | + | ||
3 | +import javax.servlet.http.HttpServletRequest; | ||
4 | + | ||
5 | +public class ClientRequest { | ||
6 | + private String code = ""; | ||
7 | + private String ip = ""; | ||
8 | + private int maxWaitSec = Instance.DEFAULT_MAX_WAIT_SEC; | ||
9 | + private int fixRateSec = Instance.DEFAULT_FIX_RATE_SEC; | ||
10 | + private long unixtime; | ||
11 | + | ||
12 | + public String getCode() { | ||
13 | + return code; | ||
14 | + } | ||
15 | + public void setCode(String code) { | ||
16 | + this.code = code; | ||
17 | + } | ||
18 | + public String getIp() { | ||
19 | + return ip; | ||
20 | + } | ||
21 | + public void setIp(String ip) { | ||
22 | + this.ip = ip; | ||
23 | + } | ||
24 | + public int getMaxWaitSec() { | ||
25 | + return maxWaitSec; | ||
26 | + } | ||
27 | + public void setMaxWaitSec(int maxWaitSec) { | ||
28 | + this.maxWaitSec = maxWaitSec; | ||
29 | + } | ||
30 | + public int getFixRateSec() { | ||
31 | + return fixRateSec; | ||
32 | + } | ||
33 | + public void setFixRateSec(int fixRateSec) { | ||
34 | + this.fixRateSec = fixRateSec; | ||
35 | + } | ||
36 | + public long getUnixtime() { | ||
37 | + return unixtime; | ||
38 | + } | ||
39 | + public void setUnixtime(long unixtime) { | ||
40 | + this.unixtime = unixtime; | ||
41 | + } | ||
42 | + | ||
43 | + public ClientRequest(String code, String ip, int maxWaitSec, int fixRateSec, long unixtime) { | ||
44 | + this.code = code; | ||
45 | + this.ip = ip; | ||
46 | + this.maxWaitSec = maxWaitSec; | ||
47 | + this.fixRateSec = fixRateSec; | ||
48 | + this.unixtime = unixtime; | ||
49 | + } | ||
50 | + | ||
51 | + public ClientRequest(ClientRequest clientRequest) { | ||
52 | + this.code = clientRequest.getCode(); | ||
53 | + this.ip = clientRequest.getIp(); | ||
54 | + this.maxWaitSec = clientRequest.getMaxWaitSec(); | ||
55 | + this.fixRateSec = clientRequest.getFixRateSec(); | ||
56 | + this.unixtime = clientRequest.getUnixtime(); | ||
57 | + } | ||
58 | + | ||
59 | + public static ClientRequest createClientRequest(HttpServletRequest request) { | ||
60 | + String code = request.getParameter("code"); | ||
61 | + String maxWaitSec = request.getParameter("maxWaitSec"); | ||
62 | + String fixRateSec = request.getParameter("fixRateSec"); | ||
63 | + String unixtime = request.getParameter("unixtime"); | ||
64 | + String ip = request.getRemoteHost(); | ||
65 | + return new ClientRequest(code, ip, | ||
66 | + maxWaitSec==null?Instance.DEFAULT_MAX_WAIT_SEC:Integer.valueOf(maxWaitSec), | ||
67 | + fixRateSec==null?Instance.DEFAULT_FIX_RATE_SEC:Integer.valueOf(fixRateSec), | ||
68 | + unixtime==null?System.currentTimeMillis()/1000:Long.valueOf(unixtime)); | ||
69 | + } | ||
70 | + | ||
71 | + public String getIdentity() { | ||
72 | + return this.code + "@" + this.ip; | ||
73 | + } | ||
74 | +} |
1 | +++ a/src/main/java/com/taover/heartbeat/bean/Instance.java | ||
@@ -0,0 +1,23 @@ | @@ -0,0 +1,23 @@ | ||
1 | +package com.taover.heartbeat.bean; | ||
2 | + | ||
3 | +public interface Instance { | ||
4 | + public static final int DEFAULT_MAX_WAIT_SEC = -1; | ||
5 | + public static final int DEFAULT_FIX_RATE_SEC = -1; | ||
6 | + | ||
7 | + /** | ||
8 | + * 获取id字符串 | ||
9 | + * @return | ||
10 | + */ | ||
11 | + String getIdentity(); | ||
12 | + | ||
13 | + /** | ||
14 | + * 是否可用 | ||
15 | + * @return | ||
16 | + */ | ||
17 | + boolean needReform(); | ||
18 | + | ||
19 | + /** | ||
20 | + * 刷新状态 | ||
21 | + */ | ||
22 | + void flush(); | ||
23 | +} |
src/main/java/com/taover/heartbeat/bean/ReformInstance.java
0 → 100644
1 | +++ a/src/main/java/com/taover/heartbeat/bean/ReformInstance.java | ||
@@ -0,0 +1,204 @@ | @@ -0,0 +1,204 @@ | ||
1 | +package com.taover.heartbeat.bean; | ||
2 | + | ||
3 | +import java.text.SimpleDateFormat; | ||
4 | +import java.util.Arrays; | ||
5 | +import java.util.Date; | ||
6 | +import java.util.List; | ||
7 | +import java.util.Map; | ||
8 | + | ||
9 | +import com.alibaba.fastjson.JSON; | ||
10 | +import com.alibaba.fastjson.JSONObject; | ||
11 | +import com.taover.util.UtilEmail; | ||
12 | +import com.taover.util.UtilLog; | ||
13 | +import com.taover.util.UtilWeixinMsg; | ||
14 | + | ||
15 | +public class ReformInstance { | ||
16 | + private List<String> emailToList; | ||
17 | + private List<String> weixinWxidList; | ||
18 | + private List<String> mobileList; | ||
19 | + | ||
20 | + public ReformInstance() {} | ||
21 | + | ||
22 | + public void doReform(Instance instance) { | ||
23 | + if(instance == null) { | ||
24 | + return; | ||
25 | + } | ||
26 | + if(this.emailToList != null && !this.emailToList.isEmpty()) { | ||
27 | + this.sendEmail(instance); | ||
28 | + } | ||
29 | + if(this.weixinWxidList != null && !this.weixinWxidList.isEmpty()) { | ||
30 | + this.sendWeixin(instance); | ||
31 | + } | ||
32 | + } | ||
33 | + | ||
34 | + private void sendWeixin(Instance instance) { | ||
35 | + String weixinContent = "报警--项目可用性监控\n"; | ||
36 | + if(instance instanceof ClientInstance) { | ||
37 | + weixinContent += this.formatWeixin((ClientInstance)instance); | ||
38 | + }else if(instance instanceof ServerInstance) { | ||
39 | + weixinContent += this.formatWeixin((ServerInstance)instance); | ||
40 | + }else { | ||
41 | + try { | ||
42 | + weixinContent += " JSON序列化:"+JSONObject.toJSONString(instance); | ||
43 | + }catch (Exception e) { | ||
44 | + weixinContent += " 对象无法序列化打印,instance.toString() ==>> "+instance.toString(); | ||
45 | + } | ||
46 | + } | ||
47 | + try { | ||
48 | + for(String weixinWxid: this.weixinWxidList) { | ||
49 | + if(weixinWxid == null || weixinWxid.trim().equals("")) { | ||
50 | + UtilWeixinMsg.sendTextMessage(weixinWxid, weixinContent); | ||
51 | + } | ||
52 | + } | ||
53 | + } catch (Exception e) { | ||
54 | + UtilLog.infoForMessage("发送微信消息失败,消息内容:"+weixinContent, this.getClass()); | ||
55 | + UtilLog.errorForException(e, this.getClass()); | ||
56 | + } | ||
57 | + } | ||
58 | + | ||
59 | + private String formatWeixin(ServerInstance instance) { | ||
60 | + String htmlContent = ""; | ||
61 | + if(instance.getLatestServerResponse() == null) { | ||
62 | + htmlContent += " 未收到服务器响应\n"; | ||
63 | + }else { | ||
64 | + if(instance.getLatestServerResponse().isOverdue()) { | ||
65 | + htmlContent += " 向服务器接口["+instance.getUrl()+"]发送请求,响应超时["+instance.getMaxWaitSec()+"s],请及时确认服务器是否正常运行\n"; | ||
66 | + }else if(!instance.getLatestServerResponse().isCodeOk()) { | ||
67 | + htmlContent += " 向服务器接口["+instance.getUrl()+"]发送请求,响应数据不正常(详细请查看邮件),请及时确认服务器是否正常运行\n"; | ||
68 | + }else { | ||
69 | + htmlContent += " 向服务器接口["+instance.getUrl()+"]发送请求,未知异常,请及时确认服务器是否正常运行\n"; | ||
70 | + } | ||
71 | + } | ||
72 | + htmlContent += " 最后一次请求时间: "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(instance.getLatestRequestUnixtime()*1000)); | ||
73 | + return htmlContent; | ||
74 | + } | ||
75 | + | ||
76 | + private String formatWeixin(ClientInstance instance) { | ||
77 | + String htmlContent = " 超过"+instance.getFixRateSec()+"秒未收到请求,请确认CODE["+instance.getCode()+"]对应的客户端是否运行正常\n"; | ||
78 | + htmlContent += " 客户端最后一次请求时间: "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(instance.getUnixtime()*1000)); | ||
79 | + htmlContent += " 客户端IP:"+instance.getIp(); | ||
80 | + return htmlContent; | ||
81 | + } | ||
82 | + | ||
83 | + private void sendEmail(Instance instance) { | ||
84 | + String subject = "报警-项目可用性监控--监控ID["+instance.getIdentity()+"]"; | ||
85 | + String htmlContent = "<h2>监控ID:"+instance.getIdentity()+"</h2>"; | ||
86 | + if(instance instanceof ClientInstance) { | ||
87 | + htmlContent += this.formatHtml((ClientInstance)instance); | ||
88 | + }else if(instance instanceof ServerInstance) { | ||
89 | + htmlContent += this.formatHtml((ServerInstance)instance); | ||
90 | + }else { | ||
91 | + try { | ||
92 | + htmlContent += "<p>"+JSONObject.toJSONString(instance)+"</p>"; | ||
93 | + }catch (Exception e) { | ||
94 | + htmlContent += "<span style=\"color:red;\">对象无法序列化打印,instance.toString() ==>> "+instance.toString()+"</span>"; | ||
95 | + } | ||
96 | + } | ||
97 | + try { | ||
98 | + UtilEmail.sendHtmlMail(emailToList, subject, htmlContent); | ||
99 | + } catch (Exception e) { | ||
100 | + UtilLog.infoForMessage("发送邮件失败,消息内容:[标题:"+subject+"],[正文:"+htmlContent+"]", this.getClass()); | ||
101 | + UtilLog.errorForException(e, this.getClass()); | ||
102 | + } | ||
103 | + } | ||
104 | + | ||
105 | + private String formatHtml(ServerInstance instance) { | ||
106 | + String htmlContent = ""; | ||
107 | + htmlContent += "<h4 style=\"color:red;\">"; | ||
108 | + if(instance.getLatestServerResponse() != null) { | ||
109 | + if(instance.getLatestServerResponse().isOverdue()) { | ||
110 | + htmlContent += " 向服务器接口["+instance.getUrl()+"]发送请求,响应超时["+instance.getMaxWaitSec()+"s],请及时确认服务器是否正常运行"; | ||
111 | + }else if(!instance.getLatestServerResponse().isCodeOk()) { | ||
112 | + htmlContent += " 向服务器接口["+instance.getUrl()+"]发送请求,响应数据不正常(详细请查看邮件),请及时确认服务器是否正常运行"; | ||
113 | + }else { | ||
114 | + htmlContent += "未知异常"; | ||
115 | + } | ||
116 | + }else { | ||
117 | + htmlContent += "未记录最后一次响应记录"; | ||
118 | + } | ||
119 | + htmlContent += "</h4>"; | ||
120 | + htmlContent += "<ul>"; | ||
121 | + htmlContent += "<li>CODE: "+instance.getCode()+"</li>"; | ||
122 | + htmlContent += "<li>URL: "+instance.getUrl()+"</li>"; | ||
123 | + htmlContent += "<li>请求频率: "+instance.getFixRateSec()+"秒/次</li>"; | ||
124 | + htmlContent += "<li>请求最大等待时间: "+instance.getMaxWaitSec()+"秒</li>"; | ||
125 | + htmlContent += "<li>客户端请求时间戳: "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(instance.getLatestRequestUnixtime()*1000))+"</li>"; | ||
126 | + htmlContent += "<li>最后一次收到的响应包: <span style=\"color:gray;\">"+JSON.toJSONString(instance.getLatestServerResponse())+"</span></li>"; | ||
127 | + htmlContent += "</ul>"; | ||
128 | + return htmlContent; | ||
129 | + } | ||
130 | + | ||
131 | + private String formatHtml(ClientInstance instance) { | ||
132 | + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | ||
133 | + String htmlContent = ""; | ||
134 | + htmlContent += "<h4 style=\"color:red;\">"; | ||
135 | + htmlContent += "超过"+instance.getFixRateSec()+"秒未收到请求,请确认CODE["+instance.getCode()+"]对应的客户端是否运行正常<br />"; | ||
136 | + htmlContent += "客户端最后一次请求时间: "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(instance.getUnixtime()*1000)); | ||
137 | + htmlContent += "</h4>"; | ||
138 | + htmlContent += "<ul>"; | ||
139 | + htmlContent += "<li>CODE: "+instance.getCode()+"</li>"; | ||
140 | + htmlContent += "<li>IP: "+instance.getIp()+"</li>"; | ||
141 | + htmlContent += "<li>请求频率: "+instance.getFixRateSec()+"秒/次</li>"; | ||
142 | + htmlContent += "<li>请求最大等待时间: "+instance.getMaxWaitSec()+"秒</li>"; | ||
143 | + htmlContent += "<li>客户端请求时间戳: "+sdf.format(new Date(instance.getUnixtime()*1000))+"</li>"; | ||
144 | + htmlContent += "<li>服务器接收时间: "+sdf.format(new Date(instance.getLastestServerUnixtime()*1000))+"</li>"; | ||
145 | + htmlContent += "<li>最后一次收到的请求包: <span style=\"color:gray;\">"+JSON.toJSONString(instance.getLastestClientRequest())+"</span></li>"; | ||
146 | + htmlContent += "</ul>"; | ||
147 | + return htmlContent; | ||
148 | + } | ||
149 | + | ||
150 | + public void loadConfig(String emailTo, String weixinWxid, String mobile) { | ||
151 | + if(strNotBlank(emailTo)) { | ||
152 | + this.emailToList = Arrays.asList(emailTo.split(",")); | ||
153 | + } | ||
154 | + if(strNotBlank(weixinWxid)) { | ||
155 | + this.weixinWxidList = Arrays.asList(weixinWxid.split(",")); | ||
156 | + } | ||
157 | + if(strNotBlank(mobile)) { | ||
158 | + this.mobileList = Arrays.asList(mobile.split(",")); | ||
159 | + } | ||
160 | + } | ||
161 | + | ||
162 | + public void loadConfig(Map<String, String> data) { | ||
163 | + Object emailTo = data.get("emailTo"); | ||
164 | + if(emailTo != null && strNotBlank(emailTo.toString())) { | ||
165 | + this.emailToList = Arrays.asList(emailTo.toString().split(",")); | ||
166 | + } | ||
167 | + Object weixinWxid = data.get("weixinWxid"); | ||
168 | + if(weixinWxid != null && strNotBlank(weixinWxid.toString())) { | ||
169 | + this.weixinWxidList = Arrays.asList(weixinWxid.toString().split(",")); | ||
170 | + } | ||
171 | + Object mobile = data.get("mobile"); | ||
172 | + if(mobile != null && strNotBlank(mobile.toString())) { | ||
173 | + this.mobileList = Arrays.asList(mobile.toString().split(",")); | ||
174 | + } | ||
175 | + } | ||
176 | + | ||
177 | + private boolean strNotBlank(String data) { | ||
178 | + return !(data == null || data.trim().equals("")); | ||
179 | + } | ||
180 | + | ||
181 | + public List<String> getEmailToList() { | ||
182 | + return emailToList; | ||
183 | + } | ||
184 | + | ||
185 | + public void setEmailToList(List<String> emailToList) { | ||
186 | + this.emailToList = emailToList; | ||
187 | + } | ||
188 | + | ||
189 | + public List<String> getWeixinWxidList() { | ||
190 | + return weixinWxidList; | ||
191 | + } | ||
192 | + | ||
193 | + public void setWeixinWxidList(List<String> weixinWxidList) { | ||
194 | + this.weixinWxidList = weixinWxidList; | ||
195 | + } | ||
196 | + | ||
197 | + public List<String> getMobileList() { | ||
198 | + return mobileList; | ||
199 | + } | ||
200 | + | ||
201 | + public void setMobileList(List<String> mobileList) { | ||
202 | + this.mobileList = mobileList; | ||
203 | + } | ||
204 | +} |
src/main/java/com/taover/heartbeat/bean/ServerInstance.java
0 → 100644
1 | +++ a/src/main/java/com/taover/heartbeat/bean/ServerInstance.java | ||
@@ -0,0 +1,128 @@ | @@ -0,0 +1,128 @@ | ||
1 | +package com.taover.heartbeat.bean; | ||
2 | + | ||
3 | +import java.net.SocketTimeoutException; | ||
4 | + | ||
5 | +import com.taover.util.UtilHttpByOkHttp; | ||
6 | + | ||
7 | +public class ServerInstance implements Instance { | ||
8 | + public int DEFAULT_REFORM_MIN_ERROR_COUNT = 1; | ||
9 | + public int DEFAULT_REFORM_MAX_ERROR_COUNT = 3; | ||
10 | + | ||
11 | + private String code; | ||
12 | + private String url; | ||
13 | + private int fixRateSec; | ||
14 | + private int maxWaitSec; | ||
15 | + private long latestRequestUnixtime; | ||
16 | + private ServerResponse latestServerResponse; | ||
17 | + private int errorServerResponseCount; | ||
18 | + | ||
19 | + public ServerInstance(String code, String url, int fixRateSec, int maxWaitSec) throws Exception { | ||
20 | + super(); | ||
21 | + if(fixRateSec < 60) { | ||
22 | + throw new Exception("固定时间间隔不允许小于60s"); | ||
23 | + } | ||
24 | + | ||
25 | + this.code = code; | ||
26 | + this.url = url; | ||
27 | + this.fixRateSec = fixRateSec; | ||
28 | + this.maxWaitSec = maxWaitSec; | ||
29 | + } | ||
30 | + | ||
31 | + @Override | ||
32 | + public void flush() { | ||
33 | + //如果小于设置的发送时间间隔,则不发送请求 | ||
34 | + if(!this.isLatestRequestGreateEqualFixRateSec()) { | ||
35 | + return; | ||
36 | + } | ||
37 | + this.latestRequestUnixtime = System.currentTimeMillis()/1000; | ||
38 | + try { | ||
39 | + this.latestServerResponse = ServerResponse.createByJSONString(UtilHttpByOkHttp.sendGet(this.url + this.getUrlParams(), null, maxWaitSec)); | ||
40 | + if(this.latestServerResponse.isCodeOk()) { | ||
41 | + this.errorServerResponseCount = 0; | ||
42 | + } | ||
43 | + } catch(SocketTimeoutException timeError) { | ||
44 | + this.latestServerResponse = ServerResponse.createOverdue(); | ||
45 | + } catch (Exception e) { | ||
46 | + this.latestServerResponse = ServerResponse.createException(e); | ||
47 | + } | ||
48 | + if(this.latestServerResponse.isOverdue() || !this.latestServerResponse.isCodeOk()) { | ||
49 | + ++this.errorServerResponseCount; | ||
50 | + } | ||
51 | + } | ||
52 | + | ||
53 | + private String getUrlParams() { | ||
54 | + return "?code="+this.code+"&fixRateSec="+this.fixRateSec+"&maxWaitSec="+this.maxWaitSec+"&unixtime="+(System.currentTimeMillis()/1000); | ||
55 | + } | ||
56 | + | ||
57 | + private boolean isLatestRequestGreateEqualFixRateSec() { | ||
58 | + return (System.currentTimeMillis()/1000 - this.latestRequestUnixtime) >= this.fixRateSec; | ||
59 | + } | ||
60 | + | ||
61 | + @Override | ||
62 | + public String getIdentity() { | ||
63 | + return this.code + "@" + this.url; | ||
64 | + } | ||
65 | + | ||
66 | + @Override | ||
67 | + public boolean needReform() { | ||
68 | + return this.isLatestRequestGreateEqualFixRateSec() | ||
69 | + && this.errorServerResponseCount>=DEFAULT_REFORM_MIN_ERROR_COUNT | ||
70 | + && this.errorServerResponseCount<=DEFAULT_REFORM_MAX_ERROR_COUNT; | ||
71 | + } | ||
72 | + | ||
73 | + public String getCode() { | ||
74 | + return code; | ||
75 | + } | ||
76 | + | ||
77 | + public void setCode(String code) { | ||
78 | + this.code = code; | ||
79 | + } | ||
80 | + | ||
81 | + public String getUrl() { | ||
82 | + return url; | ||
83 | + } | ||
84 | + | ||
85 | + public void setUrl(String url) { | ||
86 | + this.url = url; | ||
87 | + } | ||
88 | + | ||
89 | + public int getFixRateSec() { | ||
90 | + return fixRateSec; | ||
91 | + } | ||
92 | + | ||
93 | + public void setFixRateSec(int fixRateSec) { | ||
94 | + this.fixRateSec = fixRateSec; | ||
95 | + } | ||
96 | + | ||
97 | + public int getMaxWaitSec() { | ||
98 | + return maxWaitSec; | ||
99 | + } | ||
100 | + | ||
101 | + public void setMaxWaitSec(int maxWaitSec) { | ||
102 | + this.maxWaitSec = maxWaitSec; | ||
103 | + } | ||
104 | + | ||
105 | + public long getLatestRequestUnixtime() { | ||
106 | + return latestRequestUnixtime; | ||
107 | + } | ||
108 | + | ||
109 | + public void setLatestRequestUnixtime(long latestRequestUnixtime) { | ||
110 | + this.latestRequestUnixtime = latestRequestUnixtime; | ||
111 | + } | ||
112 | + | ||
113 | + public ServerResponse getLatestServerResponse() { | ||
114 | + return latestServerResponse; | ||
115 | + } | ||
116 | + | ||
117 | + public void setLatestServerResponse(ServerResponse latestServerResponse) { | ||
118 | + this.latestServerResponse = latestServerResponse; | ||
119 | + } | ||
120 | + | ||
121 | + public int getLostServerResponseCount() { | ||
122 | + return errorServerResponseCount; | ||
123 | + } | ||
124 | + | ||
125 | + public void setLostServerResponseCount(int lostServerResponseCount) { | ||
126 | + this.errorServerResponseCount = lostServerResponseCount; | ||
127 | + } | ||
128 | +} |
src/main/java/com/taover/heartbeat/bean/ServerResponse.java
0 → 100644
1 | +++ a/src/main/java/com/taover/heartbeat/bean/ServerResponse.java | ||
@@ -0,0 +1,73 @@ | @@ -0,0 +1,73 @@ | ||
1 | +package com.taover.heartbeat.bean; | ||
2 | + | ||
3 | +import org.apache.commons.lang.StringUtils; | ||
4 | + | ||
5 | +import com.alibaba.fastjson.JSONObject; | ||
6 | + | ||
7 | +public class ServerResponse { | ||
8 | + public static String RESPONSE_CODE_OK = "ok"; | ||
9 | + | ||
10 | + private boolean isOverdue; | ||
11 | + private boolean isCodeOk; | ||
12 | + private String responseContent; | ||
13 | + private Exception exception; | ||
14 | + | ||
15 | + private ServerResponse(boolean isOverdue, boolean isCodeOk, String responseContent, Exception e) { | ||
16 | + super(); | ||
17 | + this.isOverdue = isOverdue; | ||
18 | + this.isCodeOk = isCodeOk; | ||
19 | + this.responseContent = responseContent; | ||
20 | + this.exception = e; | ||
21 | + } | ||
22 | + | ||
23 | + public boolean isOverdue() { | ||
24 | + return isOverdue; | ||
25 | + } | ||
26 | + public void setOverdue(boolean isOverdue) { | ||
27 | + this.isOverdue = isOverdue; | ||
28 | + } | ||
29 | + public boolean isCodeOk() { | ||
30 | + return isCodeOk; | ||
31 | + } | ||
32 | + public void setCodeOk(boolean isCodeOk) { | ||
33 | + this.isCodeOk = isCodeOk; | ||
34 | + } | ||
35 | + public String getResponseContent() { | ||
36 | + return responseContent; | ||
37 | + } | ||
38 | + public void setResponseContent(String responseContent) { | ||
39 | + this.responseContent = responseContent; | ||
40 | + } | ||
41 | + public Exception getException() { | ||
42 | + return exception; | ||
43 | + } | ||
44 | + public void setException(Exception exception) { | ||
45 | + this.exception = exception; | ||
46 | + } | ||
47 | + | ||
48 | + public static ServerResponse createByJSONString(String response) { | ||
49 | + if(StringUtils.isBlank(response)) { | ||
50 | + return new ServerResponse(false, false, response, null); | ||
51 | + }else { | ||
52 | + try { | ||
53 | + JSONObject data = JSONObject.parseObject(response); | ||
54 | + String code = data.getString("code"); | ||
55 | + if(RESPONSE_CODE_OK.equals(code.toLowerCase())) { | ||
56 | + return new ServerResponse(false, true, response, null); | ||
57 | + }else { | ||
58 | + return new ServerResponse(false, false, response, null); | ||
59 | + } | ||
60 | + }catch (Exception e) { | ||
61 | + return new ServerResponse(false, false, response, e); | ||
62 | + } | ||
63 | + } | ||
64 | + } | ||
65 | + | ||
66 | + public static ServerResponse createOverdue() { | ||
67 | + return new ServerResponse(false, false, "", null); | ||
68 | + } | ||
69 | + | ||
70 | + public static ServerResponse createException(Exception e) { | ||
71 | + return new ServerResponse(false, false, "", e); | ||
72 | + } | ||
73 | +} |