30
Using ngx_lua in pixiv Harukasan a.k.a MICHII Shunsuke 2013-06-24

Using ngx_lua / lua-nginx-module in pixiv

Embed Size (px)

DESCRIPTION

ドリコム、リブセンスさんとの合同勉強会で話したスライドです。

Citation preview

Page 1: Using ngx_lua / lua-nginx-module in pixiv

/ 30

Using ngx_lua in pixivHarukasan

a.k.a MICHII Shunsuke2013-06-24

Page 2: Using ngx_lua / lua-nginx-module in pixiv

/ 30

はるかさんインフラ部所属 2年目

Nginx / Apache / MySQL / MongoDB

Kyototycoon / Solr / Traffic Server / Fluentd

Capistrano / Ruby on Rails / Macbook Air / Vim

2

Page 3: Using ngx_lua / lua-nginx-module in pixiv

/ 303

• about pixiv Image Cluster

• ngx_lua

• directives in nginx.conf

• nginx api in lua scripts

• ex. code from pixiv Image Cluster

Agenda

Page 4: Using ngx_lua / lua-nginx-module in pixiv

/ 304

pixiv Image Cluster

Page 5: Using ngx_lua / lua-nginx-module in pixiv

/ 305

Front

Cache Cluster

Image Store

SSD-RAID0

 HDD SSD

Thumbnailbig size

Memory

DEVICEpeak: 1k req/sec10Gbps

x20

x20

Page 6: Using ngx_lua / lua-nginx-module in pixiv

/ 306

Front

Cache Cluster

Image Store

PRODUCT

Nginx with tmpfs

Traffic Server

Apache / NginxNginx

Page 7: Using ngx_lua / lua-nginx-module in pixiv

/ 307

ngx_luagithub.com/chaoslawful/lua-nginx-module

Page 8: Using ngx_lua / lua-nginx-module in pixiv

/ 308

• embeds Lua/LuaJIT into Nginx

• has 100% non-blocking API

• has many libraries provided by OpenResty

• memcached, mysql, redis, etc.

ngx_lua

Page 9: Using ngx_lua / lua-nginx-module in pixiv

/ 309

# load from /etc/nginx/scripts/?.lua and default rootlua_package_path "/etc/nginx/scripts/?.lua;;";

server {listen 80;

# GET /fact?a=4 -> 24 (4! = 4 * 3 * 2 * 1)location /fact {content_by_lua "local val = 1for i = 2, ngx.var.arg_a doval *= i;

end";

}

# same code in filelocation /fact_script {content_by_lua_file "fact.lua";

}}

Page 10: Using ngx_lua / lua-nginx-module in pixiv

/ 3010

Directives in nginx.conf• *_by_lua, *_by_lua_file

• init_by_lua

• rewrite_by_lua

• access_by_lua

• content_by_lua

設定読み込みrewrite処理access処理bodyの生成処理

Page 11: Using ngx_lua / lua-nginx-module in pixiv

/ 3011

init_by_lua <code>masterが設定をロードするタイミングで実行する

init_by_lua " memcached = require 'resty.memcached' ";

server {! listen 8888;! default_type 'text/plain';

! location /init_by {! ! content_by_lua "! ! local hello = memcached::get('Hello');

...! ! ";! }}

Page 12: Using ngx_lua / lua-nginx-module in pixiv

/ 3012

server {listen 80;

# GET /sum?a=2&b=3 -> 5location /sum {set_by_lua $sum "return tonumber(ngx.var.arg_a) + tonumber(ngx.var.arg_b)

";

echo $sum;}

}

set_by_lua $res <code>実行したコードの返値を$resにセットする

Page 13: Using ngx_lua / lua-nginx-module in pixiv

/ 3013

server rewrite

find config

rewrite

post rewrite

pre-access

access

post-access

try files

content

logging

Request

rewrite/access/content_by_luaサーバーコンテキストのrewrite

該当するlocation configを探す

locationのrewrite処理

ファイルへのアクセス

try_fileの処理

bodyの生成

ログ書き込み

access_by_lua

content_by_lua

rewrite_by_lua

rewriteに関連する処理

アクセス制御

bodyの操作

Page 14: Using ngx_lua / lua-nginx-module in pixiv

/ 3014

server {listen 8888;

location /rewrite_by {rewrite_by_lua "ngx.var.toggle = true";if ($toggle) {

rewrite / /index_second.html;}

}}

rewrite_by_lua <code>rewriteの前に指定したコードを実行する

Page 15: Using ngx_lua / lua-nginx-module in pixiv

/ 3015

server {listen 80;

# GET /access_by?status=404 => 404 Not Foundlocation /access_by {access_by_lua "ngx.exit(ngx.var.arg_status)";

}}

access_by_lua <code>access phaseに指定したコードを実行する

Page 16: Using ngx_lua / lua-nginx-module in pixiv

/ 3016

# GET /hellolocation /hello {

content_by_lua "ngx.say('Hello, from lua')

";}

content_by_lua <code>responseを生成するコードを実行する

Page 17: Using ngx_lua / lua-nginx-module in pixiv

/ 3017

Directives in nginx.conf• LuaスクリプトでNginxの各動作を制御できる

• HTTPで必要な各フェーズでフックできる

• rewrite

• access control

• content generation

ここまで8分

Page 18: Using ngx_lua / lua-nginx-module in pixiv

/ 3018

Nginx API in lua scripts• generate content

• variables and shared tables

• access memcached / MySQL

Page 19: Using ngx_lua / lua-nginx-module in pixiv

/ 3019

location /var {content_by_lua " ngx.say('Hello, from lua!') ";

}

ngx.say content bodyに文字列を出力する

location /var {access_by_lua " ngx.exit(418) "; # i'm a teapot

}

ngx.exit 指定したステータスコードを返す

Page 20: Using ngx_lua / lua-nginx-module in pixiv

/ 3020

location /var {set $a "alpha";rewrite_by_lua "ngx.var.b = ngx.var.a .. 'beta'";echo $b;

}

ngx.var.*

ngx.ctx.*location /ctx {

access_by_lua "ngx.ctx.foo = 74";rewrite_by_lua "ngx.ctx.foo = ngx.ctx.foo + 5";content_by_lua "ngx.say('foo: ' .. ngx.ctx.foo)";

}

Nginxの変数にアクセスする

リクエスト中に共有されるテーブル

Page 21: Using ngx_lua / lua-nginx-module in pixiv

/ 3021

ngx.shared.* shared memoryテーブルhttp {

lua_shared_dict foo 10m;server {

location /shared-set {content_by_lua "

local foo = ngx.shared.foofoo:set(ngx.var.arg_key, ngx.var.arg_val)

";}location /shared-get {

content_by_lua "local foo = ngx.shared.foongx.say(foo:get(ngx.var.arg_key))

";}

}}

Page 22: Using ngx_lua / lua-nginx-module in pixiv

/ 3022

Regular Expressions• ngx.re.match

• ngx.re.gmatch

• ngx.re.sub

• ngx.re.gsub

Page 23: Using ngx_lua / lua-nginx-module in pixiv

/ 3023

local matches, err = ngx.re.match("key=val", "([^=]+)=(.+)")

ngx.re.match

ngx.re.sub

matches[0] => "key=val"matches[1] => "key"matches[2] => "val"

local newstr,n,err = ngx.re.sub("Hello,lua","lua", "nginx")

newstr = "Hello,nginx"

Page 24: Using ngx_lua / lua-nginx-module in pixiv

/ 3024

• OpenResty

• lua-resty-memcachedgithub.com/agentzh/lua-resty-memcached

• lua-resty-mysqlgithub.com/agentzh/lua-resty-mysql

• ngx.socketを使って実装されている

Access to memcached/MySQL

Page 25: Using ngx_lua / lua-nginx-module in pixiv

/ 3025

Nginx API in lua scripts• 簡単な処理を書くには十分な関数が提供されている• 正規表現• ハッシュ(md5, sha1)

• ソケット• OpenRestyを使うとmemcachedへのアクセスとかも簡単

Page 26: Using ngx_lua / lua-nginx-module in pixiv

/ 3026

Example code from

pixiv Image Cluster

Page 27: Using ngx_lua / lua-nginx-module in pixiv

/ 3027

Kyototycoon

Logical Delete

Nginx

200404

/img01.png 200

/img02.png 200

/img03.png 404

/img04.png 200

GET /img01.png GET /img03.png

404

Page 28: Using ngx_lua / lua-nginx-module in pixiv

/ 3028

Logical Delete

local memcached = require "resty.memcached"local uri = ngx.var.request_urilocal memc = memcached:new()

local val, flags, err = memc:get(request_uri)if val and val ~= "200" then exit(tonumber(val))end

logical_delete.lua

location / { access_by_lua_file logical_delete.lua;}

Page 29: Using ngx_lua / lua-nginx-module in pixiv

/ 3029

Conclusion• Nginxだけで簡単な処理を実現できる• アクセス制御とかインプレッション計測とかには便利そう

• 高速で省メモリ• メンテナンスコストを抑えられる

Page 30: Using ngx_lua / lua-nginx-module in pixiv

/ 3030

ReferencesHTTPLuaModule - Nginx Wikihttp://wiki.nginx.org/HttpLuaModule

chaoslawful/lua-nginx-module - Githubhttps://github.com/chaoslawful/lua-nginx-module