Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring webflux WebFlux控制器返回流量和背压_Spring Webflux_Reactor - Fatal编程技术网

Spring webflux WebFlux控制器返回流量和背压

Spring webflux WebFlux控制器返回流量和背压,spring-webflux,reactor,Spring Webflux,Reactor,在Spring WebFlux中,我有一个类似的控制器: @RestController @RequestMapping("/data") public class DataController { @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) public Flux<Data> getData() { return <data from database using reactive dri

在Spring WebFlux中,我有一个类似的控制器:

@RestController
@RequestMapping("/data")
public class DataController {

  @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
  public Flux<Data> getData() {
    return <data from database using reactive driver>
  } 
}
@RestController
@请求映射(“/data”)
公共类数据控制器{
@GetMapping(products=MediaType.APPLICATION\u JSON\u值)
公共数据{
返回
} 
}
  • 订阅出版商的具体内容是什么?
  • 什么(如果有的话)提供了背压?
  • 在上下文中,我试图评估在这种特定情况下使用springwebflux是否比springmvc有优势

    订阅出版商的具体内容是什么

    框架(在本例中是Spring)

    一般来说,您不应该在自己的应用程序中订阅—框架应该在必要时订阅您的发布者。在spring的上下文中,每当相关的请求到达该控制器时,就会出现这种情况

    什么(如果有的话)提供了背压

    在这种情况下,它只受连接速度的限制(我相信Webflux会查看底层TCP层),然后根据需要请求数据。然而,你的上游流量是否会听到这种背压则是另一回事——它可能会听到,或者它可能会向消费者提供尽可能多的数据

    在上下文中,我试图评估在这种特定情况下使用SpringWebFlux是否比SpringMVC更有优势

    它的主要优点是只需几个线程就可以保持大量的连接处于打开状态,因此不会产生上下文切换的开销。(这不是唯一的优势,但大多数优势通常可以归结为这一点。)通常,这只是一个值得考虑的优势,如果您需要同时保持数千个连接打开的区域


    主要的缺点是,反应式代码与标准Java代码看起来非常不同,因此通常必然更加复杂。调试也很困难-例如,普通的堆栈跟踪几乎毫无用处(尽管它们是使调试更容易的工具和技术)。

    注意:我不是spring framework的开发人员,所以欢迎发表任何评论

    订阅出版商的具体内容是什么

    它是对端口的长期订阅(服务器初始化本身)。因此,
    ReactorHttpServer.class
    具有以下方法:

    @Override
    protected void startInternal() {
        DisposableServer server = this.reactorServer.handle(this.reactorHandler).bind().block();
        setPort(((InetSocketAddress) server.address()).getPort());
        this.serverRef.set(server);
    }
    
    订阅方是绑定方法,它(据我所知)请求(Long.MAX_值),因此这里没有背压管理

    请求处理的重要部分是方法
    handle(this.reactorHandler)
    reactorHandler
    ReactorHttpHandlerAdapter
    的一个实例。堆栈的更上一层(在
    ReactorHttpHandlerAdapter
    apply
    方法中)是
    DispatcherHandler.class
    。此类的java文档以“HTTP请求处理程序/控制器的中央调度程序。调度到已注册的处理程序以处理请求,提供方便的映射工具”开头。它具有中心方法:

    @Override
    public Mono<Void> handle(ServerWebExchange exchange) {
        if (this.handlerMappings == null) {
            return createNotFoundError();
        }
        return Flux.fromIterable(this.handlerMappings)
                .concatMap(mapping -> mapping.getHandler(exchange))
                .next()
                .switchIfEmpty(createNotFoundError())
                .flatMap(handler -> invokeHandler(exchange, handler))
                .flatMap(result -> handleResult(exchange, result));
    }
    
    netyoutbind.send(…)
    的一个实现是
    reactor.netty.channel.ChannelOperations
    。对于通量返回的特定情况,此实现在
    MonoSendMany.class
    中管理NIO。该类使用
    SendManyInner.class
    订阅(…),该类通过实现
    Subscriber
    来执行背压管理,而
    onSubscribe
    则执行
    请求(128)
    。我猜Netty内部使用TCP ACK来表示传输成功

    所以

    什么(如果有的话)提供了背压

    。。。是的,例如通过
    SendManyInner.class
    提供背压,但也存在其他实现

    在上下文中,我试图评估在这种特定情况下使用SpringWebFlux是否比SpringMVC更有优势

    我认为,这绝对值得评估。然而,就性能而言,我猜结果将取决于并发请求的数量,也可能取决于
    数据的类型。一般来说,Webflux通常是高吞吐量、低延迟情况下的首选,而且我们的环境中通常可以看到更好的硬件利用率。假设您从数据库获取数据,那么使用同样支持反应式的数据库驱动程序可能会获得最佳结果。除了性能,背压管理始终是查看Webflux的一个很好的理由。自从我们采用Webflux以来,我们的数据平台就再也没有稳定性问题了(不要说,没有其他方法可以拥有一个稳定的系统,但在这里,许多问题都是开箱即用的)

    作为旁注:我建议仔细查看一下
    调度器
    ,我们最近刚刚通过为慢速数据库访问选择合适的调度器,获得了30%的cpu时间

    编辑: 参考文件中明确指出:

    ServerRequest和ServerResponse是不可变的接口,提供对HTTP请求和响应的JDK 8友好访问。请求和响应都提供针对身体流的反应流背压

    @Override
    protected Mono<Void> writeWithInternal(Publisher<? extends DataBuffer> publisher) {
        return this.response.send(toByteBufs(publisher)).then();
    }