当前位置: 首页 > 知识库问答 >
问题:

Jedis的资源实例和web应用程序块快用完了

南宫阳焱
2023-03-14

我正在运行一个Tomcat应用程序,它使用Jedis访问Redis数据库。不时形成整个应用程序块。通过使用JavaMelody监视Tomcat,我发现问题似乎与对象请求Jedis实例时的JedisPool有关。

catalina-exec-74
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:503)
org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1104)
redis.clients.util.Pool.getResource(Pool.java:20)
....

这是我正在使用的配置

JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxActive(20);
poolConfig.setTestOnBorrow(true);
poolConfig.setTestOnReturn(true);
poolConfig.setMaxIdle(5);
poolConfig.setMinIdle(5);
poolConfig.setTestWhileIdle(true);
poolConfig.setNumTestsPerEvictionRun(10);
poolConfig.setTimeBetweenEvictionRunsMillis(10000);
jedisPool = new JedisPool(poolConfig, "localhost");

所以很明显,一些线程试图获取Jedis实例,但是池是空的,不能返回实例,所以默认的池行为是等待。

我已经仔细检查了我的整个代码,我很确定我把每个Jedis实例都返回到我以前使用过的池中。所以我不知道为什么我的实例用完了。

有没有办法检查池中还有多少实例?我试图为maxActive参数找到一个合理的值,以防止应用程序阻塞。

除了不将Jedis实例返回到池中之外,还有其他方法可以创建内存漏洞吗?

共有3个答案

吴举
2023-03-14

当您使用jedis池时,每次您使用getResources()获取资源时,您都必须调用释放资源()。如果线程数超过资源数,您将有线程争用。我发现使用JavaThreadlocaljedis连接每个线程要简单得多。所以,对于每个线程,检查jedis连接是否已经存在。如果是,请使用它,否则为正在运行的线程创建一个连接。这确保不会有任何锁争用或错误条件需要处理。

夏兴平
2023-03-14

希望这个问题的部分答案能对类似情况下的人们有所帮助,尽管我不确定我的问题是否与你的问题相同(如果你已经解决了,请让我们知道!)。

我已经仔细检查了我的整个代码,我很确定我把每个Jedis实例都返回到我以前使用过的池中。所以我不知道为什么我的实例用完了。

我以为我必须——我总是把我的代码放在try/last块中,但事实证明我确实有内存泄漏:

Jedis jedis = DBHelper.pool.getResource();
    try {
        // Next line causes the leak
        Jedis jedis = DBHelper.pool.getResource();
        ...
    } finally {
        DBHelper.pool.returnResource(jedis);
    }

不知道第二个电话是如何溜进来的,但它确实溜进来了,导致了漏洞和网络应用程序被阻止。

有没有办法检查池中还有多少实例?我试图为maxActive参数找到一个合理的值,以防止应用程序阻塞。

在我的例子中,我发现了漏洞,并根据redis服务器看到的客户端数量进行了优化。我将loglevel(在redis.conf中)设置为verbose(默认值为notice),它大约每5-10秒报告一次连接的客户端数量。一旦发现内存泄漏,我就反复向调用该方法的页面发送请求,并看着redis日志报告的redis客户端不断攀升,但从未下降。。我认为这将是优化的一个良好开端?

无论如何,希望这对某人有帮助!

闻人鸿飞
2023-03-14

将资源返回到池很重要,所以请记住这样做。否则,当关闭应用程序时,它将等待资源返回

https://groups.google.com/forum/?fromgroups=#!topic/jedis_redis/UeOhezUd1tQ

在每次Jedis方法调用后,返回资源池。您的应用可能已经使用了所有线程,并等待一些线程被删除。这可能会导致您正在解释的行为,应用可能被阻止。

Jedis jedis = JedisFactory.jedisPool.getResource();
try{
    jedis.set("key","val");
}finally{
    JedisFactory.jedisPool.returnResource(jedis);
}
 类似资料:
  • 问题内容: 背景 开发一个简单的Web应用程序(Eclipse + JBoss + Apache Tomcat)以生成XML文件。 问题 “业务区域”列表针对数据库查询,而“列集群”列表使用所选的“业务区域”项目查询数据库。这两个都是存储外部文本文件的唯一查询。 这些文件当前存储在以下位置: WebContent / META-INF / business-areas.sql WebContent

  • 我有一个web应用程序,它将从jar文件动态加载其资源。 我必须如何重新编写加载和注册资源并启动服务器的主类,以便它在web应用程序内部工作? 我目前定义了一个,它在标记为的方法中加载资源。虽然这是有效的,但它会随着每个请求初始化。 我尝试将添加到应用程序中,但这导致了错误: 我的做法是完全错误的吗?或者如何创建这样一个系统,作为可部署的war运行? *编辑* 通过使用ServletContext

  • 我使用IntelliJ IDEA 14.0.2启动本地Tomcat 7.0.42实例,然后使用远程Tomcat运行配置单独部署WAR。我的web应用无法通过JNDI获取资源,我怀疑这是因为它无法远程连接到JMX,尽管如果我对JNDI查找进行注释,WAR的部署不会出现问题。如果我在同一个本地Tomcat运行配置中包含Tomcat启动和WAR部署,那么查找就可以正常工作。 以下是我认为相关的所有细节,

  • 当我在读一些CQRS的资料时,有一个反复出现的问题我没有理解。例如,假设一个客户端发出一个命令。该命令由域集成,因此它可以刷新其域模型(DM)。另一方面,命令保存在事件存储中。这是最常见的情况。 1) 当我们说DM被刷新时,我假设数据被保存在底层数据库中(如果有的话)。我说得对吗?否则,我们将处理内存瞬态模型,我想这不是一件好事吗?(在客户端请求之外,状态不应该保留在服务器端的内存中)。 2)如果

  • 问题内容: 在Glassfish 4上部署“ myapp.war”之前,我必须 创建jdbc连接池(/WEB-INF/glassfish-resources.xml-> 本身不起作用…从asadmin正常) 为池创建jdbc资源(/WEB-INF/glassfish-resources.xml-> 与上述相同) 创建auth-realm(什么也不会自动,现在使用asadmin) 创建模式(peri

  • 本文向大家介绍使用Ruby on Rails快速开发web应用的教程实例,包括了使用Ruby on Rails快速开发web应用的教程实例的使用技巧和注意事项,需要的朋友参考一下  Ruby on Rails 正在令整个 Web 开发领域受到震憾。让我们首先了解底层的技术:     Ruby 是一门免费的、简单的、直观的、可扩展的、可移植的、解释的脚本语言,用于快速而简单的面向对象编程。类似于 P