Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从java使用nginx进行端口转发_Java_Ssl_Https_Nginx_Redis - Fatal编程技术网

从java使用nginx进行端口转发

从java使用nginx进行端口转发,java,ssl,https,nginx,redis,Java,Ssl,Https,Nginx,Redis,我正在尝试制作一个java应用程序,它使用redis作为后端。因为Redis是一个非常快速的键值存储,我想使用它,但是Redis被设置为与一个客户端一起使用,所以它没有用户选项:通过身份验证。我想找到一种实现某种身份验证的方法,所以我尝试了使用redis2扩展的nginx。我这样做是因为我可以使用客户端证书和HTTPS。但这让我的应用程序非常慢 我正在考虑使用某种隧道,通过nginx代理连接到redis。对于这个redis,它是在localhost上侦听的,并且有一个地址,我想用它来访问redi

我正在尝试制作一个java应用程序,它使用redis作为后端。因为Redis是一个非常快速的键值存储,我想使用它,但是Redis被设置为与一个客户端一起使用,所以它没有用户选项:通过身份验证。我想找到一种实现某种身份验证的方法,所以我尝试了使用redis2扩展的nginx。我这样做是因为我可以使用客户端证书和HTTPS。但这让我的应用程序非常慢

我正在考虑使用某种隧道,通过nginx代理连接到redis。对于这个redis,它是在localhost上侦听的,并且有一个地址,我想用它来访问redis,但是要使用https身份验证。所以基本上我现在的方法

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

实现这一点有什么建议吗?过去几天我一直在网上搜索,但我找不到任何只会给本机连接增加一点开销的东西。

Redis设计用于在后台应用程序后面的安全网络上工作。客户端应用程序不应该直接连接到Redis。这使得Redis对于两层应用程序来说是一个糟糕的选择

现在,如果您仍然想使用Redis进行此操作,您有几个选项。您可以将Redis服务器封装在HTTP接口中。这就是nginx redis2模块提供的功能。您可能还想看看,这是类似的(不依赖于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命令来设置隧道。希望您可以使用该包直接从Java打开隧道。这是一个绝地武士的例子:

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();
    }
 }
导入redis.clients.jedis.*;
导入java.util.*;
导入com.jcraft.jsch.*;
公共级测试隧道{
绝地武士;
会议;
JSch JSch=新的JSch();
国际港口;
//以下各项均不应硬编码
静态字符串USER=“USER”;//redis服务器主机上的SSH用户
静态字符串PASSWD=“XXXXXXXX”//SSH用户密码
静态字符串HOST=“192.168.1.62”;//Redis服务器主机
静态int-PORT=6379;//Redis服务器端口
公共测试隧道(){
试一试{
//打开SSH会话
session=jsch.getSession(用户,主机,22);
session.setPassword(PASSWD);
java.util.Properties config=new java.util.Properties();
配置放置(“检查”、“否”);
config.put(“压缩”、“是”);
配置放置(“连接尝试”、“3”);
session.setConfig(config);
session.connect();
//设置从本地主机到Redis服务器的转发端口
//本地端口是短暂的(由操作系统提供)
//绝地武士使用本地端口连接到本地主机
端口=session.setPortForwardingL(0,主机,端口);
绝地=新绝地(“127.0.0.1”,波特);
}捕获(JSCHEException e){
//忽略了正确的错误处理
系统输出打印ln(e);
}
} 
公共空间断开连接(){
绝地武士;
试一试{
会议.delPortForwardingL(港口);
session.disconnect();
}捕获(JSCHEException e){
//忽略了正确的错误处理
系统输出打印ln(e);
} 
}
公共无效mytest(int n){
对于(int k=0;k
它工作正常,但请注意,由于隧道的原因,有一个开销。当网络速度较慢时(例如Internet),开销非常低。在快速LAN(1 GbE)上,更值得注意的是:当使用隧道时,延迟可以乘以3。Redis服务器能够维持的最大吞吐量也受到影响。在服务器端,sshd守护进程占用一些CPU(比Redis本身还要多)


也就是说,我不认为原始性能对两层应用程序有多大影响。

注意:有一个称为SSL-redis的SSL版本,可以在github上找到: 2.6ish

2.4ish


通过这一点并修改Jedis Java客户端,可以实现SSL身份验证。

您对Redis有一些重要的误解。首先,Redis的设计绝对不是只用于一个客户端。它可以有效地处理数千个并发客户端。第二,它实际上有一个身份验证机制,尽管它是一个全局访问级别的权限。此外,我非常确定,您尝试使用Nginx所需要的不仅仅是一些配置。要做到这一点,您需要编写一个代理中继,您不能只将Nginx放在Redis前面,因为Nginx是HTTP(并且有POP和SMTP模块)&这很好。也许您可以添加有关设置和需求的详细信息。此外,我看不到直接Redis连接的价值。Redis就是存储。它需要逻辑来找到所需的数据。将所有这些逻辑放在客户端(比如移动应用程序)中,会使客户端膨胀,并带来升级噩梦,这是很容易避免的。