@RestController
@RequestMapping("/notifications")
public class NotificationResource implements ReleaseMessageListener {
private static final Logger logger = LoggerFactory.getLogger(NotificationResource.class);
private final Multimap<String, DeferredResultWrapper> deferredResults =
Multimaps.synchronizedSetMultimap(HashMultimap.create());
// 线程池
private final ExecutorService largeNotificationBatchExecutorService;
public NotificationResource() {
largeNotificationBatchExecutorService = Executors.newFixedThreadPool(20, BambooThreadFactory.create
("NotificationResource", true));
}
/**
* 接收所有实例链接
* @return
*/
@RequestMapping(method = RequestMethod.GET)
public DeferredResult<ResponseEntity<Boolean>> pollNotification(@RequestParam(value = "instanceId") String instanceId) {
DeferredResultWrapper deferredResultWrapper = new DeferredResultWrapper(instanceId);
deferredResultWrapper.onTimeout(() -> logger.debug("notifications timeout"));
deferredResultWrapper.onCompletion(() -> deferredResults.remove("server", deferredResultWrapper));
this.deferredResults.put("server", deferredResultWrapper);
return deferredResultWrapper.getResult();
}
/**
* 通知所有实例
*/
@Override
public void handleMessage() {
logger.info("gray map modified");
for (DeferredResultWrapper wrapper : (List<DeferredResultWrapper>) new ArrayList(deferredResults.get("server"))) {
largeNotificationBatchExecutorService.submit(() -> wrapper.setResult(true));
}
}
}
通知接口
/**
* 通知接口
*/
public interface ReleaseMessageListener {
void handleMessage();
}
deferredResult包装类
/**
* 长链接包装类
*/
public class DeferredResultWrapper {
private static final long TIMEOUT = 60 * 1000;//60 seconds
// 默认返回304
private static final ResponseEntity<Boolean>
NOT_MODIFIED_RESPONSE = new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
private String instanceId;
private DeferredResult<ResponseEntity<Boolean>> result;
/**
* 构造函数
*/
public DeferredResultWrapper(String instanceId) {
this.instanceId = instanceId;
result = new DeferredResult<>(TIMEOUT, NOT_MODIFIED_RESPONSE);
}
// 超时
public void onTimeout(Runnable timeoutCallback) {
result.onTimeout(timeoutCallback);
}
public void onCompletion(Runnable completionCallback) {
result.onCompletion(completionCallback);
}
/**
* 设置返回结果
* @param notification
*/
public void setResult(boolean notification) {
result.setResult(new ResponseEntity<>(notification, HttpStatus.OK));
}
public DeferredResult<ResponseEntity<Boolean>> getResult() {
return result;
}
}
当调用接口时,都会在本地注册。
当到达60s超时时间后,会返回给调用方304。
当在60s之内想要通知调用方,会返回true且200。