sql >> Base de Datos >  >> NoSQL >> Redis

Reenvío de puertos con nginx desde java

Redis está diseñado para funcionar en una red segura, detrás de una aplicación de back-end. No se supone que las aplicaciones cliente se conecten directamente a Redis. Hace que Redis sea una mala elección para una aplicación de dos niveles.

Ahora, si aún desea usar Redis para esto, tiene varias opciones. Puede encapsular el servidor Redis en una interfaz HTTP. Esto es lo que proporciona el módulo nginx redis2. También es posible que desee echar un vistazo a webdis, que es similar (y no depende de nginx). Webdis ofrece algunos mecanismos de control de acceso. Consulte la documentación.

Otra solución es establecer un túnel, como proponías. No usaría nginx para esto, sino simplemente SSH. Supongamos que el servidor Redis se ejecuta en la máquina B (puerto 6379) y el cliente se ejecuta en la máquina A.

En la máquina A, puedo ejecutar:

ssh [email protected]_B -L 7008:host_B:6379 -N

Abrirá un túnel de A a B desde el puerto local 7008 (elección arbitraria) y esperará. El usuario debe declararse en el host B y debe conocerse su contraseña. En otra sesión, aún en el host A, ahora podemos ejecutar:

redis-cli -p 7008 ping

Tenga en cuenta que se utiliza un cliente Redis estándar. El túnel gestiona la autenticación, el cifrado y, opcionalmente, la compresión de forma transparente para el cliente.

Ahora, su cliente es una aplicación Java y probablemente no desee ejecutar comandos SSH para configurar el túnel. Con suerte, puede usar el paquete Jsch para abrir el túnel directamente desde Java. Aquí hay un ejemplo con 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();
    }
 }

Funciona bien, pero tenga en cuenta que hay una sobrecarga debido al túnel. La sobrecarga es muy baja cuando la red es lenta (Internet, por ejemplo). En una LAN rápida (1 GbE), se nota mucho más:la latencia se puede multiplicar hasta por 3 cuando se utiliza el túnel. El rendimiento máximo que puede soportar el servidor Redis también se ve afectado. En el lado del servidor, el demonio sshd requiere algo de CPU (más que el propio Redis).

Dicho esto, no creo que el rendimiento bruto importe mucho para una aplicación de dos niveles.