spring-cloud / spring-cloud-gateway

An API Gateway built on Spring Framework and Spring Boot providing routing and more.
http://cloud.spring.io
Apache License 2.0
4.51k stars 3.31k forks source link

How does gateway support SseEmitter streaming output? #3039

Closed syzpig closed 6 months ago

syzpig commented 1 year ago

Is your feature request related to a problem? Please describe. 请问网关需要如何配置,才可以支持,试了好几种方式,目前发现都不能流式输出,都是一次响应。

Describe the solution you'd like 请问,网关改配置什么可以支持流式,官网没有看到。

Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered.

Additional context Add any other context or screenshots about the feature request here.

manzhizhen commented 1 year ago

Spring Cloud Gateway is capable of supporting SSE (no additional configuration is required), what is your problem. For example, there is an SSE Web service downstream of the gateway:

    @GetMapping(value = "/stream-sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ServerSentEvent<String>> streamSseMvc() {
        return Flux.interval(Duration.ofSeconds(1))
                .map(sequence -> {
                            if (sequence > 50) {
                                return ServerSentEvent.<String>builder().comment("stop sending").build();
                            } else {
                                // 正常发送 SSE 事件
                                return ServerSentEvent.<String>builder()
                                        .id(String.valueOf(sequence))
                                        .event("message")
                                        .data("SSE - " + LocalTime.now())
                                        .build();
                            }
                        }
                )
                .doOnCancel(() -> System.out.println("SSE connection cancelled"))
                .doOnError(Throwable::printStackTrace)
                .doOnComplete(() -> System.out.println("SSE connection completed"));
    }

your Spring Cloud Gateway can use config:

spring:
  cloud:
    gateway:
      routes:
        - id: sseRouter
          uri: http://localhost:8080
          predicates:
            - Path=/stream-sse
server:
  port: 8082

you use curl can see effect:

curl --location --request GET 'http://localhost:8082/stream-sse' \
--header 'User-Agent: Apifox/1.0.0 (https://apifox.com)' \
--header 'Content-Type: text/event-stream'
swit1983 commented 10 months ago
@RequestMapping(value = "/stream/text2text",produces="text/event-stream;charset=UTF-8")
    public SseEmitter text2textStream(@RequestParam("streamId") String streamId, HttpServletResponse response)

我在一个服务user实现了一个SSE协议的服务,直接访问没有问题实时返回的,但是通过gateway代理之后,消息累积之后一次性返回,变成这样了

wcyuee commented 9 months ago
@RequestMapping(value = "/stream/text2text",produces="text/event-stream;charset=UTF-8")
    public SseEmitter text2textStream(@RequestParam("streamId") String streamId, HttpServletResponse response)

我在一个服务user实现了一个SSE协议的服务,直接访问没有问题实时返回的,但是通过gateway代理之后,消息累积之后一次性返回,变成这样了

Me too, I don't know how to solve this problem

wcyuee commented 9 months ago

事实上,单纯的springgateway不需要增加任何配置。如果你前端通过webpack dbserver转发的的话,考虑修改一下devServer: { compress: false,

spring-cloud-issues commented 6 months ago

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

spring-cloud-issues commented 6 months ago

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.

jjnian commented 3 months ago

事实上,单纯的springgateway不需要增加任何配置。如果你前端通过webpack dbserver转发的的话,考虑修改一下devServer: { compress: false,

你通过这样的方式解决了吗

jjnian commented 3 months ago
@RequestMapping(value = "/stream/text2text",produces="text/event-stream;charset=UTF-8")
    public SseEmitter text2textStream(@RequestParam("streamId") String streamId, HttpServletResponse response)

我在一个服务user实现了一个SSE协议的服务,直接访问没有问题实时返回的,但是通过gateway代理之后,消息累积之后一次性返回,变成这样了

这个问题你解决了吗

womenshizhu commented 2 months ago

客户端 返回的时候 消息积累在一起进行返回 有解决么

manzhizhen commented 2 months ago

你们有完整能复现该问题的Demo吗?

womenshizhu commented 2 months ago

解决了 response接收的时候 Flux<? extends DataBuffer> fluxBody = Flux.from(body);

                    return super.writeWith(fluxBody.map(dataBuffer -> {
                        byte[] content = new byte[dataBuffer.readableByteCount()];
                        dataBuffer.read(content);
                        String responseData = new String(content, StandardCharsets.UTF_8);

                        if (StringUtils.isNotBlank(responseData) && !responseData.contains("data:")) {
                            log.info("responseData:" + responseData);
                            logService.sendResponseLog(exchange, responseData, true);
                        }

                        return bufferFactory.wrap(content);
                    }));