鈍足ランナーのIT日記

走るのが好きな5流のITエンジニアのブログ。

趣味の範囲は広いけど、どれも中途半端なクソブロガー楽しめるWebアプリを作ってあっと言わせたい。サーバーサイドPerl(Mojolicious)、クライアントサイドVue.js。Arduinoにも触手を伸ばす予定。

今更ながら、nginx+Mojolicious+WebSocketでチャットアプリに挑戦

最近は、Unityばかり触れていて、Perlしてなかったので LTネタも尽きてしまう。というわけで こちらのエントリーを参照して、Mojoliciousでチャットアプリを作ったのは いいのだけど、本番環境では動かなかった。

http://kazuph.hateblo.jp/entry/20120310/1331396492

ソースはこちら。 https://github.com/dokechin/chat_web

原因を調べていくと・・・

$ /usr/local/nginx/sbin/nginx -v
nginx version: nginx/1.2.1

nginxのバージョンが低いからかな。。

http://stackoverflow.com/questions/12102110/nginx-to-reverse-proxy-websockets-and-enable-ssl-wss

nginxのインストール方法を忘れてしまったので、 自分のページを参照 http://stingyrunner.blog.fc2.com/blog-entry-46.html

さて、インストールしなくては。今日はここまで・・・

nginx1.6.0をインストールしてみたけれど、404が返ってくる。ううぅ。

143.90.238.110 - - [28/May/2014:08:03:30 +0900] "GET /echo HTTP/1.1" 404 - "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0"

クライアントが渡しているヘッダ

f:id:kechiya:20140528222245p:plain

nginxの設定

    upstream chat {
         server 127.0.0.1:8012;
    }

    server {
        listen 80;
        server_name chat.dokechin.com;
        #server_name www24203ue.sakura.ne.jp;
        #index index.html;
        root /home/tatsumi/chat/public;
        access_log  /var/log/chat.access.log  main;

        location / {
            proxy_set_header X-Forwarded-Proto "http";
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass http://chat;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }
    }

Mojoliciousまでは来ているただし、ログが違う

開発機

[Thu May 29 05:34:59 2014] [debug] GET "/echo".
[Thu May 29 05:34:59 2014] [debug] Routing to controller "Chat::Web::Chat" and action "echo".
[Thu May 29 05:34:59 2014] [debug] Client connected: Mojo::Transaction::WebSocket=HASH(0x80e808c0)
[Thu May 29 05:34:59 2014] [debug] 101 Switching Protocols (0.018193s, 54.966/s).

本番機

[Thu May 29 05:31:40 2014] [debug] GET "/echo".
[Thu May 29 05:31:40 2014] [debug] Template "not_found.development.html.ep" not found.
[Thu May 29 05:31:40 2014] [debug] Template "not_found.html.ep" not found.
[Thu May 29 05:31:40 2014] [debug] Rendering inline template.
[Thu May 29 05:31:40 2014] [debug] Rendering inline template.
[Thu May 29 05:31:40 2014] [debug] 404 Not Found (0.027890s, 35.855/s).

MojoliciousでHTTPヘッダー情報をログ出力したい

hookを利用して、ヘッダー情報をログ出力するように変更。

package Chat::Web;
use Mojo::Base 'Mojolicious';

# This method will run once at server start
sub startup {
  my $self = shift;

  # Router
  my $r = $self->routes;

  
  $self->hook( before_dispatch=> sub {
    my $c = shift;
    $c->app->log->info($c->req->headers->to_string);
  });

  # Normal route to controller
  $r->websocket ('/echo')->to('chat#echo');
  $r->get ('/')->to('chat#index');

}

1;

ヘッダーの比較

開発機

Connection: keep-alive, Upgrade
Cache-Control: no-cache
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Origin: http://localhost:3000
Accept-Encoding: gzip, deflate
Sec-WebSocket-Version: 13
Host: localhost:3000
Pragma: no-cache
Sec-WebSocket-Key: rr6RE14/sECc7i47y7mjew==
Upgrade: websocket

本番機

Connection: upgrade^M
Cache-Control: no-cache^M
Cookie: __utma=32193579.732112302.1369506740.1386651262.1393706303.4; __utmz=32193579.1393706303.4.4.utmcsr=yahoo|utmccn=(organic)|utmcmd=organic|utmctr=page_navigator%20mojolicous; _ga=GA1.2.732112302.1369506740^M
Origin: http://chat.dokechin.com^M
DNT: 1^M
Sec-WebSocket-Version: 13^M
Host: chat.dokechin.com^M
Sec-WebSocket-Key: 7F70rz9ewewN9kEshfDv5Q==^M
X-FORWARDED-PROTO: http^M
X-FORWARDED-FOR: 143.90.238.110^M
Upgrade: Websocket

なんか微妙に違う気がする。これらを合わせていこう こんな風に合わせてみたが404のまま

Connection: keep-alive, Upgrade^M
Cache-Control: no-cache^M
Cookie: __utma=32193579.732112302.1369506740.1386651262.1393706303.4; __utmz=32193579.1393706303.4.4.utmcsr=yahoo|utmccn=(organic)|utmcmd=organic|utmctr=page_navigator%20mojolicous; _ga=GA1.2.732112302.1369506740^M
Origin: http://chat.dokechin.com^M
DNT: 1^M
Sec-WebSocket-Version: 13^M
Host: chat.dokechin.com^M
Sec-WebSocket-Key: qHl4SaSgqsiMW/x+KaVKbA==^M
X-FORWARDED-PROTO: http^M
X-FORWARDED-FOR: 143.90.238.110^M
Upgrade: websocket

本番環境をstartlet→morboに変えたら・・

あっさりと動いた。ということはnginxの設定はあっているのかな。

morbo+Mojoliious(websoket)は動くけれど、starman+Mojolicious(websoket) では動かないということか。

Connection: keep-alive, Upgrade^M
Cache-Control: no-cache^M
Cookie: __utma=32193579.732112302.1369506740.1386651262.1393706303.4; __utmz=32193579.1393706303.4.4.utmcsr=yahoo|utmccn=(organic)|utmcmd=organic|utmctr=page_navigator%20mojolicous; _ga=GA1.2.732112302.1369506740^M
Origin: http://chat.dokechin.com^M
DNT: 1^M
Sec-WebSocket-Version: 13^M
Host: chat.dokechin.com^M
Sec-WebSocket-Key: qSDYkQmqZ9DZEYnS8SoKJA==^M
X-Forwarded-Proto: http^M
X-Forwarded-For: 210.160.37.30^M
Upgrade: websocket

開発環境でもplackupで起動すると動かなかった

plackup --port 3000 chat.psgi

うーん。いまいち理解していないけれど。

psgiサーバ(starmanやstartlet)でWebSocketを使う時は、MojoliciousでやらずにPlack::App::WebSocketを使うということなのかな。 うーん。それは作りにくいなぁ。。

本番環境hypnotoadへ

結局、本番環境starmanを諦め、hypnotoadへ。

ランチャー

#!/bin/bash
HOME=~
. ~/.bash_profile
exec hypnotoad -f /home/tatsumi/chat/script/chat_web

Configファイルの用意(chat.conf)

{
  hypnotoad => {
    listen  => ['http://*:8012'],
    workers => 10
  }
};

Configの読み込み部分の用意

package Chat::Web;
use Mojo::Base 'Mojolicious';

# This method will run once at server start
sub startup {
  my $self = shift;

  # Router
  my $r = $self->routes;
  
  my $config = $self->plugin( 'Config', { file => 'chat.conf' } );

  # Normal route to controller
  $r->websocket ('/echo')->to('chat#echo');
  $r->get ('/')->to('chat#index');

}

1;