我们在AIX盒子上有大量记录集,我们通过网络发送到Linux盒子并处理它。 每条记录的大小约为277字节。
完整的流程就像:
i)程序A将记录发送到java进程B(在AIX框上都有)。
ii)AIX上的Java进程B将记录发送到linux上的Java程序C.两者都通过Java套接字进行通信,其中B是客户端,C是服务器。
iii)程序C处理每条记录并将ACK发送回程序B.
iv)程序B将ACK发送回程序A,然后程序A发送下一条记录。
我认为所有这些ACK都占用网络,整个过程变得非常缓慢。例如。在最近一次运行中,它在4小时内处理了330,000条记录,然后我们得到了套接字重置,客户端失败了。
我试图找出在这种情况下哪个更好的协议可以减少网络流量并加快完成速度。在4小时内330,000条记录真的很慢,因为处理程序C上的每条记录的时间不到5-10秒,但总体流量是这样我们正面临这个缓慢的问题。
提前致谢,
-JJ
答案 0 :(得分:1)
如果每条记录需要5秒,并且有330,000条记录,则需要花费1,650,000秒,这是19天。如果您需要4个小时来处理330,000条记录,那么它们是否需要43毫秒。
每个请求可能需要43毫秒的一个原因是,如果要为每个请求创建一个关闭连接。它可能会将大部分时间用于创建/关闭而不是执行。一个简单的方法是创建一次连接,只有在出现错误时才重新连接。
如果使用持久连接,则每个请求的开销可能会降至100微秒以下。
有没有理由你不能发送一批1000条记录的数据来处理,这会返回1个ACK并将开销减少1000倍?
答案 1 :(得分:1)
在发送下一条记录之前等待ack一直回到A肯定会让你失望,因为在发生这种情况时C基本上是空闲的。你为什么不搬到排队架构?为什么不在C上创建一个持久队列,它可以从A(通过B)接收记录,然后在C上有一个(或许多)处理器用于此队列。
通过这种方式,您可以分离A从C处理它们的速度中发送的速度。 A的确认为消息已成功传递到队列。我会为此目的使用HornetQ。
修改强>
HornetQ入门指南是here。
如果你不能使用它,对于最简单的非持久性内存中队列,只需使用Java的并发库中的ThreadPoolExecutor。您可以像这样创建一个ThreadPoolExecutor:
new ThreadPoolExecutor(
threadPoolSize, threadPoolSize, KEEP_ALIVE, MILLISECONDS,
new LinkedBlockingQueue<Runnable>(queueSize), ThreadPoolExecutor.DiscardOldestPolicy.discardOldest());
其中queueSize可以是MAX_INT。您可以在ThreadPool上使用Runnable调用execute()来执行任务。因此,您在C中接收代码可以简单地将这些Runnables创建并使用Record on参数化到ThreadPool,然后立即将ack返回到A(通过B)。