【问题标题】:Spring SSE (SseEmitter): Flutter Client receiving events only after timeoutSpring SSE(SseEmitter):Flutter Client 仅在超时后接收事件
【发布时间】:2023-01-25 21:21:10
【问题描述】:

我的后端是在 Spring Boot(2.7.0), Spring (5.3.20) 中开发的 在我的应用程序中,我想使用 Spring MVC Server-Sent-Events SSE 流式传输数据:通过 http 协议的异步服务器到客户端通信

服务器端:

订阅端点: 超时时间临时设置为 2 分钟

@RestController
@RequestMapping(value = ApiConstants.STREAM_API)@Validated
public class StreamingController {

    private final StreamingService service;

    @GetMapping(value = "/subscribe", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter subscribe() {
        SseEmitter emitter = new SseEmitter(120000L); //Timeout 2 Minutes
        try {
            emitter.send(SseEmitter.event().name("INIT"));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        emitter.onCompletion(() -> service.getEmitters().remove(emitter));
        emitter.onTimeout(()-> service.getEmitters().remove(emitter));
        emitter.onError((ex)-> service.getEmitters().remove(emitter));
        service.getEmitters().add(emitter);
        return emitter;
  }
}

@Service
@Transactional
public class StreamingService {

    @Getter
    @Setter
    private List<SseEmitter> emitters = new CopyOnWriteArrayList<>();

}

在数据库中持久化特定实体后发送事件的实体监听器类:

@Service
@Transactional
public class EntityListener {

    private final StreamingService streamingService;

    @PostPersist
    protected void afterCreate(final Entity createdEntity) {
            List<SseEmitter> emitters = new ArrayList<>(streamingService.getEmitters());
            for (SseEmitter emitter : emitters) {
                try {
                    SseEmitter.SseEventBuilder event = SseEmitter.event()
                            .data("Last Score" + createdEntity.getScore())
                            .id(String.valueOf(createdEntity.getId()))
                            .name("Event Name");
                    emitter.send(event);
                } catch (Exception ex) {
                    emitter.completeWithError(ex);
                    streamingService.getEmitters().remove(emitter);
                }
            }
        }
    }
}

客户端

颤振代码

print("Subscribing..");
Future<http.StreamedResponse>? response;

try {
    final _client = http.Client();

    var request = http.Request("GET", Uri.parse('http://localhost:5555/stream/subscribe'));
    
    Map<String, String> headers = {};
    headers.addAll(service.header);
    headers["Authorization"] = __token!;
    headers["Cache-Control"] = "no-cache";
    headers["Accept"] = "text/event-stream";

    request.headers.addAll(headers);

    response = _client.send(request);
    print("Subscribed!");
} catch (e) {
    print("Caught $e");
}

response?.asStream().listen((streamedResponse) {
    print("Received streamedResponse.statusCode:${streamedResponse.statusCode}");
    streamedResponse.stream.listen((data) {
        print("Received data:${utf8.decode(data)}");
    });
});

问题是我的事件没有在调用方法发送后立即发送。只有在 SseEmitter 超时后,它们才会同时(具有相同的时间戳)到达客户端。

预期是 Flutter 监听器实时接收事件

【问题讨论】:

    标签: spring flutter spring-boot server-sent-events


    【解决方案1】:

    您可能应该验证您的服务器配置,或者如果您正在使用它,还应该验证 nginx 配置。并确认您的请求响应的标头包含以下内容:

    Content-Type: text/event-stream;
    Cache-Control: no-cache;
    X-Accel-Buffering: no; 
    

    这是对你的问题的一个很好的解释:https://serverfault.com/questions/801628/for-server-sent-events-sse-what-nginx-proxy-configuration-is-appropriate

    【讨论】:

      猜你喜欢
      • 2022-06-25
      • 1970-01-01
      • 1970-01-01
      • 2012-09-13
      • 2019-08-24
      • 2021-11-17
      • 2020-10-27
      • 2020-04-11
      • 2019-08-19
      相关资源
      最近更新 更多