42
mruby_nginx_module 久保 達彦 [email protected] pyfes 2013/11/30

mruby_nginx_module at pyfes 2013.11

Embed Size (px)

Citation preview

Page 1: mruby_nginx_module at pyfes 2013.11

mruby_nginx_module~

久保 達彦 [email protected]

pyfes 2013/11/30

Page 2: mruby_nginx_module at pyfes 2013.11

自己紹介✦ 久保 達彦(H.N:bokko)

✦ @cubicdaiya(twitter, github) ✦ Senior Software Engineer@pixiv Inc.

✦ インフラチーム所属

✦ ミドルウェアの開発・運用とかやってます

Page 3: mruby_nginx_module at pyfes 2013.11

Goはじめました

Page 4: mruby_nginx_module at pyfes 2013.11

普段はnginxのモジュールとか作ってます

✦ mruby_nginx_module ✦ Embed mruby into nginx

✦ ngx_small_light ✦ Dynamic Image Transformation for nginx

✦ ngx_access_token ✦ Porting of mod_access_token into nginx

✦ Nginx本体にも2件ほどパッチ送りました

Page 5: mruby_nginx_module at pyfes 2013.11

WEB+DBでもnginxの記事を書きましたWEB+DB PRESS Vol.72 !

□詳解nginx

!

設定の柔軟性と 優れたスケーラビリティ !

□共著者

@harukasan @semind

Page 6: mruby_nginx_module at pyfes 2013.11

nginx in pixiv

✦ リバースプロキシとかキャッシュとかWebDAVとか色々な箇所で稼働しています

✦ Using ngx_lua in pixiv

✦ http://www.slideshare.net/harukayon/ngx-lua-public

✦ @harukasan++

Page 7: mruby_nginx_module at pyfes 2013.11

とあるpixivを支えるインフラエンジニア談

Page 8: mruby_nginx_module at pyfes 2013.11

mruby_nginx_module ~Embed mruby into nginx~

Page 9: mruby_nginx_module at pyfes 2013.11

mruby_nginx_module✦ nginxの拡張モジュール

✦ nginx.confでmrubyが書ける

✦ nginxのモジュールがmrubyで書ける

✦ ngx_mrubyからfork at 2013/07

✦ それまではPull Request送る形で開発に参加してました

✦ http://git.io/d3sJtw

Page 10: mruby_nginx_module at pyfes 2013.11

ngx_mrubyとの違い

✦ (mod|ngx)_mrubyはWebサーバの拡張記述統一が目的の一つ

✦ Apacheでもnginxでもできる限り同じように書けるのが重要

✦ 機能は極力mrbgemsで実現する方向

✦ mruby_nginx_moduleはnginxとの親和性を重視

✦ 機能は極力nginxのAPIで実現する方向

Page 11: mruby_nginx_module at pyfes 2013.11

ドキュメント http://cubicdaiya.github.io/

mruby_nginx_module/

Page 12: mruby_nginx_module at pyfes 2013.11

mruby

✦ 軽量Ruby

✦ 組み込み分野向けにまつもとゆきひろ氏が開発

✦ Cと連携しやすいように設計されてる

✦ 個人的にはリッチなLuaというイメージ

Page 13: mruby_nginx_module at pyfes 2013.11

Luaから見たmruby

✦ Cとの連携が非常に楽

✦ Luaのスタック操作に比べるとかなり直感的

✦ オブジェクト指向機能のサポート

✦ Luaでもtableで頑張ることはできるがmrubyに比べると弱い

Page 14: mruby_nginx_module at pyfes 2013.11

ngx_luaとmruby_nginx_module(あるいはngx_mruby)

Page 15: mruby_nginx_module at pyfes 2013.11

ngx_lua

✦ ノンブロッキングアーキテクチャ

✦ nginxやその他拡張モジュールとの親和性が非常に高い

✦ 関連モジュールが豊富(lua-resty-xxx)

✦ 拡張モジュールというかもはやフレームワークの域

✦ lua-jitと組み合わせたら鬼に金棒

✦ OpenRestyの中核モジュール

Page 16: mruby_nginx_module at pyfes 2013.11

mruby_nginx_module

✦ まだまだ発展途上

✦ 機能とかライブラリとかいろいろ足りてない

✦ ノンブロッキングなアーキテクチャにするのが当面の課題

✦ フック関連のディレクティブ群はほぼ同等レベルまで実装済

✦ mruby_(rewrite|access|content|log)_handler等

Page 17: mruby_nginx_module at pyfes 2013.11

今のところ使える機能✦ コードキャッシュ

✦ 各種ハンドラへのフック(rewrite,access,content,log)

✦ ヘッダおよびボディのフィルタリング

✦ nginxの変数へのアクセス(set & get)

✦ Nginx::(Request|Context|Time|Base64|Digest|etc)

✦ by Nginx Core API(not mrbgems)

✦ Regexp(PCREベース)

Page 18: mruby_nginx_module at pyfes 2013.11

nginxの実行フェーズとディレクティブ一覧

nginxの処理フェーズ(実行順) mruby_nginx_moduleのディレクティブ 備考start-up nginx & modules mruby_init, mruby_require

server rewrite serverコンテキストのrewrite

find config 該当するlocationの探索

rewrite mruby_rewrite_handler locationのrewrite

post rewritepre-access !

access mruby_access_handler !

ファイルへのアクセス

post-accesstry files try_files

content mruby_content_handler bodyの生成

log mruby_log_handler ロギング

Page 19: mruby_nginx_module at pyfes 2013.11

その他のディレクティブ

mruby_nginx_moduleのディレクティブ 用途

mruby_cache コードキャッシュのOn/Off(default:On)

mruby_set mrubyの実行結果をnginxの変数にsetする

mruby_header_filter HTTPヘッダの内容をフィルタリング or 上書きする

mruby_body_filter HTTPボディの内容をフィルタリング or 上書きする

Page 20: mruby_nginx_module at pyfes 2013.11

Hello, World!

Page 21: mruby_nginx_module at pyfes 2013.11

nginxの変数にset

#=> 55

Page 22: mruby_nginx_module at pyfes 2013.11

ファイル指定も可能

・先頭に「/」がある場合は絶対パス

・それ以外の場合は相対パス(conf_prefixがroot)

Page 23: mruby_nginx_module at pyfes 2013.11

ヘッダ書き換え

# 本来はtext/html

Page 24: mruby_nginx_module at pyfes 2013.11

レスポンスボディも(ry

Page 25: mruby_nginx_module at pyfes 2013.11

各処理フェーズでデータ共有

Page 26: mruby_nginx_module at pyfes 2013.11

Builtin-Regexp based PCRE

Page 27: mruby_nginx_module at pyfes 2013.11

nginxとmrubyとPCRE

✦ nginxは正規表現処理にPCREを利用している

✦ mrubyには今のところRegexpが標準で入っていない

✦ 別途mrbgemが必要(例:iij/mruby-regexp-pcre)

✦ PCREベースのmrbgemはnginxに組み込むのが困難

✦ nginxがpcre_(malloc|free)を上書きしてる

✦ でもPCREは使いたい

Page 28: mruby_nginx_module at pyfes 2013.11

なので、

✦ iij/mruby-regexp-pcreのコードを直接取り込み & 改変

✦ pcre_(malloc|free)をさらに上書き

✦ ngx_luaも似たようなことをやってる

✦ http://bokko.hatenablog.com/entry/2013/10/13/142154

Page 29: mruby_nginx_module at pyfes 2013.11

Nginx::Request

location = /mruby { mruby_content_handler_code ' r = Nginx::Request.new Nginx.rputs(r.uri + "\n") # => /mruby Nginx.rputs(r.method + "\n") # => GET, POST, etc Nginx.rputs(r.protocol + "\n") # => HTTP/1.x '; }

■処理中のリクエスト情報にアクセス

Page 30: mruby_nginx_module at pyfes 2013.11

Nginx::Request

location /mruby { set $maintainer "bokko"; mruby_content_handler_code ' r = Nginx::Request.new maintainer = r.var.maintainer Nginx.rputs(maintainer + "\n") # => bokko '; }

■nginxの変数にアクセス

Page 31: mruby_nginx_module at pyfes 2013.11

Nginx::Headers_in

hin = Nginx::Headers_in.new host = hin["Host"] # Host header agent = hin["User-Agent"] # User-Agent header table = hin.headers_in_hash # all headers with hash table

■リクエストヘッダへのアクセス

Page 32: mruby_nginx_module at pyfes 2013.11

Nginx::Headers_out

time = Nginx::Time.time() http_time = Nginx::Time.http_time(time + 60 * 60 * 24) !# Expiresヘッダを設定

hout = Nginx::Headers_out.new hout["Expires"] = http_time.to_s

■レスポンスヘッダへのアクセス

Page 33: mruby_nginx_module at pyfes 2013.11

Nginx::Time

time = Nginx::Time.time # => epoch value !time = 1377710189 Nginx::Time.http_time(time) # => Wed, 28 Aug 2013 17:16:29 GMT Nginx::Time.cookie_time(time) # => Wed, 28-Aug-13 17:16:29 GMT !Nginx::Time.utc_time # => UTC Time(2013-11-30 xx:xx:xx) Nginx::Time.local_time # => local time(2013-11-30 xx:xx:xx) !http_time = Nginx::Time.http_time(time) Nginx::Time.parse_http_time(http_time) # => 1377710189

■nginxのtime系APIのラッパー

Page 34: mruby_nginx_module at pyfes 2013.11

Nginx::Digest

md5 = Nginx::Digest.md5("bokko") Nginx::Digest.hexdigest(md5) # => fe9749… !sha1 = Nginx::Digest.sha1("bokko") Nginx::Digest.hexdigest(sha1) # => cea3d1… !hmac_sha1 = Nginx::Digest.hmac_sha1("data", "key") Nginx::Digest.hexdigest(hmac_sha1) # => 10415…

■MD5, SHA1, HMAC-SHA1, etc

Page 35: mruby_nginx_module at pyfes 2013.11

Nginx::Base64

encoded = Nginx::Base64.encode("bokko") # => Ym9ra28= Nginx::Base64.decode(encoded) # => bokko

■Base64 encode/decode

Page 36: mruby_nginx_module at pyfes 2013.11

少し発展的な例

Page 37: mruby_nginx_module at pyfes 2013.11

(mod|ngx)_access_tokenっぽいアクセス認証

Page 38: mruby_nginx_module at pyfes 2013.11

(mod|ngx)_access_token✦ S3のクエリ文字列認証っぽい機能を提供

✦ 特定のアクセストークンに基づいた認証

✦ リソースの有効期限設定

✦ mod_access_token ✦ livedoor(現LINE)が開発

✦ ngx_access_token ✦ @cubicdaiyaが開発

Page 39: mruby_nginx_module at pyfes 2013.11

xxx_access_tokenの認証方式以下のパラメータをリクエストURLに付加する

!・AccessKey -> 公開鍵文字列

・Expires -> 有効期限(エポック値)

・Signature -> シグネチャ

!Text = Method + Uri + Expires + AccessKey Signature = Base64(HMAC_SHA1(Text, (※) SecretKey)) !

(※)秘密鍵文字列(サーバ側で設定)

Page 40: mruby_nginx_module at pyfes 2013.11

ngx_access_token by mruby_nginx_module

Page 41: mruby_nginx_module at pyfes 2013.11

(mod|ngx)_access_tokenと比べて、

✦ mod_access_token by C

✦ 約200行

✦ ngx_access_token by C

✦ 約300行

✦ ngx_access_token by mruby

✦ 約10行

スクリプト言語の力ってすごいですね

Page 42: mruby_nginx_module at pyfes 2013.11

今後の課題

✦ 共有メモリAPI(Nginx::Shared)

✦ サブリクエストAPI(Nginx::SubRequest)

✦ ノンブロッキングソケットAPI(Nginx::Socket)

✦ Fiber(コルーチン)導入

✦ etc