我正在提供一个由servlet服务的RESTful服务(在Tomcat 7.0.X和Ubuntu Linux中运行)。我每小时已经收到大约2万个查询,而且会增长得更多。 servlet接收请求,准备响应,在MySQL数据库表中插入记录并传递响应。数据库中的日志是绝对必需的。最近匆忙,所有这一切都以同步的方式发生。我的意思是,在Tomcat线程传递响应之前,它必须在数据库表中创建记录。问题是这个日志占用总时间的90%以上,更糟糕的是:当数据库变慢时,服务大约需要10-15秒,而不是20毫秒。
我稍后做了一些改进:每个Tomcat线程创建一个额外的线程,执行"(新线程(新的特定对象))。start();"它以异步方式处理SQL插入,因此响应更快地到达客户端。但是当MySQL运行速度较慢且线程数量增加时,这些线程需要占用太多内存,并且数千个内核运行JVM Tomcat。
我需要的是能够尽可能多地接受HTTP请求,尽可能快地记录每个请求(不同步),并且当MySQL获得时,使一切都快速且RAM的使用率非常低慢和插入需要排队。我认为当http请求的速度高于数据库日志中的插入速度时,我需要某种队列来缓冲条目。
我正在考虑这些想法:
1-自己创建某种FIFO队列,可能使用一些Apache公共集合,以及轮询集合并创建数据库记录的某种线程。但是我应该使用什么样的系列?我应该如何编程轮询它的线程,以便它不会独占CPU?我认为"同时(真实)......"会占用CPU周期。关于使其线程安全吗?怎么做?我认为自己做这件事太费劲了,我很可能会重新发明轮子。
2- log4J?我从来没有直接使用它,但似乎这个框架被设计用于创建" appenders"与数据库交谈。那会是这样做的吗?
3-使用某种专门针对此的任何其他框架?
你会建议什么?
提前致谢!
答案 0 :(得分:0)
立刻想到的是像你说的那样的队列。您可以使用ActiveMQ http://activemq.apache.org/或RabbitMQ http://www.rabbitmq.com/等内容。
这个想法只是开火而忘记。发送消息几乎没有开销。
然后你可以连接一些“离线”以从队列中获取消息,并以你需要的速度将它们写入数据库。
我觉得我整天都在Stack Overflow上插件,但我们在工作中使用Mule(http://www.mulesoft.org/)来完成此操作。 Mule的一大优点是,您可以显式设置从队列中读取的线程数以及写入数据库的线程数。它允许您对限制消息进行细粒度控制。
答案 1 :(得分:0)
绝对要看一下使用ThreadPoolExecutor。您可以提供线程池大小,它将为您处理所有并发和排队。唯一可能的问题是,如果您的JVM因任何原因崩溃,您将丢失池中的所有排队项目。
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html
我也一定会考虑尽可能优化MySQL数据库。每小时20k条目可以很快变得毛茸茸。更好地优化硬件,操作系统和索引,插入越快,队列就越小。
答案 2 :(得分:0)
首先:非常感谢您的宝贵建议!
到目前为止,我已经找到了部分解决方案,我已经成功实施了它:
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/LinkedBlockingQueue.html
现在我正在考虑使用队列提供程序(如果它已满),作为故障转移解决方案。到目前为止,我已经考虑过亚马逊的队列服务,但这需要花钱。我还将检查Ryan建议的队列解决方案。