http service: replace JedisPool with own pool implementation

JedisPool appears to not work correctly and is losing connections.
This commit is contained in:
Adam
2019-01-15 09:40:29 -05:00
parent a47c63e931
commit c50023eb89
5 changed files with 92 additions and 17 deletions

View File

@@ -105,6 +105,12 @@
<groupId>redis.clients</groupId> <groupId>redis.clients</groupId>
<artifactId>jedis</artifactId> <artifactId>jedis</artifactId>
<version>2.10.0</version> <version>2.10.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>

View File

@@ -54,17 +54,12 @@ import org.springframework.scheduling.annotation.EnableScheduling;
import org.sql2o.Sql2o; import org.sql2o.Sql2o;
import org.sql2o.converters.Converter; import org.sql2o.converters.Converter;
import org.sql2o.quirks.NoQuirks; import org.sql2o.quirks.NoQuirks;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
@SpringBootApplication @SpringBootApplication
@EnableScheduling @EnableScheduling
@Slf4j @Slf4j
public class SpringBootWebApplication extends SpringBootServletInitializer public class SpringBootWebApplication extends SpringBootServletInitializer
{ {
@Value("${redis.host:localhost}")
private String redisHost;
@Bean @Bean
protected ServletContextListener listener() protected ServletContextListener listener()
{ {
@@ -135,12 +130,6 @@ public class SpringBootWebApplication extends SpringBootServletInitializer
return new Sql2o(dataSource, new NoQuirks(converters)); return new Sql2o(dataSource, new NoQuirks(converters));
} }
@Bean
JedisPool jedis()
{
return new JedisPool(new JedisPoolConfig(), redisHost);
}
@Override @Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
{ {

View File

@@ -44,6 +44,7 @@ import net.runelite.http.api.ws.WebsocketMessage;
import net.runelite.http.api.ws.messages.LoginResponse; import net.runelite.http.api.ws.messages.LoginResponse;
import net.runelite.http.service.account.beans.SessionEntry; import net.runelite.http.service.account.beans.SessionEntry;
import net.runelite.http.service.account.beans.UserEntry; import net.runelite.http.service.account.beans.UserEntry;
import net.runelite.http.service.util.redis.RedisPool;
import net.runelite.http.service.ws.SessionManager; import net.runelite.http.service.ws.SessionManager;
import net.runelite.http.service.ws.WSService; import net.runelite.http.service.ws.WSService;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -58,7 +59,6 @@ import org.sql2o.Connection;
import org.sql2o.Sql2o; import org.sql2o.Sql2o;
import org.sql2o.Sql2oException; import org.sql2o.Sql2oException;
import redis.clients.jedis.Jedis; import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
@RestController @RestController
@RequestMapping("/account") @RequestMapping("/account")
@@ -98,7 +98,7 @@ public class AccountService
private final String oauthClientId; private final String oauthClientId;
private final String oauthClientSecret; private final String oauthClientSecret;
private final AuthFilter auth; private final AuthFilter auth;
private final JedisPool jedisPool; private final RedisPool jedisPool;
@Autowired @Autowired
public AccountService( public AccountService(
@@ -106,7 +106,7 @@ public class AccountService
@Value("${oauth.client-id}") String oauthClientId, @Value("${oauth.client-id}") String oauthClientId,
@Value("${oauth.client-secret}") String oauthClientSecret, @Value("${oauth.client-secret}") String oauthClientSecret,
AuthFilter auth, AuthFilter auth,
JedisPool jedisPool RedisPool jedisPool
) )
{ {
this.sql2o = sql2o; this.sql2o = sql2o;

View File

@@ -25,20 +25,20 @@
package net.runelite.http.service.chat; package net.runelite.http.service.chat;
import java.time.Duration; import java.time.Duration;
import net.runelite.http.service.util.redis.RedisPool;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis; import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
@Service @Service
public class ChatService public class ChatService
{ {
private static final Duration EXPIRE = Duration.ofMinutes(2); private static final Duration EXPIRE = Duration.ofMinutes(2);
private final JedisPool jedisPool; private final RedisPool jedisPool;
@Autowired @Autowired
public ChatService(JedisPool jedisPool) public ChatService(RedisPool jedisPool)
{ {
this.jedisPool = jedisPool; this.jedisPool = jedisPool;
} }

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 2019, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.http.service.util.redis;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
@Component
public class RedisPool
{
private final BlockingQueue<Jedis> queue;
RedisPool(@Value("${redis.pool.size:10}") int queueSize, @Value("${redis.host:localhost}") String redisHost)
{
queue = new ArrayBlockingQueue<>(queueSize);
for (int i = 0; i < queueSize; ++i)
{
Jedis jedis = new PooledJedis(redisHost);
queue.offer(jedis);
}
}
public Jedis getResource()
{
Jedis jedis;
try
{
jedis = queue.poll(1, TimeUnit.SECONDS);
}
catch (InterruptedException e)
{
throw new RuntimeException(e);
}
if (jedis == null)
{
throw new RuntimeException("Unable to acquire connection from pool, timeout");
}
return jedis;
}
class PooledJedis extends Jedis
{
PooledJedis(String host)
{
super(host);
}
@Override
public void close()
{
queue.offer(this);
}
}
}