2006年10月4日水曜日

Firefoxの「選択した部分のソースを表示」はJavaScriptで動的に生成したHTMLも表示される

これ知りませんでした。「選択した部分のソースを表示」しても、普通にその部分の生のソースが出てくるだけかと思い込んでました。

最近はJemplateなんかを使って動的にHTMLを生成するというのをやることが多いんですが、これ、HTMLのメンテがしづらいとデザイナーさんからはすこぶる評判がわるかったんです。
これで少しはメンテが楽になるかなー。

via: subtechグループ - マングローブ - JavaScriptなんかでいじられた後の現在のソースを表示

巨大なFLVを再生中に他のリンクをクリックしてもなかなか移動できない現象を回避する方法

FlipClipでクリップを見ていると、再生の途中で画面内のリンクをクリックして他のページに移動しようとしても、なかなか移動できなくてイライラすることがあったので、これを回避する方法がないものかと考えていたのですが、今日試した方法が有効だったので紹介します。

この現象は、再生している動画のサイズが大きい場合によく起こる現象で、リンクをクリックしてもブラウザはこの大きな動画の再生に忙しいのか、なかなか画面を切り替えてくれません。

そこで考えたのが、クリックした時に、再生している動画をけしてしまうという方法です。
試した方法は簡単で、リンクなどをクリックしてページが切り替わるタイミングで、再生中のフレームを含むdiv要素のinnnerHTMLを空にしてしまうというものです。
コードのイメージはこんな感じです。

>

<script type="text/javascript"><:!--
Event.observe(window, 'beforeunload', function(){
$('clipPlayer').innerHTML='';
});
--></script>
<

最初はbeforeunloadではなくunloadで試してみましたが、タイミングが遅いらしく、効果がありませんでした。
beforeunloadはブラウザによっては動かないといった情報をどこかで見たような気がしたのですが、IE, FireFox, Safariでうまく動いたので、互換性に問題なしと判断し、FlipClipでもこの方法を早速採用しました。

画面の移動がスムースになって、いい感じです。



特定のネットワークからは無制限に、外からのアクセスはパスワードを要求

今までapacheでアクセス制限かけるときはIP制限ならIP制限だけ、標準認証なら標準認証だけしか設定したことがなかったし、それで事足りていたのでなにも困ることはなかったんですが、社内のネットワークやサーバ間で通信する相手からのアクセスは無制限に行いたいけど、その他のネットワークからのアクセスはパスワードで制限したいという状況になったので、ちょっと調べてみたら、結構簡単にできました。

>

Require valid-user
Allow from 192.168.1
Satisfy Any
<

Apacheのドキュメントに普通に書いてありました。マニュアルはちゃんとよんどかないとだめですね。

それにしてもSatisfy Anyってわかりやすい書き方ですね。どっちか満たせばOKって、覚えやすい。


2006年10月1日日曜日

フリップ・クリップも絶賛社員募集中です!

naoyaさんのバイト募集に便乗して、弊社の社員募集を出してみます。

弊社はFlipClipという動画共有サービスを運営している会社です。

http://www.flipclip.net/

動画共有サービスというとYouTubeがまっさきに思いつくと思いますが、
YouTubeをイメージしてもらって、そこからEvilさを引いて、かわいらしさをプラスするとFlipClipのイメージに近くなるかなーと思います。
ただ、YouTubeの真似をして、日本版YouTubeを作る気はありません。
ブログによって、誰でも自分の意見を世界に発信できるようになったように、
FlipClipを使うと、誰でも動画を簡単に世界に発信できるようになるといわれるようなサービスに
したいと思っています。そのために動画を公開する人が使いやすかったり、便利だったりする機能を
どんどん強化していきたいと考えています。

フリップ・クリップでは、上記のようなサービスの開発に興味があり、
以下のようなことができる方を募集しています。

- PerlでWebアプリを開発したことのあるエンジニア(Sledge経験者大歓迎。Linux,Apache,MySQLに詳しい方さらに大歓迎)
- ActionScriptがバリバリかけるFlashエンジニア
- XHTML+CSSなコーディングがバリバリできるデザイナー、コーダー
- GFSのような世界中の動画を管理できるような巨大ストレージシステムを構築したいと考えている方
- 巨大なトラフィックをさばけるようなサーバの構築・運用をしたいと考えている方

弊社の会社概要は以下のとおりです。
http://www.flipclip.net/company

現在、Perlエンジニアが僕を含めて2名、デザイン・コーディング・広報まで担当している、デザイナーが1名、営業・マーケティング担当が1名の4名がメインで活動しています。
そして、関連会社のアトムにFlash、デザイン、サーバ構築運用の部分を手伝ってもらっています。

社員はみんな、動画を使ってあんなことできないか、こんなことできないか、あーでもないこーでもないと議論しながら、面白いアイデアはどんどん実装していこうというスタンスで開発を進めています。

FlipClipはすべてPerlで書かれていて、フレームワークにSledgeを採用しています。
OSは、CentOS4.3で、WebサーバはApache+mod_perl, DBにMySQL, SMTPサーバにPostfixを採用しています。
動画の変換部分もffmpegやQuickTimeなど様々なソフトウェアを組み合わせて自前で構築しています。
ソースコードの管理にはSubversionを使っています。

簡単に弊社を紹介させていただきましたが、ちょっとでも興味をもたれた方は、
horiyasu at gmail.com までご連絡ください。


via: naoyaのはてなダイアリー - バイト募集してます。

2006年9月30日土曜日

MT3.3でBerkeley DBからPostgreSQLへの移行する際の注意点

MTのエントリが多くなりすぎて、再構築ができなくなったと友達から連絡をもらい、確認したところ、DBにBerkeleyDBを使っていたので、それを改善すべくDBをBerkeleyDBからPostgreSQLに移行してみました。
その際、MTのマニュアルにしたがってやってみたところ、そのままではうまくいかなかったので、行った作業をメモ的に残しておきます。

* PostgreSQLの設定

まず、マニュアルをみてPostgreSQLの設定をしました。

基本マニュアルどおりに進めて、mt-config.cgiの設定を変更し、
データベースの作成をおこないました。
DBの文字コードはUTF-8だったので、DB作成の際、文字コードを指定しました。
>

createdb -E UNICODE --owner xxxxx
<

* 移行スクリプトを実行

次にマニュアルどおりMT付属の移行スクリプトを実行したところ、DBの文字コードと違う文字コードのデータを入れようとした旨のエラーメッセージが出て、移行スクリプトを完了できませんでした。
文字コードの違うデータというのは、トラックバックPingのデータで、トラックバック元のブログの文字コードがUTF-8ではないものがエラーではじかれているようでした。
これは、文字コードが違うPingを探し出して削除するのは面倒くさかったので、移行スクリプトのほうを修正して、インサートに失敗しても処理を続行するようにして、回避しました。
修正点は以下のとおり。saveに失敗してもdieしないようにしただけです。MTの方で、DBへのアクセスが高度に抽象化されているので、修正は非常に簡単です。
>

--- ./mt-db2sql.cgi.org Sat Sep 30 00:54:15 2006
+++ ./mt-db2sql.cgi Sat Sep 9 20:09:45 2006
@@ -141,8 +141,8 @@
$obj->allow_comments(0)
if defined $obj->allow_comments && $obj->allow_comments eq '';
}
- $obj->save
- or die $obj->errstr;
+ $obj->save;
+ # or die $obj->errstr;
}

# fix up the category parents
<

この修正版のスクリプトを再度実行したところ、今度は問題なく、データの移行が完了しました。

* シーケンスの作成、更新

これで万事OKかと思ったんですが、この状態でエントリを作成しようとすると、以下のようなエラーがでて、作成できなくなってしまいました。

>

Saving entry failed: ERROR: ExecInsert: Fail to add null value in not null attribute entry_id
<

このエラーでググッてみると、どうやらDB内にシーケンスがないためのようです。
先ほどの移行用スクリプトだと、テーブルは作成されてもシーケンスは作成してくれないみたいです。
そうとわかれば、後はシーケンスを手動で作成するだけです。
以下のSQLを実行し、シーケンスを作成し、格納されている値を現在の最大値にセットしたところ、問題なく動くようになりました。

>

CREATE SEQUENCE mt_author_id;
CREATE SEQUENCE mt_blog_id;
CREATE SEQUENCE mt_category_id;
CREATE SEQUENCE mt_comment_id;
CREATE SEQUENCE mt_config_id;
CREATE SEQUENCE mt_entry_id;
CREATE SEQUENCE mt_fileinfo_id;
CREATE SEQUENCE mt_ipbanlist_id;
CREATE SEQUENCE mt_log_id;
CREATE SEQUENCE mt_notification_id;
CREATE SEQUENCE mt_objecttag_id;
CREATE SEQUENCE mt_permission_id;
CREATE SEQUENCE mt_placement_id;
CREATE SEQUENCE mt_plugindata_id;
CREATE SEQUENCE mt_tag_id;
CREATE SEQUENCE mt_tbping_id;
CREATE SEQUENCE mt_template_id;
CREATE SEQUENCE mt_templatemap_id;
CREATE SEQUENCE mt_trackback_id;

select setval('mt_author_id',(select max(author_id) from mt_author));
select setval('mt_blog_id',(select max(blog_id) from mt_blog));
select setval('mt_category_id',(select max(category_id) from mt_category));
select setval('mt_comment_id',(select max(comment_id) from mt_comment));
select setval('mt_config_id',(select max(config_id) from mt_config));
select setval('mt_entry_id',(select max(entry_id) from mt_entry));
select setval('mt_fileinfo_id',(select max(fileinfo_id) from mt_fileinfo));
select setval('mt_ipbanlist_id',(select max(ipbanlist_id) from mt_ipbanlist));
select setval('mt_log_id',(select max(log_id) from mt_log));
select setval('mt_notification_id',(select max(notification_id) from mt_notification));
select setval('mt_objecttag_id',(select max(objecttag_id) from mt_objecttag));
select setval('mt_permission_id',(select max(permission_id) from mt_permission));
select setval('mt_placement_id',(select max(placement_id) from mt_placement));
select setval('mt_plugindata_id',(select max(plugindata_id) from mt_plugindata));
select setval('mt_tag_id',(select max(tag_id) from mt_tag));
select setval('mt_tbping_id',(select max(tbping_id) from mt_tbping));
select setval('mt_template_id',(select max(template_id) from mt_template));
select setval('mt_templatemap_id',(select max(templatemap_id) from mt_templatemap));
select setval('mt_trackback_id',(select max(trackback_id) from mt_trackback));
<

以上BerkeleyDBからPostgreSQLへの移行の際の注意点をまとめると、

- 文字コードの問題でエラーがでるため、移行スクリプトを修正して、エラーを無視するようにする。
- シーケンスは作成されないので手動で作成する。

の2つを注意しないといけないようです。

2006年7月31日月曜日

コネクションプーリング都市伝説は正しそう

またちょっと古いねたですが、WEB+DB PRESS vol.33でnipotanさんが書いてたコネクションプーリング都市伝説を読んだ時、ほんとのところどっちが速いのかってのをabでベンチマークをとってみました。

ベンチマークとったときにエントリを書こうと思ってたんですが、モチベーションがあがらず今になっちゃいました。。

以下がベンチマークの結果です。

プーリングを有効にした場合


>

Server Hostname: rakuda.localhost
Server Port: 80

Document Path: /
Document Length: 12323 bytes

Concurrency Level: 20
Time taken for tests: 107.840 seconds
Complete requests: 1000
Failed requests: 0
Broken pipe errors: 0
Total transferred: 12579000 bytes
HTML transferred: 12323000 bytes
Requests per second: 9.27 [#/sec] (mean)
Time per request: 2156.80 [ms] (mean)
Time per request: 107.84 [ms] (mean, across all concurrent requests)
Transfer rate: 116.65 [Kbytes/sec] received

Connnection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 1
Processing: 640 2140 486.9 1999 4674
Waiting: 639 2139 486.9 1999 4673
Total: 640 2140 486.9 1999 4674
ERROR: The median and mean for the initial connection time are more than twice the standard
deviation apart. These results are NOT reliable.

Percentage of the requests served within a certain time (ms)
50% 1999
66% 2066
75% 2141
80% 2267
90% 2650
95% 3388
98% 3774
99% 3941
100% 4674 (last request)
<

コネクションプーリングを無効にした場合


>

Server Hostname: rakuda.localhost
Server Port: 80

Document Path: /
Document Length: 12323 bytes

Concurrency Level: 20
Time taken for tests: 104.939 seconds
Complete requests: 1000
Failed requests: 0
Broken pipe errors: 0
Total transferred: 12579000 bytes
HTML transferred: 12323000 bytes
Requests per second: 9.53 [#/sec] (mean)
Time per request: 2098.78 [ms] (mean)
Time per request: 104.94 [ms] (mean, across all concurrent requests)
Transfer rate: 119.87 [Kbytes/sec] received

Connnection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 3
Processing: 353 2081 502.0 1969 5219
Waiting: 351 2081 502.0 1969 5219
Total: 353 2081 502.0 1969 5219

Percentage of the requests served within a certain time (ms)
50% 1969
66% 2033
75% 2117
80% 2192
90% 2503
95% 3011
98% 4032
99% 4571
100% 5219 (last request)
<

これ以外にもいくつかパスを替えてベンチマークをとったところ、いずれも若干ですがプーリングしないほうが早かったので、現在はプーリングしないほうで運用しています。

Sledgeのセッション用テーブルはMyISAMにしています。

naoyaさんのエントリーnaoyaのはてなダイアリー - MyISAM vs InnoDBに反応して、久々にエントリを書いてみます。

FlipClipは、すべてMyISAMで運用しているんですが、理由はあんまりなくて、デフォルトでMyISAMだからってのが大きいのと、スナップショットを取るのにmysqlsnapshotに手を加えたものを使っているので、InnoDBにするとそれを使えなくなるというのが主な理由です。それにまだDBがボトルネックだうはーってな状態になったことがないってのもあります。

それでも少し前にサーバのチューニングをそろそろ考えたほうがいいかなーということを考えたことがありまして、
その時にチューニングの候補に考えたものの一つが、Sledgeのセッション用のテーブルをMyISAMからInnoDBに替えてみるということでした。
セッションテーブルはスナップショットを取る必要ないですし、InnoDBにして早くなったらラッキーってのと、Sledgeのセッション用のテーブルは1リクエストで必ず1回書き込みが行われるので、読み込みと書き込みが同程度発生するので、更新系が多い場合はInnoDBがよいというのにあてはまるかなと思ったからです。

そこで実際にSledgeで作ったアプリケーションを使ってセッションテーブルをInnoDBにした場合と、MyISAMにした場合でどれほど性能に差がでるかabを使って簡単にベンチマークしてみました。

以下がabを使って同時10リクエストで合計1000リクエスト実行した際の結果です。

MyISAMの場合


>

Benchmarking rakuda.localhost (be patient)
Server Software: Apache/1.3.36
Server Hostname: rakuda.localhost
Server Port: 80

Document Path: /
Document Length: 14911 bytes

Concurrency Level: 10
Time taken for tests: 110.009 seconds
Complete requests: 1000
Failed requests: 0
Broken pipe errors: 0
Total transferred: 15167000 bytes
HTML transferred: 14911000 bytes
Requests per second: 9.09 [#/sec] (mean)
Time per request: 1100.09 [ms] (mean)
Time per request: 110.01 [ms] (mean, across all concurrent requests)
Transfer rate: 137.87 [Kbytes/sec] received

Connnection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 1
Processing: 292 1096 223.5 1031 1976
Waiting: 291 1096 223.5 1031 1976
Total: 292 1096 223.5 1031 1976
ERROR: The median and mean for the initial connection time are more than twice the standard
deviation apart. These results are NOT reliable.

Percentage of the requests served within a certain time (ms)
50% 1031
66% 1071
75% 1109
80% 1145
90% 1338
95% 1753
98% 1832
99% 1888
100% 1976 (last request)
<

InnoDBの場合


>

Benchmarking rakuda.localhost (be patient)
Server Software: Apache/1.3.36
Server Hostname: rakuda.localhost
Server Port: 80

Document Path: /
Document Length: 14911 bytes

Concurrency Level: 10
Time taken for tests: 110.730 seconds
Complete requests: 1000
Failed requests: 0
Broken pipe errors: 0
Total transferred: 15167000 bytes
HTML transferred: 14911000 bytes
Requests per second: 9.03 [#/sec] (mean)
Time per request: 1107.30 [ms] (mean)
Time per request: 110.73 [ms] (mean, across all concurrent requests)
Transfer rate: 136.97 [Kbytes/sec] received

Connnection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 0
Processing: 765 1102 273.9 1010 2476
Waiting: 765 1102 273.9 1010 2476
Total: 765 1102 273.9 1010 2476

Percentage of the requests served within a certain time (ms)
50% 1010
66% 1059
75% 1120
80% 1180
90% 1466
95% 1787
98% 1973
99% 2198
100% 2476 (last request)
<


結果としてMyISAMもInnoDBも速度的にはほとんど変わらなかった(ちょっとMyISAMのほうが速かった)ので、今まで通りMyISAMでいいかという結論に達しました。