diff --git a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java --- a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java +++ b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java @@ -1,5 +1,6 @@ /* * (C) Copyright 2017-2020 OpenVidu (https://openvidu.io) + * (C) Copyright 2021 Christian Mollekopf (mollekopf@kolabsystems.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -58,7 +59,9 @@ import io.openvidu.server.kurento.core.KurentoSessionEventsHandler; import io.openvidu.server.kurento.core.KurentoSessionManager; import io.openvidu.server.kurento.kms.DummyLoadManager; +import io.openvidu.server.kurento.kms.MaxWebRtcLoadManager; import io.openvidu.server.kurento.kms.FixedOneKmsManager; +import io.openvidu.server.kurento.kms.FixedNKmsManager; import io.openvidu.server.kurento.kms.KmsManager; import io.openvidu.server.kurento.kms.LoadManager; import io.openvidu.server.recording.DummyRecordingDownloader; @@ -105,9 +108,17 @@ if (openviduConfig.getKmsUris().isEmpty()) { throw new IllegalArgumentException("'KMS_URIS' should contain at least one KMS url"); } - String firstKmsWsUri = openviduConfig.getKmsUris().get(0); - log.info("OpenVidu Server using one KMS: {}", firstKmsWsUri); - return new FixedOneKmsManager(); + + List kmsUris = openviduConfig.getKmsUris(); + + if (kmsUris.size() == 1) { + String firstKmsWsUri = kmsUris.get(0); + log.info("OpenVidu Server using one KMS: {}", firstKmsWsUri); + return new FixedOneKmsManager(); + } + + log.info("OpenVidu Server using KMS: {}", kmsUris); + return new FixedNKmsManager(); } @Bean @@ -175,7 +186,7 @@ @Bean @ConditionalOnMissingBean public LoadManager loadManager() { - return new DummyLoadManager(); + return new MaxWebRtcLoadManager(10000); } @Bean diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/DummyLoadManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/DummyLoadManager.java --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/DummyLoadManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/DummyLoadManager.java @@ -24,4 +24,8 @@ return 1; } + @Override + public boolean allowMoreElements(Kms kms) { + return true; + } } diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/FixedNKmsManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/FixedNKmsManager.java new file mode 100644 --- /dev/null +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/FixedNKmsManager.java @@ -0,0 +1,76 @@ +/* + * (C) Copyright 2015 Kurento (http://kurento.org/) + * (C) Copyright 2021 Christian Mollekopf (mollekopf@kolabsystems.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.openvidu.server.kurento.kms; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.annotation.PostConstruct; + +import org.apache.commons.lang3.RandomStringUtils; +import org.kurento.client.KurentoClient; +import org.kurento.commons.exception.KurentoException; + +import io.openvidu.server.core.IdentifierPrefixes; + +public class FixedNKmsManager extends KmsManager { + + @Override + public List initializeKurentoClients(List kmsProperties, boolean disconnectUponFailure) throws Exception { + List kmss = new ArrayList<>(); + for (KmsProperties kmsProps : kmsProperties) { + KurentoClient kClient = null; + Kms kms = new Kms(kmsProps, loadManager); + try { + kClient = KurentoClient.create(kmsProps.getUri(), this.generateKurentoConnectionListener(kms.getId())); + this.addKms(kms); + kms.setKurentoClient(kClient); + + // TODO: This should be done in KurentoClient connected event + kms.setKurentoClientConnected(true); + kms.setTimeOfKurentoClientConnection(System.currentTimeMillis()); + + kmss.add(kms); + } catch (KurentoException e) { + log.error("KMS in {} is not reachable by OpenVidu Server", kmsProps.getUri()); + if (kClient != null) { + kClient.destroy(); + } + } + } + return kmss; + } + + @Override + @PostConstruct + protected void postConstructInitKurentoClients() { + try { + List kmsProps = new ArrayList<>(); + for (String kmsUri : this.openviduConfig.getKmsUris()) { + String kmsId = KmsManager.generateKmsId(); + kmsProps.add(new KmsProperties(kmsId, kmsUri)); + } + this.initializeKurentoClients(kmsProps, true); + } catch (Exception e) { + log.error("Shutting down OpenVidu Server"); + System.exit(1); + } + } + +} + diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java @@ -106,7 +106,7 @@ } public boolean allowMoreElements() { - return true; // loadManager.allowMoreElements(this); + return loadManager.allowMoreElements(this); } public boolean isKurentoClientConnected() { diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/KmsManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/KmsManager.java --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/KmsManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/KmsManager.java @@ -116,7 +116,7 @@ public synchronized Kms getLessLoadedConnectedAndRunningKms() throws NoSuchElementException { List kmsLoads = getKmsLoads().stream().filter(kmsLoad -> kmsLoad.kms.isKurentoClientConnected() - && mediaNodeStatusManager.isRunning(kmsLoad.kms.getId())).collect(Collectors.toList()); + && mediaNodeStatusManager.isRunning(kmsLoad.kms.getId()) && kmsLoad.kms.allowMoreElements()).collect(Collectors.toList()); if (kmsLoads.isEmpty()) { throw new NoSuchElementException(); } else { diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/LoadManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/LoadManager.java --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/LoadManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/LoadManager.java @@ -21,4 +21,5 @@ public double calculateLoad(Kms kms); -} \ No newline at end of file + public boolean allowMoreElements(Kms kms); +} diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/MaxWebRtcLoadManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/MaxWebRtcLoadManager.java new file mode 100644 --- /dev/null +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/MaxWebRtcLoadManager.java @@ -0,0 +1,57 @@ +/* + * (C) Copyright 2017-2019 OpenVidu (https://openvidu.io/) + * (C) Copyright 2021 Christian Mollekopf (mollekopf@kolabsystems.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package io.openvidu.server.kurento.kms; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MaxWebRtcLoadManager implements LoadManager { + private static final Logger log = LoggerFactory.getLogger(MaxWebRtcLoadManager.class); + + private int maxWebRtcPerKms; + + public MaxWebRtcLoadManager(int maxWebRtcPerKms) { + this.maxWebRtcPerKms = maxWebRtcPerKms; + } + + @Override + public double calculateLoad(Kms kms) { + int numWebRtcs = countWebRtcEndpoints(kms); + if (numWebRtcs > maxWebRtcPerKms) { + return 1; + } else { + return numWebRtcs / (double) maxWebRtcPerKms; + } + } + + @Override + public boolean allowMoreElements(Kms kms) { + return countWebRtcEndpoints(kms) < maxWebRtcPerKms; + } + + private synchronized int countWebRtcEndpoints(Kms kms) { + try { + return kms.getKurentoClient().getServerManager().getPipelines().size(); + } catch (Throwable e) { + log.warn("Error counting KurentoClient pipelines", e); + return 0; + } + } +} +