使用guava的cache实现ssh connection的缓存
使用guava的cache实现ssh connection的缓存1、业务需求java后台需要根据前端传入的IP地址和密码使用ssh连接到linux虚拟机。为了简化系统,假设连接使用的用户名固定,这样只需要提供IP和密码就可以连接到linux机器。所以目前这个系统需要缓存大量的ssh connection,不然每次执行命令都需要从新连接linux将会很慢。2、解决方案2.1 不使用缓存每次都是新建c
·
使用guava的cache实现ssh connection的缓存
1、业务需求
java后台需要根据前端传入的IP地址和密码使用ssh连接到linux虚拟机。为了简化系统,假设连接使用的用户名固定,这样只需要提供IP和密码就可以连接到linux机器。
所以目前这个系统需要缓存大量的ssh connection,不然每次执行命令都需要从新连接linux将会很慢。
2、解决方案
2.1 不使用缓存
每次都是新建connection。这样是真的慢,也很没有必要。
2.2 目前的方案
每一个前端请求缓存一个connection。我想了好久,找了好久也找不到一个方案,当然自己也写不出来。只好用这个方案了。每次如果要执行ssh命令,就先到request域中找,找到直接返回,找不到就新建一个connection并放入request中。这样同一个请求可以达到复用connecton,在退出后还可以使用监听器关闭connection。
弊端:复用性不高,每次request销毁后悔判断一下,当前request域中是否有connection。
2.3 新的方法
学习guava无意中想到了这里的cache正好可以用来存储connection。
他满足:
- 缓存connection
- 移除时的监听器
- 缓存淘汰策略满足
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>sshcache</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>sshcache</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>ch.ethz.ganymed</groupId>
<artifactId>ganymed-ssh2</artifactId>
<version>build210</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.3-jre</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package com.example.sshcache.util;
import ch.ethz.ssh2.Connection;
import com.google.common.base.Joiner;
import com.google.common.cache.*;
import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
public class SshConnectionUtil {
private static LoadingCache<String,Connection> sshLoadingCache = null;
static {
sshLoadingCache = CacheBuilder.newBuilder()
.expireAfterAccess(5,TimeUnit.MINUTES)
.maximumSize(1000)
.removalListener(new RemovalListener<String, Connection>(){
@Override
public void onRemoval(RemovalNotification<String, Connection> removalNotification) {
if(!Objects.isNull(removalNotification.getValue())){
removalNotification.getValue().close();
removalNotification.setValue(null);
}
String key = removalNotification.getKey();
System.out.println("ip:" + key.substring(0,key.indexOf(',')) + " removed");
}
} )
.build(new CacheLoader<String, Connection>() {
@Override
public Connection load(String key) {
//从SQL或者NoSql 获取对象
//Iterable<String> split = Splitter.on(',').split(key);
String[] split = key.split(",");
String username = split.length == 3 ? split[2] : "root";
String password = split[1];
String ip = split[0];
Connection connection = new Connection(ip, 22);
boolean b = false;
try {
connection.addConnectionMonitor(v -> {
System.out.println(v);
});
b = connection.authenticateWithPassword(username, password);
if(b) {
return connection;
}else {
return null;
}
}catch (IOException e){
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}finally {
if(!b){
connection.close();
}
}
return null;
}
});
}
public static Connection getConnection(String ip,String password,String username){
String join = Joiner.on(',').skipNulls().join(ip, password, username);
try {
Connection connection = sshLoadingCache.get(join);
return connection;
}catch (ExecutionException e){
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
Connection root = SshConnectionUtil.getConnection("192.168.11.110", "123456", "root");
System.out.println(root);
}
}
更多推荐
已为社区贡献1条内容
所有评论(0)