SlideShare a Scribd company logo
nginx + lua + ObjectStorage 
ファイルアップロード/ダウンロードの高速化 
2014.12.11 
Code the Clouds Mix-up Vol.2 
株式会社MNU 雪本修一
雪本 修一 
Shuichi Yukimoto 
株式会社MNU 
代表取締役社長 
電気通信大学の認定ベンチャーとして起業。 
現在も現役プログラマとしてコードを書いている。 
好きな言語はJavaScript,Scheme,Lisp,Python 
SoftLayerを使い始めて一年ぐらい 
弊社はSoftLyerのリフェラルパートナーです。 
twitter:@nsas454 
facebook:shuichi.yukimoto
今日のお話 
• PBOXで実装した技術についてのご紹介 
• nginxの拡張モジュールを使ったアップロード 
とダウンロードの高速化を実現した仕組み 
• nginxの拡張モジュールの実装方法について
nginx 
• ロシアのIgor Sysoev氏によって、1日に5億リ 
クエストを処理するWebサイトのHTTPサーバー 
として開発された 
• 注目されるようになったのは、C10K問題(クラ 
イアント1万台問題、注2)が叫ばれるようになっ 
た2000年代後半です
Lua 
• 動的型付言語 
• 高速に動作する 
• ゲームなどで広く利用されている言語 
• インクリメンタルGCで有名 
• nginxもluaで実装されているそうです。 
• wikipediaより
nginx + lua + ObjectStorage  ファイルアップロード/ダウンロードの高速化
nginx + lua + ObjectStorage  ファイルアップロード/ダウンロードの高速化
ファイル 
フロントエンドバックエンドストレージ 
nginx gunicorn object 
Storage 
認証/リクエスト 
PUT 
• pboxはnginx + gunicornで構成されているが、 
ファイルのアップロード、ダウンロード処理を 
gunicornでやるのは高コスト 
• アップロード/ダウンロードには複雑な処理は必要 
無いにもかかわらず、gunicornのセッションを専 
有するのは良くない!
ファイル 
フロントエンドバックエンドストレージ 
nginx 
object 
PUT 
gunicorn Storage 
redis 
tornade 
LUA 
PUTリクエスト 
認証/ストレージ情報 
• nginx拡張でなるべく多くの同時リクエストを 
捌きつつ、静的ファイルの送受信を行う
何故nginx拡張を使うのか? 
• pboxはnginx + gunicornで構成されているが、ファ 
イルのアップロード、ダウンロード処理をgunicorn 
でやるのは高コスト 
• アップロード/ダウンロードには複雑な処理は必要 
無いにもかかわらず、gunicornのセッションを専有 
するのは良くない方法 
• nginx拡張でなるべく多くの同時リクエストを捌き 
つつ、静的ファイルの送受信を行う
nginx + HttpLuaModule
インストール 
• luajitのインストール 
• nginx + HttpLuaModuleのビルド&インストール 
• 詳細は 
• http://wiki.nginx.org/HttpLuaModule
nginx.conf 
• luaモジュールをインストールしたら、専用のディレクティブが使える 
• 例えば、content_by_lua_file でcontentフェーズにluaを呼び出すこ 
とができる。 
• 参考: http://wiki.nginx.org/HttpLuaModule#Directives 
• nginxのフェーズについては http://wiki.nginx.org/Phases を参照 
• レスポンス全体をluaで作る場合はcontentフェーズを使う。認証だけ 
luaを使う場合はaccess_by_lua_file ディレクティブを使用するなど 
の使い分けを行う。pboxでどうしているかは後述
nginxのフェーズ 
• nginx の Phase のうち、Rewrite, Access, Content, Log のフェーズに 
対してフックする仕組みを提供
lua-nginx-module が提供 
する主なフックの仕組み 
• Rewrite Phase 
• set_by_lua:変数の設定、ヘッダの操作、リダイレクト等が可能 
• rewrite_by_lua:Rewrite Phase の最後で実施され、自由度の高い rewrite処理を実現可能 
• Access Phase 
• access_by_lua:自由度の高い認可処理を実現可能 
• Content Phase 
• content_by_lua:コンテンツの生成 
• header_filter_by_lua:コンテンツ生成後、header に対するフィルタ処理(書き換えや追加など)に対応 
• body_filter_by_lua:コンテンツ生成後、body に対するフィルタ処理 
• Log Phase 
• log_by_lua:ログ処理のタイミングで動作。ここでリクエストの情報を変数にためておくことで、nginx + 
lua だけで集計の仕組みを作ることも可能
luaで何ができるのか? 
• 特に重要なのは以下の2つ 
• サブリクエスト 
• tcp/udpソケット通信 
• 詳しくは下記で説明
サブリクエスト 
• ざっくり言えば、他のlocationを呼ぶ機能 
• ngx.location.captureを使用する 
• 一度のリクエストで何回もサブリクエストを 
呼ぶことができたりする
tcp/udpソケット通信 
• ngx.socket.tcp / ngx.socket.udp でソケット通信ができ 
る。luaの組込ソケットと互換のインターフェイスを持って 
いるが、内部動作が違うのでかならずこちらを使うこと。 
• このソケットはnon-blockで動作し、待ち時間で別のリ 
クエストを処理してくれる 
• pboxではこのソケットの上にHTTPプロトコルを実装した 
lua-resty-httpを使用してObjectStorageとの通信を行っ 
ている。
アップロード/ダウンロードの概要 
• pboxのファイルアップロード/ダウンロードは以下の動作が必要 
• 認証:リクエストヘッダで送られてくる認証トークンが正しいかSQL 
に保存された情報との比較を行う。また、ここでObjectStorageへの 
url、認証情報を取得する 
• ObjectStorageへのアップロード/ダウンロード:1で得られた情 
報を元に実際にファイルをアップロード/ダウンロードする 
• (アップロードの場合のみ)SQLへアップロードしたファイルのメ 
タ情報を保存する:ObjectStorageで管理できない追加情報をpbox 
持たせるため、ファイル・ディレクトリの情報はSQL側で持っている
HttpLuaModule 
• pboxはcontentフェーズでluaを使用し、 
• 1. 認証を内部サブリクエスト 
• 2. オブジェクトストレージへのアクセスにソ 
ケット 
• 上記を使用しているが、次のようにする方法も 
あった(RestfulなAPIのために断念した)。
余談 
• ダウンロード: accessフェーズのみluaで行い、 
contentはObjectStorageへプロキシすることも 
できる(proxy_passディレクティブを使う)。 
• アップロード: ObjectStorageへのアップロード 
前と後にluaの処理が入る。(またレスポンスは 
ObjectStorageのものを直接使わず、メタ情報 
をjson返したい。)そのため、contentフェーズ 
をluaで書く。
まとめ 
• nginxのフェーズの概念は超重要。1つは省力化のため。 
アップロードはproxy_passを使うことでluaの記述を 
減らすこともできる(pboxではやらないが)。 
• もう1つは出来ることが違う。たとえば、accessフェー 
ズでレスポンスの中身を書き換えることはできない。 
logフェーズや、post_actionではluaからサブリクエ 
ストが使えないなど、フェーズを意識する必要がある。
さいごに 
• とりあえず、重要な事は2つだけ 
• サブリクエスト(ngx.location.capture)はマジ便利 
• 100% non-blockingなHTTP通信でObjectStorage 
へアクセスしてます
Appendix
location /internals { 
internal; 
proxy_pass http://backend; 
} 
location ~ /([^/]+)/files/(.*)$ { 
content_by_lua_file content_file.lua; 
} 
nginx.conf
local http = require "resty.http" 
local cjson = require "cjson" 
local user = ngx.var[1] -- location の $1 相当 
local path = ngx.var[2] -- location の $2 相当 
--- 認証 
local res = ngx.location.capture('/internals/auth', { 
args = { token = token, user=user, 
path=path }, 
}) 
if res.status ~= 200 then 
ngx.exit(res.status) 
end 
--- ObjectStorageへのURL,Tokenを認証時に返してもらう 
local body = cjson.decode(res.body) 
local host = body.host 
local path = body.path 
local token = body.token 
--- 通信確立 
local httpc = http.new() 
httpc:connect(host, 80) 
--- ObjectStorageへGETリクエスト発行 
local res, err = httpc:request{ 
path = path, 
method = 'GET', 
headers = {['X-Auth-Token'] = token} 
} 
--- レスポンスボディをそのままnginxのレスポンスとして返す 
local reader = res.body_reader 
repeat 
local chunk, err = reader(chunk_size) 
ngx.say(chunk) 
until not chunk 
content_file.lua

More Related Content

PPTX
NginxとLuaを用いた動的なリバースプロキシでデプロイを 100 倍速くした
PDF
Using ngx_lua / lua-nginx-module in pixiv
PDF
nginxの紹介
PDF
lua_nginx_module JSON-RPC 2.0 Batch Request
PDF
Webサーバ勉強会#4
PPTX
Zabbixの分散構築~ConoHa VPSでのzabbix server構築~
PPTX
Nginx勉強会
PDF
さくらのDockerコンテナホスティング-Arukasの解説とインフラを支える技術(July Tech Festa 2016 『IoTxAIxインフラ時代...
NginxとLuaを用いた動的なリバースプロキシでデプロイを 100 倍速くした
Using ngx_lua / lua-nginx-module in pixiv
nginxの紹介
lua_nginx_module JSON-RPC 2.0 Batch Request
Webサーバ勉強会#4
Zabbixの分散構築~ConoHa VPSでのzabbix server構築~
Nginx勉強会
さくらのDockerコンテナホスティング-Arukasの解説とインフラを支える技術(July Tech Festa 2016 『IoTxAIxインフラ時代...

What's hot (20)

PDF
Docker ホスティングサービス 'Arukas' での Mesos + Marathon の活用について(Mesos勉強会)
PDF
Nginx バージョンアップ動向(2015/01〜2015/06)
PPTX
OpenShift from Easy way to Hard ? Way
PPTX
自宅ラック勉強会 2.2 夏のZabbix特別教室 ~構築編~
PPTX
Java on Azure with Docker container
PPTX
はじめての Cloud Foundry: .NET アプリケーションのはじめ方
PDF
Bluemix sign-up
PDF
GitHubのリポジトリ(32個)を 覗いてみよう。 ただし、READMEだけね
PDF
Mackerelによる
簡単サーバー管理入門と発展形
PPTX
AWSのElastic BeanstalkでWordPressを 構築レスで導入してみる。
PDF
Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話
PPTX
誰にでもできるパフォーマンスチューニング
PDF
Reading NATS
PDF
Mackerel & Norikra mackerel meetup #4 LT
PPTX
ZabbixとAWS
PPTX
Webアプリケーションによる電源管理システムのご紹介
PPTX
Jenkins User Conference 東京 2015
PDF
Nginx バージョンアップ動向(2015/07〜2015/12)
PDF
Chefで始めるWindows Server構築
PDF
Devlove mackerel
Docker ホスティングサービス 'Arukas' での Mesos + Marathon の活用について(Mesos勉強会)
Nginx バージョンアップ動向(2015/01〜2015/06)
OpenShift from Easy way to Hard ? Way
自宅ラック勉強会 2.2 夏のZabbix特別教室 ~構築編~
Java on Azure with Docker container
はじめての Cloud Foundry: .NET アプリケーションのはじめ方
Bluemix sign-up
GitHubのリポジトリ(32個)を 覗いてみよう。 ただし、READMEだけね
Mackerelによる
簡単サーバー管理入門と発展形
AWSのElastic BeanstalkでWordPressを 構築レスで導入してみる。
Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話
誰にでもできるパフォーマンスチューニング
Reading NATS
Mackerel & Norikra mackerel meetup #4 LT
ZabbixとAWS
Webアプリケーションによる電源管理システムのご紹介
Jenkins User Conference 東京 2015
Nginx バージョンアップ動向(2015/07〜2015/12)
Chefで始めるWindows Server構築
Devlove mackerel
Ad

Similar to nginx + lua + ObjectStorage ファイルアップロード/ダウンロードの高速化 (20)

PDF
Pbox on softlayer
PPT
Osoljp201210 oi swift
PDF
OSC2011Tokyo/Fall OpenStack Swift入門
PDF
第2回名古屋SoftLayer勉強会 PBOX on SoftLayer
PPTX
ConoHaオブジェクトストレージ 利用ケース
PPTX
コア・コンテキスト管理 - FIWARE WednesdayWebinars
PDF
WebSocket Protocol と Plack::Middleware::WebSocket
PPTX
OpenStack Congress Deep Dive
PDF
OpenStack Object Storage; Usage
PDF
Webフレームワークを作ってる話 #osakapy
PPTX
Dokkuの活用と内部構造
PPT
Webサーバの基礎知識【編集済み】
PDF
コンテナ事例 CircleCI, Cucumber-Chef
PDF
OSC2012 Nagoya - OpenStack - Storage System; Overview
PDF
CloudStack Ecosystem Day - OpenStack/Swift
PDF
クラウド開発に役立つ OSS あれこれ
PDF
OpenStack超入門シリーズ いまさら聞けないSwiftの使い方
PDF
大規模運用で見えるWebプロトコルの理想と現実、そして今後 #html5j #html5j_b
PPT
Lesson01
 
PDF
Node-v0.12のTLSを256倍使いこなす方法
Pbox on softlayer
Osoljp201210 oi swift
OSC2011Tokyo/Fall OpenStack Swift入門
第2回名古屋SoftLayer勉強会 PBOX on SoftLayer
ConoHaオブジェクトストレージ 利用ケース
コア・コンテキスト管理 - FIWARE WednesdayWebinars
WebSocket Protocol と Plack::Middleware::WebSocket
OpenStack Congress Deep Dive
OpenStack Object Storage; Usage
Webフレームワークを作ってる話 #osakapy
Dokkuの活用と内部構造
Webサーバの基礎知識【編集済み】
コンテナ事例 CircleCI, Cucumber-Chef
OSC2012 Nagoya - OpenStack - Storage System; Overview
CloudStack Ecosystem Day - OpenStack/Swift
クラウド開発に役立つ OSS あれこれ
OpenStack超入門シリーズ いまさら聞けないSwiftの使い方
大規模運用で見えるWebプロトコルの理想と現実、そして今後 #html5j #html5j_b
Lesson01
 
Node-v0.12のTLSを256倍使いこなす方法
Ad

More from Shuichi Yukimoto (16)

PDF
Ocif2016_go_web_freamwork
PDF
Slackbot_by_OpenWhisk
PDF
Softlayer_API_openWhisk
PDF
Send grid softlayer_nagoya
PDF
Softlayer_bluemix-summit
PDF
Softlayer_summit
PDF
SendGridを使ってみよう
PPTX
PDF
Emacs softLayer
PDF
Soft layer APIの使い方と実装のポイント
PDF
Softlayer勉強会#2
PDF
勉強会資料#1
PDF
SoftLayerオブジェクトストレージと連携サービスPBOXについて
PDF
Object storageを使ってみる
PDF
Mnu特許説明スライド
PPTX
第2回ビジネスモバイル研究会
Ocif2016_go_web_freamwork
Slackbot_by_OpenWhisk
Softlayer_API_openWhisk
Send grid softlayer_nagoya
Softlayer_bluemix-summit
Softlayer_summit
SendGridを使ってみよう
Emacs softLayer
Soft layer APIの使い方と実装のポイント
Softlayer勉強会#2
勉強会資料#1
SoftLayerオブジェクトストレージと連携サービスPBOXについて
Object storageを使ってみる
Mnu特許説明スライド
第2回ビジネスモバイル研究会

nginx + lua + ObjectStorage ファイルアップロード/ダウンロードの高速化

  • 1. nginx + lua + ObjectStorage ファイルアップロード/ダウンロードの高速化 2014.12.11 Code the Clouds Mix-up Vol.2 株式会社MNU 雪本修一
  • 2. 雪本 修一 Shuichi Yukimoto 株式会社MNU 代表取締役社長 電気通信大学の認定ベンチャーとして起業。 現在も現役プログラマとしてコードを書いている。 好きな言語はJavaScript,Scheme,Lisp,Python SoftLayerを使い始めて一年ぐらい 弊社はSoftLyerのリフェラルパートナーです。 twitter:@nsas454 facebook:shuichi.yukimoto
  • 3. 今日のお話 • PBOXで実装した技術についてのご紹介 • nginxの拡張モジュールを使ったアップロード とダウンロードの高速化を実現した仕組み • nginxの拡張モジュールの実装方法について
  • 4. nginx • ロシアのIgor Sysoev氏によって、1日に5億リ クエストを処理するWebサイトのHTTPサーバー として開発された • 注目されるようになったのは、C10K問題(クラ イアント1万台問題、注2)が叫ばれるようになっ た2000年代後半です
  • 5. Lua • 動的型付言語 • 高速に動作する • ゲームなどで広く利用されている言語 • インクリメンタルGCで有名 • nginxもluaで実装されているそうです。 • wikipediaより
  • 8. ファイル フロントエンドバックエンドストレージ nginx gunicorn object Storage 認証/リクエスト PUT • pboxはnginx + gunicornで構成されているが、 ファイルのアップロード、ダウンロード処理を gunicornでやるのは高コスト • アップロード/ダウンロードには複雑な処理は必要 無いにもかかわらず、gunicornのセッションを専 有するのは良くない!
  • 9. ファイル フロントエンドバックエンドストレージ nginx object PUT gunicorn Storage redis tornade LUA PUTリクエスト 認証/ストレージ情報 • nginx拡張でなるべく多くの同時リクエストを 捌きつつ、静的ファイルの送受信を行う
  • 10. 何故nginx拡張を使うのか? • pboxはnginx + gunicornで構成されているが、ファ イルのアップロード、ダウンロード処理をgunicorn でやるのは高コスト • アップロード/ダウンロードには複雑な処理は必要 無いにもかかわらず、gunicornのセッションを専有 するのは良くない方法 • nginx拡張でなるべく多くの同時リクエストを捌き つつ、静的ファイルの送受信を行う
  • 12. インストール • luajitのインストール • nginx + HttpLuaModuleのビルド&インストール • 詳細は • http://wiki.nginx.org/HttpLuaModule
  • 13. nginx.conf • luaモジュールをインストールしたら、専用のディレクティブが使える • 例えば、content_by_lua_file でcontentフェーズにluaを呼び出すこ とができる。 • 参考: http://wiki.nginx.org/HttpLuaModule#Directives • nginxのフェーズについては http://wiki.nginx.org/Phases を参照 • レスポンス全体をluaで作る場合はcontentフェーズを使う。認証だけ luaを使う場合はaccess_by_lua_file ディレクティブを使用するなど の使い分けを行う。pboxでどうしているかは後述
  • 14. nginxのフェーズ • nginx の Phase のうち、Rewrite, Access, Content, Log のフェーズに 対してフックする仕組みを提供
  • 15. lua-nginx-module が提供 する主なフックの仕組み • Rewrite Phase • set_by_lua:変数の設定、ヘッダの操作、リダイレクト等が可能 • rewrite_by_lua:Rewrite Phase の最後で実施され、自由度の高い rewrite処理を実現可能 • Access Phase • access_by_lua:自由度の高い認可処理を実現可能 • Content Phase • content_by_lua:コンテンツの生成 • header_filter_by_lua:コンテンツ生成後、header に対するフィルタ処理(書き換えや追加など)に対応 • body_filter_by_lua:コンテンツ生成後、body に対するフィルタ処理 • Log Phase • log_by_lua:ログ処理のタイミングで動作。ここでリクエストの情報を変数にためておくことで、nginx + lua だけで集計の仕組みを作ることも可能
  • 16. luaで何ができるのか? • 特に重要なのは以下の2つ • サブリクエスト • tcp/udpソケット通信 • 詳しくは下記で説明
  • 17. サブリクエスト • ざっくり言えば、他のlocationを呼ぶ機能 • ngx.location.captureを使用する • 一度のリクエストで何回もサブリクエストを 呼ぶことができたりする
  • 18. tcp/udpソケット通信 • ngx.socket.tcp / ngx.socket.udp でソケット通信ができ る。luaの組込ソケットと互換のインターフェイスを持って いるが、内部動作が違うのでかならずこちらを使うこと。 • このソケットはnon-blockで動作し、待ち時間で別のリ クエストを処理してくれる • pboxではこのソケットの上にHTTPプロトコルを実装した lua-resty-httpを使用してObjectStorageとの通信を行っ ている。
  • 19. アップロード/ダウンロードの概要 • pboxのファイルアップロード/ダウンロードは以下の動作が必要 • 認証:リクエストヘッダで送られてくる認証トークンが正しいかSQL に保存された情報との比較を行う。また、ここでObjectStorageへの url、認証情報を取得する • ObjectStorageへのアップロード/ダウンロード:1で得られた情 報を元に実際にファイルをアップロード/ダウンロードする • (アップロードの場合のみ)SQLへアップロードしたファイルのメ タ情報を保存する:ObjectStorageで管理できない追加情報をpbox 持たせるため、ファイル・ディレクトリの情報はSQL側で持っている
  • 20. HttpLuaModule • pboxはcontentフェーズでluaを使用し、 • 1. 認証を内部サブリクエスト • 2. オブジェクトストレージへのアクセスにソ ケット • 上記を使用しているが、次のようにする方法も あった(RestfulなAPIのために断念した)。
  • 21. 余談 • ダウンロード: accessフェーズのみluaで行い、 contentはObjectStorageへプロキシすることも できる(proxy_passディレクティブを使う)。 • アップロード: ObjectStorageへのアップロード 前と後にluaの処理が入る。(またレスポンスは ObjectStorageのものを直接使わず、メタ情報 をjson返したい。)そのため、contentフェーズ をluaで書く。
  • 22. まとめ • nginxのフェーズの概念は超重要。1つは省力化のため。 アップロードはproxy_passを使うことでluaの記述を 減らすこともできる(pboxではやらないが)。 • もう1つは出来ることが違う。たとえば、accessフェー ズでレスポンスの中身を書き換えることはできない。 logフェーズや、post_actionではluaからサブリクエ ストが使えないなど、フェーズを意識する必要がある。
  • 23. さいごに • とりあえず、重要な事は2つだけ • サブリクエスト(ngx.location.capture)はマジ便利 • 100% non-blockingなHTTP通信でObjectStorage へアクセスしてます
  • 25. location /internals { internal; proxy_pass http://backend; } location ~ /([^/]+)/files/(.*)$ { content_by_lua_file content_file.lua; } nginx.conf
  • 26. local http = require "resty.http" local cjson = require "cjson" local user = ngx.var[1] -- location の $1 相当 local path = ngx.var[2] -- location の $2 相当 --- 認証 local res = ngx.location.capture('/internals/auth', { args = { token = token, user=user, path=path }, }) if res.status ~= 200 then ngx.exit(res.status) end --- ObjectStorageへのURL,Tokenを認証時に返してもらう local body = cjson.decode(res.body) local host = body.host local path = body.path local token = body.token --- 通信確立 local httpc = http.new() httpc:connect(host, 80) --- ObjectStorageへGETリクエスト発行 local res, err = httpc:request{ path = path, method = 'GET', headers = {['X-Auth-Token'] = token} } --- レスポンスボディをそのままnginxのレスポンスとして返す local reader = res.body_reader repeat local chunk, err = reader(chunk_size) ngx.say(chunk) until not chunk content_file.lua