Redis est conçu pour fonctionner sur un réseau sécurisé, derrière une application backend. Les applications clientes ne sont pas censées se connecter directement à Redis. Cela fait de Redis un mauvais choix pour une application à 2 niveaux.
Maintenant, si vous souhaitez toujours utiliser Redis pour cela, vous avez plusieurs options. Vous pouvez encapsuler le serveur Redis dans une interface HTTP. C'est ce que propose le module nginx redis2. Vous pouvez également jeter un œil à webdis, qui est similaire (et ne dépend pas de nginx). Webdis propose des mécanismes de contrôle d'accès. Voir la documentation.
Une autre solution consiste à établir un tunnel, comme vous l'avez proposé. Je n'utiliserais pas nginx pour cela, mais simplement le vieux SSH. Supposons que le serveur Redis s'exécute sur la machine B (port 6379) et que le client s'exécute sur la machine A.
Sur la machine A, je peux exécuter :
ssh [email protected]_B -L 7008:host_B:6379 -N
Il ouvrira un tunnel de A à B à partir du port local 7008 (choix arbitraire) et attendra. L'utilisateur doit être déclaré sur l'hôte B, et son mot de passe connu. Dans une autre session, toujours sur l'hôte A, nous pouvons maintenant exécuter :
redis-cli -p 7008 ping
Veuillez noter qu'un client Redis standard est utilisé. Le tunnel gère l'authentification, le chiffrement et éventuellement la compression de manière transparente pour le client.
Maintenant, votre client est une application Java et vous ne souhaitez probablement pas exécuter de commandes SSH pour configurer le tunnel. Heureusement, vous pouvez utiliser le package Jsch pour ouvrir le tunnel directement depuis Java. Voici un exemple avec 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();
}
}
Cela fonctionne bien, mais veuillez noter qu'il y a une surcharge due au tunnel. L'overhead est très faible lorsque le réseau est lent (Internet par exemple). Sur un LAN rapide (1 GbE), c'est beaucoup plus perceptible :la latence peut être multipliée jusqu'à 3 lorsque le tunnel est utilisé. Le débit maximal que le serveur Redis peut supporter est également impacté. Côté serveur, le démon sshd utilise un peu de CPU (plus que Redis lui-même).
Cela dit, je ne pense pas que les performances brutes importent beaucoup pour une application à 2 niveaux.