我正在开发一个MVC spring web app,我想将我的用户的动作(他们点击的内容等)存储在数据库中以进行离线分析。假设一个动作是一个元组(long userId,long actionId,Date timestamp)。我对用户的操作并不特别感兴趣,但我以此为例。
我希望很多(不同的)用户可以采取很多动作(分钟(秒))。因此处理时间至关重要。
在我当前的实现中,我已经定义了一个带有连接池的数据源,用于将操作存储在数据库中。我从控制器的请求方法调用一个服务,这个服务调用一个DAO,它将动作保存到数据库中。
此实现效率不高,因为它等待来自控制器的调用以及一直到数据库的调用以将响应返回给用户。因此我想将这个“动作保存”包装到一个线程中,以便对用户的响应更快。该线程不需要完成以获得响应。
我没有这些大规模,并发和时间关键型应用程序的经验。所以任何反馈/评论都会非常有用。
现在我的问题是:
你会如何设计这样的系统? 你会实现一个服务,然后将其包装到每个动作调用的线程中吗?
我应该使用什么? 我检查了Spring Batch和这个JobLauncher,但我不确定这对我是否合适。
在控制器,服务,DAO和数据源级别进行并发访问时会发生什么?
更笼统地说,设计此类应用程序的最佳做法是什么?
感谢您的帮助!
答案 0 :(得分:2)
通常,在Java EE应用程序中生成自己的线程被认为是不好的形式。
更好的方法是通过JMS写入本地队列,然后有一个单独的组件,例如消息驱动的bean(很容易使用EJB或Spring),它将数据库持久存储到数据库中。
另一种方法是只写入日志文件,然后让进程读取日志文件并每天或每次写入数据库。
要考虑的事项是: -
所有这些都会影响处理队列/日志文件的线程数,是否需要持久的JMS队列,以及是否应该在远程系统上对主容器进行处理。
希望这能回答你的问题。
答案 1 :(得分:2)
如果您对用户采取的操作感兴趣,您应该能够从他们发送的HTTP请求中找出答案,因此您最好将传入的请求记录在转发到应用程序服务器的Apache Web服务器中。将一组Web服务器放在应用程序服务器之前是一种典型的做法(它们对于提供静态内容很有用),而且它们通常都是记录请求。这样,日志记录将很快,您的应用程序将不必处理它,并且最大的工作是编写脚本以将日志插入数据库,您可以在其中进行分析。
答案 2 :(得分:2)
这就是我为此所做的:
使用aspectJ来标记我想要收集的用户的所有操作。 然后我用异步dbAppender发送到log4j ......
这使您可以使用log4j日志记录级别打开或关闭它。
完美无缺。
答案 3 :(得分:2)
获取单个对象@ apps级别并使用每个用户操作更新它。 这个单例对象应该有一个Hashmap作为泛型,应该在它达到10000计数的阈值后定期刷新,并将其保存到DB,作为一个弹簧批。
另外,定期刷新/清理它每次处理时的最后一个记录数。我们还可以每周/每月重新初始化单例实例。请记住,这可能会导致更新相同的问题,以防您的应用程序部署到多个JVM中。因此,您需要在单例中实现克隆不支持的异常。