nginx java接口,使用java中的nginx进行端口转发

I'm trying to make a java application which uses redis as a backend. Since Redis is a really fast key-value store which I'd like to use, but redis is made to be used with 1 client so it doesn't have an option for user:pass authentication. I'd like to find a way to implement some kind of authentication, so I tried nginx with the redis2 extension. I did this because I could use client-side certficates and HTTPS. But it's making my application really slow.

I'm thinking about using some kind of tunnel which connects to redis via nginx proxy. For this redis would be listen on localhost and there would be an address which I'd like to use to reach redis, but with https authentication. So basically my current method

JAVA - Jedis - LAN - REDIS ,would be

JAVA - Jedis(with localhost as the tunnel entrance?)-

-SSL LAN - Nginx(tunnel exit) - Redis

Any tip for achieving this? I've been googled the web for the last days but i couldn't come up anything that adds only a little overhead to the native connection.

解决方案

Redis is designed to work on a secure network, behind a backend application. Client applications are not supposed to connect directly to Redis. It makes Redis a poor choice for a 2-tier application.

Now if you still want to use Redis for this, you have several options. You can encapsulate the Redis server in a HTTP interface. This is what the nginx redis2 module provide. You might also want to have a look at webdis, which is similar (and does not depend on nginx). Webdis offers some access control mechanisms. See the documentation.

Another solution is to establish a tunnel, as you proposed. I would not use nginx for this, but just plain old SSH. Let's suppose Redis server runs on machine B (port 6379) and client runs on machine A.

On machine A, I can run:

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

It will open a tunnel from A to B from local port 7008 (arbitrary choice), and waits. The user should be declared on host B, and its password known. In another session, still on host A, we can now run:

redis-cli -p 7008 ping

Please note a standard Redis client is used. The tunnel handles authentication, encryption and optionally compression in a transparent way for the client.

Now, your client is a Java application, and you probably do not want to run SSH commands to setup the tunnel. Hopefully, you can use the Jsch package to open the tunnel directly from Java. Here is an example with 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();

}

}

It works fine, but please note there is an overhead due to the tunnel. The overhead is very low when the network is slow (the Internet for instance). On a fast LAN (1 GbE), it is much more noticeable: the latency can be multiplied by up to 3 when the tunnel is used. The maximum throughput the Redis server can sustain is also impacted. On server-side, the sshd daemon takes some CPU (more than Redis itself).

That said, I don't think raw performance matters much for a 2-tier application.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值