社内勉強会資料(Varnish Module)

8,687 views
8,565 views

Published on

7/20に社内勉強で発表したいろんなVMODの紹介資料
ほとんど口頭なので参考程度に・・・

社内勉強会資料(Varnish Module)

  1. 1. Varnish Cache ことはじめ 2012/07/20 技術統括部 いわなちゃん(@xcir)
  2. 2. Varnishの特徴● コンテンツのキャッシュ● Cライクなドメイン言語VCLによる柔軟な制御● むしろVCL中にC言語が書ける(インラインC)● 高速なリバースプロキシ● フラグメントキャッシュなESIへの対応● ロードバランシングとヘルスチェックが可能● gzipの圧縮解凍が可能 うちでは主に静的コンテツに使ってます
  3. 3. とまぁ細かい点は 僕のブログにあるVarnishCache入門をご覧ください(ステマ) http://blog.xcir.net/
  4. 4. VCLでできること・できないこと● できること ● 条件分岐 ● 数値演算・文字列操作(結合・正規表現)● できない・難しいこと ● 文字列から数値への変換 ● 時刻計算 ● Base64などの符号化やハッシュ作成 ● バックエンドからのResponseヘッダを除く 外部のリソースを取得すること 設定ファイルとしては非常に柔軟だが 微妙に痒いところがある
  5. 5. VCLのサンプルsub vcl_recv{ //クライアントからのレスポンスを受け取る if(req.url ~ "(?|&)purge=1" && client.ip ~ local){//キャッシュ削除 ban("obj.http.X-HOST ~ "+ req.http.host + " && obj.http.X-URL ~ " + regsub(req.url,"?.*$","")); error 200 "banned."; } //admin/以外のクッキー削除 if(req.http.Cookie && !(req.http.host ~ "^blog.example.net" && req.url ~ "^/admin/")){ unset req.http.Cookie; } if(req.http.host ~ "^blog.example.net"){ set req.backend = blog; if( ! req.backend.healthy){ //blog 死亡 set req.backend = cdn; //blog 死亡のためcdn/sorry.htmlに向ける set req.url = "/sorry.html"; }elseif(req.url ~ "^/admin/"){ //admin はキャッシュしない return(pass); } }elseif(req.http.host ~ "^cdn.example.net"){ set req.backend = cdn; }else{//不明なホストは403 error 403 "Forbidden"; } return(lookup);}
  6. 6. インラインCでできること・できないこと● できること ● Cでできることなら大抵できる● できない・難しいこと ● セッション跨いだをデータの維持 – コストの高いデータを初期化しても 次のセッションでまた初期化する必要が・・・ ● Varnish本体側の各種関数や変数へのアクセス – 重要な構造体のメンバにアクセスできなかったり・・・
  7. 7. Inline-Cのサンプル memcachedに接続C{#include <stdlib.h>#include <stdio.h>#include <libmemcached/memcached.h>void mctest(char *k ,char *v){ struct memcached_st *mmc = NULL; struct memcached_server_st *servers = NULL; memcached_return rc; mmc = memcached_create(NULL); servers = memcached_server_list_append(servers,"localhost", 11211, &rc); rc = memcached_server_push(mmc, servers); memcached_server_list_free(servers); rc = memcached_set(mmc, k, strlen(k), v, strlen(v), 600, 0); memcached_free(mmc);}}Csub mcSet{if(req.http.X-mck && req.http.X-mcv){C{char *key=VRT_GetHdr(sp,HDR_REQ,"006X-mck:");char *value=VRT_GetHdr(sp,HDR_REQ,"006X-mcv:");mctest(key,value);}C}remove req.http.X-mck;remove req.http.X-mcv;}sub vcl_recv{set req.http.X-mck = "Last:req.xid";set req.http.X-mcv = req.xid;call mcSet;
  8. 8. インラインCだけだと正直キツイ へ(^o^)へ わーい設定に    |へ   / \(^o^ )へ インラインでCが書けるぞー   \|    > <( ^o^)> よっしゃ複雑な処理を・・・  三) )三 < ̄ ̄> Σ ( ^o^)  <) )>グキッ < ̄ ̄> _人人 人人_ > 突然の死 <  ̄Y^Y^Y^Y ̄VCLコード中のちょっとした日付演算などにはいいけど大規模なコードを書くには向かない VCL中にコードを書くため配布もしづらい
  9. 9. Varnish Module(VMOD) ことはじめ 2012/07/20 技術統括部 いわなちゃん(@xcir)
  10. 10. VMODでできること・できないこと● できること ● Cでできることなら大抵 ● セッションを跨いだデータの保持 ● Varnish本体の各種関数や変数へのアクセス● できないこと ● あまりない モジュール形式なので配布もしやすいし 使いやすい
  11. 11. VMODのサンプル memcachedに接続■vcc(vmodのヘッダファイルみたいなもの)Function VOID mcset(STRING,STRING)■c#include <stdlib.h>#include <stdio.h>#include <libmemcached/memcached.h>void vmod_mcset(struct sess *sp, const char *k ,const char *v){ struct memcached_st *mmc = NULL; struct memcached_server_st *servers = NULL; memcached_return rc; mmc = memcached_create(NULL); servers = memcached_server_list_append(servers, "localhost", 11211, &rc); rc = memcached_server_push(mmc, servers); memcached_server_list_free(servers); rc = memcached_set(mmc, k, strlen(k), v, strlen(v), 600, 0); memcached_free(mmc);}■VCLexample.mcset("Last:req.xid",req.xid);
  12. 12. いろんなVMODの紹介● 公式でリストされているVMODを紹介します ● https://www.varnish-cache.org/vmods● 紹介しているサンプルコードは基本的に ドキュメントから拾って改変してます ● 流石に全部動作確認する時間はなかったので 動かないかも● 明らかに動かないものは省いてます 試しに使ってみたいものがあれば 聞いてみてください
  13. 13. Authentication● Basic認証を行うモジュール ID/PWを固定で簡単に認証を入れたい時は便利 ● Developed by Omega Software Development Group ● https://github.com/omegasdg/libvmod-authentication サンプルコード import authentication; vcl_recv{ if(req.url ~ "^/protected/") { if(!authentication.match("admin", "test")) { error 401 "Authentication Required"; } } } vcl_error{ if (obj.status == 401) { set obj.http.WWW-Authenticate = {"Basic realm="Authorization Required""}; synthetic {"Error 401 Unauthorized"}; return(deliver); } }
  14. 14. crashhandler● セグフォを起こしてバックトレースを取得する VMODやインラインCでのデバッグに使う ● Developed by Kristian Lyngstøl ● https://github.com/varnish/libvmod-crashhandler サンプルコード import crashhandler; vcl_recv{ if(req.url ~ "^/crash/") { crashhandler.crash(); } }
  15. 15. cURL● VCL中にHTTPで他リソースを取得する APIを叩いてその結果のような使い方ができるかも ● Developed by Varnish Software ● https://github.com/varnish/libvmod-curl サンプルコード import curl; sub vcl_recv { curl.fetch("http://example.com/test"); if (curl.header("X-Foo") == "bar") { … } curl.free(); }
  16. 16. dClass OpenDDR (decision classification)● UAからデバイス情報を取得する(OpenDDR) ぱっと見た感じディスプレイサイズなども取得可能 ● Developed by Weather Channel ● https://github.com/TheWeatherChannel/dClass サンプルコード import dclass; sub vcl_init { dclass.init_dclass("/some/path/OpenDDR/1.0.0.0/resources"); dclass.init_dclass_p("/some/path/dClass/dtrees/browser.dtree",1); } sub vcl_recv { set req.http.dclass_openddr = dclass.classify(req.http.user-agent); set req.http.dclass_browser = dclass.classify_p(req.http.user-agent,1); if(dclass.get_ifield("displayWidth") > 320){ .... } }
  17. 17. DeviceAtlas Mobile Detection● モバイルデバイスの各種情報を取得 ● Developed by Varnish Software ● Varnishソフトウェアが有償で提供しています ● https://www.varnish-cache.org/vmod/deviceatlas-mobile-detection
  18. 18. Digest● HMAC-sha1などダイジェストやBase64が扱える SHA1などのDigestの出力はHEXエンコードされて いるので注意 ● Developed by Kristian Lyngstøl ● https://github.com/varnish/libvmod-digestサンプルコードimport digest;sub vcl_recv { if (digest.hmac_sha256("key",req.http.x-some-header) != digest.hmac_sha256("key",req.http.x-some-header-signed)) { error 401 "Naughty user!"; }}
  19. 19. example vmod - hello world!● VMODを作るときに参考になります ● Developed by Martin Blix Grydeland ● https://github.com/varnish/libvmod-example サンプルコード import example; sub vcl_deliver { # This sets resp.http.hello to "Hello, World" set resp.http.hello = example.hello("World"); }
  20. 20. Header manipulation● ヘッダーの操作を行うモジュール 主にクッキーの値の追加や削除を行う ● Developed by Kristian Lyngstøl ● https://github.com/varnish/libvmod-header サンプルコード import header; sub vcl_fetch { header.append(beresp.http.Set-Cookie,"foo=bar"); header.remove(beresp.http.Set-Cookie,"dontneedthiscookie"); }
  21. 21. Memcached● Memcacheへ値のset/get/incrなどを行う ● Developed by Aaron Stone ● https://github.com/sodabrew/libvmod-memcached サンプルコード import memcached; sub vcl_deliver { memcached.servers("localhost"); memcached.set("your_counter", "1", 100, 0); memcached.incr("your_counter", 10); set resp.http.count = memcached.incr("your_counter", 1); }
  22. 22. null - Binary data in synthetic● バイナリデータを送信したいときに利用 vcl_errorでインラインCから使うのが一般的 ● Developed by Kristian Lyngstøl ● https://github.com/varnish/libvmod-header サンプルコード import null; sub vcl_error { C{ Vmod_Func_null.synth(sp,"TEST",4); }C return(deliver); }
  23. 23. POST/GET/Cookie parse● POST/GET/Cookieの内容をパースする わ た し で す    / ̄\    ● Developed by   | ^o^ |     \_/    ● https://github.com/xcir/libvmod-parsereq サンプルコード import parsereq; vcl_recv{ if(parsereq.post_header("hoge")){ ... } }
  24. 24. redirect● Varnishのめんどくさいリダイレクトを簡単にする わ た し で す    / ̄\    ● Developed by   | ^o^ |     \_/    ● https://github.com/xcir/libvmod-redirect サンプルコード import redirect; sub vcl_recv { if (req.http.user-agent ~ "iP(hone|od)") { error(redirect.location(302,"http://www.example.com/iphoneversion/") , "Moved Temporarily"); } }
  25. 25. Redis● Redisにコマンドを送信する ● Developed by ZephirWorks ● https://github.com/zephirworks/libvmod-redis サンプルコード import redis; sub vcl_init{ redis.init_redis("localhost", 6379, 200); } sub vcl_recv { redis.send("LPUSH client " + client.ip); set req.http.x-redis = redis.call("LTRIM client 0 99"); }
  26. 26. Secure download● Nginxやlighttpdにもある特定の時間まで有効な 使い捨てURL機能を実現する ● Developed by Aurelien Guillaume ● https://github.com/footplus/libvmod-secdown サンプルコード import secdown; sub vcl_recv { if (req.url ~ "^/protected/") { set req.url = secdown.check_url(req.url, "h4ckme", "/expired.html", "/error.html") } }
  27. 27. Shield● クライアントの接続を即切断する機能 dDoS攻撃などの対策に使う ● Developed by Martin Blix Grydeland ● https://github.com/varnish/libvmod-shield サンプルコード import shield; sub vcl_recv { if (req.url ~ "i-am-an-attacker") { shield.conn_reset(); } }
  28. 28. std - the standard VMOD● VCL中からログ出力を行うなどの基本的なVMOD VMODのサンプルコード的な役割も ● Developed by Per Buer ● 標準でインストールされます サンプルコード import std; sub vcl_recv { std.log(“hogehoge”); }
  29. 29. URL Code● URLエンコード・デコードを行う ● Developed by Fastly Inc ● https://github.com/fastly/libvmod-urlcode サンプルコード import urlcode; sub vcl_recv { set req.url = "/example?url=" + urlcode.encode("http://" + req.http.host + req.url); }
  30. 30. URL Sort● URLのクエリをソートしてクエリの順番が違うだけ で別のキャッシュにならないように正規化する ● Developed by Fastly Inc ● https://github.com/cyberroadie/varnish-urlsort サンプルコード import urlsort; sub vcl_recv { set req.url =urlsort.sortquery(req.url); }
  31. 31. Variable Support● 文字列・整数・実数が扱える変数を提供する ● Developed by Varnish Software ● https://github.com/varnish/libvmod-var サンプルコード import var; sub vcl_recv { if (req.http.user-agent ~ iP(od|ad|hone) ) { set var.set_int("idevs", var.get_int("i1") + 1 ); } }
  32. 32. いろいろVMODが存在● 公式でリストされてないものだと ● LDAP認証 ● Firewall ● などなど これらを使うことで より高度なVarnishライフが・・・
  33. 33. それでも欲しい機能がないなら・・・
  34. 34. VMODを作ってみよう 僕のブログにあるinline-C/VMODガイドブック をご覧ください(ステマ)
  35. 35. ご清聴ありがとうございました

×