2014年3月21日金曜日

[Node.js]ExpressJS 3.xから4.xにUpdate

nodejs_express_3to4connect-redisを1.5にアップデートしたらエラーで動かない。。。

express 4.0にする必要があったので3.xで作成したアプリを4.xに移行したときの覚書。

環境: node.js v0.10.26, express v4.0.0-rc3

参考サイト

4.0からはconnectが削除されるので、付随していたミドルウェアを自前で読み込まなければならない。

例を見るのが分かりやすい。

express 3.xの記述例

var express = require('express');
var app = express();
var RedisStore = require('connect-redis')(express);

var C = require('./config');
var GA = require('./lib/google-analytics');
var system = require('./routes/system');

// Load Module
app.use(express.urlencoded());
app.use(express.json());
app.use(express.cookieParser(C.cookieSecret));
app.use(express.session({
  key: C.cookieKey,
  secret: C.cookieSecret,
  store: new RedisStore({
    db: C.db.session.database
  })
}));
app.use(express.compress()); // Use gzip
app.use(app.router);

app.all('*', function(req, res, next) {
  // Tracking
  GA.trackPage(req.url, req);

  // Continue
  next();
});

// System
app.post('/login', system.login);

app.listen(C.port);

 

express 4.xの記述例

var express = require('express');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var RedisStore = require('connect-redis')(session);
var compress = require('compression')();

var app = express();

var C = require('./config');
var GA = require('./lib/google-analytics');
var system = require('./routes/system');

// Load Module
app.use(bodyParser());
app.use(cookieParser(C.cookieSecret));
app.use(session({
  key: C.cookieKey,
  secret: C.cookieSecret,
  store: new RedisStore({
    db: C.db.session.database
  })
}));
app.use(compress); // Use gzip

app.all('*', function(req, res, next) {
  // Tracking
  GA.trackPage(req.url, req);

  // Continue
  next();
});

// System
app.route('/login').post(system.login);

app.listen(C.port);

 

 

< Related Posts >

2014年3月11日火曜日

Node.js環境のためにMySQLからMariaDBに移行

mysql_to_mariadbAndroid, iOSアプリからのアクセスをNode.jsで実装したけれど、データベース(MySQL)がたまに応答しなくなる現象が発生したので調査したときの覚書。

環境:CentOS 5.10 x86_64, MySQL 5.5.36, Node.js v0.10.26, node-mysql 2.1.0

 


1.MySQL Community Editionの限界

Node.js + node-mysqlからMySQLにクエリを投げると、その分だけスレッドが立つ(1つのコネクションに対して1つのスレッド)。

デフォルトの設定では、すぐ「too many connections」とエラーになってしまうので、my.cnfに「max_connections」を設定する。

しかし、コネクション数が256を超えた辺りで、レスポンスが非常に悪くなるらしい。公式サイトにコネクション数とパフォーマンスのグラフがある。

my.cnfの「thread_handling=pool-of-threads」としたいけど、これはMySQL Enterprise版の機能らしい。

調べてみると、MySQLからフォークした「MariaDB」というのがMySQL互換でスレッドプールも備えているので試してみた。

 


2.MariaDBについて

下記サイトが詳しい。

 


3.MariaDB 5.5をCentOSにインストール(失敗)

※この章は失敗したログ。成功した方法は次の章で

まずは既存データベースのバックアップ
# mysqldump -p hogedb > hogedb_20140310.sql

MySQLサーバーは停止。
# /etc/rc.d/init.d/mysqld stop


公式サイトを参考にYUMのリポジトリを追加する。

# vi /etc/yum.repos.d/MariaDB.repo

# MariaDB 5.5 CentOS repository list - created 2014-03-10 06:49 UTC
# http://mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/5.5/centos5-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1

# yum clean all
# yum update

するとMariaDBが既存MySQLを置き換えようとして下記エラー

--> Processing Dependency: mysql = 5.5.36-1.el5.remi for package: mysql-libs
--> Finished Dependency Resolution
mysql-libs-5.5.36-1.el5.remi.x86_64 from installed has depsolving problems
  --> Missing Dependency: mysql = 5.5.36-1.el5.remi is needed by package mysql-libs-5.5.36-1.el5.remi.x86_64 (installed)
Error: Missing Dependency: mysql = 5.5.36-1.el5.remi is needed by package mysql-libs-5.5.36-1.el5.remi.x86_64 (installed)

よくmysql-libsはインストールしてあるし、よく分からないのでmysqlを削除する
# yum remove mysql*

MariaDB Serverをインストール
# yum install MariaDB-server MariaDB-client

サーバー起動。自動起動するようになってるか確認。
# /etc/rc.d/init.d/mysql start
# chkconfig --list | grep mysql

PHP用のライブラリをインストール
# yum install php-mysql

ここでまた置き換えようとしたときと同じエラー。別の方法でアップグレードすることにした。

 


4.既存のMySQLをREMIリポジトリを使ってアップグレード

(前の章で失敗したのはVMware Fusionで元に戻した)

下記記事にアップグレードする方法が載ってた。

remiリポジトリの追加方法は前の記事を参考に。

リポジトリを追加するのはさっきと一緒。
# vi /etc/yum.repos.d/MariaDB.repo

# MariaDB 5.5 CentOS repository list - created 2014-03-10 06:49 UTC
# http://mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/5.5/centos5-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1

# yum clean all

まずは既存のMySQL関連ソフトを削除(データベースは削除されない)。
# yum remove mysql-server mysql-libs mysql-devel mysql*

Remiリポジトリを使ってMariaDBのインストール
# yum --enablerepo=remi-test --disablerepo=remi install compat-mysql55
# yum install MariaDB-server MariaDB-client php-mysql --enablerepo=remi

サーバー起動。自動起動するようになってるか確認。
# /etc/rc.d/init.d/mysql start
# chkconfig --list | grep mysql

データベースのアップグレード
# mysql_upgrade -p

これで既存のWordPressとphpMyAdminは動いた。

 


5.my.cnfの設定

前の設定は/etc/my.cnf.rpmsaveに保存されているので、これを見ながら追記する。
# vi /etc/my.cnf.d/server.cnf

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
default-storage-engine = MyISAM
ft_min_word_len = 1
thread_handling = pool-of-threads
max_connections = 500
table_open_cache = 6400

# Tuning
key_buffer_size = 512MB
sort_buffer_size = 8MB
read_rnd_buffer_size = 8MB
join_buffer_size = 1MB
read_buffer_size = 1MB
query_cache_size = 512M
query_cache_limit = 1MB

# Profile
slow_query_log = ON
long_query_time = 0.5
log_output = TABLE

環境に合わせてチューニングが必要。あくまで参考程度に。

文法を確認して再起動。
# /etc/rc.d/init.d/mysql configtest
# /etc/rc.d/init.d/mysql restart

 

遅いクエリにはインデックスを付けて、とりあえずNode.jsからの大量のコネクションを捌けるようになった(と思う)。

そのうちハードスペックに合わせたチューニング方法も調べたい。

 

< 2014/03/11 Modified >
yum updateしようとすると前と同じmysql-libsのエラーが表示されるので、mysql関係は除外するように設定。
# vi /etc/yum.conf

exclude=mysql*

 

 

< Related Posts >

2014年3月6日木曜日

RedisをInstallして、Node.js + RedisでSession管理

redis_nodejsNodejsのセッション管理の仕組みをどうするか迷っていたときの覚書。

環境: CentOS 5.10 x86_64

すでにMySQLが導入済みなのでconnect-mysql-sessionMySQL-Clusterにするか迷ったけど、調査した結果Redisを使うことに決定。

理由

 

参考:

 


1.Redisのインストール

Redisについては下記記事が分かりやすい。

REMIリポジトリがインストールされているなら、最新版をYUM経由で取得できる。

# yum install redis --enablerepo=remi

起動。自動起動も設定。
# /etc/rc.d/init.d/redis start
# chkconfig redis on

 


2.connect-redisのインストール

# npm install connect-redis --save

 


3.Node.js + Expressの環境に導入

var express = require('express');
var app = express();
var RedisStore = require('connect-redis')(express)

app.use(express.urlencoded());
app.use(express.json());
app.use(express.cookieParser(C.cookieSecret));
app.use(express.session({
  key:C.cookieKey,
  secret: C.cookieSecret,
  store: new RedisStore()
}));
app.use(express.compress()); // Use gzip
app.use(app.router);

 

確認
# redis-cli
> select 0
> keys *

1) "sess:kwjGrEaxnzE6KZy44LtiNSwt"

 

 

< Related Posts >

 

            2014年3月5日水曜日

            SSL + IE11の環境でtype="password"の値が取得できない

            ssl_ie11_password会員登録の画面でユーザーから「登録できない」と問合せがあったので調べたときの覚書。

            <会員登録処理の流れ>
            ユーザー名、パスワード、パスワード確認を入力

            POST

            プレビュー画面
            ※このときPOSTされた値はdisplay:noneで隠してある。

            POST

            登録

             

            調べてみるとプレビュー画面からPOSTする際に確認用パスワードの値を取得出来ていない。

            IE11のバグとして上がっているみたい。

             

            この現象の確認と対策用に作成したスクリプトはこちら

            <html>
            <head>
                <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
                <title>POSTテスト</title>
                <style>
                    .hide {display: none;}
                </style>
            </head>
            <body>
                <?php var_dump($_POST);?>
                <form id="submit-form" method="post">
                    <div class="frame <?php if (!empty($_POST)) echo 'hide';?>">
                        <input type="text" name="test" value=""/>
                        <input type="password" name="pass" value="<?php if (!empty($_POST['pass'])) echo $_POST['pass'];?>"/>
                        <input type="password" name="pass_confirm" value="<?php if (!empty($_POST['pass_confirm'])) echo $_POST['pass_confirm'];?>"/>
                    </div>
                    <button>submit</button>
                </form>
                <script>
            jQuery(function($){
                var jForm = $('#submit-form');
                jForm.submit(function() {
                    alert(jForm.find('[name=pass_confirm]').val());
                    if (confirm('post?')) {
                        return true;
                    }
                    return false;;
                });

                <?php if (!empty($_POST)) :?>
                // this is for SSL + IE11
                //jForm.find('[name=pass_confirm]').val('<?php echo $_POST['pass_confirm'];?>');
                <?php endif;?>
            });
            </script>
            </body>
            </html>

             

            最後のコメントを外すとSSL + IE11の環境でも動作するようになる。

            SSL証明書をインストールしていないサーバーでも再現しなかったので注意。

             

            < Related Posts >

            Related Posts Plugin for WordPress, Blogger...

            Blog Archives