bbs.cgi再開発プロジェクト 3
■ このスレッドは過去ログ倉庫に格納されています
つまり、ロックじゃなくてrename()を使うというのと、意味合いは同じです。 (rename()はアトミックだから) というわけで今の処理、 http://qb3.2ch.net/test/read.cgi/operate/1076174286/490 の、 490 名前:FOX ★[] 投稿日:04/02/24 22:13 ID:??? bbs.cgi のもっとも後半部分にこんなのがあるですよ。 open(RDAT,"<$dattemp"); @logdat=<RDAT>;#ログを配列に読み込む close(RDAT); #ログのカキコ数を取得 $lognum = @logdat; if(-w $dattemp && $lognum > 999){ open(OVER, ">>$dattemp"); print OVER "1001<><>Over 1000 Thread<>このスレッドは1000を超えました。 <br> もう書けないので、新しいスレッドを立ててくださいです。。。 <>\n"; close(OVER); chmod(0555, $dattemp); $lognum++; を、 print OVER "1001<><>Over 1000 Thread<>このスレッドは1000を超えました。 <br> もう書けないので、新しいスレッドを立ててくださいです。。。 <>\n"; fchmod(0555, OVER); close(OVER); $lognum++; にすればいいんではないかなと。 # Perlよくしらないから、0555とOVERの順番は逆かも。 つかCのchmod()と引数の順番反対な気が。< Perl うん。それも一理ある。>>141 visudoとかcrontab -eとか、いろんなところに使われているですね。 こういう新機軸のかずかずを最初に実装した4BSDは、 いろんな意味で偉大だったと再認識するわけで。 ただ、こういうのって、負荷が超高くなるとか、きびしー条件じゃないと、 なかなか不具合が露見しにくいとこだから、いい実験なのかもしれんですね。< live8 open(RDAT,"<$dattemp"); seek(RDAT, 0, 2); $lognum = $.; close(RDAT); ちゅーか、Perl4の書き方は止めようよ。 ほれ http://www.pure.ne.jp/ ~learner/program/Perl_oo.html flock って、ここだけでも使っちゃダメ? #ログのカキコ数を取得 $lognum = @logdat; if(-w $dattemp && $lognum > 999){ open(OVER, ">>$dattemp"); flock(OVER,2); seek(OVER,0,2); print OVER "1001<><>Over 1000 Thread<>このスレッドは1000を超えました。 <br> もう書けないので、新しいスレッドを立ててくださいです。。。 <>\n"; chmod(0555, $dattemp); close(OVER); $lognum++; fchmod()って、ひょっとして標準のPerlにはついてないのかしら。 とりあえず、状況を管理人に通報しておきましたです。 原因も明確なので、あとは様子見しか正直やることがないかと。 おぉ、>>150 はごばーく。無視してくださいです。 以下のプログラムで、ちょっとテスト。いちおう動いた。 でも、ちょっと強引。 で、h2phしてsyscall.phを作っておく必要ありの模様。 これ入れれば、ほぼ間違いなく3000とか4000いくのはなくなると思われ。 うまく動くようなら、麻原判決の前に、live8でテストしてみるか。 #! /usr/local/bin/perl # # fchmod test via syscall # # may be needed 'h2ph' require 'syscall.ph'; open(TTT,"A"); syscall(&SYS_fchmod, fileno(TTT), 0555); close(TTT); exit; あとは、rename()の助けを借りて、コピーして元datの複製を作っといて、 複製をchmod()してrename()するぐらいかなぁ。 でも、こんなことすると効率悪い気がするなぁ。 if (まだ書き込める) { 元ファイルの複製を作る; chmod(555,複製); rename(複製, 元ファイル); } >>154 はいかにも筋悪だなぁ。 複製を作っている間に、どんどん書き込まれる予感。 やっぱ、>>152 しかない気がする。 で、いちおう、make(perlcc)は通った模様。 ひ(りゃ的にOKなら、ちょっとやってみっか。 # なんだか、びんぼーくじを引いてるような気もする、する。 そしてずるずる引き込まれていくというのは内緒です。 sysopen はダメなのかな? sysopen FH, $filename, O_RDONLY, 0555 or die; みたいな。。。 ♪open Systemcall がよく判ってなかったりして(汗) 私としては、こーゆーのはぜひとも次世代を担う若者にやってほしいわけですよ、よ、よ。やっぱ。 わたしがperlの文法を覚えたのは 旧実験室のやつがきっかけだというのは、ないしょです。 >>158 sysopen使うなら、syscall使うのと50歩100歩かも。 つか、プログラマじゃない人にPerlをいじらしたらいけません(素)。 おじさんはダメだよ、おじさんは。 あれですね、一回 bbs.cgi を整理しないといけないのかも。 継ぎ足し継ぎ足しでやってますからねー、 処理を変えずにうまいこと順番を変えていく。 色々試してみる。 いつかは Best Choice が見つかるかも。 (見つからないかも) >>162 には、激しく同意。同意だが、、、。 どなたか、柱になってすすめていただける人がいれば、 ちょっぴり支えるぐらいはできるかも。 細い杖だけどね。 わたしゃ、お守り関係で正直もうお腹いっぱい、PIEおっぱい。 >>163 ( ´д)ヒソ(´д`)ヒソ(д` ) >>163 (;´Д`) ちょっとやってみよう。 とりあえず、現在の大まかな処理を書いてみよう。 今なんとなくぼーと観察してたけど、 なんだか、何らかのシステム資源が足りなくなった瞬間にこの現象が始まる気がする。 つまり、fchmodにしても解決しない問題なのかも。かも。 で、ある速度を超えると、どうも資源が足りなくなってるような。 今回のだと、なんだか「セックルキター」ってのがどばどばっと書かれて、 該当datの読み込み数が50回/secを超えたあたりか。 で、いったんこの状態になると、軽くなるまではずっとこの状態が続くように思えるんで、 やっぱ、資源が足りない系な気がするなぁ。 でも、syslogにはそれっぽいの、出てないんだよなぁ。 うぅ、様子見ようと思ったら1869でとまっちゃった。 1) お茶でも飲みましょう 2) 串なホストを弾く 3) ブラ変 4) Cookieなかったら食え 5) 広告開いておく 6) 入力変数成型 7) ホスト取得(携帯は端末ID) 8) 512KB越え or datが書き込めないならエラー 9) Cookie設定 10) ●とかトリップとかキャップとか 11) ブラウザ変ですよん 12) 入力変数のCheck 13) PROXY制限(BBX Rock54 Samba24) 14) スレ立て制限 15) もうちょっと落ち着いて書きこみしてください 16) ID生成 and dat書き込み 17) subject.txt更新 and 1000越え判定 18) HTML出力 19) ふう、疲れた 7でホストを取得する前に2で串なホストを弾いてますね。どんなからくりなんだろう。 >>173 13)のSamba24は連投規制ですよね? timecount/timecloseもないので、この2つで一体化すると良いと思います。 あ、現在の処理か、、 512KB処理と1000超え判定がかなり場所的に離れてますね、、 ホスト取得というのは、書き込んだ時用の記録だと思います 串を弾くのは単純にREMOTE_ADDRだったり、REMOTE_HOSTを使えばいい話ですし をーなんだか愉しそうな香りが(嬉嬉嬉)@bbs.cgi 大改竄計画 173 を検証してみて不要なものとか重複しているところとか 80kg 超えているところとかを検討するとよさそうですね。 でもゆっくりとした時間が取れないので鬱(泪) で、16 以降は単一プロセスでやらせたいなぁ。。。 bbs.cgi が受け持つのは 15 までにする。 あと、 bbs.cgi の起動数の制限を設けたいなぁ。1 鯖につき 50 プロセスまでとか。 書き込まれた内容を処理する前に、 書き込めるかどうかのチェックを、できる限り 済ませておく方向に、できないだろうか… 書き込めなかったら成型処理しても無駄な訳だし… 8)は15)の後に移動するとともに処理直前でsubject.txtをロックしてから 判定と書き込みを行いオーバーしたか18)が終わったらロック解除。 ほとんどオンメモリ状態なはずなので実際の処理は1msかかってないと思うんですよ。 ならばsubject.txtやdatの書き込みとHTML生成はシーケンシャルでもよいかななんてね。 OSのファイルキャッシュがまともに働いていれば、という前提付きですが。 >181 16以降の ファイル書き込みは(TCP経由で)常駐プログラムだけがやるとか? >>185 そんな感じです。 整形された line の先頭に、"bbs<>key<>" を付けて、tai64 形式のファイル名を付けて、特定のディレクトリに投げるの。 でもって、書き込みやさんはその特定のディレクトリだけを監視して(1秒おきにとか)、 何かしらファイルが放り込まれたら書き込みの操作を 1 人でやるの。 svc にさせてもよいかなぁ。 >>186 書き込み屋さんは非同期で動くんですか? bbs.cgiがレスポンスを返すのはHTMLの生成が終わった後でなければマズい気がするんですが……。 >186 ファイルに書き出すのはやめた方がいいと思う 極端な話SQL鯖のような感じにリアルタイムで返って来るようにする リアルタイムで返って来ないと・・・ 書き込んだ内容が反映されてない -> なんらかの規制になってると判断する可能性有 2chブラウザのかちゅ〜しゃに至っては書き込み後自動的にdat読み込む >>188 まずいっけ? もし生成が溜まっていても、bbs.cgiがチェックしていればよさそうだけど。 >>189 書き出しはDBIにしておけば、MySQLでもDBI::Fileでも任意のドライバに変えるのは簡単。 今まではfileオープンしてそこに追記していたんだから。 tai64で1つごとにファイル書き込みしたとしても次元が違うぐらい速度が上がると思うけど。 案1 「bby -- スレッド情報一元管理システム」と同じDNS使用 dnsに板とキーを投げる dnsは板・キー・レスカウントを保持 通常は127.0.0.1を返し レス数1000になったら127.0.0.2を返す 案2 レス数管理にSQL鯖使用 >190 >書き出しはDBIにしておけば、MySQLでもDBI::Fileでも任意のドライバに変えるのは簡単。 2つのプログラム(2重起動含む)から1つのファイルを使って大丈夫なのか? DNSはキャッシュされるのでそういう用途には向いていないと思います。 >2つのプログラム(2重起動含む)から1つのファイルを使って大丈夫なのか? そういう泥臭いことを引き受けてくれるのがDBIです。 パフォーマンスを考えるとSQLデータベースになりますが、それはまぁ後々の話として。 インターフェースさえDBIにしておけば後でいくらでも入れ替えられます。 http://module.jp/works.html のPerlによるハイパフォーマンスWebアプリケーションの開発を参考に >192 http://member.nifty.ne.jp/hippo2000/perltips/DBD/file.htm >このモジュールは内部で flock() を使っています。 2つのプロセスから同時に使えない気がするけど *dat書き込みプロセスがtxt経由するファイル使用中にbbs.cgiプロセスが書き込めないのはダメだぞ bbs.cgiプロセスとdat書き込みプロセスはtxt経由ではなくTCP経由ってこと? 突貫工事で一番簡単な方法。 #DATを書き込む前に open(FILE, '>> ../$FORM{'bbs'}/dat/$FORM{'key'}.idx'); print FILE '1'; close(FILE); # レス数取得 $res = -s '../$FORM{'bbs'}/dat/$FORM{'key'}.idx'; # DAT書き込み open(FILE, '>> ../$FORM{'bbs'}/dat/$FORM{'key'}.dat'); print FILE ""; #適当に if ($res >= 1000) { #レスが1000超えてるときは1000ストップ print(FILE "1000 over ..."); close(FILE); chmod(0444, '../$FORM{'bbs'}/dat/$FORM{'key'}.dat'); } else { #通常は何もせずクローズ close(FILE); } 突貫だけあってその後いろいろめんどくさいです。 素人が書き逃げするですよ 8) 512KB越え or datが書き込めない or ロックディレクトリが存在するならエラー 17) subject.txt更新 and 1000越え判定 1000越えててカキコ可能なら ・ロックディレクトリ作成 ・1001カキコ ・chmod --- 成功したらロックディレクトリ消去 1)の前に "keyfile.txt"(増加カウントファイル)のサイズをチェックして 1000いってなかったら"1>>keyfile.txt"を実行 1000超えてたら書き込み失敗 *書き込めなくてもカウントする 書き込めなかったら マイナスカウントファイルを作って・・・ >>196 use IO::File; my $file = = new IO::File; 以下perldoc IO::File参照 後ついでに http://member.nifty.ne.jp/hippo2000/perltips/phpperl.htm PerlよりPHPの方が軽くて速いは本当? mod_perl化さえ出来れば、コンパイル後状態で動作するのでCで書くCGIに次ぐ動作速度になる。 つまりメンテナンス性で考えるとmod_perlで動くようにPerlで書けばOk。 http://p22.aaacafe.ne.jp/ ~deagle/AE/Perl-CGI/IO-SafeFile/transaction.html 排他処理、およびプロセスの頓死対策 >201 排他処理やると ABCDEFG・・・と50ms順番に投稿したとする(cgiの処理は75msかかるとする) 書き込み成功 ACEG・・・ (奇数回) 書き込み失敗 BDFH・・・ (偶数回) こんな感じになる >>202 ロックが取れなかったら書き込み失敗とみなすならそうですが、 ロックは取れなかったら取れるまで待つものなので、 全部がちゃんと書き込めるです。 >203 >ロックは取れなかったら取れるまで待つものなので NHK実況板だけで動作確認して次は NTV実況板・・・と1つの板毎に実装していかないとlive8鯖がいきなり死ぬ可能性あるね よし。レス数はctimeにやらせよう。 1970/1/1 9:0:1 が1レス目ってことで。 するとアレアレ。 subject.txtなんて/bbs/datみるだけであっという間にできちゃったりアレアレ。 flockなんて過去の遺物です。 1000のプロセスが全て並行で動いていることを想定して考えないと。 >>205 お、それ結構(・∀・)ゐゐ!! かも。 ちょっと移転作業がめんどくなりそうだけど。 今1000ストップが遅れてるのってあれでしょ? dat書き込んだあとに/bbs/html/*.htmlからレス数とって、 1000ストップ判定するっていう処理だったかな。 うるおぼえ。 まず、DATに書く前に1000ストップ判定すべきですよ。 これだけでかなり違うかと。 処理順で言えば、DATを書き込む処理からエラーを吐いちゃいけないので、 DATを開くときにエラーにすればいいんじゃないすか? んで、実際書けない時のエラーはずーっと上の方でやっちゃっているわけで、 間の処理が長くていっぱいかけるわけですよ。 「開く前に調べる」 これだけではないかと・・・。 それと、bbs.cgiを作り直すなら、設計からやるように(す use IO::File; use Fcntl qw(:flock :mode); use constant LIMIT_SIZE => 512*1024; $file = new IO::File($DATAFILE, '+<') or DispError("ERROR!", "スレッドが見つからない"); flock($file, LOCK_EX); DispError("ERROR!", "このスレッドには書けない") unless -w $DATAFILE and -s $file < LIMIT_SIZE; @logdat = $file->getlines(); $lognum = scalar @logdat; $file->print("$outdat\n"); $logdat[$lognum++] = "$outdat\n"; if ($lognum >= 1000) { $file->print("1001<><>Over 1000 Thread<>このスレッドは〜\n"); $lognum++; chmod(S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH, $DATAFILE); } $file->close(); flockを使っていいなら楽なんだけど。 >>205 http://nais.to/ ~yto/tools/kuttuki-counter/ くっつきカウンター と同じアイデアだね。 秒数を進めるところで競合が起こるけど。 今のレス数からepoch + secondすればいいから厳密に1000秒を検知しなくていいのなら面白いね。 >>208 >それと、bbs.cgiを作り直すなら、設計からやるように(す じゃあサブルーチンごとにパラメータとか列記していきましょうよ。 1)から分かる範囲でやりましょう。 泥縄的にアプローチ。 chmodが効かない(全部closeされるまで反映されない?)のが問題なわけで、 (1) chmodと同時に適当なファイル(たとえば「スレッドキー.stop」)も作る (2) サイズオーバーや書込み禁止のチェックと同時に (1) のファイルの存在チェックも行う とすれば、とりあえずは解決するかな、と。 スレッドが1000に達するたびにファイルができるのが難点だけど。 >chmodが効かない(全部closeされるまで反映されない?)のが問題なわけで そうなのか 書き込む直前に1000行ったことを知らせるファイルチェック -> ファイルがあったらエラー 現在の投稿が1000なら1000行ったことを知らせるファイルを作る 実際の書き込み chmodをやる でどうだ >>213 ファイル生成のコストがそれなりにかかりますよ。 ディスクI/Oはなるべく避けたいですし。 そです 1,000 超えて 3,000 とか行くのは いつかなと? その前にチャレンジ版を投入するといいかな? 改善を目指したけど、結果は改悪になるかもしれないけどさ。 今日のめちゃいけはヨモギダ祭りですよ。 あの「ヨモギダ」ですよ。 318 :名無しさん :04/02/28 03:08 ID:atMg9E5Y 2/28(土)ヨモギタ少年愚連隊・記憶編 ←ここ 3/ 2(火)16:00〜16:59・チャンネルα「ヨモギダ・ダイジェスト」 「今週土曜から撮影9年超大型企画ついに解禁ヨモギダ少年と感動の再会最新作」 3/ 3(水)16:00〜16:59・チャンネルα「めちゃ2イケてるッ!(再放送)」 「180日超大作!!岡村大学受験涙と感動ヨモギダ少年3年後の姿」 3/ 4(木)16:00〜16:59・チャンネルα「めちゃ2イケてるッ!(再放送)」 「岡村受験(秘)結果速報・ヨモギダ原宿で盗撮された涙の衝撃映像は」 3/ 5(金)16:00〜16:59・チャンネルα「めちゃ2イケてるッ!(再放送)」 「岡村(秘)大学受験本番・美人教師は19歳東大生・恋と勉強の記録公開」 3/ 6(土)15:25〜17:25・めちゃ2イケてるッ!ヨモギダ完結編 3/ 6(土)ヨモギタ少年愚連隊02編 3/13(土)ヨモギタ少年愚連隊03編 3/20(土)ヨモギタ少年愚連隊04編 今日のブレーメンはたぶんなかなかだと思うけど、単にスレが速いだけでは なかなか再現しないんすよね。 ROMも含めたユーザ数が多くないと、再現しないみたい。 ゴールデンタイムで各局の主力番組が目白押しの時の、 一番の人気番組で発生することが多いみたいだから、、、。 とすると、どれが該当するだろう。 live総合スレで聞いてみるかな。 >>217 peko系実況だけ3000にして人柱にして見るのはどうよと振ってみるテスト。 で、来週金曜1855-2148、TBSでオウム特番あり。 あとテロ朝は1、3、5の深夜、五輪サッカーの予選中継が。 open(OUT, $DATAFILE, "a+"); これが Configration Error になるんですが どうすればいいのかなぁ。。。 >214 >ファイル生成のコストがそれなりにかかりますよ。 「1つのファイル作成」と「数百のプロセス待機」のコストを考えるとどうだろ? 実況板とそれ以外の板でbbs.cgiの使い分けが必要になるかも >>223 open(OUT, "+>>$DATAFILE"); とか? 試してみたが、他プロセスでファイルをopenしているときでも、chmodは効く。 パーミッションはopen時に判定で、print時は関係無いみたい。 となると、以下の部分で1000越えのメッセージいくつも書かれるのが納得いかないが、 もしかして別のところでchmodで書き込み可能にしてない? if(-w $dattemp && $lognum > 999){ open(OVER, ">>$dattemp"); print OVER "1001<><>Over 1000 Thread<>このスレッドは1000を超えました。 <br> もう書けないので、新しいスレッドを立ててくださいです。。。 <>\n"; close(OVER); chmod(0555, $dattemp); >>117 で $DATAFILE なのに >>140 で $dattemp なのが気になったり。 >>229 サブルーチンなので、変数名が変わってるだけかと。 >>228 あるbbs.cgiが「1000を超えました」を書いて、 そのbbs.cgiがdatをクローズして、chmodするまでのわずかな時間に、 別のbbs.cgiが書いていると。 典型的な競合状態ってやつではないかなと。 つまり、プログラミング的には「腕の見せ所」のはず。 228じゃないけど あるプロセスがchmodを行って、完了する前に別のプロセスが書き込みモードでopenしてしまう。 すると、最初のプロセスのchmodが完了せず、別のプロセスの書き込み完了まで待たされる。 その間に、さらに別のプロセスがオープンして、、 という感じで、全プロセスがファイルをcloseしない限り、chmodが完了しないのかな。 でも、なんかおかしいな。 ファイルに対する実際の処理は、要求された順番に行われて欲しいのに chmod完了待ちの間に、次のopenが成功してしまうというのはどうも・・ カーネル内部でこの辺の優先度がいじられてるのかな。 http://www.dd.iij4u.or.jp/ ~okuyamak/Documents/NetworkFileSystem.Tune.4.html の真ん中ちょい下で「chmodを優先するのもアリ」と書いてあるけど その逆に「chmodをあとまわし」にしているのかもしれない。 >>233 のリンク先にこんなのがありますね。 http://www.dd.iij4u.or.jp/ ~okuyamak/Documents/NetworkFileSystem.Tune.4.html より引用: File System は、実は、順序による結果の一意決定性の保証をしなくても File System と して動作するものを作ることができる。 たとえば、2つの process がほぼ同時に write() と chmod() を リクエストしてきたとしよう。 一応、順序的には『write→chmod』だとする。 この場合、File System は、 「んー。なんかこの write、時間がかかりそうだな。 先に chmod やるか」 と言って、内部で順序を入れ替えてしまっても、 実は バレナイ 。 ばれないということは (公平性には欠けるかも知れないが)、 File System の実装としては「あり」だと言うことになる。 しかし、write() と chmod() の間の時間が十分に離れていれば、 そしてこの間にこれ以外の リクエストがいっさい来なければ、 write() と chmod() はこの順序通りに実行される。 仮に、同一のファイルに対する write() 並びに chmod() で、 しかも chmod() されると write() が実行できなくなるような場合、 外部から観察した場合のリクエスト順序 と 内部でのリクエスト順序 が一致しなくなる。 しかも、常に一定の結果になれば良いのだが、 その保証が無い場合、journal を利用しても結果が再現できなくなる。 上の例だと、 wirte と chmod が十分時間間隔を開けて到着したので write->chmod の順で ファイルシステムに反映した結果を client に返したのだが、 この直後に system down を起こしたとしよう。 journal を実行する際には write と chmod は十分短い間隔で 要求されるので、 chmod->write の順で実行してしまったら、 同じ結果を得ることはできない。 つまり、>>234 の例とは逆に、chmod()が(コストが高いから等の理由で) なかなかスケジュール(実行)されないということも、当然ありうるということになりますね。 chmodの後の >$lognum++; って、subject.txtに書き込むレス数で使われるはずで、実際subject.txtには 1000以上の数値が書き込まれているから、chmodで待つということは無いと 思うんだけど。 えと、>>197 あるいは >>212 (←これは俺と別の人)の方法はどうでしょう。 これなら over 1000 判定されたら、 すでに 8) 以降にある別プロセスは蹴れないけれど 8) 以前のプロセスは蹴ることができるので、まあ 1050 位で止まると思う。 >>212 の人が言うように泥縄的アプローチではあるけれど。 >>238 chmodに成功しているけど反映に時間がかかると仮定すると > ・chmod --- 成功したらロックディレクトリ消去 はマズいような。 >>238-239 >213-214にあるが ファイルを作らないでやる方法を考える方が先らしい ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる