NebulaGraph的SessionPool使用过程中有时会出现如下异常:
Get sessionId[1747361254442548] failed: Session `1747361254442548’ not found: Session not existed!
主要原因在于NebulaGraph服务器端的Session有默认超时时间,长时间没有使用会被自动回收清理,可以通过graphd服务的session_timeout_ms参数查看或修改调整。NebulaGraph客户端尝试使用一个不存在的Session ID进行查询操作,便会导致出现以上的异常提示。
看了一下语句执行的源码,发现NebulaGraph的SessionPool在执行查询操作的时候,已经针对SessionError的异常情况增加了一次重试机制,避免异常的发生。
public String executeJsonWithParameter(String stmt, Map<String, Object> parameterMap)throws ClientServerIncompatibleException, AuthFailedException, IOErrorException, BindSpaceFailedException {stmtCheck(stmt);checkSessionPool();NebulaSession nebulaSession = getSession();String result;try {result = nebulaSession.executeJsonWithParameter(stmt, parameterMap);if (isSessionErrorForJson(result)) {sessionList.remove(nebulaSession);nebulaSession = getSession();result = nebulaSession.executeJsonWithParameter(stmt, parameterMap);}} catch (IOErrorException e) {if (e.getType() == IOErrorException.E_CONNECT_BROKEN) {sessionList.remove(nebulaSession);nebulaSession = getSession();result = nebulaSession.executeJsonWithParameter(stmt, parameterMap);return result;}useSpace(nebulaSession, null);throw e;}useSpaceForJson(nebulaSession, result);return result;
}
private boolean isSessionErrorForJson(String result) {if (result == null) {return true;}int code = JSON.parseObject(result).getJSONArray("errors").getJSONObject(0).getIntValue("code");return code == ErrorCode.E_SESSION_INVALID.getValue()|| code == ErrorCode.E_SESSION_NOT_FOUND.getValue()|| code == ErrorCode.E_SESSION_TIMEOUT.getValue();
}
针对这种情况可以考虑下面几个方式处理:
1、尝试增加重试次数,但是重试的次数不好确定,需要根据自身实际的情况确认。
public String executeJsonWithParameter(String stmt, Map<String, Object> parameterMap)throws ClientServerIncompatibleException, AuthFailedException, IOErrorException, BindSpaceFailedException {stmtCheck(stmt);checkSessionPool();NebulaSession nebulaSession = getSession();String result;try {result = nebulaSession.executeJsonWithParameter(stmt, parameterMap);int retrySessionCount = 0;while (isSessionErrorForJson(result) && retrySessionCount < 10) {long sessionID = nebulaSession.getSessionID();sessionList.remove(nebulaSession);nebulaSession = getSession();result = nebulaSession.executeJsonWithParameter(stmt, parameterMap);retrySessionCount++;log.debug("ng session error {} {} {}", sessionID, nebulaSession.getSessionID(), retrySessionCount);}} catch (IOErrorException e) {if (e.getType() == IOErrorException.E_CONNECT_BROKEN) {sessionList.remove(nebulaSession);nebulaSession = getSession();result = nebulaSession.executeJsonWithParameter(stmt, parameterMap);return result;}useSpace(nebulaSession, null);throw e;}useSpaceForJson(nebulaSession, result);return result;
}
2、SessionError的时候不再从sessionList里面取Session,而是每次都重新创建一个新的Session。
public String executeJsonWithParameter(String stmt, Map<String, Object> parameterMap)throws ClientServerIncompatibleException, AuthFailedException, IOErrorException, BindSpaceFailedException {stmtCheck(stmt);checkSessionPool();NebulaSession nebulaSession = getSession();String result;try {result = nebulaSession.executeJsonWithParameter(stmt, parameterMap);if (isSessionErrorForJson(result)) {long sessionID = nebulaSession.getSessionID();sessionList.remove(nebulaSession);nebulaSession = createSessionObject(SessionState.USED);result = nebulaSession.executeJsonWithParameter(stmt, parameterMap);log.debug("ng session error {} {}", sessionID, nebulaSession.getSessionID());}} catch (IOErrorException e) {if (e.getType() == IOErrorException.E_CONNECT_BROKEN) {sessionList.remove(nebulaSession);nebulaSession = getSession();result = nebulaSession.executeJsonWithParameter(stmt, parameterMap);return result;}useSpace(nebulaSession, null);throw e;}useSpaceForJson(nebulaSession, result);return result;
}