LoginSignup
8
5

More than 5 years have passed since last update.

ArchLinuxでWebsocket-railsをスタンドアロンで動かし、Nginx+Unicornと連携させるまでやってみた

Posted at

Arch Linuxをインストールしたので練習がてら以前うまく行かなかったことに挑戦
とはいえ、ディレクトリ構成が違うだけで他のディストリとあまり変わらない

前提条件

  • Ruby をインストール済み
  • Rails をインストール済み

Archさんならどっちもすぐにインストール出来ちゃうからありがたい

Nginxのインストール

ちゃちゃっとNginxをインストール

sudo pacman -S nginx

とりあえずNginxの設定ファイルをバックアップ

sudo cp /etc/nginx/nginx.conf /etc/nginx/default.conf.bk

設定ファイルは後でいじるので、とりまNginxは放置

Unicornインストール

Rails 4.2 + Unicorn + Nginx でアプリケーションサーバの構築
を参考にUnicornの設定まで行う。
現段階ではDevelopment環境のままで。
Unicornは実行しておく

Nginxの設定

Archだと上記ページのNginxの設定だけでは動かなかったので
nginx.confを以下のように編集

/etc/nginx/nginx.conf
events {
        worker_connections 1024;
}

http {
        upstream unicorn {
                server unix:/tmp/unicorn.sock;
        }

        server {
                listen 80 default_server;

                access_log /var/log/nginx/access.log;
                error_log /var/log/nginx/error.log;

                root Railsプロジェクトのルートパス;

                client_max_body_size 100m;
                error_page 404 /404.html;
                error_page 500 502 503 504 /500.html;
                try_files $uri/index.html $uri @unicorn;

                location @unicorn {
                        proxy_set_header X-Real-IP $remote_addr;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                        proxy_set_header Host $http_host;
                        proxy_pass http://unicorn;
                }
        }
}

どうやらpermissionでエラーをはくことがあるらしいので
railsプロジェクトのルートまでのディレクトリ(特にユーザルートディレクトリ)のアクセス権限変更

chmod o+x /home/username/

最後にNginxを再起動

sudo systemctl restart nginx

ここまでで普通のRailsアプリケーションは動くはず

Redisインストール

次にRedisをインストール

sudo pacman -S redis
sudo redis-server /etc/redis.conf

これでRedisサーバが起動するはず

Redis-railsの設定

Websocket-railsをスタンドアロンで実行するにはRedisが必要みたい
RailsのセッションストアとしてRedisを使う(Mac/EC2:AmazonLinux)
を参考にRailsの設定

Gemfileに以下を追記

gem 'redis'
gem 'redis-rails'

Bundle installする

bundle install --path vendor/bundle

config/initializers/session_store.rbをコメントアウト

config/initializers/session_store.rb
# Rails.application.config.session_store :cookie_store, key: '_sample_session'

config/environments/development.rbに追加

config/environments/development.rb
  config.session_store :redis_store, servers: 'redis://localhost:6379/0', expire_in: 1.day

Websocket-railsのインストール

ここからはRailsで複数グループ対応のチャットアプリを作ってみた
を参考に

Websocket-railsをGemfileに追加

gem 'websocket-rails'

Bundle installする

bundle install --path vendor/bundle

Websocket-rails関係のファイルを生成

rails g websocket_rails:install

config/environments/development.rbに追記

config/environments/development.rb
config.middleware.delete Rack::Lock

今回はスタンドアロンで実行するので
config/initializers/websocket_rails.rbを以下のように編集

config/initializers/websocket_rails.rb
WebsocketRails.setup do |config|
  config.standalone = true
  config.synchronize = false
  config.standalone_port = 3001

  config.redis_options = { host: 'localhost', port: '6379' }
end

Nginxの設定にWebsocket-railsのルーティング追加
nginx.confは以下のようになる

追加したのは
upstream thin と location /websocket

/etc/nginx/nginx.conf
events {
        worker_connections 1024;
}

http {
        upstream unicorn {
                server unix:/tmp/unicorn.sock;
        }

        upstream thin {
                server 127.0.0.1:3001;
        }

        server {
                listen 80 default_server;

                access_log /var/log/nginx/access.log;
                error_log /var/log/nginx/error.log;

                root Railsプロジェクトのルートパス;

                client_max_body_size 100m;
                error_page 404 /404.html;
                error_page 500 502 503 504 /500.html;
                try_files $uri/index.html $uri @unicorn;

                location @unicorn {
                        proxy_set_header X-Real-IP $remote_addr;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                        proxy_set_header Host $http_host;
                        proxy_pass http://unicorn;
                }

                location /websocket {
                        proxy_pass http://thin;
                        proxy_http_version 1.1;
                        proxy_set_header Upgrade $http_upgrade;
                        proxy_set_header Connection "upgrade";
                }
        }
}

Websocket-railsを使う

Websocket用のController作成

rails g controller は使えないので自分で作成
今回は
app/controllers/sockets_controller.rb

app/controllers/sockets_controller.rb
class SocketsController < WebsocketRails::BaseController
  def message_recieve
    WebsocketRails[:channel1].trigger :message, message
  end
end

次にルーティングの設定
Websocket-railsはconfig/events.rbでルーティング設定する

config/events.rb
WebsocketRails::EventMap.describe do
  subscribe :websocket, to: SocketsController, with_method: :message_recieve
end

Chat画面の作成

Controller作成

まずはChatsコントローラ作成

rails g controller chats

chats_controller.rbにindexを追加

app/controller/chats_controller.rb
class ChatsController < ApplicationController
  def index
  end
end

chats_controllerをconfig/routes.rbでルーティング

config/routes.rb
Rails.application.routes.draw do
  root 'chats#index'
end

Viewの作成

app/views/chats/index.html.erbを以下のように作成

app/views/chats/index.html.erb
<h1>Chat</h1>

Name : <input id="name" type="text"><br />
Comment : <input id="comment" type="text"><br />
<input id="send" type="button" value="send">

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Comment</th>
    </tr>
  </thead>

  <tbody id="chat_body">
  </tbody>
</table>

次に
app/assets/javascripts/chats.coffeeを以下のように編集

app/assets/javascripts/chats.coffee
class @ChatClass

  constructor: () ->
    @dispatcher = new WebSocketRails('localhost/websocket', true)
    @channel = @dispatcher.subscribe('channel1')
    @events()

  events: () =>
    $('#send').on 'click', @sendMessage
    @dispatcher.bind 'message', @receiveMessage
    @channel.bind 'message', @receiveMessage

  sendMessage: (event) =>
    name = $('#name').val()
    comment = $('#comment').val()
    @dispatcher.trigger 'websocket', { name: name, comment: comment }
    $('#comment').val('')

  receiveMessage: (message) =>
    name = document.createElement('td')
    name.innerHTML = message.name

    comment = document.createElement('td')
    comment.innerHTML = message.comment

    row = document.createElement('tr')
    row.appendChild name
    row.appendChild comment

    $('#chat_body').prepend row

$ ->
  window.chatClass = new ChatClass()

Development環境で実行

まずはRedisが動いてることを確認
動いてなければ

sudo redis-server /etc/redis.conf

次にWebsocket-railsをスタンドアロンで起動

bundle exec rake websocket_rails:start_server RAILS_ENV=development

その後Unicornを起動

bundle exec rake unicorn:start

最後にNginxを再起動

sudo systemctl restart nginx

これで
http://localhost
にアクセスするとチャット画面がでてくるはず

次はproduction環境で動かしてみようかな

8
5
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
8
5