diff --git a/virtual-patient-web/src/main/java/com/supervision/controller/HeartController.java b/virtual-patient-web/src/main/java/com/supervision/controller/HeartController.java
new file mode 100644
index 00000000..78779e9a
--- /dev/null
+++ b/virtual-patient-web/src/main/java/com/supervision/controller/HeartController.java
@@ -0,0 +1,68 @@
+package com.supervision.controller;
+
+import cn.hutool.cache.CacheUtil;
+import cn.hutool.cache.impl.TimedCache;
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.StrUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.*;
+
+
+@Slf4j
+@Api(tags = "心跳检查")
+@RestController
+@RequestMapping("heart")
+@RequiredArgsConstructor
+public class HeartController {
+
+
+    TimedCache<Object, Object> onlineCache = CacheUtil.newTimedCache(50*1000);
+
+    {
+        onlineCache.setListener((key,value)->{
+            log.info(" onlineCache : remove listener key: " + key + " value: "+value);
+            onlineCache.remove(key);
+        });
+    }
+    @ApiOperation("心跳")
+    @GetMapping("ping")
+    public void ping (String processId, HttpServletRequest request) {
+
+        String ipAddress = request.getHeader("X-Real-IPheader");
+
+        if (StrUtil.isEmpty(ipAddress)){
+            log.info("X-Real-IPheader is empty ....,use ip " + request.getRemoteAddr());
+            ipAddress = request.getRemoteAddr();
+        }
+
+        if (StrUtil.isNotEmpty(ipAddress)){
+            log.info("onlineCache : set cache... processId: "+ processId + " value "+ipAddress);
+            onlineCache.put(processId,ipAddress);
+        }
+    }
+
+    @ApiOperation("存活节点")
+    @GetMapping("get")
+    public Map<String, Object> getOnline () {
+        Map<String, Object> result = new HashMap<>();
+        Set<Object> objects = onlineCache.keySet();
+        if (CollectionUtil.isNotEmpty(objects)){
+            for (Object key : objects) {
+                result.put(key.toString(),onlineCache.get(key));
+            }
+        }
+        return result;
+
+    }
+
+
+
+}