Disconnected kurento websocket

hello
i have on-perimise openvidu 2.29 with 16 gig ram and 16 core cpu and when more than 40 participants join in a session i see this error

[WARN] 2025-01-20 08:49:02,473 [SessionHandler-16q3flqqclas80bk8q7oj67u47-e418-t0] io.openvidu.server.kurento.endpoint.PublisherEndpoint - EP str_CAM_K8JW_con_Fz29uNkaSG: Elements failed connecting (source 39bba06c-75d9-4464-85a8-d67ba1b34ca2_kurento.MediaPipeline/89f2f13e-83db-4657-89b2-5837e88f7ab1_kurento.PassThrough → sink 39bba06c-75d9-4464-85a8-d67ba1b34ca2_kurento.MediaPipeline/303c0092-32d8-4181-a831-0ce1b24d961e_kurento.WebRtcEndpoint)
java.lang.IllegalStateException: JsonRpcClient is disconnected from WebSocket server at ‘ws://localhost:8888/kurento’
at org.kurento.jsonrpc.client.JsonRpcClientNettyWebSocket.sendTextMessage(JsonRpcClientNettyWebSocket.java:171)
at org.kurento.jsonrpc.client.AbstractJsonRpcClientWebSocket.internalSendRequestWebSocket(AbstractJsonRpcClientWebSocket.java:427)
at org.kurento.jsonrpc.client.AbstractJsonRpcClientWebSocket$1.internalSendRequest(AbstractJsonRpcClientWebSocket.java:134)
at org.kurento.jsonrpc.internal.JsonRpcRequestSenderHelper.sendRequest(JsonRpcRequestSenderHelper.java:113)
at org.kurento.jsonrpc.client.JsonRpcClient.sendRequest(JsonRpcClient.java:128)
at org.kurento.client.internal.transport.jsonrpc.RomClientJsonRpcClient.sendRequest(RomClientJsonRpcClient.java:232)
at org.kurento.client.internal.transport.jsonrpc.RomClientJsonRpcClient.invoke(RomClientJsonRpcClient.java:117)
at org.kurento.client.internal.client.RomManager.invoke(RomManager.java:167)
at org.kurento.client.internal.client.RemoteObject.invoke(RemoteObject.java:206)
at org.kurento.client.internal.client.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:170)
at org.kurento.client.internal.client.RemoteObjectInvocationHandler.internalInvoke(RemoteObjectInvocationHandler.java:139)
at org.kurento.client.internal.client.DefaultInvocationHandler.invoke(DefaultInvocationHandler.java:39)
at com.sun.proxy.$Proxy90.connect(Unknown Source)
at io.openvidu.server.kurento.endpoint.PublisherEndpoint.internalSinkConnect(PublisherEndpoint.java:459)
at io.openvidu.server.kurento.endpoint.PublisherEndpoint.connect(PublisherEndpoint.java:207)
at io.openvidu.server.kurento.endpoint.SubscriberEndpoint.subscribe(SubscriberEndpoint.java:72)
at io.openvidu.server.kurento.core.KurentoParticipant.receiveMedia(KurentoParticipant.java:283)
at io.openvidu.server.kurento.core.KurentoSessionManager.subscribe(KurentoSessionManager.java:696)
at io.openvidu.server.rpc.RpcHandler.receiveVideoFrom(RpcHandler.java:425)
at io.openvidu.server.rpc.RpcHandler.handleRequest(RpcHandler.java:149)
at org.kurento.jsonrpc.internal.JsonRpcHandlerManager.handleRequest(JsonRpcHandlerManager.java:142)
at org.kurento.jsonrpc.internal.server.ProtocolManager$3.run(ProtocolManager.java:218)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
[INFO] 2025-01-20 08:49:02,473 [SessionHandler-16q3flqqclas80bk8q7oj67u47-e418-t0] io.openvidu.server.kurento.core.KurentoParticipant - PARTICIPANT con_MwRex1ttMp: Is now receiving video from con_Fz29uNkaSG in room 3861
[WARN] 2025-01-20 08:49:02,473 [SessionHandler-hlq1d1a43i53ev1k0fo69sm473-e520-t0] io.openvidu.se

It could be related to network conditions.

Does it always happen with that number of participants?

We held several testing meetings. Our sessions include 8 publishers, and other users are subscribers. In the last test, 40 participants joined. Once the number of participants exceeded 30, the service encountered an issue, and no user could join the session. After about 5 minutes, some users were able to join the session. However, when the number of users reached 40, no one else could join, and the issue was not resolved. As a result, we had to cancel the test and i monitor server cpu and network bandwidth both is OK.
If you need more logs or additional details, please let us know.

Hi
I have the same issue. do you have any suggestion @cruizba?

java.lang.UnsupportedOperationException: JsonNull
at com.google.gson.JsonElement.getAsString(JsonElement.java:179) ~[gson-2.8.9.jar!/:na]
at io.openvidu.java.client.Connection.lambda$resetWithJson$7(Connection.java:399) ~[openvidu-java-client-2.29.0.jar!/:na]
at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na]
at io.openvidu.java.client.Connection.resetWithJson(Connection.java:397) ~[openvidu-java-client-2.29.0.jar!/:na]
at io.openvidu.java.client.Connection.(Connection.java:51) ~[openvidu-java-client-2.29.0.jar!/:na]
at io.openvidu.java.client.Session.lambda$resetWithJson$3(Session.java:753) ~[openvidu-java-client-2.29.0.jar!/:na]
at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na]
at io.openvidu.java.client.Session.resetWithJson(Session.java:750) ~[openvidu-java-client-2.29.0.jar!/:na]
at io.openvidu.java.client.Session$4.handleResponse(Session.java:280) ~[openvidu-java-client-2.29.0.jar!/:na]
at io.openvidu.java.client.Session$4.handleResponse(Session.java:275) ~[openvidu-java-client-2.29.0.jar!/:na]
at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:202) ~[httpclient5-5.1.4.jar!/:5.1.4]
at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:143) ~[httpclient5-5.1.4.jar!/:5.1.4]
at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:117) ~[httpclient5-5.1.4.jar!/:5.1.4]
at io.openvidu.java.client.Session.fetch(Session.java:295) ~[openvidu-java-client-2.29.0.jar!/:na]
at io.openvidu.java.client.Session$8.handleResponse(Session.java:687) ~[openvidu-java-client-2.29.0.jar!/:na]
at io.openvidu.java.client.Session$8.handleResponse(Session.java:660) ~[openvidu-java-client-2.29.0.jar!/:na]
at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:202) ~[httpclient5-5.1.4.jar!/:5.1.4]
at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:143) ~[httpclient5-5.1.4.jar!/:5.1.4]
at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:117) ~[httpclient5-5.1.4.jar!/:5.1.4]
at io.openvidu.java.client.Session.getSessionHttp(Session.java:706) ~[openvidu-java-client-2.29.0.jar!/:na]
at io.openvidu.java.client.Session.(Session.java:69) ~[openvidu-java-client-2.29.0.jar!/:na]
at io.openvidu.java.client.OpenVidu.createSession(OpenVidu.java:248) ~[openvidu-java-client-2.29.0.jar!/:na]
at ir.template.controlmeeting.service.OpenViduServiceImpl.createSession(OpenViduServiceImpl.java:160) ~[classes!/:na]

error is here: 

protected Connection resetWithJson(JsonObject json) {

	this.connectionId = json.get("connectionId").getAsString();
	this.status = json.get("status").getAsString();
	this.token = !json.get("token").isJsonNull() ? json.get("token").getAsString() : null;

	if (!json.get("publishers").isJsonNull()) {
		JsonArray jsonArrayPublishers = json.get("publishers").getAsJsonArray();

		// 1. Set to store fetched publishers and later remove closed ones
		Set<String> fetchedPublisherIds = new HashSet<>();
		jsonArrayPublishers.forEach(publisherJsonElement -> {

			JsonObject publisherJson = publisherJsonElement.getAsJsonObject();
			Publisher publisherObj = new Publisher(publisherJson);
			String id = publisherObj.getStreamId();
			fetchedPublisherIds.add(id);

			// 2. Update existing Publisher
			this.publishers.computeIfPresent(id, (pId, p) -> {
				p = p.resetWithJson(publisherJson);
				return p;
			});

			// 3. Add new Publisher
			this.publishers.computeIfAbsent(id, pId -> {
				return publisherObj;
			});
		});

		// 4. Remove closed connections from local collection
		this.publishers.entrySet().removeIf(entry -> !fetchedPublisherIds.contains(entry.getValue().getStreamId()));
	}

	if (!json.get("subscribers").isJsonNull()) {
		JsonArray jsonArraySubscribers = json.get("subscribers").getAsJsonArray();

		// 1. Array to store fetched Subscribers and later remove closed ones
		Set<String> fetchedSubscriberIds = new HashSet<>();
		jsonArraySubscribers.forEach(subscriber -> {

			String sub = subscriber.getAsJsonObject().get("streamId").getAsString();
			fetchedSubscriberIds.add(sub);

			if (!this.subscribers.contains(sub)) {
				// 2. Add new Subscriber
				this.subscribers.add(sub);
			}
		});

		// 3. Remove closed Subscribers from local collection
		this.subscribers.removeIf(subId -> !fetchedSubscriberIds.contains(subId));
	}

	if (!json.get("createdAt").isJsonNull()) {
		this.createdAt = json.get("createdAt").getAsLong();
	}
	if (!json.get("activeAt").isJsonNull()) {
		this.activeAt = json.get("activeAt").getAsLong();
	}
	if (!json.get("location").isJsonNull()) {
		this.location = json.get("location").getAsString();
	}
	if (!json.get("ip").isJsonNull()) {
		this.ip = json.get("ip").getAsString();
	}
	if (!json.get("platform").isJsonNull()) {
		this.platform = json.get("platform").getAsString();
	}
	if (!json.get("clientData").isJsonNull()) {
		this.clientData = json.get("clientData").getAsString();
	}

	// COMMON
	ConnectionType type = ConnectionType.valueOf(json.get("type").getAsString());
	String data = (json.has("serverData") && !json.get("serverData").isJsonNull())
			? json.get("serverData").getAsString()
			: null;
	Boolean record = (json.has("record") && !json.get("record").isJsonNull()) ? json.get("record").getAsBoolean()
			: null;

	// WEBRTC
	OpenViduRole role = (json.has("role") && !json.get("role").isJsonNull())
			? OpenViduRole.valueOf(json.get("role").getAsString())
			: null;

	List<IceServerProperties> customIceServers = new ArrayList<>();
	if (json.has("customIceServers") && json.get("customIceServers").isJsonArray()) {
		JsonArray customIceServersJsonArray = json.get("customIceServers").getAsJsonArray();
		customIceServersJsonArray.forEach(iceJsonElem -> {
			JsonObject iceJsonObj = iceJsonElem.getAsJsonObject();
			String url = (iceJsonObj.has("url") && !iceJsonObj.get("url").isJsonNull())
					? iceJsonObj.get("url").getAsString()
					: null;
			String username = (iceJsonObj.has("username") && !iceJsonObj.get("username").isJsonNull())
					? iceJsonObj.get("username").getAsString()
					: null;
			String credential = (iceJsonObj.has("credential") && !iceJsonObj.get("credential").isJsonNull())
					? iceJsonObj.get("credential").getAsString()
					: null;
			customIceServers.add(
					new IceServerProperties.Builder().url(url).username(username).credential(credential).build());
		});
	}

	// IPCAM
	String rtspUri = (json.has("rtspUri") && !json.get("rtspUri").isJsonNull()) ? json.get("rtspUri").getAsString()
			: null;
	Boolean adaptativeBitrate = (json.has("adaptativeBitrate") && !json.get("adaptativeBitrate").isJsonNull())
			? json.get("adaptativeBitrate").getAsBoolean()
			: null;
	Boolean onlyPlayWithSubscribers = (json.has("onlyPlayWithSubscribers")
			&& !json.get("onlyPlayWithSubscribers").isJsonNull())
					? json.get("onlyPlayWithSubscribers").getAsBoolean()
					: null;
	Integer networkCache = (json.has("networkCache") && !json.get("networkCache").isJsonNull())
			? json.get("networkCache").getAsInt()
			: null;

	this.connectionProperties = new ConnectionProperties(type, data, record, role, null, rtspUri, adaptativeBitrate,
			onlyPlayWithSubscribers, networkCache, customIceServers);

	return this;
}

exactly at this line:
String sub = subscriber.getAsJsonObject().get(“streamId”).getAsString();