socket.ioのサーバをリモートで動かして技術検証がしたい。
サクッと動かせるsocket.ioに対応したサーバがないかな、と調べた時Herokuが対応している事を知りました。
Herokuの魅力としては制約はあるものの、なんといっても無料でsocket.ioサーバを試す事が出来るというところ!
この記事ではHerokuでsocket.ioのサーバを動かす方法を記載します。
検証した環境
1 | heroku | 7.60.2 |
ローカル環境を作成
まずローカルでsocket.ioサーバを立ち上げられるようにします。
以前書いた以下の記事のコードを使用します。
本題とそれるため要点のみ記載していきます。
まずsocket.ioサーバを動かすのに必要なパッケージを追加
$ yarn add express socket.io
app.js にsocket.ioを用いたsocket通信を行えるようにし、
const express = require('express')
const app = express()
const http = require('http')
const server = http.createServer(app)
const { Server } = require('socket.io')
const io = new Server(server)
const port = process.env.PORT || 8000
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html')
})
io.on('connection', socket => {
console.log('a user connected')
socket.on('my-event-a', message => {
console.log(`from client. ${message}`)
// 送信元も含めすべてのsocketに対してメッセージを送信する
io.sockets.emit('my-event-b', `from server. ${message}`)
})
})
server.listen(port, '0.0.0.0', (err, _) => {
if (err) throw err
console.log(`Example app listening on port ${port}`)
})
Herokuでの確認をしやすくするため、socket.ioでの通信を行えるhtmlファイルも追加します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>socket.io sample</title>
<script src="/socket.io/socket.io.js" ></script>
<script src="https://code.jquery.com/jquery-1.11.1.js" ></script>
<script>
var socket = io();
$(function(){
$('#form').submit(function(){
// inputに入力した内容を my-event-a という名前のイベントを送る
socket.emit('my-event-a', $('#input').val());
$('#input').val('');
return false;
});
// my-event-b という名前のイベントを受け取ったら li を作る
socket.on('my-event-b',function(msg){
$('#messages').append($('<li>').text(msg));
});
});
</script>
</head>
<body>
<ul id="messages"></ul>
<form id="form">
<input id="input" autocomplete="off" /><button>Send</button>
</form>
</body>
</html>
npm-scripts で動くようにしておきます
"scripts": {
"serve": "node app.js"
},
この状態でyarn run serve
でサーバを起動すればsocket通信が試せる状態になり、
http://localhost:3000/ にアクセスするかPostmanを使う事で簡単に試す事が出来ます!
以前の記事の動画そのまま貼っちゃいますが、
以下のようにPostmanでもsocket.ioを用いた通信が確認出来ます。
Herokuにデプロイする
Herokuが公式でsocket.ioを用いたサーバをデプロイする方法の記事を公開しています。
Node.js での Heroku の WebSocket の使用 | Heroku Dev Center
せっかくなので上記記事を参考にしつつ進めます。
Heroku CLIの用意
CLIを用いた方法が書かれているので、せっかくなのでHerokuのCLIを使ってみます。
CLIのインストール方法は同じく公式ページに記載があります
Heroku スターターガイド (Node.js) | Heroku Dev Center
$ brew install heroku/brew/heroku
インストール出来た事を確認
$ heroku -v
› Warning: Our terms of service have changed: https://dashboard.heroku.com/terms-of-service
heroku/7.60.2 darwin-x64 node-v14.19.0
warningが出ていますが、とりあえずインストールが出来たようなので先に進めます。
CLIでログインする
CLIとアカウントを紐付けるためCLIでログインします。
ログインが成功すると 「Logged in as <メールアドレス>」 というメッセージが表示されます。
# 実行して何かキーを謳歌するとブラウザが開いてログインすると Logged in メッセージが表示される
$ heroku login
heroku: Press any key to open up the browser to login or q to exit:
・・・
Logged in as <メールアドレス>
アプリをデプロイする
デプロイの仕方は公式のやり方を参考にします
Heroku スターターガイド (Node.js) | Heroku Dev Center
まずHerokuにアプリを作成します。
$ heroku create
Creating app... done, ⬢ sharp-xxxxxx-12345
・・・
このコマンドを実行するとコマンドを叩いたリポジトリとHerokuのアプリケーションが連携出来るようになります。
Heroku でアプリを作成すると、Heroku でソースコードを受け取ることができるよう準備できます。
アプリを作成すると、heroku という名前の git リモートリポジトリも作成され、ローカルの git リポジトリと関連付けられます。
公式で↑のように書かれていて、
Gitコマンドを確認すると確かに「heroku」というremoteブランチが出来ている事が分かります。
git remote -v
heroku https://git.heroku.com/sharp-xxxxxx-12345.git (fetch)
heroku https://git.heroku.com/sharp-xxxxxx-12345.git (push)
origin ssh://git@github.com/yuki-takara/xxxx.git (fetch)
origin ssh://git@github.com/yuki-takara/xxxx.git (push)
Procfileを追加
Herokuでは、プロジェクトのルートフォルダに Procfileを追加する事でHerokuにpushしたアプリケーションが起動時に実行するコマンドを指定することが出来ます。
詳細な説明は端折ってしまいますが、
今回は以下のように書く事でyarn run serve
が実行されてsocket.ioサーバが起動します。
web: yarn run serve
ここまで出来たらherokuにデプロイします!
「Verifying deploy… done.」と表示されれば成功です。
$ git push heroku main
・・・
remote: Verifying deploy... done.
最後にHerokuでsocket.ioを実施する記事に戻ります。
Node.js での Heroku の WebSocket の使用 | Heroku Dev Center
すると「セッションアフィニティ」というものを有効にするように、と書かれているため有効にします
$ heroku features:enable http-session-affinity
Enabling http-session-affinity for ⬢ sharp-xxxxxx-12345... done
ここまで実行してデプロイされたであろうURLを開くと
おっと、、エラーが、、、
エラーの対応
エラーの確認は上記画像に書かれているようにherokuのコマンドで確認が出来ます
$ heroku logs --tail
・・・
Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
↑のようなエラーメッセージが出ていました。
調べてみるとアプリケーションで設定しているポートがHerokuが設定するポートと違うのが問題の模様。
これは1行変更する事で対応が出来ました!
const port = process.env.PORT || 3000
Herokuではprocess.env.PORT
にHerokuが設定しているポート番号が環境変数で流れてくるんでしょうね。
これで再度デプロイするとページが開けるようになります!
↑ めちゃくちゃ分かりづらいんですが、
- 左: Postnam
- 右: Herokuにデプロイしたwebページ
です。
動画の8,9秒あたりでPostmanから投稿するとHerokuにデプロイしたwebページでもsocket通信を通じてメッセージを受信出来ていることが確認出来ます!