我有2个微服务(A和B)。
A有一个接受POST请求的端点。当用户发出POST请求时,会发生以下情况:
第2步发生在我创建的Java线程池(Executors.newCachedThreadPool)上。通过在新线程上执行步骤2,服务A端点的响应时间不受影响。
但是,如果服务B需要很长时间才能响应,则服务A在接收许多POST请求时可能会创建太多线程。为了解决这个问题,我可以使用固定的线程池(Exectuors.newFixedThreadPool)。
除了固定的线程池,我还应该使用异步非阻塞HTTP客户端吗?比如这里的一个:https://hc.apache.org/httpcomponents-asyncclient-dev/。我使用的Jersey HTTP客户端正在阻止。
似乎使用异步HTTP客户端是正确的。 但是,如果我切换到一个固定的线程池,我认为异步HTTP客户端不会带来显着的好处 - 我是否认为这是错误的?
答案 0 :(得分:0)
即使您使用固定线程池其中的所有线程也将在步骤2中被阻止,这意味着他们不会做任何有意义的工作 - 只需等待您的API返回响应这不是一个务实的资源管理。在这种情况下,您将能够处理有限数量的传入请求,因为线程池中的线程将始终处于忙碌状态而不是处理新请求。
对于非阻塞客户端,您只阻止一个单独的线程(让他们称之为调度程序线程),负责发送和等待所有请求/响应。它将在" while循环中运行" (你可以称之为事件循环)并检查是否所有包都作为响应被接收,因此它们已准备好接收工作线程。
在后一种情况下,您可以获得更多可用的线程,以便做一些有意义的工作,这样您的吞吐量就会增加。
答案 1 :(得分:0)
不同之处在于,对于同步客户端,步骤A线程将连接到第2步端点并等待响应。使第2步实现异步将直接返回200(或其他任何)将有助于减少等待时间;但它仍然会进行连接并等待响应。
使用非阻塞客户端,步骤A调用本身将由另一个线程完成。所以一切都从步骤A线程解开。此外,系统可以将该线程用于其他内容,直到它从步骤B得到响应并需要恢复工作。
这个想法是你的原始线程不会在等待响应时花费太多时间,而是在中间执行其他工作时重复使用。
答案 2 :(得分:0)
使用非阻塞HTTP客户端的原因是为了防止在线程切换时使用过多的CPU。如果您已经通过限制后台线程的数量来解决该问题,那么非阻塞IO不会提供任何明显的好处。
您的设置还有另一个问题:它非常容易受到DDOS攻击(有意或无意)的攻击。如果有人经常调用您的服务,它将在内部创建巨大的工作负载,这将使服务长时间保持忙碌状态。您肯定需要限制后台任务队列(这是Executor类的受支持功能),如果有太多待处理任务,则返回503(或等效)。