c46556e1f6
The idea is to run a loadbalancer node which maps each BBB node to a path. That way each user gets only one gUM permission query for a cluster. The loadbalancer node only serves the html5 client, each BBB node will serve its own API and handle the websockets for freeswitch and bbb-webrtc-sfu. Configuring a cluster setup =========================== * let bbb-lb.example.com be the loadbalancer node * let bbb-01.eaxmple.com be a BBB node Loadbalancer ------------ On the loadbalancer node add an nginx configuration similar to this one for each BBB node: ``` location /bbb-01/html5client/ { proxy_pass https://bbb-01.example.com/bbb-01/html5client/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; } ``` BBB Node -------- On the BBB node add the following options to `/etc/bigbluebutton/bbb-web.properties`: ``` defaultHTML5ClientUrl=https://bbb-lb.example.com/bbb-01/html5client/join presentationBaseURL=https://bbb-01.example.com/bigbluebutton/presentation accessControlAllowOrigin=https://bbb-lb.example.com ``` Add the following options to `/etc/bigbluebutton/bbb-html5.yml`: ``` public: app: basename: '/bbb-01/html5client' bbbWebBase: 'https://bbb-01.eaxmple.com/bigbluebutton' learningDashboardBase: 'https://bbb-01.eaxmple.com/learning-dashboard' media: stunTurnServersFetchAddress: 'https://bbb-01.eaxmple.com/bigbluebutton/api/stuns' sip_ws_host: 'bbb-01.eaxmple.com' presentation: uploadEndpoint: 'https://bbb-01.eaxmple.com/bigbluebutton/presentation/upload' ``` Create the following unit file overrides: * `/etc/systemd/system/bbb-html5-frontend@.service.d/cluster.conf` * `/etc/systemd/system/bbb-html5-backend@.service.d/cluster.conf` with the following content: ``` [Service] Environment=ROOT_URL=https://127.0.0.1/bbb-01/html5client ``` Change the nginx `$bbb_loadbalancer_node` variable to the name of the load balancer node in `/etc/bigbluebutton/nginx/loadbalancer.nginx` to allow CORS requests: ``` set $bbb_loadbalancer_node https://bbb-lb.example.com ``` Prepend the mount point of bbb-html5 in all location sections except from the `location @html5client` section in `/etc/bigbluebutton/nginx/bbb-html5.nginx` ``` location @html5client { ... } location /bbb-01/html5client/locales { ... } ```
81 lines
2.2 KiB
JavaScript
81 lines
2.2 KiB
JavaScript
import _ from 'lodash';
|
|
|
|
const MEDIA = Meteor.settings.public.media;
|
|
const STUN_TURN_FETCH_URL = MEDIA.stunTurnServersFetchAddress;
|
|
const CACHE_STUN_TURN = MEDIA.cacheStunTurnServers;
|
|
const FALLBACK_STUN_SERVER = MEDIA.fallbackStunServer;
|
|
|
|
let STUN_TURN_DICT;
|
|
let MAPPED_STUN_TURN_DICT;
|
|
|
|
const fetchStunTurnServers = function (sessionToken) {
|
|
if (STUN_TURN_DICT && CACHE_STUN_TURN) return Promise.resolve(STUN_TURN_DICT);
|
|
|
|
const handleStunTurnResponse = ({ stunServers, turnServers }) => {
|
|
if (!stunServers && !turnServers) {
|
|
return Promise.reject(new Error('Could not fetch STUN/TURN servers'));
|
|
}
|
|
|
|
const turnReply = [];
|
|
_.each(turnServers, (turnEntry) => {
|
|
const { password, url, username } = turnEntry;
|
|
turnReply.push({
|
|
urls: url,
|
|
password,
|
|
username,
|
|
});
|
|
});
|
|
|
|
const stDictionary = {
|
|
stun: stunServers.map(server => server.url),
|
|
turn: turnReply,
|
|
};
|
|
|
|
STUN_TURN_DICT = stDictionary;
|
|
|
|
return Promise.resolve(stDictionary);
|
|
};
|
|
|
|
const url = `${STUN_TURN_FETCH_URL}?sessionToken=${sessionToken}`;
|
|
return fetch(url, { credentials: 'include' })
|
|
.then(res => res.json())
|
|
.then(handleStunTurnResponse);
|
|
};
|
|
|
|
const mapStunTurn = ({ stun, turn }) => {
|
|
const rtcStuns = stun.map(url => ({ urls: url }));
|
|
const rtcTurns = turn.map(t => ({ urls: t.urls, credential: t.password, username: t.username }));
|
|
return rtcStuns.concat(rtcTurns);
|
|
};
|
|
|
|
const getFallbackStun = () => {
|
|
const stun = FALLBACK_STUN_SERVER ? [FALLBACK_STUN_SERVER] : [];
|
|
return { stun, turn: [] };
|
|
};
|
|
|
|
const getMappedFallbackStun = () => (FALLBACK_STUN_SERVER ? [{ urls: FALLBACK_STUN_SERVER }] : []);
|
|
|
|
const fetchWebRTCMappedStunTurnServers = function (sessionToken) {
|
|
return new Promise(async (resolve, reject) => {
|
|
try {
|
|
if (MAPPED_STUN_TURN_DICT && CACHE_STUN_TURN) {
|
|
return resolve(MAPPED_STUN_TURN_DICT);
|
|
}
|
|
|
|
const stDictionary = await fetchStunTurnServers(sessionToken);
|
|
|
|
MAPPED_STUN_TURN_DICT = mapStunTurn(stDictionary);
|
|
return resolve(MAPPED_STUN_TURN_DICT);
|
|
} catch (error) {
|
|
return reject(error);
|
|
}
|
|
});
|
|
};
|
|
|
|
export {
|
|
fetchStunTurnServers,
|
|
fetchWebRTCMappedStunTurnServers,
|
|
getFallbackStun,
|
|
getMappedFallbackStun,
|
|
};
|