社内勉強会資料(varnish module)
DESCRIPTION
7/20に社内勉強で発表したいろんなVMODの紹介資料ほとんど口頭なので参考程度に・・・TRANSCRIPT
Varnish Cacheことはじめ
2012/07/20技術統括部
いわなちゃん(@xcir)
Varnishの特徴
● コンテンツのキャッシュ
● Cライクなドメイン言語VCLによる柔軟な制御
● むしろVCL中にC言語が書ける(インラインC)● 高速なリバースプロキシ
● フラグメントキャッシュなESIへの対応
● ロードバランシングとヘルスチェックが可能
● gzipの圧縮解凍が可能
うちでは主に静的コンテツに使ってます
とまぁ細かい点は
僕のブログにあるVarnishCache入門をご覧ください(ステマ)
http://blog.xcir.net/
VCLでできること・できないこと
● できること● 条件分岐● 数値演算・文字列操作(結合・正規表現)
● できない・難しいこと● 文字列から数値への変換● 時刻計算● Base64などの符号化やハッシュ作成
● バックエンドからのResponseヘッダを除く外部のリソースを取得すること
設定ファイルとしては非常に柔軟だが微妙に痒いところがある
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);}
インラインCでできること・できないこと
● できること● Cでできることなら大抵できる
● できない・難しいこと● セッション跨いだをデータの維持
– コストの高いデータを初期化しても次のセッションでまた初期化する必要が・・・
● Varnish本体側の各種関数や変数へのアクセス– 重要な構造体のメンバにアクセスできなかったり・・・
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;
へ(^o^)へ わーい設定に |へ /
(^\ o^ )へ インラインでCが書けるぞー \| >
( ^< o^) > よっしゃ複雑な処理を・・・ 三) )三< ̄ ̄>
Σ ( ^o^) <) )>グキッ< ̄ ̄>
_人人 人人_> 突然の死 < ̄Y^Y^Y^Y ̄
VCLコード中のちょっとした日付演算などにはいいけど大規模なコードを書くには向かない
VCL中にコードを書くため配布もしづらい
インラインCだけだと正直キツイ
Varnish Module(VMOD)ことはじめ
2012/07/20技術統括部
いわなちゃん(@xcir)
VMODでできること・できないこと
● できること● Cでできることなら大抵
● セッションを跨いだデータの保持● Varnish本体の各種関数や変数へのアクセス
● できないこと● あまりない
モジュール形式なので配布もしやすいし使いやすい
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);
いろんなVMODの紹介
● 公式でリストされているVMODを紹介します
● https://www.varnish-cache.org/vmods● 紹介しているサンプルコードは基本的に
ドキュメントから拾って改変してます● 流石に全部動作確認する時間はなかったので
動かないかも
● 明らかに動かないものは省いてます
試しに使ってみたいものがあれば聞いてみてください
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); }}
crashhandler● セグフォを起こしてバックトレースを取得する
VMODやインラインCでのデバッグに使う● Developed by Kristian Lyngstøl
● https://github.com/varnish/libvmod-crashhandler
サンプルコードimport crashhandler;
vcl_recv{ if(req.url ~ "^/crash/") { crashhandler.crash(); }}
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(); }
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){....
}}
DeviceAtlas Mobile Detection● モバイルデバイスの各種情報を取得
● Developed by Varnish Software
● Varnishソフトウェアが有償で提供しています
● https://www.varnish-cache.org/vmod/deviceatlas-mobile-detection
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!"; }}
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");}
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");}
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);}
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);}
POST/GET/Cookie parse● POST/GET/Cookieの内容をパースする
● Developed by
● https://github.com/xcir/libvmod-parsereq
サンプルコードimport parsereq;
vcl_recv{ if(parsereq.post_header("hoge")){ ... }}
わ た し で す / ̄\ | ^o^ | \_/
redirect● Varnishのめんどくさいリダイレクトを簡単にする
● Developed by
● 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"); }}
わ た し で す / ̄\ | ^o^ | \_/
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");}
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") }}
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(); }}
std - the standard VMOD● VCL中からログ出力を行うなどの基本的なVMOD
VMODのサンプルコード的な役割も● Developed by Per Buer
● 標準でインストールされます
サンプルコードimport std;
sub vcl_recv { std.log(“hogehoge”);}
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);}
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);}
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 ); }}
いろいろVMODが存在
● 公式でリストされてないものだと● LDAP認証
● Firewall● などなど
これらを使うことでより高度なVarnishライフが・・・
それでも欲しい機能がないなら・・・
VMODを作ってみよう
僕のブログにあるinline-C/VMODガイドブック
をご覧ください(ステマ)
ご清聴ありがとうございました