mala氏の Studying HTTP with Perl を見ながら書いたノートの清書

  • リクエストを 5000/sec とかするときのための
  • 200/secでよければ別にLWP使ってればいいよマジで、実際便利だし。

非並列なhttpアクセス

LWP::RobotUA robots.txt見たりするので行儀が良い
URI::Fetch キャッシュとかする、インターフェースがいい
HTTP::Lite 依存モジュールなし、どこでも使えるよ
LWPx::ParanoidAgent ローカルIPは弾く、WEB魚拓的サービスに

並列なhttpアクセス

AnyEvent::HTTP 簡単
Coro::LWP コルーチン、黒魔術(なにをしてるか理解して使おう)
AnyEvent::Curl curlのオプションを覚えなくてはダメ
  • Coro::LWPはLWPをcoro使用に全て置き換えるから注意。
    • coroそのものを知りましょう

Curlって

cURLのこと、Cpan記法だからCurlだけど実際のCurlは言語。
curlっていうコマンドラインのfetch、wgetの仲間みたいなやつもある。

perlで並列処理をする場合

イベント駆動+prefork が最適解

I/O待ち
非同期
重い処理
worker
ブロッキング
forkして別プロセス

preforkは諸問題あるからイベント駆動がおすすめ
いちおう、処理時間、アクセス時間が完璧に計算出来るのであればpreforkの方がいい。

早いパーサ

HTTP::Response::Parser
  • ヘッダとかLastModifiedの速度とかbodyを分けるためのパーサ
  • 既存の重い
  • PurePerlでがんばって、XSした
  • picohttpparser(とても優秀) を使った
  • 欠点:今は不安定(関連libのせい、verupなど待ち

DNS解決が遅い

  • DNS解決に時間がかかってしまうとリクエスト投げれない
  • Squidにまかすといろいろ解決
  • Squid側でローカルIPをはじくことも出来るし(LWPx::Paranoidかわりになる)

RPC

プロトコルを作るな、httpでいい。httpは充分早いし。汎用性高いし。

テスト手法

  • タイムアウトするくらい反応遅いサーバを作ってそこにアクセス
  • あと、認証とかストリーミングとか
  • キーワード:Plack, PSGI app
タイムアウトサーバのコード
app => sub {
    my $env = shift;
    my $req = Plack::Request->new($env);
    sleep 2;
    return [
        200, [ 'Content-Type' => 'text/plain' ],
        ["Hellow World after 2 sec"] 
    ];
},
クライアント側の方
client => sub {
    my $cb  = shift;
    my $req = HTTP::Request->new(GET => "http://localhost/hello");
    my $cv  = $cb->($req, sub{}, {timeout => 1});
    my $res = $cv->recv;
    ok( !$res->is_success, "fail by timeouot" );
    is( $res->code, 500, "check status code");
    is( $res->{error}, 
        WWW::Curl::Easy->new->strerror(CURLE_OPERATION_TIMEDOUT),
       "error str"
    );
}


おわり

via http://subtech.g.hatena.ne.jp/mala/20101020

GoogleIMEの勝手に切り替わる問題について

ctrl+shiftを押すとIMEがMSIMEに切り替わる問題の解決方法。

  1. 言語バー右クリック
  2. 設定(「テキスト サービスと入力言語」ダイアログ)
  3. 設定タブのキーの設定ボタン
  4. 詳細なキー設定ダイアログで「入力言語を切り替える」のホットキーをOFF


via http://ooze-flash.com/2010/09/google-ime.html

イベント・無名関数・引数・クロージャ

忘れがちなコードをメモ。
無名関数はその無名関数の含まれるスコープ(1個外側のイメージ)で動く。
無名関数に引数を持たせる場合は即実行される。
だから2重に囲む必要がある。

    var target="hondarake";
    (function(arg){
        $("#backmask").click(function(){HideDialog(arg);});
    })(target);


via http://efcl.info/adiary/setTimeout%20%E3%81%A7%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B%E9%96%A2%E6%95%B0%E3%81%AB%E5%BC%95%E6%95%B0%E3%82%92%E6%B8%A1%E3%81%99

QNAPのNAS、TS-419Pは多分良い

RAID-5設定で半年安定稼動した。
忘れないうちにメモる。

速度

よく覚えてないけど300GBを一週間でぶちこめた。
細かいファイルだと重いとか、とにかく原因不明に重いとかないのでないのでよしと出来る。

安定性

半年持ってる。これまで使ってきたNASがクソばかりで半年以内に死ぬのが多かったから相対的に良し。

アクセス制御

フォルダごとに出来る。フィーリングでやって失敗しなかった。

その他

機能がいろいろあったがsambaファイルサーバとしてしか使わないから、webサーバ機能とかあるけど知らない。


googleニュース設置時の記録

設定

  • 記事本文は表示したくない
    • resultStyle : GSnewsBar.RESULT_STYLE_COMPRESSED,
  • target="_blank"にしたい
    • linkTarget : GSearch.LINK_TARGET_BLANK,
<!-- News Bar Code and Stylesheet -->
<SCRIPT src="http://www.google.com/uds/api?file=uds.js&v=1.0&source=uds-nbw"
type="text/javascript"></SCRIPT>
<STYLE type="text/css">
@import url("http://www.google.com/uds/css/gsearch.css");
</STYLE>
<SCRIPT type="text/javascript">
window._uds_nbw_donotrepair = true;
</SCRIPT>
<SCRIPT src="http://www.google.com/uds/solutions/newsbar/gsnewsbar.js?mode=new"
type="text/javascript"></SCRIPT>
<STYLE type="text/css">
@import url("http://www.google.com/uds/solutions/newsbar/gsnewsbar.css");
</STYLE>
<STYLE>
.titleBox_gsnb {
display:none;
}
a.gs-title:link {
border-left:10px solid #476bb4;
padding-left:5px;
color: #0099FF;
}
a.gs-title:link * {
color: #0099FF;
}
a.gs-title:visited {
border-left:10px solid #476bb4;
padding-left:5px;
color: #0071CC;
}
a.gs-title:visited * {
color: #0071CC;
}
a.gs-title:hover {
border-left:14px solid #476bb4;
padding-left:5px;
color: #00CCff;
}
a.gs-title:hover * {
color: #00CCff;
}
</STYLE>
<!-- /News Bar Code and Stylesheet -->
<!-- ++Begin News Bar Wizard Generated Code++ -->
  <div id="newsBar-bar">
    <span style="color:#676767;font-size:11px;margin:10px;padding:4px;">Loading...</span>
  </div>
  <SCRIPT type="text/javascript">
    function LoadNewsBar() {
      var newsBar;
      var options = {
        largeResultSet : false,
        resultStyle : GSnewsBar.RESULT_STYLE_COMPRESSED,
        title : "",
        linkTarget : GSearch.LINK_TARGET_BLANK,
        horizontal : false,
        autoExecuteList : {
          executeList : ["奄美大島"]
        }
      }
      newsBar = new GSnewsBar(document.getElementById("newsBar-bar"), options);
    }
    GSearch.setOnLoadCallback(LoadNewsBar);
  </SCRIPT>
<!-- ++End News Bar Wizard Generated Code++ -->



<DIV id="fragment-2">
<!-- ++Begin News Bar Wizard Generated Code++ -->
  <div id="newsBar-bar2">
    <span style="color:#676767;font-size:11px;margin:10px;padding:4px;">Loading...</span>
  </div>
  <SCRIPT type="text/javascript">
    function LoadNewsBar2() {
      var newsBar;
      var options = {
        largeResultSet : false,
        resultStyle : GSnewsBar.RESULT_STYLE_COMPRESSED,
        title : "",
        linkTarget : GSearch.LINK_TARGET_BLANK,
        horizontal : false,
        autoExecuteList : {
          executeList : ["喜界島"]
        }
      }
      newsBar = new GSnewsBar(document.getElementById("newsBar-bar2"), options);
    }
    GSearch.setOnLoadCallback(LoadNewsBar2);
  </SCRIPT>
<!-- ++End News Bar Wizard Generated Code++ -->
</DIV>
<DIV id="fragment-3">
<!-- ++Begin News Bar Wizard Generated Code++ -->
  <div id="newsBar-bar3">
    <span style="color:#676767;font-size:11px;margin:10px;padding:4px;">Loading...</span>
  </div>
  <SCRIPT type="text/javascript">
    function LoadNewsBar3() {
      var newsBar;
      var options = {
        largeResultSet : false,
        resultStyle : GSnewsBar.RESULT_STYLE_COMPRESSED,
        title : "",
        linkTarget : GSearch.LINK_TARGET_BLANK,
        horizontal : false,
        autoExecuteList : {
          executeList : ["徳之島"]
        }
      }
      newsBar = new GSnewsBar(document.getElementById("newsBar-bar3"), options);
    }
    GSearch.setOnLoadCallback(LoadNewsBar3);
  </SCRIPT>
<!-- ++End News Bar Wizard Generated Code++ -->
</DIV>
<DIV id="fragment-4">
<!-- ++Begin News Bar Wizard Generated Code++ -->
  <div id="newsBar-bar4">
    <span style="color:#676767;font-size:11px;margin:10px;padding:4px;">Loading...</span>
  </div>
  <SCRIPT type="text/javascript">
    function LoadNewsBar4() {
      var newsBar;
      var options = {
        largeResultSet : false,
        resultStyle : GSnewsBar.RESULT_STYLE_COMPRESSED,
        title : "",
        linkTarget : GSearch.LINK_TARGET_BLANK,
        horizontal : false,
        autoExecuteList : {
          executeList : ["沖永良部島"]
        }
      }
      newsBar = new GSnewsBar(document.getElementById("newsBar-bar4"), options);
    }
    GSearch.setOnLoadCallback(LoadNewsBar4);
  </SCRIPT>
<!-- ++End News Bar Wizard Generated Code++ -->
</DIV>
<DIV id="fragment-5">
<!-- ++Begin News Bar Wizard Generated Code++ -->
  <div id="newsBar-bar5">
    <span style="color:#676767;font-size:11px;margin:10px;padding:4px;">Loading...</span>
  </div>
  <SCRIPT type="text/javascript">
    function LoadNewsBar5() {
      var newsBar;
      var options = {
        largeResultSet : false,
        resultStyle : GSnewsBar.RESULT_STYLE_COMPRESSED,
        title : "",
        linkTarget : GSearch.LINK_TARGET_BLANK,
        horizontal : false,
        autoExecuteList : {
          executeList : ["与論島"]
        }
      }
      newsBar = new GSnewsBar(document.getElementById("newsBar-bar5"), options);
    }
    GSearch.setOnLoadCallback(LoadNewsBar5);
  </SCRIPT>
<!-- ++End News Bar Wizard Generated Code++ -->
</DIV>