java - 由于服务器启动时 ecache 请求的负载过大,数据库服务器停止
问题描述
我有中型和流量电子商务网站。一次大约有 200-300 名游客。Webapp 的特点是:
- 内置Java,Spring用于MVC
- 使用Ehcache缓存来自数据库的多个数据请求
- 用于连接数据库的纯JDBC(使用tomcat的连接池)
- 部署在 AWS EC2 中的 tomcat 上
- 使用 RDS 作为数据库服务器
- 分配给 webapp 的大约 100 个数据库连接
我广泛使用 Ehcache 来缓存大部分目录数据,因为它是网站上所有流量的请求。但是,当我在 tomcat 上部署新版本时,几乎总是数据库服务器由于触发过多查询而停滞不前。Ehcache 在这里无法提供帮助,因为到目前为止还没有缓存任何内容。最好的情况是大约需要 45 分钟,直到网站仍然非常缓慢并且 ehcache 设法缓存重要数据。最坏的情况是网站崩溃并且应用程序停止运行。
在开发环境中它工作得非常顺利,因为没有流量。为了快速找到解决此问题的方法,我们进行了快速修复。
解决方法是:在ServletContextListener
我们对与目录相关的大多数关键服务进行了虚拟打击,这些服务因过多的查询而占用了数据库服务器。由于这一变化,一旦应用程序被部署,我们就会在内存中获取与目录相关的所有数据,然后 ehcache 将它们全部缓存起来。此后,应用程序变为可供公众使用。虽然,当我们部署应用程序时,这种变化导致了大约 30 秒的启动延迟,但我们设法摆脱了 45 分钟的缓慢网站。
这个修复确实解决了我们的问题,但感觉不是一个好的解决方案。因为与目录或其他关键数据相关的所有内容都在内存中,无论它是否会习惯。它大约是 3.5 GB 的数据。而且,现在在开发环境中工作是一场噩梦。因为开发系统中的内存不足。
请提出解决此问题的好方法。
解决方案
在启动时填充缓存感觉是个好主意。这就是我会做的。如果它适合内存,我不介意加载太多东西。
另一种方法是制定过期策略并定期 ping 缓存以删除过期条目。但这听起来更像是在浪费时间。
分布式缓存也可以解决这个问题,但这意味着给你的架构增加一层复杂性。我只会在必要时这样做。我认为不是。
然后,为了防止在开发中加载,只需使用一个 Spring 配置文件,该配置文件会导致加载仅在生产中处于活动状态(理想情况下是暂存)。
推荐阅读
- javascript - 使用js设置输入元素值时如何触发更改事件
- intellij-idea - IntelliJ IDEA GitLab 集成
- java - 运行 java -jar 和 java -cp 时没有主清单属性错误
- mongodb - 需要使用聚合框架和查找(例如计数和详细信息)将来自不同集合的文档加入 MongoDB 中的同一文档中
- kubeflow - microk8s 禁用 kubeflow 文件 disable.kubeflow.sh 错误
- java - PostConstruct 调用了两次
- r - R tidymodels / VIP变量重要性确定
- java - 动态过滤 - Spring-Boot
- javascript - 如何在javascript的for循环中使用异步等待
- django - 表单中的 Django ValueError