Gid*_*eon 8 java multithreading tomcat spring-mvc asynccontroller
这是我的第一个问题所以请耐心等待我:)
我正在尝试创建一个服务:
我在虚拟机和Tomcat7上使用spring运行它.我会事先道歉并提到我对Tomcat很新
无论如何,我期待很多并发GET请求到这个服务(成千上万的同时请求)我基本上想要实现的是尽可能地使这个服务可扩展(如果这是不可能的那么至少一个可以处理数十万个并发请求的服务)
我一直在阅读A LOT关于服务中的异步请求处理,特别是在Tomcat中,但我有些事情对我来说仍然不清楚:
我为同样的问题提出了很多问题而道歉,但是我和我的同事们争论这些事情一个多星期没有任何具体的答案.
我还有一个更普遍的问题:您认为使我描述的服务具有可扩展性的最佳方法是什么?(暂时不要添加更多机器),您是否可以针对目标解决方案发布任何示例或参考?
我发布了更多我一直在关注的链接链接,但我目前的声誉不允许.我将非常感谢任何可以理解的参考文献或具体的例子,我很乐意澄清任何相关问题
干杯!
这里面有很多问题,但我会尝试解决其中的一些问题。
异步 I/O 是一件好事,尤其是在服务大量请求的服务器上 - 它允许您使用更少的线程来处理更多的请求。对于您正在编写的代理,您确实希望 HTTP 客户端(向外部 URL 发出请求)也是异步的,这样处理请求或接收远程响应都不会涉及阻塞 I/O。
也就是说,与使用像Netty这样从头开始异步的框架相比,使用 Tomcat 或 Java EE 服务器做这些事情可能会更困难,因为这些服务器事后才添加了异步 I/O 。作为构建在 Netty 之上的框架的作者,我有点偏见。
为了演示您只需要很少的代码即可完成您所描述的操作,我编写了一个小型服务器,它在 3 个 Java 源文件中执行您在此处描述的操作,并将其放在 github 上- 它构建了一个独立的 JAR,您可以运行java -jar
它来尝试一下,我试图清晰地评论它。
归根结底,网络应用程序大部分时间都在等待 I/O 发生。特别是在代理的情况下,使用传统的线程 I/O,您将收到一个请求,并且接收请求的线程将负责同步应答它- 这意味着,如果它必须向在另一台服务器上,该线程被阻塞,等待来自远程服务器的答案。这意味着该线程不能用于其他任何用途。因此,如果您有 10 个线程,并且所有线程都在等待响应,则您的服务器将无法再应答任何请求,直到其中一个线程完成并释放线程为止。使用异步 I/O,当某些 I/O 完成时您会收到回调。换句话说,当有事情要做时(例如从代理请求到达的响应),您的代码不会停滞不前,直到操作系统将数据刷新到套接字并从网卡中取出。当您的代码等待该 HTTP 请求完成时,发送代理请求的线程可以自由地用于处理另一个请求,这意味着一个线程可以对一个请求做一些工作,对另一个请求做一些工作,然后再对另一个请求做一些工作。 ,最终完成第一个请求。由于线程是操作系统提供的有限资源,因此这允许您用更少的硬件做更多的事情。
至于Callable
vs. DeferredResult
,使用 aCallable
只是在工作发生时移动(Callable
稍后在某个线程或其他线程上执行,但仍然期望同步返回结果); DeferredResult
听起来更像是您需要的,因为这允许您的代码运行并执行它想要的任何工作,然后在需要设置某些内容时设置结果(触发响应的完成)。
老实说,我认为如果你想真正有效地实现这一点,你最好远离 Java EE 堆栈 - 其中很多内容都假设 I/O 是同步的,因此尝试用它做异步事情是很困难的向上游游(例如,JDBC 的骨子里就是同步 I/O - 如果你真的希望它能够扩展并且你想使用 SQL 数据库,那么你最好使用这样的东西)。
有关使用Netty进行此类操作的另一个示例,请参阅tiny-maven-proxy项目 - 代码不太漂亮,但它显示了一个执行 HTTP 代理的示例,其中响应正文按块馈送到客户端 -块,当它到达时 - 所以你永远不会真正将完整的响应主体拉入内存,这意味着即使具有巨大响应的请求也不会耗尽内存来运行代理。Tiny-maven-proxy 还在文件系统上缓存。我在演示中没有做这些事情,因为这会让代码变得更加复杂。
归档时间: |
|
查看次数: |
1598 次 |
最近记录: |