Hutool Sftp 负载均衡踩坑记

踩坑背景

最近有个项目使用到了Sftp,部署的时候发现了一个奇怪的现象,当sftp通过ip直接连接的时候,程序是一切正常的,在使用运维给的LB地址时,老是会出现下面这个报错

cn.hutool.extra.ssh.JschRuntimeException: JschException: Session.connect: java.net.SocketException: Connection reset
    at cn.hutool.extra.ssh.JschUtil.openSession(JschUtil.java:116)
    at cn.hutool.extra.ssh.JschUtil.openSession(JschUtil.java:97)
    at cn.hutool.extra.ssh.JschSessionPool.lambda$getSession$64b21fc$1(JschSessionPool.java:45)
    at cn.hutool.core.lang.SimpleCache.get(SimpleCache.java:112)
    at cn.hutool.extra.ssh.JschUtil.getSession(JschUtil.java:55)
    at cn.hutool.extra.ssh.Sftp.init(Sftp.java:166)
    at cn.hutool.extra.ssh.Sftp.init(Sftp.java:93)
    at cn.hutool.extra.ssh.Sftp.init(Sftp.java:80)
    at cn.hutool.extra.ssh.Sftp.init(Sftp.java:70)
    at cn.hutool.extra.ssh.Sftp.init(Sftp.java:56)
    at 

报错的同时,在服务器上尝试使用命令行LB地址连接Sftp却是一切正常的!!!同时经过排查发现,当程序刚启动尝试第一次连接的时候并没有出现这个奇怪的问题,正当我看这个奇怪的堆栈百思不得其解的时候,突然注意到了一个奇怪的打印

at cn.hutool.core.lang.SimpleCache.get(SimpleCache.java:112)

经过排查发现,hutool的Sftp工具类是默认开启了一个JschSessionPool的连接池,默认的直接使用 new Sftp(…) 或者 JschUtil.getSession(…) 都会把新建立的连接放到 JschSessionPool 这个连接池中,而恰恰就是这个连接池导致的问题!!!

修改方案

如果你也是使用的hutool Sftp工具类且涉及一些比较复杂的网络场景,建议跳过Hutool的Sftp自带的连接池逻辑,改成直接使用 JschUtil.createSession(…) 手动建立连接并且手动释放,这种场景反而更好做一些细粒度的控制

教训总结

在使用一个工具类前,必须要大致了解其底层实现逻辑以及相关issue,避免老是踩前辈们踩过的坑!!!!!!!!!!

Linux上使用Selenium运行有头浏览器

通常我们服务器vps是没有安装gui显示的,但是为了避免使用无头浏览器(很容易被识别),我们可以用Xvfb。

Xvfb

Xvfb是一个实现 X11 显示服务器协议的显示服务器。该程序将允许您以“无头”模式运行任何应用程序。基本上,这个程序不会在物理屏幕上输出 GUI,而是创建一个虚拟帧缓冲区并在那里“显示”UI。

安装

sudo apt-get install xvfb

使用

先启动一个xvfb服务 指定id,然后我们启动项目时也指定这个id运行

 
export DISPLAY=:7 指定变量
Xvfb -ac $DISPLAY -screen 0 1280x1024x8 //比如这样 启动一个服务 指定虚拟id是7  
//然后直接运行就可以 会根据环境变量找到xvfb服务的
 java -jar xxxx.jar

可以尝试这个脚本使用 https://gist.github.com/tsl0922/ab8d370a85653c4354ad
最好的方式就是启动一个xvfb服务 这样就可以直接使用有头浏览器了
创建 一个脚本 xvfb.sh 内容如下
#!/bin/bash

XVFB=/usr/bin/Xvfb
XVFBARGS="$DISPLAY -ac -screen 0 1024x768x16"
PIDFILE=${HOME}/xvfb_${DISPLAY:1}.pid
case "$1" in
  start)
    echo -n "Starting virtual X frame buffer: Xvfb"
    /sbin/start-stop-daemon --start --quiet --pidfile $PIDFILE --make-pidfile --background --exec $XVFB -- $XVFBARGS
    echo "."
    ;;
  stop)
    echo -n "Stopping virtual X frame buffer: Xvfb"
    /sbin/start-stop-daemon --stop --quiet --pidfile $PIDFILE
    echo "."
    ;;
  restart)
    $0 stop
    $0 start
    ;;
  *)
  echo "Usage: /etc/init.d/xvfb {start|stop|restart}"
  exit 1
esac
exit 0

启动方式 
bash xvfb.sh start