Compare commits

...

11 Commits
leak ... master

Author SHA1 Message Date
youys 23e23fc39c fix 2023-06-09 19:39:28 +08:00
youys 4f79c0350a fix 2023-06-09 18:50:20 +08:00
youys 9c9524f143 add error log 2023-06-09 18:38:30 +08:00
youys 05509e1b22 add error log 2023-06-09 16:19:58 +08:00
youys ab8d1e7884 fix 2023-06-08 18:58:15 +08:00
youys 946e95ca01 windows云主机唯一id,tpiID和envId更换位置 2023-06-08 18:54:20 +08:00
youys c2746343db 去掉延长时间接口调用 2023-06-07 18:23:19 +08:00
youys 58ce89db32 阿里云唯一id生成添加tpiType 2023-05-19 21:16:55 +08:00
youys 11f9a4def3 增加envId 2023-05-18 20:12:39 +08:00
weishao c0f3c001eb 如果webssh先收到请求 2023-02-08 18:05:27 +08:00
weishao 5515110795 gameid->myshixun_id 2022-12-23 20:20:22 +08:00
6 changed files with 108 additions and 165 deletions

View File

@ -14,6 +14,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.WebSocketSession;
import javax.annotation.Resource;
@ -62,6 +63,9 @@ public class EducoderGuacamoleWebSocketTunnelHandler extends GuacamoleWebSocketT
return tpiId + "-" + NumberUtils.toInt(position, 1);
}
public String generateUniqId(String envId, String tpiId, String tpiType) {
return tpiId + "-" + envId + "-" + tpiType;
}
@Override
GuacamoleTunnel createTunnel(WebSocketSession session) throws GuacamoleException {
Properties properties = new Properties();
@ -71,8 +75,10 @@ public class EducoderGuacamoleWebSocketTunnelHandler extends GuacamoleWebSocketT
e.printStackTrace();
}
String tpiID = properties.getProperty("tpiID");
String envId = properties.getProperty("envId");
String tpiType = properties.getProperty("tpiType");
//生成唯一键
String uniqId = generateUniqId(tpiID);
String uniqId = generateUniqId(envId, tpiID, tpiType);
WindowsInfo windowsInfo = getWindowsInfo(uniqId);
@ -94,7 +100,7 @@ public class EducoderGuacamoleWebSocketTunnelHandler extends GuacamoleWebSocketT
socket = new ConfiguredGuacamoleSocket(new InetGuacamoleSocket(guacamoleServer, guacamoleServerPort),
config);
}catch (Exception e){
e.printStackTrace();
logger.error("createTunnel is Exception uniqueId:{}", uniqId, e);
}
// Return a new tunnel which uses the connected socket

View File

@ -11,6 +11,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.*;
import java.util.concurrent.atomic.AtomicBoolean;
public abstract class GuacamoleWebSocketTunnelHandler implements WebSocketHandler, SubProtocolCapable {
/**
@ -65,62 +67,11 @@ public abstract class GuacamoleWebSocketTunnelHandler implements WebSocketHandle
}
Thread readThread = new Thread() {
AtomicBoolean flag = new AtomicBoolean(true);
@Override
public void run() {
StringBuilder buffer = new StringBuilder(BUFFER_SIZE);
GuacamoleReader reader = tunnel.acquireReader();
char[] readMessage;
try {
try {
// Attempt to read
while ((readMessage = reader.read()) != null) {
// Buffer message
buffer.append(readMessage);
// Flush if we expect to wait or buffer is getting
// full
if (!reader.available() || buffer.length() >= BUFFER_SIZE) {
session.sendMessage(new TextMessage(buffer));
buffer.setLength(0);
}
}
// No more data
String message = Integer.toString(GuacamoleStatus.SUCCESS.getGuacamoleStatusCode());
afterConnectionClosed(session,
new CloseStatus(GuacamoleStatus.SUCCESS.getWebSocketCode(), message));
}
// Catch any thrown guacamole exception and attempt
// to pass within the WebSocket connection, logging
// each error appropriately.
catch (GuacamoleClientException e) {
logger.info("WebSocket connection terminated: {}", e.getMessage());
logger.debug("WebSocket connection terminated due to client error.", e);
String message = Integer.toString(e.getStatus().getGuacamoleStatusCode());
afterConnectionClosed(session, new CloseStatus(e.getStatus().getWebSocketCode(), message));
} catch (GuacamoleConnectionClosedException e) {
logger.debug("Connection to guacd closed.", e);
String message = Integer.toString(GuacamoleStatus.SUCCESS.getGuacamoleStatusCode());
afterConnectionClosed(session,
new CloseStatus(GuacamoleStatus.SUCCESS.getWebSocketCode(), message));
} catch (GuacamoleException e) {
logger.error("Connection to guacd terminated abnormally: {}", e.getMessage());
logger.debug("Internal error during connection to guacd.", e);
String message = Integer.toString(e.getStatus().getGuacamoleStatusCode());
afterConnectionClosed(session, new CloseStatus(e.getStatus().getWebSocketCode(), message));
}
} catch (Exception e) {
logger.debug("I/O error prevents further reads.", e);
}
process(session, flag);
}
};
@ -182,4 +133,68 @@ public abstract class GuacamoleWebSocketTunnelHandler implements WebSocketHandle
return false;
}
}
private void process(WebSocketSession session, AtomicBoolean flag) {
if (flag.get()) {
StringBuilder buffer = new StringBuilder(BUFFER_SIZE);
GuacamoleReader reader = tunnel.acquireReader();
char[] readMessage;
try {
try {
// Attempt to read
while ((readMessage = reader.read()) != null) {
// Buffer message
buffer.append(readMessage);
// Flush if we expect to wait or buffer is getting
// full
if (!reader.available() || buffer.length() >= BUFFER_SIZE) {
session.sendMessage(new TextMessage(buffer));
buffer.setLength(0);
}
}
// No more data
String message = Integer.toString(GuacamoleStatus.SUCCESS.getGuacamoleStatusCode());
afterConnectionClosed(session,
new CloseStatus(GuacamoleStatus.SUCCESS.getWebSocketCode(), message));
}
// Catch any thrown guacamole exception and attempt
// to pass within the WebSocket connection, logging
// each error appropriately.
catch (GuacamoleClientException e) {
logger.info("WebSocket connection terminated: {}", e.getMessage());
String message = Integer.toString(e.getStatus().getGuacamoleStatusCode());
afterConnectionClosed(session, new CloseStatus(e.getStatus().getWebSocketCode(), message));
} catch (GuacamoleConnectionClosedException e) {
logger.error("Connection to guacd closed.", e);
if(flag.getAndSet(false)) {
process(session, flag);
}else {
String message = Integer.toString(GuacamoleStatus.SUCCESS.getGuacamoleStatusCode());
afterConnectionClosed(session,
new CloseStatus(GuacamoleStatus.SUCCESS.getWebSocketCode(), message));
}
} catch (GuacamoleException e) {
logger.error("Connection to guacd terminated abnormally ", e);
if(flag.getAndSet(false)) {
process(session, flag);
}else{
String message = Integer.toString(e.getStatus().getGuacamoleStatusCode());
afterConnectionClosed(session, new CloseStatus(e.getStatus().getWebSocketCode(), message));
}
}
} catch (Exception e) {
logger.debug("I/O error prevents further reads.", e);
}
}
}
}

View File

@ -50,6 +50,12 @@ public class RunOnlyHandler extends TextWebSocketHandler {
JSONObject msg = JSON.parseObject(payload);
if (LOG_TYPE.equals(msg.getString(TYPE))) {
String runOnlyResultKey = RUN_ONLY_RESULT_KEY_PREFIX + msg.getString(DATA);
// webssh先收到请求需要等待一会
int i = 0;
while (!redisHelper.hasKey(runOnlyResultKey) && i < 5 * 10) {
ThreadUtil.sleepSilently(100);
i++;
}
String runOnlyResult = redisHelper.get(runOnlyResultKey);
while (CASE_OUTPUT_SEPARATOR.equals(runOnlyResult) && redisHelper.hasKey(runOnlyResultKey)) {
ThreadUtil.sleepSilently(100);

View File

@ -1,86 +1,21 @@
package net.educoder.bridge.webssh.model;
import lombok.Data;
@Data
public class ConnectInfo {
private String host;
private String port;
private String username;
private String secret;
private String gameid;
private String myshixun_id;
private int rows;
private int columns;
private int width;
private int height;
public int getRows() {
return rows;
}
public void setRows(int rows) {
this.rows = rows;
}
public int getColumns() {
return columns;
}
public void setColumns(int columns) {
this.columns = columns;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return Integer.parseInt(port);
}
public void setPort(String port) {
this.port = port;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public String getGameid() {
return gameid;
}
public void setGameid(String gameid) {
this.gameid = gameid;
public String getTpiID() {
return myshixun_id;
}
}

View File

@ -29,11 +29,7 @@ import net.educoder.bridge.common.utils.Base64Util;
@Service
public class JchService {
@Autowired
private WebsshService websshService;
@Autowired
private WebsshOverTimeService overTimeService;
private static List<WebscoketObj> sessionQueue = new CopyOnWriteArrayList<>();
private Logger logger = LoggerFactory.getLogger(getClass());
@ -70,22 +66,19 @@ public class JchService {
/**
* 处理客户端发过来的数据
*
*
* @param buffer
*/
public void recv(String buffer, WebSocketSession session) {
logger.debug("webssh收到数据{}", buffer);
WebscoketObj webscoketObj = findBySession(session);
boolean overtime = Boolean.FALSE;
try {
// logger.debug("recv函数进程{},sessionID:{},信息:{}",
// Thread.currentThread().getId(), session.getId(), buffer);
JSONObject object = JSONObject.parseObject(buffer);
String tp = object.getString("tp");
if ("init".equals(tp)) {
// 初始化连接
// {"tp":"init","data":{"host":"106.75.96.108","port":"41080","username":"root","secret":"123123","gameid":"1080","rows":"30"}}
// {"tp":"init","data":{"host":"106.75.96.108","port":"41080","username":"root","secret":"123123","myshixun_id":"1080","rows":"30"}}
ConnectInfo connectInfo = object.getObject("data", ConnectInfo.class);
if (webscoketObj != null) {
WebscoketObj finalWebscoketObj = webscoketObj;
@ -98,7 +91,6 @@ public class JchService {
});
}
} else if ("client".equals(tp)) {
overtime = Boolean.TRUE;
String data = object.getString("data");
if (webscoketObj != null) {
transTossh(webscoketObj.getOutputStream(), data);
@ -114,12 +106,10 @@ public class JchService {
connectInfo.getWidth(), connectInfo.getHeight());
}
} else if ("overtime".equals(tp)) {
overtime = Boolean.TRUE;
ConnectInfo connectInfo = webscoketObj.getConnectInfo();
if (webscoketObj.getConnectInfo() != null) {
logger.info("前端主动延长pod存活时间, websocket:{}, tpiID:{},host:{},端口:{}", session.getId(),
connectInfo.getGameid(), connectInfo.getHost(), connectInfo.getPort());
}
logger.info("前端主动延长pod存活时间, 不需要通过此接口进行延长了:{}, tpiID:{},host:{},端口:{}", session.getId(),
connectInfo.getTpiID(), connectInfo.getHost(), connectInfo.getPort());
}
} catch (Exception e) {
logger.error("转发 websocket {}命令到ssh出错: ", session.getId(), e);
@ -127,15 +117,7 @@ public class JchService {
closeByWebsocket(session);
}
// 延长pod存活时间
try {
if (webscoketObj.getConnectInfo() != null && overtime) {
String gameId = webscoketObj.getConnectInfo().getGameid();
overTimeService.websshOverTime(gameId);
}
} catch (Exception e) {
logger.error("pod 接收消息出错", e);
}
}
private void transTossh(OutputStream outputStream, String data) throws IOException {
@ -146,7 +128,7 @@ public class JchService {
}
private void connectTossh(WebscoketObj webscoketObj, ConnectInfo connectInfo, WebSocketSession webSocketSession) {
Session session = null;
Session session = null;
try {
JSch jsch = new JSch();
JSch.setLogger(jschLogger);
@ -154,7 +136,7 @@ public class JchService {
// 启动线程
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session = jsch.getSession(connectInfo.getUsername(), connectInfo.getHost(), connectInfo.getPort());
session = jsch.getSession(connectInfo.getUsername(), connectInfo.getHost(), Integer.parseInt(connectInfo.getPort()));
session.setConfig(config);
session.setPassword(connectInfo.getSecret());
@ -208,8 +190,7 @@ public class JchService {
webscoketObj.setConnectInfo(connectInfo);
websshService.active("" + connectInfo.getGameid());
logger.info("websocket {} open连接: tpiId:{},host:{},端口:{}", webSocketSession.getId(), connectInfo.getGameid(),
logger.info("websocket {} open连接: tpiId:{},host:{},端口:{}", webSocketSession.getId(), connectInfo.getTpiID(),
connectInfo.getHost(), connectInfo.getPort());
// 循环读取
@ -220,7 +201,7 @@ public class JchService {
String str = webSocketSession.isOpen() ? "is not" : "is";
str = webscoketObj.getSession().getId() + " " + str;
str = String.format("websocket %s closed.ssh读取终止连接: tpiId:%s,host:%s,端口:%s", str,
connectInfo.getGameid(), connectInfo.getHost(), connectInfo.getPort());
connectInfo.getTpiID(), connectInfo.getHost(), connectInfo.getPort());
if (webSocketSession.isOpen()) {
logger.error(str);
} else {
@ -232,7 +213,7 @@ public class JchService {
}
} catch (Exception e) {
logger.error("连接关闭: websocketId:" + webscoketObj.getSession().getId() + ", tpiId:" + connectInfo.getGameid()
logger.error("连接关闭: websocketId:" + webscoketObj.getSession().getId() + ", tpiId:" + connectInfo.getTpiID()
+ ", host:" + connectInfo.getHost() + ",端口: " + connectInfo.getPort(), e);
} finally {
if (session != null) {
@ -294,7 +275,7 @@ public class JchService {
}
this._close(webscoketObj);
}
public void closeByWebsocket(WebSocketSession session) {
WebscoketObj webscoketObj = findBySession(session);
sessionQueue.remove(webscoketObj);
@ -303,20 +284,20 @@ public class JchService {
return;
} else {
ConnectInfo info = webscoketObj.getConnectInfo();
logger.info("websocket {}连接中断 tpiId {} ", session.getId(), info.getGameid());
logger.info("websocket {}连接中断 tpiId {} ", session.getId(), info.getTpiID());
this._close(webscoketObj);
}
}
/**
* 通过gameId来匹配
*
*
* @param gameId
*/
public int findExistConnectByGameId(String gameId) {
long count = sessionQueue.stream().filter(webscoketObj -> webscoketObj.getConnectInfo() != null
&& gameId.equals(webscoketObj.getConnectInfo().getGameid())).count();
&& gameId.equals(webscoketObj.getConnectInfo().getTpiID())).count();
logger.debug("当前gameID对应的websocket数目{}", count);
return (int) count;
}

View File

@ -9,12 +9,12 @@ import javax.annotation.PostConstruct;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@Service
//@Service
public class WebsshOverTimeService {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
// @Autowired
private WebsshService websshService;
private static ConcurrentHashMap<String, String> recvGameIdMap = new ConcurrentHashMap<>();
@ -45,7 +45,7 @@ public class WebsshOverTimeService {
}
if (recvGameIds.length() > 0) {
recvGameIds.setLength(recvGameIds.length() - 1);
websshService.overTime(recvGameIds.toString());
// websshService.overTime(recvGameIds.toString());
}
} catch (Exception e) {
logger.error("发送接收到websocket消息 tpi失败", e);