はじめに
この資料は WebRTC Meetup Tokyo #21 のLT発表資料です。
(が、WebRTC成分はゼロです)
自己紹介
- インフォコム株式会社 がねこまさし
- @massie_g
- WebRTC Meetup Tokyo / Begginers Tokyo スタッフ
Cloud Run とは
- Cloud Run は Google Cloud Platform (GCP)の新しいサービス
- 自分で作ったコンテナを、Googleが用意したサーバー環境上で動かせる
- http(s) の口を持ったWebアプリ/Web APIサーバーを手軽に作れる
- スケーリングも勝手に面倒見てくれる
Cloud Run でできないこと
- コンテナを使っていても、できないことがある
- 単体ではステートを持てない
- データーの永続化はできない
→ 他のサービスを組み合わせて利用
※WebRTC的に気になること
- シグナリングサーバーに使えるのか? (WebSocketは使えるか?)
Cloud Run を使うには
- 準備
- コンテナのビルド
- コンテナのデプロイ
詳しくは別記事にて ... Google Cloud Run を使うまで
サンプルの準備
- シンプルな、1対1のビデオチャットのサンプル
- サーバー側(コンテナ)は、Webサーバーと、WebSocketサーバー機能を持つ
- Node.js + express + ws
- 同一ポートで、httpとwebsocketを使用
- PORT環境変数で指定されたポート番号を使用
サーバーのソースコードの抜粋
GitHubはこちら https://github.com/mganeko/webrtc_1to1
// --- get PORT from env --
let port = process.env.PORT;
// --- prepare server ---
const http = require("http");
const WebSocketServer = require('ws').Server;
const express = require('express');
const app = express();
app.use(express.static('public'));
let webServer = null;
const hostName = 'localhost';
// --- http ---
webServer = http.Server(app).listen(port, function () {
console.log('Web server start. http://' + hostName + ':' + webServer.address().port + '/');
});
// --- websocket signaling ---
const wsServer = new WebSocketServer({ server: webServer });
コンテナのビルド
Dockerfile
# Use the offical node.js image
FROM node:10.15.3-alpine
RUN mkdir /root/work
WORKDIR /root/work/
RUN apk add git
RUN git clone https://github.com/mganeko/webrtc_1to1.git
WORKDIR /root/work/webrtc_1to1
RUN npm install
# Run the web service on container startup.
EXPOSE 8080
CMD [ "node", "server_1to1.js" ]
※本当は node を直接起動するのは良くないらしい
「Docker node PID 1」で検索
ローカルでコンテナを実行
$ docker build -t mganeko/webrtc_1to1 .
$ docker run -d -e PORT=1323 -p 8002:1323 --name webrtc mganeko/webrtc_1to1
mganeko/webrtc_1to1 はイメージ名(適宜置き換えてください)
2つのブラウザで http://localhost:8002 に接続 → OK
Cloud Run で実行
$ gcloud builds submit --project cloud-run-webrtc1to1 --tag gcr.io/cloud-run-webrtc1to1/webrtc-1to1
$ gcloud beta run deploy --project cloud-run-webrtc1to1 --image gcr.io/cloud-run-webrtc1to1/webrtc-1to1
それぞれの値は適宜置き換えてください。
cloud-run-webrtc1to1 ... プロジェクトID
webrtc-1to1 ... サービス名
gcr.io/cloud-run-webrtc1to1/webrtc-1to1 ... イメージのURL
結果は NG
WebSocketが繋がらない (400 Bad Request)
Cloud Run の制約
- The container must listen for requests on 0.0.0.0 on the port defined by the PORT environment variable.
- Your container instances must start an HTTP server within 4 minutes after receiving a request.
どうやらHTTPのみ使えて、WebSocketは使えない
※(2021.02.07追記)CloudRunでWebSocketやHTTP/2, gRPCが使えるようになりました。
無理やりシグナリングするには
- HTTPで無理やり → Long Polling (COMET) しかない
自分で Log Polling 実装するにはどうすれば..?
あ、それって Socket.io がフォールバックでサポートしているはず!
Socket.io版サンプル
- シンプルな、1対1のビデオチャットのサンプル
- サーバー側(コンテナ)は、Webサーバーと、Socket.ioサーバー機能を持つ
- Node.js + express + socket.io
- 同一ポートで、httpとsocket.io(websocketとフォールバック)を使用
- PORT環境変数で指定されたポート番号を使用
サーバー側ソースコードの抜粋
// --- get PORT from env --
let port = process.env.PORT;
// --- prepare server ---
const http = require("http");
const express = require('express');
const app = express();
app.use(express.static('public'));
let webServer = null;
const hostName = 'localhost';
// --- http ---
webServer = http.Server(app).listen(port, function () {
console.log('Web server start. http://' + hostName + ':' + webServer.address().port + '/');
});
// --- socket.io server ---
const io = require('socket.io')(webServer);
console.log('socket.io server start. port=' + webServer.address().port);
結果
- websocket接続はエラー
- xhr poll でシグナリングはできる
時間があったらデモ
厳密には
- リクエストが増えると、自動的にスケールアウト
- デフォルト設定では 80
- 実運用では、同じインスタンスに繋がるとは限らない → シグナリングできない可能性あり
- 試しに同時リクエスト数を 1 に設定 → シグナリングできない
- ※どころか、コンソールの動きが一部おかしくなる??
シグナリングには、別の手段が順当
- リアルタイム通信サービスを使う (Firebase, milkcocoaなど)
- Cloud Run on GKE を使う(多分、行けるはず)
- Google App Engine を使う
- Standard Environment ... WebSocket NG
- Flexible Environment ... WebSocket OK
- Google Compute Engine や、他のIaaSを使う
- heroku も WebSocket 使える様子... Using WebSockets on Heroku with Node.js
ちなみに Google App Engine FE は IaaSより高い
まとめ
- Cloud Run 便利そう
- が、シグナリングザーバーには向いてない
どうもありがとうございました!