SlideShare a Scribd company logo
nginx luaでJSON-RPC batch
requestを実装して地雷踏んだ話
2016/02/08 @mosa_siru
1
@mosa_siru
2
@mosa_siru (もさ)
• ボンバーマン極めてる人
• 2013-2015 DeNA
• Mobage 3rd party API運用
• ハッカドール新規開発(サーバーサイド)
• 2015- Gunosy
• 広告運用、新規事業開発
3
今日の内容
4
今日の内容
• JSON-RPCの紹介
• JSON-PRCって?
• JSON-RPC Batch Requestが便利!
• lua_nginx_moduleでBatch Request実装した話
• 地雷踏んだ話
5
JSON-RPCって?
6
JSON-PRC
• とってもシンプルなRPCプロトコル
• リクエストもレスポンスも全部指定のJSON形
式でやろうぜ!
• 多数の言語でサーバー・クライアント共にフ
レームワーク化やライブラリ化されている
7
Example(1)
8
Request
{"jsonrpc": "2.0", "method": "subtract", "params": [5, 2], "id": 1}
{"jsonrpc": "2.0", "result": 3, "id": 1}
Response
Example(2)
9
Request
{"jsonrpc": "2.0", "method": "getUser", "params": { "user_id": 1 }, "id": 1}
{"jsonrpc": "2.0", "result": {"name": "mosa", "email": "mosa@hogefuga.com"}, "id": 1
Response
JSON-PRC
• とってもシンプル!
• 特定のmethodにパラメータつきで1つの単純なリクエスト
を送って、1つのレスポンスをもらう
• 外部に公開するAPIでもない限り、URI設計や冪等性とか
色々気にしないといけないRestFulよりも扱いやすい
• 大抵のネイティブアプリとサーバーAPI間の通信、
Internal APIなどはこれで十分
10
Batch Request Example
11
Request
[
{"jsonrpc": "2.0", "method": "subtract", "params": [5, 2], "id": 1},
{"jsonrpc": "2.0", "method": "getUser", "params": { "user_id": 1 }, "id": 2}
]
[
{"jsonrpc": "2.0", "result": 3, "id": 1},
{"jsonrpc": "2.0", "result": {"name": "mosa", "email": "mosa@hogefuga.com"}, "id":
2}
]
Response
Batch Request
• 複数のリクエストを一気に送って、一気にレ
スポンスがもらえるプロトコル
• JSON Arrayで送ってJSON Arrayで返る



12
• 仕様上、送ったArrayの順番通りにレスポンスが並ぶこ
とは保証されない

=> 識別子として "id"のkeyをclientは見るべき
Batch Requestのメリット
• リクエスト数を減らすことができる
• APIの設計がシンプルになる(1つのリソースに対して1つ
作っておけば良く、UIを気にしなくて良い)
• クライアント側で、複数のAPIのレスポンスを待ったハンド
リングがシンプルにできる
• 「2つのAPIの結果を待たないと描画してはいけない」
• 「どれかがこけた場合は全体をエラーにする」
13
Batch Requestのデメリット
• 重い処理に引きずられる
• 処理に10秒かかるリクエストA
• 処理に1秒かかるリクエストB
• A,BをBatch Requestにすると、最低10秒かか
る
14
Batch Requestは

どう実装すべきか
15
実装(1) フレームワークで行う
フレームワーク側で、for loop でそれぞれ順番
に処理し、全て終わったらまとめてレスポンス
を生成する
16
実装(1) フレームワークで行う
17
• 既存のフレームワーク実装はだいたいこれ。
• 10個分のbatch requestを投げたら処理に10倍
時間がかかることになり、イケてない
• 並列でそれぞれのスレッド(プロセス)が処理す
るのが理想だが、言語によっては複雑な実装
になる
実装(2) Proxy serverをたてる
proxyがJSON Arrayのそれぞれに対し、非同期
で並列にバックエンドのJSON-RPCサーバーに
リクエストを投げ、全て返ってきたら1つにまと
めてレスポンスを生成する
実装(2) Proxy serverをたてる
19
• 管理コンポーネントが増えるので、運用の複雑さが増
す
• 異常が起きた場合、どの経路で死んだのか多数のロ
グを漁ることになる
• proxy serverの台数管理も考えないといけない
• single requestも考えると、appへのreverse proxy設定
をnginxとproxyで二重管理することになりうる
実装(3) nginxで行う
nginxのレイヤーでbatch requestはバラしてし
まう
(2)のproxyの役割をluaが担当
20
実装(3) nginxで行う
21
• backendのJSON-RPC APIはsingle requestさえ捌ければ良
く、サーバー言語に依らずこの構成が取ることができる
• 管理コンポーネントも増えない
• イベントドリブンなnginxの性質を活かし、ノンブロッキング
(=backendの処理を待たない)並列なbatch requestを簡単に
実装することができる
• single requestも同じnginxで捌けるので、reverse proxy設定
が二重管理にならない
というわけで
nginx + luaで実装した話
22
library化しました
23
https://github.com/mosasiru/lua-resty-jsonrpc-
batch
簡単に、batch requestが並列にノンブロッキン
グに実装できます。
24
Basic Usage解説
25
• /api が裏側のJSON-RPC APIに投げる(single
request用)
• /api/batch がbatch requestを分解し、 

/api に subrequest (処理を移譲)
• 内部的には、lua_nginx_moduleの
localtion.capture_multi を利用しています
26
Advanced Usage解説
27
• でかいArrayが来ると攻撃になるので、最大サイズを10とする
• subrequestの処理時間をnginx access logに入れるために、
nginx変数に値を入れている
• ライブラリに用意されたフックポイントを利用している
• 「jsonrpc "substract" methodは /jsonrpc/method/substract
のパスで受けたい」など、動的なlocationに対応している
• というわけで、色々拡張できるようになっています
運用可能なの?
28
subrequest の調査
29
• 事前にかなりの検証をした (CentOS 6.2, ngx_openresty1.7.10.1)
• lua実行中にnginx reloadされるとどうなるか?
• subrequest実行中にnginx reloadされるとどうなるか?
• luaでエラーになるとどうなるか?
• upstreamでエラーになるとどうなるか?
• upstreamがtimeoutするとどうなるか?
• client timeoutするとどうなるか?
subrequest の調査
30
• 検証の結果、以下に気をつければ問題ないことがわかる
• アクセスログにsubrequestの情報を盛り込むべき
• luaエラー時にハンドリングできるようlua pcallを利用するべき
• nginx reloadは問題なく可能!
• subrequest upstreamで刺さる分には影響ない
• luaで刺さるとnginx workerプロセスごと刺さる(がくぶる
• upstreamのレスポンスサイズがproxy buffersを超え、proxy_max_temp_file_size
も超えるかOFFにしていると応答が返らない

(しかしnginx workerプロセスは刺さらない)
導入してみた
31
問題なくリクエストを捌ける、
が…
32
• 数万req/min を余裕で1台で捌けるが
• なぜか徐々にリークするメモリー
• なぜか時々出るソケットリークエラー



• そしてソケット開けなくなって死ぬ
[alert] 15248#0: open socket #123 left in connection 456
とりあえず
定期reloadする運用…
33
調査の結果
34
upstreamのレスポンスサイズがproxy buffersを超え、
proxy_max_temp_file_size も超えるかOFFにしていると
応答が返らない(ただしworkerプロセスはブロックされ
ない)
• とあるAPIにてこれが起きていた。
• このときソケットを閉じ忘れるようだ
• メモリも開放されないようだ
コードとか読むかんじ
35
upstreamのレスポンスサイズがproxy buffersを
超え、proxy_max_temp_file_size も超えたとき
• single request: bufferingしないで直接
upstream =>clientにwriteしてくれる
• subrequest: 全部bufferingしようとして死ぬ
subrequest利用時には
proxy_buffersを
適切に上げる運用にしましょう
36
おわり
37

More Related Content

PDF
nginx + lua + ObjectStorage ファイルアップロード/ダウンロードの高速化
PDF
nginxの紹介
PDF
フィードフォースと AWS と私
PDF
Webサーバ勉強会#4
PDF
My sqlとplugin
PPTX
Nginx勉強会
PDF
Docker ホスティングサービス 'Arukas' での Mesos + Marathon の活用について(Mesos勉強会)
PPTX
Zabbixの分散構築~ConoHa VPSでのzabbix server構築~
nginx + lua + ObjectStorage ファイルアップロード/ダウンロードの高速化
nginxの紹介
フィードフォースと AWS と私
Webサーバ勉強会#4
My sqlとplugin
Nginx勉強会
Docker ホスティングサービス 'Arukas' での Mesos + Marathon の活用について(Mesos勉強会)
Zabbixの分散構築~ConoHa VPSでのzabbix server構築~

What's hot (19)

PDF
Using ngx_lua / lua-nginx-module in pixiv
PDF
さくらのDockerコンテナホスティング-Arukasの解説とインフラを支える技術(July Tech Festa 2016 『IoTxAIxインフラ時代...
KEY
恐るべきApache, Web勉強会@福岡
PPTX
ConoHaオブジェクトストレージ 利用ケース
PDF
LocalStack
PDF
ISUCONの勝ち方 YAPC::Asia Tokyo 2015
PDF
社内向けTech Talk資料~Fluentdの基本紹介~
PDF
松本克彦 ピグにおけるリアルタイムランキングの導入
PDF
Mackerel & Norikra mackerel meetup #4 LT
PPTX
パブリッククラウドConoHaを使ってOpenStack APIを理解する
PDF
MSPとしてのオペチー向けReadOnly IAMポリシー
PPTX
OpenShift from Easy way to Hard ? Way
PDF
WordBench千葉「レベル別Nginx活用法」
PDF
WordBeach 2012
PDF
Gazelle & CPAN modules for performance. Shibuya.pm Tech Talk #17 LT
KEY
Osc2012.dbに行ってきました
PPTX
誰にでもできるパフォーマンスチューニング
PDF
クラウド環境向けZabbixカスタマイズ紹介(第5回Zabbix勉強会)
PPTX
EC2でNginxを使ってみよう JAWS大阪第9回勉強会資料
Using ngx_lua / lua-nginx-module in pixiv
さくらのDockerコンテナホスティング-Arukasの解説とインフラを支える技術(July Tech Festa 2016 『IoTxAIxインフラ時代...
恐るべきApache, Web勉強会@福岡
ConoHaオブジェクトストレージ 利用ケース
LocalStack
ISUCONの勝ち方 YAPC::Asia Tokyo 2015
社内向けTech Talk資料~Fluentdの基本紹介~
松本克彦 ピグにおけるリアルタイムランキングの導入
Mackerel & Norikra mackerel meetup #4 LT
パブリッククラウドConoHaを使ってOpenStack APIを理解する
MSPとしてのオペチー向けReadOnly IAMポリシー
OpenShift from Easy way to Hard ? Way
WordBench千葉「レベル別Nginx活用法」
WordBeach 2012
Gazelle & CPAN modules for performance. Shibuya.pm Tech Talk #17 LT
Osc2012.dbに行ってきました
誰にでもできるパフォーマンスチューニング
クラウド環境向けZabbixカスタマイズ紹介(第5回Zabbix勉強会)
EC2でNginxを使ってみよう JAWS大阪第9回勉強会資料
Ad

Viewers also liked (20)

PDF
Go, memcached, microservices
PDF
マイクロにしすぎた結果がこれだよ!
PDF
Elasticsearch for Hackadoll
PDF
ニュースパスのクローラーアーキテクチャとマイクロサービス
PDF
捗るリコメンドシステムの裏事情(ハッカドール)
PDF
Twitter SmartList (第5回若手webエンジニア交流会)
PDF
コミュニティ分類アルゴリズムの高速化とソーシャルグラフへの応用
PDF
How we built Lingr - ITpro Challenge Presentation
PDF
テストの自動化を考える前に
PDF
Rails の自動読み込みを支える技術
PDF
EVOLVE`13 Keynote: Scrambled Eggs
PDF
SimpleとEasyの選択
PDF
Perl Dancer for Python programmers
PDF
クロスドメインアクセスを理解してWeb APIを楽しく使おう
PDF
Bitbucketを活用したコードレビュー改善事例
PDF
Lean & Agile ♥ UX Design
PDF
今日から始めるDigitalOcean
PDF
JavascriptでもTestがしたい!
PDF
Dockerを使ったローカルでの開発から本番環境へのデプロイまで
PDF
Golang入門
Go, memcached, microservices
マイクロにしすぎた結果がこれだよ!
Elasticsearch for Hackadoll
ニュースパスのクローラーアーキテクチャとマイクロサービス
捗るリコメンドシステムの裏事情(ハッカドール)
Twitter SmartList (第5回若手webエンジニア交流会)
コミュニティ分類アルゴリズムの高速化とソーシャルグラフへの応用
How we built Lingr - ITpro Challenge Presentation
テストの自動化を考える前に
Rails の自動読み込みを支える技術
EVOLVE`13 Keynote: Scrambled Eggs
SimpleとEasyの選択
Perl Dancer for Python programmers
クロスドメインアクセスを理解してWeb APIを楽しく使おう
Bitbucketを活用したコードレビュー改善事例
Lean & Agile ♥ UX Design
今日から始めるDigitalOcean
JavascriptでもTestがしたい!
Dockerを使ったローカルでの開発から本番環境へのデプロイまで
Golang入門
Ad

More from mosa siru (6)

PDF
LayerXのQAチームで目指したい動き方 (社内資料)
PDF
開発速度が速い #とは(LayerX社内資料)
PDF
KYC and identity on blockchain
PPTX
マイニングプールの収益配分と攻撃手法
PDF
Payment Channel Introduction
PDF
how to make twitter list automatically
LayerXのQAチームで目指したい動き方 (社内資料)
開発速度が速い #とは(LayerX社内資料)
KYC and identity on blockchain
マイニングプールの収益配分と攻撃手法
Payment Channel Introduction
how to make twitter list automatically

lua_nginx_module JSON-RPC 2.0 Batch Request