Java 在发动机罩下使用Netty和Tomcat时,弹簧webFlux会出现差异

Java 在发动机罩下使用Netty和Tomcat时,弹簧webFlux会出现差异,java,tomcat,netty,spring-webflux,nonblocking,Java,Tomcat,Netty,Spring Webflux,Nonblocking,我正在学习SpringWebFlux,我已经阅读了以下系列文章(,) 在第三篇文章中,我面对以下文本: 记住,相同的应用程序代码在Tomcat、Jetty或Netty上运行。 目前,Tomcat和Jetty支持是在Servlet之上提供的 3.1异步处理,因此每个线程只能有一个请求。当相同的代码在Netty服务器平台上运行时 约束解除,服务器可以分派请求 同情web客户端。只要客户没有 布洛克,大家都很高兴。netty服务器和服务器的性能指标 客户端可能显示类似的特征,但Netty服务器是 不限

我正在学习SpringWebFlux,我已经阅读了以下系列文章(,)

在第三篇文章中,我面对以下文本:

记住,相同的应用程序代码在Tomcat、Jetty或Netty上运行。 目前,Tomcat和Jetty支持是在Servlet之上提供的 3.1异步处理,因此每个线程只能有一个请求。当相同的代码在Netty服务器平台上运行时 约束解除,服务器可以分派请求 同情web客户端。只要客户没有 布洛克,大家都很高兴。netty服务器和服务器的性能指标 客户端可能显示类似的特征,但Netty服务器是 不限于每个线程处理一个请求,因此 不使用大型线程池,我们可能会看到一些 资源利用的差异。我们稍后再讨论这个问题 在本系列的另一篇文章中

首先,尽管这篇文章是在2016年写的,但我在该系列中没有看到更新的文章。我很清楚,tomcat默认有100个线程来处理请求,一个线程同时处理一个请求,但我不理解短语它被限制为每个线程一个请求这是什么意思


此外,我还想知道Netty在具体案例中是如何工作的(我想了解与Tomcat的区别)。它能处理每个线程2个请求吗?

目前有两个基本概念来处理对web服务器的并行访问,各有优缺点:

  • 阻塞
  • 非阻塞
  • 阻止Web服务器 阻塞的第一个概念,多线程服务器在一个池中有有限数量的线程。每个请求都将被分配到特定的线程,该线程将被分配,直到请求得到完全服务。这基本上与超市中排队结帐的顾客的工作方式相同,一次一个顾客,可能有平行线。在大多数情况下,web服务器中的请求在处理请求时的大部分时间都是cpu空闲的。这是因为它必须等待I/O:读取套接字,写入db(基本上也是IO),读取结果并写入套接字。此外,使用/创建一组线程速度较慢(上下文切换),并且需要大量内存。因此,这个概念通常不能非常有效地使用其拥有的硬件资源,并且对并行服务的客户端数量有严格限制。此属性被误用在所谓的饥饿攻击中,例如,一种攻击,通常一个客户端可以轻而易举地拒绝一个大型多线程web服务器

    总结
    • (+)更简单的代码
    • (-)并行客户端的硬限制
    • (-)需要更多内存
    • (-)对常规web服务器工作的硬件使用效率低下
    • (-)容易做
    大多数“传统”web服务器都是这样工作的,例如较旧的tomcat、ApacheWebServer,以及比3或3.1更旧的一切
    Servlet

    非阻塞Web服务器 相比之下,非阻塞web服务器可以仅使用一个线程为多个客户端提供服务。这是因为它使用了。这些只是内核调用,当可以写入或读取某些内容时,它们会立即返回并回调,从而使cpu可以自由地执行其他工作。重复我们的超市比喻,这就像是,当一个收银员需要他的主管解决一个问题时,他不会等待并封锁整个通道,而是开始检查下一个客户,直到主管到达并解决第一个客户的问题

    这通常在事件循环或更高的抽象中完成,如或。本质上,这样的服务器不能同时处理任何事情(当然,您可以有多个非阻塞线程),但它们能够并行地为数千个客户机提供服务,因为内存消耗不会像多线程概念那样急剧扩展(请阅读:最大并行客户机没有硬限制)。也没有线程上下文切换。缺点是,非阻塞代码的读写通常更复杂(例如),并且在请求执行大量cpu昂贵工作的情况下无法很好地预启动

    总结
    • (-)更复杂的代码
    • (-)cpu密集型任务的性能更差
    • (+)比web服务器更有效地使用资源
    • (+)更多没有硬限制的并行客户端(最大内存除外)
    大多数现代的“快速”web服务器和框架都支持非阻塞概念:Netty、Vert.x、Webflux、nginx、servlet 3.1+、Node、Go web服务器

    作为补充说明,查看此基准页面,您将看到大多数最快的web服务器通常是非阻塞的:


    另见

    使用Servlet 2.5时,Servlet容器会将请求分配给线程,直到该请求得到完全处理

    当使用Servlet3.0异步处理时,服务器可以在应用程序处理请求时在单独的线程池中调度请求处理。然而,当涉及到I/O时,工作总是发生在服务器线程上,并且总是阻塞。这意味着“慢速客户端”可以独占服务器线程,因为服务器在网络连接不良的情况下读/写该客户端时被阻塞

    在Servlet3.1中,异步I/O是允许的,在这种情况下,不再使用“一个请求/线程”模型。在任何时候,都可以在服务器管理的不同线程上调度位请求处理

    Servlet3.1+容器通过ServletAPI提供了所有这些可能性。利用异步处理或非阻塞I/O取决于应用程序。在非阻塞I/O的情况下,范例更改非常重要,使用起来非常困难