From 5170d636f987518695020fef801c5ac1b195e064 Mon Sep 17 00:00:00 2001 From: richie Date: Thu, 21 Mar 2019 20:12:43 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0redis=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E4=BB=A3=E7=90=86=E7=9A=84=E6=9C=8D=E5=8A=A1=E5=99=A8=E7=9A=84?= =?UTF-8?q?=E7=89=B9=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugin.xml | 5 +- .../redis/core/RedisDatabaseConnection.java | 41 ++----- .../fr/plugin/db/redis/core/RedisPool.java | 63 +++++++++-- .../redis/core/RedisScriptTableDataModel.java | 9 +- .../db/redis/core/RedisTableDataModel.java | 10 +- .../fr/plugin/db/redis/core/emb/Redis.java | 15 +++ .../db/redis/core/emb/impl/ProxyRedis.java | 32 ++++++ .../db/redis/core/emb/impl/SimpleRedis.java | 28 +++++ .../core/pool/RedisConnectionPoolConfig.java | 53 +++++++++ .../core/pool/RedisConnectionProxyConfig.java | 97 ++++++++++++++++ .../db/redis/ui/RedisConnectionPane.java | 79 ++++++++++--- .../pool/RedisConnectionPoolConfigPane.java | 57 ++++++++++ .../proxy/RedisConnectionProxyConfigPane.java | 107 ++++++++++++++++++ .../fr/plugin/db/redis/util/RedisUtils.java | 9 ++ .../plugin/db/redis/locale/redis.properties | 9 ++ .../db/redis/locale/redis_en_US.properties | 9 ++ .../db/redis/locale/redis_zh_CN.properties | 11 +- 17 files changed, 569 insertions(+), 65 deletions(-) create mode 100644 src/main/java/com/fr/plugin/db/redis/core/emb/Redis.java create mode 100644 src/main/java/com/fr/plugin/db/redis/core/emb/impl/ProxyRedis.java create mode 100644 src/main/java/com/fr/plugin/db/redis/core/emb/impl/SimpleRedis.java create mode 100644 src/main/java/com/fr/plugin/db/redis/core/pool/RedisConnectionPoolConfig.java create mode 100644 src/main/java/com/fr/plugin/db/redis/core/pool/RedisConnectionProxyConfig.java create mode 100644 src/main/java/com/fr/plugin/db/redis/ui/pool/RedisConnectionPoolConfigPane.java create mode 100644 src/main/java/com/fr/plugin/db/redis/ui/proxy/RedisConnectionProxyConfigPane.java diff --git a/plugin.xml b/plugin.xml index 0aa97e9..08c4e6a 100755 --- a/plugin.xml +++ b/plugin.xml @@ -3,13 +3,14 @@ com.fr.solution.plugin.db.redis.v10 yes - 5.2 + 6.0 10.0 2018-11-29 richie + [2019-03-21]增加代理服务配置。
+ [2019-03-18]修复连接没有释放的问题。
[2019-03-18]增加程序数据集,可以使用javascript进行取数,需要2019-03-01之后的版本。
[2019-02-15]结果集可以通过JavaScript脚本进行转换。
[2018-11-30]解决远程设计时无法查询key列表的问题。
diff --git a/src/main/java/com/fr/plugin/db/redis/core/RedisDatabaseConnection.java b/src/main/java/com/fr/plugin/db/redis/core/RedisDatabaseConnection.java index 4d86e06..c82aab8 100755 --- a/src/main/java/com/fr/plugin/db/redis/core/RedisDatabaseConnection.java +++ b/src/main/java/com/fr/plugin/db/redis/core/RedisDatabaseConnection.java @@ -5,6 +5,7 @@ import com.fr.config.holder.factory.Holders; import com.fr.data.impl.AbstractDatabaseConnection; import com.fr.data.impl.Connection; import com.fr.locale.InterProviderFactory; +import com.fr.plugin.db.redis.core.emb.Redis; import com.fr.security.SecurityToolbox; import com.fr.stable.ArrayUtils; import com.fr.stable.StableUtils; @@ -19,14 +20,10 @@ import java.util.Set; public class RedisDatabaseConnection extends AbstractDatabaseConnection { private static final int DEFAULT_REDIS_PORT = 6379; - private static final int MAX_TOTAL = 10; - private static final int MAX_WAIT = -1; private Conf host = Holders.simple(StringUtils.EMPTY); private Conf port = Holders.simple(DEFAULT_REDIS_PORT); private Conf password = Holders.simple(StringUtils.EMPTY); - private Conf maxTotal = Holders.simple(MAX_TOTAL); - private Conf maxWait = Holders.simple(MAX_WAIT); public RedisDatabaseConnection() { @@ -56,27 +53,12 @@ public class RedisDatabaseConnection extends AbstractDatabaseConnection { this.password.set(password); } - public int getMaxTotal() { - return maxTotal.get(); - } - - public void setMaxTotal(Integer maxTotal) { - this.maxTotal.set(maxTotal); - } - - public int getMaxWait() { - return maxWait.get(); - } - - public void setMaxWait(int maxWait) { - this.maxWait.set(maxWait); - } @Override public void testConnection() throws Exception { - Jedis client = createRedisClient(); + Redis client = createRedisClient(); try { - String text = client.ping(); + String text = client.getClient().ping(); if (!"pong".equalsIgnoreCase(text)) { throw new Exception(text); } @@ -86,8 +68,8 @@ public class RedisDatabaseConnection extends AbstractDatabaseConnection { } - public Jedis createRedisClient() { - return RedisPool.getPool().getResource(getHost(), getPort(), getPassword(), getMaxTotal(), getMaxWait()); + public Redis createRedisClient() { + return RedisPool.getPool().getResource(getHost(), getPort(), getPassword()); } @Override @@ -100,8 +82,11 @@ public class RedisDatabaseConnection extends AbstractDatabaseConnection { if (ArrayUtils.isEmpty(args)) { return ArrayUtils.EMPTY_STRING_ARRAY; } else { - Set keys = createRedisClient().keys(args[0]); - return keys.toArray(new String[0]); + Redis redis = createRedisClient(); + Set keys = redis.getClient().keys(args[0]); + String[] array = keys.toArray(new String[0]); + redis.close(); + return array; } } @@ -161,8 +146,6 @@ public class RedisDatabaseConnection extends AbstractDatabaseConnection { if (StringUtils.isNotEmpty(pwd)) { setPassword(SecurityToolbox.encrypt(pwd)); } - setMaxTotal(reader.getAttrAsInt("maxTotal", MAX_TOTAL)); - setMaxWait(reader.getAttrAsInt("maxWait", MAX_WAIT)); } } } @@ -176,8 +159,6 @@ public class RedisDatabaseConnection extends AbstractDatabaseConnection { if (StringUtils.isNotEmpty(getPassword())) { writer.attr("password", SecurityToolbox.decrypt(getPassword())); } - writer.attr("maxTotal", getMaxTotal()); - writer.attr("maxWait", getMaxWait()); writer.end(); } @@ -187,8 +168,6 @@ public class RedisDatabaseConnection extends AbstractDatabaseConnection { cloned.host = (Conf) host.clone(); cloned.port = (Conf) port.clone(); cloned.password = (Conf) password.clone(); - cloned.maxTotal = (Conf) maxTotal.clone(); - cloned.maxWait = (Conf) maxWait.clone(); return cloned; } } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/db/redis/core/RedisPool.java b/src/main/java/com/fr/plugin/db/redis/core/RedisPool.java index 0cdd3d0..5087d88 100644 --- a/src/main/java/com/fr/plugin/db/redis/core/RedisPool.java +++ b/src/main/java/com/fr/plugin/db/redis/core/RedisPool.java @@ -1,5 +1,14 @@ package com.fr.plugin.db.redis.core; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.db.redis.core.emb.Redis; +import com.fr.plugin.db.redis.core.emb.impl.ProxyRedis; +import com.fr.plugin.db.redis.core.emb.impl.SimpleRedis; +import com.fr.plugin.db.redis.core.pool.RedisConnectionPoolConfig; +import com.fr.plugin.db.redis.core.pool.RedisConnectionProxyConfig; +import com.fr.ssh.jsch.JSch; +import com.fr.ssh.jsch.JSchException; +import com.fr.ssh.jsch.Session; import com.fr.stable.StringUtils; import com.fr.third.redis.clients.jedis.Jedis; import com.fr.third.redis.clients.jedis.JedisPool; @@ -25,18 +34,30 @@ public class RedisPool { private Map jedisPoolMap = new ConcurrentHashMap(); - public Jedis getResource(String host, int port, String password, int maxTotal, int maxWait) { - JedisPool jedisPool = jedisPoolMap.get(host); - if (jedisPool == null) { - jedisPool = createJedisPool(host, port, password, maxTotal, maxWait); - jedisPoolMap.put(host, jedisPool); + public Redis getResource(String host, int port, String password) { + if (RedisConnectionProxyConfig.getInstance().isOpen()) { + try { + return createJedisBySSH(host, port, password); + } catch (JSchException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } else { + JedisPool jedisPool = jedisPoolMap.get(host); + if (jedisPool == null) { + jedisPool = createJedisPool(host, port, password); + jedisPoolMap.put(host, jedisPool); + } + return new SimpleRedis(jedisPool.getResource()); } - return jedisPool.getResource(); + Jedis jedis = new Jedis(host, port); + jedis.auth(password); + return new SimpleRedis(jedis); } - private JedisPool createJedisPool(String host, int port, String password, int maxTotal, int maxWait) { + private JedisPool createJedisPool(String host, int port, String password) { + RedisConnectionPoolConfig poolConfig = RedisConnectionPoolConfig.getInstance(); JedisPoolConfig config = new JedisPoolConfig(); - config.setMaxTotal(maxTotal); + config.setMaxTotal(poolConfig.getMaxTotal()); //连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true config.setBlockWhenExhausted(true); //设置的逐出策略类名, 默认DefaultEvictionPolicy(当连接超过最大空闲时间,或连接数超过最大空闲连接数) @@ -51,7 +72,7 @@ public class RedisPool { config.setMaxIdle(10); //最大连接数,可配置 //获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间, 默认-1 - config.setMaxWaitMillis(maxWait); + config.setMaxWaitMillis(poolConfig.getMaxWait()); //逐出连接的最小空闲时间 默认1800000毫秒(30分钟) config.setMinEvictableIdleTimeMillis(1800000); //最小空闲连接数, 默认0 @@ -72,4 +93,28 @@ public class RedisPool { return new JedisPool(config, host, port, TIME_OUT); } } + + private Redis createJedisBySSH(String host, int port, String password) throws JSchException { + RedisConnectionProxyConfig proxyConfig = RedisConnectionProxyConfig.getInstance(); + JSch jsch = new JSch(); + if (StringUtils.isNotBlank(proxyConfig.getPrivateKeyPath())) { + jsch.addIdentity(proxyConfig.getPrivateKeyPath()); + } + Session session = jsch.getSession(proxyConfig.getUsername(), proxyConfig.getHost(), proxyConfig.getPort()); + if (StringUtils.isNotBlank(proxyConfig.getPassword())) { + session.setPassword(proxyConfig.getPassword()); + } + session.setConfig("StrictHostKeyChecking", "no"); + session.connect(); + + int newPort = session.setPortForwardingL(0, host, port); + + Jedis jedis = new Jedis(host, newPort); + + if (StringUtils.isNotBlank(password)) { + jedis.auth(password); + } + return new ProxyRedis(session, jedis); + + } } diff --git a/src/main/java/com/fr/plugin/db/redis/core/RedisScriptTableDataModel.java b/src/main/java/com/fr/plugin/db/redis/core/RedisScriptTableDataModel.java index c673af4..f163ac8 100644 --- a/src/main/java/com/fr/plugin/db/redis/core/RedisScriptTableDataModel.java +++ b/src/main/java/com/fr/plugin/db/redis/core/RedisScriptTableDataModel.java @@ -5,6 +5,7 @@ import com.eclipsesource.v8.V8Array; import com.eclipsesource.v8.V8Object; import com.fr.base.TableData; import com.fr.data.AbstractDataModel; +import com.fr.plugin.db.redis.core.emb.Redis; import com.fr.plugin.db.redis.help.Console; import com.fr.plugin.db.redis.help.Files; import com.fr.plugin.db.redis.help.RedisClient; @@ -40,10 +41,10 @@ public class RedisScriptTableDataModel extends AbstractDataModel { if (columnNames != null) { return; } - Jedis jedis = mc.createRedisClient(); - jedis.select(dbIndex); + Redis redis = mc.createRedisClient(); + redis.getClient().select(dbIndex); V8 v8 = V8.createV8Runtime(); - RedisClient client = new RedisClient(v8, jedis); + RedisClient client = new RedisClient(v8, redis.getClient()); V8Object v8Console = initConsole(v8); V8Object v8Require = initRequire(v8); V8Object v8Client = initRedis(v8, client); @@ -72,7 +73,7 @@ public class RedisScriptTableDataModel extends AbstractDataModel { v8Row.release(); data.add(row); } - jedis.close(); + redis.close(); v8Table.release(); v8Column.release(); returnObj.release(); diff --git a/src/main/java/com/fr/plugin/db/redis/core/RedisTableDataModel.java b/src/main/java/com/fr/plugin/db/redis/core/RedisTableDataModel.java index f5a5870..f54dd9d 100755 --- a/src/main/java/com/fr/plugin/db/redis/core/RedisTableDataModel.java +++ b/src/main/java/com/fr/plugin/db/redis/core/RedisTableDataModel.java @@ -5,7 +5,9 @@ import com.fr.data.AbstractDataModel; import com.fr.log.FineLoggerFactory; import com.fr.plugin.PluginLicense; import com.fr.plugin.PluginLicenseManager; +import com.fr.plugin.db.redis.core.emb.Redis; import com.fr.plugin.db.redis.core.visit.VisitorFactory; +import com.fr.plugin.db.redis.util.RedisUtils; import com.fr.script.Calculator; import com.fr.stable.StringUtils; import com.fr.third.redis.clients.jedis.Jedis; @@ -29,17 +31,17 @@ public class RedisTableDataModel extends AbstractDataModel { if (StringUtils.isEmpty(query)) { return; } - Jedis redisClient = mc.createRedisClient(); - redisClient.select(dbIndex); + Redis redis = mc.createRedisClient(); + redis.getClient().select(dbIndex); FineLoggerFactory.getLogger().info("Connect to redis and select database:" + dbIndex); try { long start = System.currentTimeMillis(); - DataWrapper wrapper = VisitorFactory.getKeyValueResult(calculator, ps, redisClient, query, rowCount); + DataWrapper wrapper = VisitorFactory.getKeyValueResult(calculator, ps, redis.getClient(), query, rowCount); FineLoggerFactory.getLogger().info("Fetch data from redis spend time {} ms.", System.currentTimeMillis() - start); wrapper.transform(script); data = wrapper.getData(); columnNames = wrapper.getColumnNames(); - redisClient.close(); + redis.close(); } catch (Exception e) { throw new RuntimeException(e.getCause()); } diff --git a/src/main/java/com/fr/plugin/db/redis/core/emb/Redis.java b/src/main/java/com/fr/plugin/db/redis/core/emb/Redis.java new file mode 100644 index 0000000..5582443 --- /dev/null +++ b/src/main/java/com/fr/plugin/db/redis/core/emb/Redis.java @@ -0,0 +1,15 @@ +package com.fr.plugin.db.redis.core.emb; + +import com.fr.third.redis.clients.jedis.Jedis; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-03-21 + */ +public interface Redis { + + Jedis getClient(); + + void close(); +} diff --git a/src/main/java/com/fr/plugin/db/redis/core/emb/impl/ProxyRedis.java b/src/main/java/com/fr/plugin/db/redis/core/emb/impl/ProxyRedis.java new file mode 100644 index 0000000..f7f528d --- /dev/null +++ b/src/main/java/com/fr/plugin/db/redis/core/emb/impl/ProxyRedis.java @@ -0,0 +1,32 @@ +package com.fr.plugin.db.redis.core.emb.impl; + +import com.fr.plugin.db.redis.core.emb.Redis; +import com.fr.ssh.jsch.Session; +import com.fr.third.redis.clients.jedis.Jedis; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-03-21 + */ +public class ProxyRedis implements Redis { + + private Session session; + private Jedis jedis; + + public ProxyRedis(Session session, Jedis jedis) { + this.session = session; + this.jedis = jedis; + } + + @Override + public Jedis getClient() { + return jedis; + } + + @Override + public void close() { + jedis.close(); + session.disconnect(); + } +} diff --git a/src/main/java/com/fr/plugin/db/redis/core/emb/impl/SimpleRedis.java b/src/main/java/com/fr/plugin/db/redis/core/emb/impl/SimpleRedis.java new file mode 100644 index 0000000..db55482 --- /dev/null +++ b/src/main/java/com/fr/plugin/db/redis/core/emb/impl/SimpleRedis.java @@ -0,0 +1,28 @@ +package com.fr.plugin.db.redis.core.emb.impl; + +import com.fr.plugin.db.redis.core.emb.Redis; +import com.fr.third.redis.clients.jedis.Jedis; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-03-21 + */ +public class SimpleRedis implements Redis { + + private Jedis jedis; + + public SimpleRedis(Jedis jedis) { + this.jedis = jedis; + } + + @Override + public Jedis getClient() { + return jedis; + } + + @Override + public void close() { + jedis.close(); + } +} diff --git a/src/main/java/com/fr/plugin/db/redis/core/pool/RedisConnectionPoolConfig.java b/src/main/java/com/fr/plugin/db/redis/core/pool/RedisConnectionPoolConfig.java new file mode 100644 index 0000000..c6cce19 --- /dev/null +++ b/src/main/java/com/fr/plugin/db/redis/core/pool/RedisConnectionPoolConfig.java @@ -0,0 +1,53 @@ +package com.fr.plugin.db.redis.core.pool; + +import com.fr.config.ConfigContext; +import com.fr.config.DefaultConfiguration; +import com.fr.config.holder.Conf; +import com.fr.config.holder.factory.Holders; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-03-21 + */ +public class RedisConnectionPoolConfig extends DefaultConfiguration { + + private static volatile RedisConnectionPoolConfig instance = null; + + public static RedisConnectionPoolConfig getInstance() { + if (instance == null) { + instance = ConfigContext.getConfigInstance(RedisConnectionPoolConfig.class); + } + return instance; + } + + private static final int MAX_TOTAL = 10; + private static final int MAX_WAIT = -1; + + private Conf maxTotal = Holders.simple(MAX_TOTAL); + private Conf maxWait = Holders.simple(MAX_WAIT); + + public int getMaxTotal() { + return maxTotal.get(); + } + + public void setMaxTotal(Integer maxTotal) { + this.maxTotal.set(maxTotal); + } + + public int getMaxWait() { + return maxWait.get(); + } + + public void setMaxWait(int maxWait) { + this.maxWait.set(maxWait); + } + + @Override + public Object clone() throws CloneNotSupportedException { + RedisConnectionPoolConfig cloned = (RedisConnectionPoolConfig) super.clone(); + cloned.maxTotal = (Conf) maxTotal.clone(); + cloned.maxWait = (Conf) maxWait.clone(); + return cloned; + } +} diff --git a/src/main/java/com/fr/plugin/db/redis/core/pool/RedisConnectionProxyConfig.java b/src/main/java/com/fr/plugin/db/redis/core/pool/RedisConnectionProxyConfig.java new file mode 100644 index 0000000..7748ccf --- /dev/null +++ b/src/main/java/com/fr/plugin/db/redis/core/pool/RedisConnectionProxyConfig.java @@ -0,0 +1,97 @@ +package com.fr.plugin.db.redis.core.pool; + +import com.fr.config.ConfigContext; +import com.fr.config.DefaultConfiguration; +import com.fr.config.holder.Conf; +import com.fr.config.holder.factory.Holders; +import com.fr.stable.StringUtils; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-03-21 + */ +public class RedisConnectionProxyConfig extends DefaultConfiguration { + + private static volatile RedisConnectionProxyConfig instance = null; + + public static RedisConnectionProxyConfig getInstance() { + if (instance == null) { + instance = ConfigContext.getConfigInstance(RedisConnectionProxyConfig.class); + } + return instance; + } + + private Conf open = Holders.simple(false); + + private Conf host = Holders.simple(StringUtils.EMPTY); + + private Conf port = Holders.simple(22); + + private Conf username = Holders.simple(StringUtils.EMPTY); + + private Conf password = Holders.simple(StringUtils.EMPTY); + + private Conf privateKeyPath = Holders.simple(StringUtils.EMPTY); + + + public boolean isOpen() { + return open.get(); + } + + public void setOpen(boolean open) { + this.open.set(open); + } + + public String getHost() { + return host.get(); + } + + public void setHost(String host) { + this.host.set(host); + } + + public int getPort() { + return port.get(); + } + + public void setPort(int port) { + this.port.set(port); + } + + public String getUsername() { + return username.get(); + } + + public void setUsername(String username) { + this.username.set(username); + } + + public String getPassword() { + return password.get(); + } + + public void setPassword(String password) { + this.password.set(password); + } + + public String getPrivateKeyPath() { + return privateKeyPath.get(); + } + + public void setPrivateKeyPath(String privateKeyPath) { + this.privateKeyPath.set(privateKeyPath); + } + + @Override + public Object clone() throws CloneNotSupportedException { + RedisConnectionProxyConfig cloned = (RedisConnectionProxyConfig) super.clone(); + cloned.open = (Conf) open.clone(); + cloned.host = (Conf) host.clone(); + cloned.port = (Conf) port.clone(); + cloned.username = (Conf) username.clone(); + cloned.password = (Conf) password.clone(); + cloned.privateKeyPath = (Conf) privateKeyPath.clone(); + return cloned; + } +} diff --git a/src/main/java/com/fr/plugin/db/redis/ui/RedisConnectionPane.java b/src/main/java/com/fr/plugin/db/redis/ui/RedisConnectionPane.java index 2907f47..39ad667 100755 --- a/src/main/java/com/fr/plugin/db/redis/ui/RedisConnectionPane.java +++ b/src/main/java/com/fr/plugin/db/redis/ui/RedisConnectionPane.java @@ -2,7 +2,10 @@ package com.fr.plugin.db.redis.ui; import com.fr.design.border.UITitledBorder; import com.fr.design.data.datapane.connect.DatabaseConnectionPane; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.gui.ibutton.UIPasswordField; +import com.fr.design.gui.ilable.ActionLabel; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.itextfield.UIIntNumberField; import com.fr.design.gui.itextfield.UINumberField; @@ -11,11 +14,19 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; -import com.fr.general.Inter; +import com.fr.design.utils.gui.GUICoreUtils; import com.fr.plugin.db.redis.core.RedisDatabaseConnection; +import com.fr.plugin.db.redis.core.pool.RedisConnectionPoolConfig; +import com.fr.plugin.db.redis.core.pool.RedisConnectionProxyConfig; +import com.fr.plugin.db.redis.ui.pool.RedisConnectionPoolConfigPane; +import com.fr.plugin.db.redis.ui.proxy.RedisConnectionProxyConfigPane; +import com.fr.transaction.Configurations; +import com.fr.transaction.WorkerFacade; import javax.swing.*; import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; public class RedisConnectionPane extends DatabaseConnectionPane { @@ -23,8 +34,7 @@ public class RedisConnectionPane extends DatabaseConnectionPane