torutkのブログ

ソフトウェア・エンジニアのブログ

Redmineのファイル機能で大きなファイルを扱う際の注意点

(その後、ある程度の回避ができたので題名修正しました。)

Redmineを開発環境の基盤ツールとして使うと、最初からWiki掲示板/ファイル共有が整うので、開発環境を構築する身にはうれしい話ですが、ファイル共有に関しては課題があります。それは、Redmine(というよりはRuby on Rails)が大きなファイルを扱うのに向いてないということです。ここでいう大きなファイルとは、DVDのISOイメージ等で1つのファイルで数GBの大きさです。

ソフトウェア開発環境では、開発ツールのインストールイメージを共有しておきたいので、DVDのISOイメージファイルを扱いたいというニーズがあります。

この場合の問題点として

  • ファイルのアップロードに非常に時間がかかる
  • あげくアップロードに失敗する

があります。

実験

CentOS 6.3、Redmine 2.2.1、Passenger、Apacheの環境で1GBメモリ、32GBディスク(KVM仮想ゲスト)空きディスクが18GBという環境で、5GB弱のファイルをRedmineにアップロードしてみた。

結果は、ブラウザにはInternal Server Errorが表示、Redmineのログには次のエラーが残ってました。

Saving attachment '/var/lib/redmine-2.2.1/files/130113040148_sample.iso' (4915200000 bytes)
Completed 500 Internal Server Error in 150945ms

Errno::ENOSPC (No space left on device - /var/lib/redmine-2.2.1/files/130113040148_sample.iso):
  app/models/attachment.rb:111:in `write'
  app/models/attachment.rb:111:in `block in files_to_final_location'
  app/models/attachment.rb:107:in `open'
  app/models/attachment.rb:107:in `files_to_final_location'
  lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb:84:in `block in save_attachments'
  lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb:80:in `each'
  lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb:80:in `save_attachments'
  app/models/attachment.rb:239:in `attach_files'
  app/controllers/files_controller.rb:45:in `create'

このとき、ディスクの残り容量がやけに少ないので、しらべると/tmpで大きな容量を占めていました。そこで、/tmpディレクトリを見ると

4800000 /tmp/RackMultipart20130113-27685-1g47rji
4800000 /tmp/RackMultipart20130113-31845-1r5t7o8

のように、なぜか2つ今回アップロードしたファイルと同じサイズのファイルが置かれています。
どうやら、/tmpとredmineのfilesディレクトリと3箇所に5GBのファイルが過渡状態として作られ、15GBほど食ってしまっていたようです。

ディスク空き領域を増やして再実験

ディスクを増やして再実験してみたところ、20分ほど時間がかかりましたがアップロード成功しました。

さて、次はこのファイルをダウンロードしてみます。

「接続がリセットされました」

redmineのログでは、

Sent file /var/lib/redmine-2.2.1/files/130113154459_sample.iso (0.2ms)
Completed 200 OK in 757ms (ActiveRecord: 654.2ms)

と正常終了したことになっています。

apacheのログにも残っていないので、topコマンドで様子をみながらダウンロードしてみました。すると、

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 1830 apache    20   0 3020m 726m  464 S  5.7 72.9   0:08.13 httpd
 1505 apache    20   0  348m 100m  684 R 23.0 10.1   6:25.42 ruby

httpdプロセスがどんどんメモリ肥大しているのが分かりました。このとき、スワップファイルもどんどん消費し、スラッシング状態になっています。

http://d.hatena.ne.jp/torutk/20120413/p1 で以前対処したことがある問題でした。
Ruby on Rails 3では対処方法が変更になっています。日記内のリンク先にRails 3での処置方法が言及されています。それを参照しながら確認した結果を以下ページに追記しました。
http://www.02.246.ne.jp/~torutk/swetools/redmine/setupCentOS6.html#xsendfile

Railsの大きなファイルのアップロード

最初はRedmine Large fileをキーワードにぐぐってましたが、Redmine自体がファイルアップロードを作りこんでいるのではないので、Railsに変えて少しぐぐってみると、次の記事を見つけました。

http://www.jedi.be/blog/2009/04/10/rails-and-large-large-file-uploads-looking-at-the-alternatives/

ちょうど同じようなことをしていました。/tmpにできた2つのファイルについても言及しています。Passengerについても言及していて、どうやらアップロード中にメモリ増大という問題があるようです。

Redmineファイル共有の使い方

小さなサイズ(直感的な目安で100MB以下)のファイルにとどめ、大きなファイルについては、Redmineのファイル機能を使うのは避け、別途ファイル共有の仕組みを構築するのが現実的です。ファイル共有としては、Apache等のWebサーバー(アップロードは管理者が手作業で配備する)か、FTPサーバーあたりになるのかと思います。

Samba(Windowsのファイル共有)を使わない訳

数十人の開発者が使用する開発環境で、Windowsのファイル共有(Samba)を提供すると、まず用意したディスク容量を食いつぶし、要不要の判別が困難なディレクトリ/ファイルで溢れてしまいます。過去、いろいろな施策をとってきましたが、有効な手立ては今のところありません。