用java的nginx进行端口转发

我正在试图做一个使用redis作为后端的Java应用程序 。 由于Redis是一个非常快速的键值存储,所以我希望使用这个存储,但redis被用于1个客户端,所以它没有用户选项:通过身份validation。 我想find一种方法来实现某种身份validation,所以我尝试了nginxredis2扩展。 我这样做是因为我可以使用客户端的证书和HTTPS。 但是这使得我的应用程序非常慢。

我正在考虑使用某种通过nginx代理连接到redis的隧道。 对于这个redis会在本地主机上监听,并且会有一个地址我想用来访问redis,但是使用httpsauthentication。 所以基本上我现在的方法

JAVA - Jedis - LAN - REDIS ,would be JAVA - Jedis(with localhost as the tunnel entrance?)- -SSL LAN - Nginx(tunnel exit) - Redis 

任何提示实现这一点? 我一直在网上search最后的日子,但我不能提出任何事情,只增加了一点本地连接的开销。

Redis旨在在后端应用程序后面的安全网络上工作。 客户端应用程序不应直接连接到Redis。 这使得Redis成为2层应用程序的一个糟糕的选择。

现在,如果您仍然希望使用Redis,那么您有几个选择。 您可以将Redis服务器封装在HTTP接口中。 这是nginx redis2模块提供的。 你可能也想看看webdis ,这是相似的(并不依赖于nginx)。 Webdis提供了一些访问控制机制。 请参阅文档。

另一个解决方案是按照你的建议建立一个隧道。 我不会为此使用nginx,而只是简单的旧的SSH。 假设Redis服务器在机器B(端口6379)上运行,客户端在机器A上运行

在机器A上,我可以运行:

 ssh user@host_B -L 7008:host_B:6379 -N 

它将打开从本地端口7008(任意选择)从A到B的隧道,然后等待。 用户应该在主机B上声明,并且密码是已知的。 在另一个会议上,仍然在主机A上,我们现在可以运行:

 redis-cli -p 7008 ping 

请注意使用标准的Redis客户端。 隧道以透明的方式处理认证,加密和可选的压缩。

现在,您的客户端是Java应用程序,您可能不希望运行SSH命令来设置隧道。 希望您可以使用Jsch包直接从Java打开隧道。 以下是Jedis的一个例子:

 import redis.clients.jedis.*; import java.util.*; import com.jcraft.jsch.*; public class TestTunnel { Jedis jedis; Session session; JSch jsch = new JSch(); int port; // None of the following should be hardcoded static String USER = "user"; // SSH user on the redis server host static String PASSWD = "XXXXXXXX"; // SSH user password static String HOST = "192.168.1.62"; // Redis server host static int PORT = 6379; // Redis server port public TestTunnel() { try { // Open the SSH session session = jsch.getSession( USER, HOST, 22 ); session.setPassword( PASSWD ); java.util.Properties config = new java.util.Properties(); config.put("StrictHostKeyChecking", "no"); config.put("Compression", "yes"); config.put("ConnectionAttempts","3"); session.setConfig(config); session.connect(); // Setup port forwarding from localhost to the Redis server // Local port is ephemeral (given by the OS) // Jedis connects to localhost using the local port port = session.setPortForwardingL( 0, HOST, PORT ); jedis = new Jedis( "127.0.0.1", port ); } catch ( JSchException e ) { // Proper error handling omitted System.out.println(e); } } public void disconnect() { jedis.disconnect(); try { session.delPortForwardingL( port ); session.disconnect(); } catch ( JSchException e ) { // Proper error handling omitted System.out.println(e); } } public void mytest( int n ) { for ( int k = 0; k < n; k++) { jedis.set("k" + k, "value"+k); } System.out.println("Read: "+jedis.get("k0") ); } public static void main(String[] args) { TestTunnel obj = new TestTunnel(); obj.mytest(10); obj.disconnect(); } } 

它工作正常,但请注意有隧道的开销。 当网络速度很慢时(例如互联网),开销非常低。 在快速LAN(1 GbE)上,更加明显:使用隧道时,延迟可以乘以3。 Redis服务器能够承受的最大吞吐量也受到影响。 在服务器端,sshd守护进程需要一些CPU(超过Redis本身)。

也就是说,我认为对于一个2层应用程序,原始性能并不重要。

注意:有一个名为SSL-REDIS的SSL版本的redis,可以在github上找到: https : //github.com/bbroerman30/ssl-redis 2.6ish

https://github.com/tritondigital/ssl-redis 2.4ish

通过这个和修改Jedis Java客户端,可以实现SSL认证。