Understanding asynchronous web processing
我刚读完有关异步WebServlet处理的内容。 [本文]很不错。
但是,从根本上来说,我很困惑为什么此方法是"下一代Web处理"并且实际上根本没有使用。似乎我们在避免更好地配置我们的Web应用程序服务器(WAS)-nginx,apache,tomcat,IIS-而是将问题提交给Web开发人员。
在深入探讨推理之前,我想简要解释一下WAS如何接受并处理请求。
WAS可以通过使用多个处理器(通常每个CPU内核一个)同时处理多个连接,每个处理器具有多个线程。
现在,这使我进入了查询。如果WAS可以处理的请求数量取决于它处理队列的速度,而该速度低于分配给WAS的处理器/线程数,那么为什么要在APP内创建一个异步方法来卸载请求从WAS到不属于WAS的另一个线程,而不仅仅是增加WAS可用的线程数?
如果您认为弹出的(不是这样)新的Web套接字,则当Web套接字建立与WAS的连接时,会为该连接分配一个线程,该线程保持打开状态,以便客户端和WAS可以保持持续的通信。此线程最终是WAS上的线程-表示它正在占用服务器资源-无论是属于WAS还是独立于WAS(取决于APP设计)。
但是,为什么不创建一个不属于WAS的独立线程,为什么不增加WAS可用的线程数呢?最终,您可以拥有的线程数取决于服务器上可用的资源-内存,CPU。还是通过将Connection卸载到新线程,您根本不需要考虑要为WAS分配多少个线程(这很危险,因为现在您可以在没有适当监视的情况下耗尽服务器资源)。似乎问题正在传递给APP-因此是开发人员-而不是由WAS管理。
还是我只是误解了Web应用服务器的工作方式?
将其放入一个简单的Web Application Server示例中。以下将直接将传入的Connection卸载到线程。我并没有限制可以创建的线程数,但是我仅限于Macbook上允许的开放连接数。我还注意到,如果积压(ServerSocket中的第二个数字,当前为50)设置得太小,我将开始在客户端接收
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | import java.io.IOException; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Date; public class Server { public static void main(String[] args) throws IOException { try (ServerSocket listener = new ServerSocket(9090, 50)) { while (true) { new Run(listener.accept()).start(); } } } static class Run extends Thread { private Socket socket; Run(Socket socket) { this.socket = socket; } @Override public void run() { try { System.out.println("Processing Thread" + getName()); PrintWriter out = new PrintWriter(this.socket.getOutputStream(), true); out.println(new Date().toString()); } catch (IOException e) { e.printStackTrace(); } finally { try { this.socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } } |
现在使用异步,您只是将线程传递给另一个线程。您仍然受到系统资源的限制-允许的打开文件数,连接数,内存,CPU等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | import java.io.IOException; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Date; public class Server { public static void main(String[] args) throws IOException { try (ServerSocket listener = new ServerSocket(9090, 100)) { while (true) { new Synchronous(listener.accept()).start(); } } } // assumed Synchronous but really it's a Thread from the WAS // so is already asynchronous when it enters this Class static class Synchronous extends Thread { private Socket socket; Synchronous(Socket socket) { this.socket = socket; } @Override public void run() { System.out.println("Passing Socket to Asynchronous" + getName()); new Asynchronous(this.socket).start(); } } static class Asynchronous extends Thread { private Socket socket; Asynchronous(Socket socket) { this.socket = socket; } @Override public void run() { try { System.out.println("Processing Thread" + getName()); PrintWriter out = new PrintWriter(this.socket.getOutputStream(), true); out.println(new Date().toString()); } catch (IOException e) { e.printStackTrace(); } finally { try { this.socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } } |
在关于Netflix的tuning-tomcat-for-a-highthroughput \\的博客中,看起来Tomcat与我的第一个代码示例相同。因此,不需要应用程序中的异步处理。
缺省情况下,
Tomcat具有两个影响负载的属性,
上阅读有关它们的信息。
晚了,但也许总比没有好。 :)
对于"为什么要使用yy servlet?",我没有很好的答案,但我认为有关信息的另一点会对您有所帮助。
您要为WAS描述的是Tomcat在其BIO连接器中所做的事情。基本上,每个连接模型都是一个线程。这不仅限制了maxThreads设置,还限制了您可以服务的请求数量,还因为如果未发送Connection:Close,则工作线程可能会继续被束缚,等待连接上的其他请求。 (请参阅https://www.javaworld.com/article/2077995/java-concurrency/java-concurrency-asynchronous-processing-support-in-servlet-3-0.html和Tomcat的BIO有什么区别?连接器和NIO连接器?)
切换到NIO连接器后,tomcat可以维持数千个连接,同时仍然仅保留一小部分工作线程。