Redis е проектиран да работи в защитена мрежа, зад бекенд приложение. Клиентските приложения не трябва да се свързват директно с Redis. Това прави Redis лош избор за 2-степенно приложение.
Сега, ако все още искате да използвате Redis за това, имате няколко опции. Можете да капсулирате сървъра Redis в HTTP интерфейс. Това предоставя модулът nginx redis2. Може също да искате да разгледате webdis, който е подобен (и не зависи от nginx). Webdis предлага някои механизми за контрол на достъпа. Вижте документацията.
Друго решение е да се създаде тунел, както предложихте. Не бих използвал nginx за това, а просто стар SSH. Да предположим, че Redis сървърът работи на машина B (порт 6379), а клиентът работи на машина A.
На машина А мога да стартирам:
ssh [email protected]_B -L 7008:host_B:6379 -N
Той ще отвори тунел от А до Б от локален порт 7008 (произволен избор) и изчаква. Потребителят трябва да бъде деклариран на хост B и паролата му известна. В друга сесия, все още на хост А, вече можем да изпълним:
redis-cli -p 7008 ping
Моля, имайте предвид, че се използва стандартен клиент Redis. Тунелът обработва удостоверяване, криптиране и по избор компресиране по прозрачен начин за клиента.
Сега вашият клиент е Java приложение и вероятно не искате да изпълнявате SSH команди за настройка на тунела. Надяваме се, че можете да използвате пакета Jsch, за да отворите тунела директно от 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();
}
}
Работи добре, но имайте предвид, че има режийни разходи поради тунела. Разходите са много ниски, когато мрежата е бавна (например Интернет). При бърза LAN (1 GbE) това е много по-забележимо:латентността може да се умножи до 3, когато се използва тунелът. Максималната пропускателна способност, която Redis сървърът може да поддържа, също е засегната. От страна на сървъра, sshd демонът отнема малко CPU (повече от самия Redis).
Въпреки това не мисля, че необработената производителност има голямо значение за двустепенно приложение.