У меня есть требование отправлять уведомление из базы данных SQL пользователю, поскольку сервер отправляет события в Spring Boot. Я использовал SseEmitter для реализации этого.
1) @GetMapping(value = "/v2/user/notifications/event",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public ResponseEntity<SseEmitter> sendNotification(@RequestHeader(value = "Authorization") final String token) {
HttpHeaders headers = new HttpHeaders();
headers.add("Connection","keep-alive");
headers.add("Cache-Control", "no-cache");
List<HttpStatus> httpStatuses = new ArrayList<>();
httpStatuses.add(0, HttpStatus.OK);
SseEmitter sseEmitter = new SseEmitter(Long.MAX_VALUE);
Integer nextEventFireTime = appConfig.getConfiguration().getInteger("sse.nextEventFireTime");
ScheduledExecutorService scheduledExecutorService =
Executors.newScheduledThreadPool(Constants.MAX_THREAD_POOL_SSE);
scheduledExecutorService.scheduleAtFixedRate(() -> {
try {
service.sendNotification(sseEmitter, token);
} catch (BaseException e) {
httpStatuses.add(0, HttpStatus.INTERNAL_SERVER_ERROR);
sseEmitter.completeWithError(e);
scheduledExecutorService.shutdown();
}
} , 0, nextEventFireTime, TimeUnit.SECONDS);
return new ResponseEntity<>(sseEmitter, headers, httpStatuses.get(0));
}
* nextEventFireTime настроен как 15
2)@Override
public synchronized void sendNotification(SseEmitter emitter, String token) throws BaseException {
NotificationMetadata notificationMetadata =
getUnreadNotificationCount(token);
List<Notification2> notificationList;
notificationList =
getSseNotifications(token);
SseEmitter.SseEventBuilder event = SseEmitter.event();
NotificationResponse2 notificationResponse2 = new NotificationResponse2();
notificationResponse2.setData(notificationList);
notificationResponse2.setMetadata(notificationMetadata);
event.name(Constants.SSE_EVENT_NAME).data(notificationResponse2)
.build();
try {
emitter.send(event.reconnectTime(15000L));
} catch (Exception e) {
throw new BaseException("Failed to send notification event.. "+e.getMessage(), Constants.ERROR_CODE_INTERNAL_ERROR,
"sendNotification", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Клиент ожидает ответа, и это занимает около 17 минут, когда в базе данных нет данных для уведомления, но запрос счетчика извлекает данные, а когда есть данные, то также требуется 4-5 минут, чтобы дать ответ.
Я использую SseEmitter в первый раз, и когда я отлаживаю код на сервере, выполняется, но ответ все еще ожидает ответа.
Может ли кто-нибудь помочь мне с этим вопросом?
Я использовал synchronized, потому что есть 2 запроса для получения данных, и я хочу, чтобы один поток завершил выполнение до прерывания другого потока. Я не использую планировщик задач, потому что SSE должен передавать данные только тогда, когда одна регистрация выполняется от пользователя, и я создаю событие, а затем выполняю сборку в следующей строке.
Результат вызова build игнорируется, следовательно, это событие 1 ... Затем вы вызываете reconnectTime, который создает другое событие, следовательно, вы создаете несколько событий. Кроме того, если вы хотите, чтобы он был однопоточным, тогда зачем вообще делать его асинхронным? Похоже, много работы без всякой выгоды.




Почему метод
synchronized? Кроме того, зачем воссоздаватьScheduledExecutorService, вам лучше настроитьTaskSchedulerи использовать его повторно (теперь вы рискуете создать множество потоков, которые могут действительно замедлить работу). Вы также дважды перестраиваете событие, не зная, зачем вы это делаете.