22
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

websocket_railsのaws ec2環境での通信設定

Posted at

railsでwebsocketを使用する場合、websocket_railsという便利なgemがあります。
これを使ってみましたが、awsのcentosの本番環境での通信設定に半日ぐらい要してしまいました。
少しややっこしいので、手順等、残しておきます。

ローカル接続確認

まずはローカルでのwebsocket_railsの接続確認。

Gemfileに gem ‘websocket-rails’を追記して、bundle installを実行。

Gemfile追記
gem 'thin'
gem 'websocket-rails', github: 'moaa/websocket-rails', branch: 'sync_fixes'
gem 'redis', '3.2.0'

次にwebsocket-railsに必要なファイルをgenerate。

rails g websocket_rails:install

以下のファイルがgenerateされる。

  • config/events.rb
    railsのroutes.rbような物。websocketのイベントのマッピングで使用します。

  • config/initializers/websocket_raiils.rb
    websocket_raiilsのセットアップ用。

  • app/assets/javascripts/application.js
    websocket_railsに必要な
    //= require websocket_rails/main
    が追記される

websocket確認用のサンプルで下記のような簡単なをhtml作成

html
<div ng-view="" class="ng-scope">
<textarea rows="5" style="width: 50%;" ng-model="testMsg" class="ng-valid ng-scope ng-dirty ng-valid-parse ng-touched"></textarea>
<br class="ng-scope">
<button type="button" class="btn btn-default ng-scope" ng-click="testSend()">送 信/button>
<br class="ng-scope">
<label class="ng-scope">受信メッセージ</label>
<br class="ng-scope">
<p ng-bind="reciveModel.reciveMsg" class="ng-binding ng-scope"></p>
<label class="ng-scope">入力内容</label>
<br class="ng-scope">
<p ng-bind="testMsg" class="ng-binding ng-scope"></p>
</div>

スクリーンショット 2015-08-04 9.26.39.png

javascriptにWebSocketRailsの接続、送信、受信処理を記述

angularjsを使用
// WebSocketRailsが初期化されてないければ初期化して接続
if ($rootScope.wsRails == undefined ||
    $rootScope.wsRails == null) {
  try {
    $rootScope.wsRails = new WebSocketRails("127.0.0.1:3001/websocket");		
  } catch (e) {
    alert("error");
  }
};

// websocketの受信イベントのバインド
$rootScope.wsRails.unbind();
$rootScope.wsRails.bind("websocket_chat", function(message){
  $scope.reciveModel.reciveMsg = message;
  $scope.$apply();
});

// テスト送信処理
$scope.testSend = function() {
  $rootScope.wsRails.trigger("websocket_chat", $scope.testMsg);
};

config/events.rbに「websocket_chat」イベントのマッピングを設定。

events.rb
subscribe :websocket_chat, to: WebsocketChatController, with_method: :message_recieve

railsのコントローラーにwebsocket_chat_controller.rbを追加

websocket_chat_controller.rb
class WebsocketChatController < WebsocketRails::BaseController
  def message_recieve
    # クライアントからのメッセージを取得
    recieve_message = message()
    
    # websocket_chatイベントで接続しているクライアントにブロードキャスト
    broadcast_message(:websocket_chat, recieve_message)
  end
end

ここまでやってrailsを起動しても、下記のようなエラーが出る。

/Users/qq/Documents/workspace/fesny/vendor/bundle/ruby/2.0.0/gems/redis-3.2.0/lib/redis/client.rb:320:in `rescue in establish_connection': Error con
necting to Redis on localhost:6379 (ECONNREFUSED) (Redis::CannotConnectError)

Redisに繋がらないといっているので、osxにRedisを入れます。

Homebrewを利用してインストール

brew install redis

起動

 redis-server /usr/local/etc/redis.conf

接続確認

redis-cli

Redisをインストール、起動した後にrailsを起動すると、正常に起動。
だけど、websocketの接続に失敗している。

WebSocket connection to 'ws://127.0.0.1:3001/websocket' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED

なぜかなあと調べていたところ、githubのwebsocket-railsにStandalone-Server-Modeで起動せよという記述を発見。
https://github.com/websocket-rails/websocket-rails/wiki/Standalone-Server-Mode

thinで開発環境でやる場合でもStandalone-Server-Modeでやらないといけないのだろうか?
よく分からないが実行してみる事に。。

config/initializers/websocket_rails.rbを下記設定に変更。

websocket_rails.rb
  config.standalone = true
  config.standalone_port = 3001
  config.redis_options = {driver: :ruby}
  config.synchronize = false
  config.redis_options = {:host => 'localhost', :port => '6379'}

websocket_railsの起動

sudo rake websocket_rails:start_server

websocket_railsの停止

sudo rake websocket_rails:stop_server

websocket_railsの起動確認

ps aux | grep websocket
root            6703   2.4  2.2  3125404  93444   ??  S    10:09AM   0:04.89 thin server (0.0.0.0:3001) [websocket_rails]  

websocket_railsが起動している状態で、動かしてみると、WebSocketが正常に動いた。

この後、本番環境でも確認してみる事に。
本番でうまく環境構築できなければ、開発が無駄になってしまうので。。

本番接続確認

本番環境はaws ec2でcentos用のディストリビューションを使用し、OSバージョンは7.1で、webサーバーはnginxです。
すでにrailsの別のプロダクトで運用中の為、バーチャルドメインで配置して、railsもデプロイします。

その後、redisが入っていない為、yumインストール

yum install redis

redisの起動

systemctl start redis

接続確認

redis-cli

railsの起動(unicorn)、websocket_railsの起動を行う。
特にエラーは発生せず、ログの「log/websocket_rails_server.log」、「log/websocket_rails.log」にもエラーははかれていない。
しかし、javascriptのwebscoketの接続部分でエラーが発生している。
ここから半日ぐらいハマりました。

まずjavascriptのサーバーのIPが127.0.0.1のままになっていたので、修正。

$rootScope.wsRails = new WebSocketRails("サーバーIP:3001/websocket");

次にawsのインバウンドポートの3001を開ける。
これでもまだ接続エラー。

ポートをサーバーサイドで確認すると3001はthinが待ち受けしている模様。

netstat -tanp
tcp        0      0 0.0.0.0:3001            0.0.0.0:*               LISTEN      21787/thin server ( 

クライアントからとサーバーからでtelnetで確認してみるが接続できる。

telnet 127.0.0.1 3001
telnet サーバーIP 3001

ここで、もしかしてnginxでproxyしないといけないのかと思い、nginxのconfに下記を追記。

upstream yeomanserver {
        server 127.0.0.1:3001;
}
    location /websocket {
        proxy_pass http://yeomanserver;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

nginxは80番ポートで待ち受けているので、javascriptの3001ポートの使用部分を削除。

$rootScope.wsRails = new WebSocketRails("サーバーIP/websocket");

ここまでやっても接続できない。
log/production.logを見ても何もログは出力されていないもよう。
3001ポートでの待ち受けはしているはず。
websocket_railを止めて、実行するとエラー内容が変わる為、nginxはthinと連携でなんらかのエラーが起こっている?
その後、いくらくぐってもそれらしい情報は出てこず。
途方にくれそうになった時にブラウザに何の気無しに下記を入力。

http://サーバーIP:3001

するとMySQLとの接続が失敗したとメッセージが出る。
rails(unicorn)の起動は成功しているし、実行ページのブラウザ表示も問題ない。
接続失敗のユーザー名をみるとどうやらdevelopmentモードで起動しているもよう。

websocket_railsの起動もproductionモードの指定ができるようなので、下記コマンドで起動。

sudo rake websocket_rails:start_server export RAILS_ENV="production"

最後に

その後、本番環境でもWebSocketは正常につながり、送受信も正常に動きました。
websocket_railsでもhttpで接続したら、普通のrailsと同じような動作をするんですね。
しょうもない問題ですが、半日ぐらいはまったので、備忘録として残しておきます。


参考
Railsで複数グループ対応のチャットアプリを作ってみた
github websocket-rails
github websocket-rails issues 211
MacにRedisをインストールする

22
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?