82
古橋貞之 e MessagePack Project gumiStudy#7 #gumilab #msgpack @frsyuki http://d.hatena.ne.jp/viver/

Gumi study7 messagepack

Embed Size (px)

Citation preview

Page 1: Gumi study7 messagepack

古橋貞之

e

MessagePackProjectgumiStudy#7#gumilab

#msgpack @frsyukihttp://d.hatena.ne.jp/viver/

Page 2: Gumi study7 messagepack
Page 3: Gumi study7 messagepack
Page 4: Gumi study7 messagepack

Manager

Gateway

Server

Page 5: Gumi study7 messagepack

Application

ServerManager

Gateway

Manager

冗長構成

Server

Server

Server

Server

Server

Application

GatewayApplication

Gateway

レプリケーション

Tokyo Cabinet

Page 6: Gumi study7 messagepack

Application

Gateway

Gateway

Application

Server Server Server

memcached protocol

MessagePack-RPC

・Hides cluster configuration from applications. “memcached server on localhost”

localhost:11211 Asynchronous RPC library

Page 7: Gumi study7 messagepack

Tools

Written in Ruby

> automates operation tasks

> easy to implement

> easy to customize

kumoctl

kumostat

kumotop

MessagePack-RPCAsynchronous RPC libraryCross-language RPC

Page 8: Gumi study7 messagepack
Page 9: Gumi study7 messagepack
Page 10: Gumi study7 messagepack

MessagePack - 高速シリアライザ

> いつ/どこで MessagePack を使うか> MessagePack の手法

背景

> シリアライザの設計手法と MessagePack の選択> フォーマットと Embedded Type Information> MessagePack の型システムと型変換

MessagePack-RPC - 多機能RPC> プロトコル> 並列性 - Parallel Pipelining> 並列イベント駆動I/O

事例

Page 11: Gumi study7 messagepack

MessagePack - 高速シリアライザ

> いつ/どこで MessagePack を使うか> MessagePack の手法

背景

> シリアライザの設計手法と MessagePack の選択> フォーマットと Embedded Type Information> MessagePack の型システムと型変換

MessagePack-RPC - 多機能RPC> プロトコル> 並列性 - Parallel Pipelining> 並列イベント駆動I/O

事例

Page 12: Gumi study7 messagepack

背景

• 多言語でシステムを構築したい> C++で分散KVSを実装 + Rubyで管理を自動化> Rubyでプロトタイプ → 段階的にC++に移植> Javaサーバ + Rubyクライアント

• スケールアウト時代に耐える通信システムが欲しい> 多数のサーバやクライアントが並列して通信> マルチコア環境でもスケールする並列性

Page 13: Gumi study7 messagepack

理想

Interface

C++

Interface

Java

Interface

Ruby

高速で多機能で使いやすいオープンソースのライブラリ

各言語の利点を活かして本質的な設計に集中

通信のパイプライン化や並列化などの高速化手法をシンプルに使える

Page 14: Gumi study7 messagepack

現実1 JSON+XML+HTTP/TCPC++

Java Ruby

遅い/面倒なライブラリ+通信部分は自作

各言語の利点は活かせるが、オブジェクトの交換は面倒

Interface

Interface Interface

通信を並列化するにはマルチスレッドorイベント駆動プログラミングが必要。パイプライン化などの高速化手法は実装が難しい。バグりやすい。「高負荷になると固まる」

人間が読めるので、デバッグはしやすい

Page 15: Gumi study7 messagepack

現実2 SOAPやXML-RPCC++

Java Ruby

遅くてトラフィックが大きく仕様が複雑な通信ライブラリ

Interface

Interface Interface

遅い。トラフィックが大きい。並列化はユーザー任せ。

標準化はされている

Page 16: Gumi study7 messagepack

Interface

Interface

現実3 同じ言語で固める

Java Ruby

後で別のシステムやモジュールと接続したくなったときに困る

言語の短所に付き合わされる例:GCが遅い

Java

書きやすい言語でプロトタイピング →効率の良い言語で本番実装 は難しい

実はそんなに速くない(並列性が低い)スケールアウト時代の実装に使えない

言語の長所を活かせない

Page 17: Gumi study7 messagepack

従来の問題

• 多言語対応自体の実装が面倒で、本質的な機能の実装に集中できない

• オーバーヘッドの大きいプログラムができあがる> リソースの消費量が増え、サーバの台数が増える

• 並列化や非同期化が難しく、高負荷に対応しにくい> 自前実装はバグの元 =「高負荷になると固まる」> ネットワーク/マルチスレッド/イベント駆動には罠が多い

Page 18: Gumi study7 messagepack

従来の問題2

• 書きやすい言語でプロトタイピングしたい→ 効率の良い言語で本番実装 を段階的に行いたい> 例:サーバだけRubyからC++に移植

• プロトコルを後から(無停止で)更新したい> サーバの一部を最新版に更新> ↑繰り返して無停止で全サーバを更新

ローリングアップデート

Page 19: Gumi study7 messagepack

MessagePackによる解決

• 高速で多機能で多言語対応した通信システムを提供> 本質的な機能の実装に集中できる> 用途に合った言語を選択できる> プロトタイピング→別の言語で本番実装 も容易

• データサイズやCPU負荷を削減して、サーバの台数を減らす

• 互換性を保ったままプロトコルを拡張可能にする• 通信を並列性してマルチコア・スケールアウトに対応

Page 20: Gumi study7 messagepack

解決手法

• MessagePack:効率の良いシリアライザ> 中間の型システム+型変換APIを導入 各言語の差異を吸収する JSONとの相互変換が可能な型システム> 高速化手法 ゼロコピー化 効率の良いバッファリング機能を内臓  (ストリーミングAPI)

Page 21: Gumi study7 messagepack

解決手法

• MessagePack-RPC:高機能なRPC> 並列化手法 非同期呼び出し Parallel Pipelining 並列イベント駆動I/O> 高速化手法 コネクションプーリング> 使いやすいAPI:複雑な並列I/Oを隠蔽 Session Future

Page 22: Gumi study7 messagepack

MessagePackの用途

• サーバ間の通信> 分散システムのプロトタイプの実装> 新しいサーバプログラムの実装 管理ツールの実装 クライアントライブラリの実装

• シリアライザ単体で利用> KVSやログに保存するレコードのシリアライズ> JSONを置き換え

Page 23: Gumi study7 messagepack

MessagePack - 高速シリアライザ

> いつ/どこで MessagePack を使うか> MessagePack の手法

背景

> シリアライザの設計手法と MessagePack の選択> フォーマットと Embedded Type Information> MessagePack の型システムと型変換

MessagePack-RPC - 多機能RPC> プロトコルと Parallel Pipelining> 並列イベント駆動I/O> FutureとSessionによる隠蔽

事例

Page 24: Gumi study7 messagepack

MessagePack - 高速シリアライザ

> いつ/どこで MessagePack を使うか> MessagePack の手法

背景

> シリアライザの設計手法と MessagePack の選択> フォーマットと Embedded Type Information> MessagePack の型システムと型変換

MessagePack-RPC - 多機能RPC> プロトコルと Parallel Pipelining> 並列イベント駆動I/O> FutureとSessionによる隠蔽

事例

Page 25: Gumi study7 messagepack

シリアライザ

• シリアライザの役割> オブジェクトをバイト列に変換> バイト列からオブジェクトを復元

• シリアライザの用途> オブジェクトをDBやキャッシュに保存> オブジェクトをネットワーク越しに転送

Page 26: Gumi study7 messagepack

require 'msgpack' # gem install “msgpack"raw = [1,2,3].to_msgpack #=> "\x93\x01\x02\x03"MessagePack.unpack(raw) #=> [1,2,3]

public class Main { public static void main(String[] args) { byte[] raw = MessagePack.pack(new MyClass()); MyClass dst = MessagePack.unpack(raw, MyClass.class); }}

int main() { msgpack::sbuffer raw; std::vector<int> src; std::vector<int> dst; msgpack::pack(raw, src); msgpack::unpack(raw.data(), raw.size())->convert(&dst);}

Ruby

Java

C++

Page 27: Gumi study7 messagepack

シリアライザの設計方法

• バイナリかテキストか> 人間には読めないが速い <-> 読めるが遅い

• シリアライズ後のデータに型情報を埋め込むか> データサイズが大きくなる <-> 小さく済む> バイト列だけから復元可能 <-> IDLが必要

• 多言語に対応するか

Page 28: Gumi study7 messagepack

MessagePackの選択

• バイナリ形式のシリアライズフォーマット> 大きなバイト列をゼロコピーで扱う

• 型情報をシリアライズ後のデータに埋め込む> コンパクトに埋め込むエンコーディング手法> JSONと互換性のある型システム 整数, 真偽値, 配列, 連想配列, ...

• 多言語に対応> MessagePackの型 と 言語の型 を相互に変換

Page 29: Gumi study7 messagepack

フォーマット

JSON MessagePack

null

Integer

Array

String

Map

null c0

10 0a

[20] 91 14

“30” a2 ‘3’ ‘0’

{“40”:null} 81 a2 ‘4’ ‘0’ c0

Page 30: Gumi study7 messagepack

フォーマット

JSON MessagePack

null

Integer

Array

String

Map

null c0

10 0a

[20] 91 14

“30” a2 ‘3’ ‘0’

{“40”:null} 81 a2 ‘4’ ‘0’ c0

4 bytes 1 byte

2 bytes 1 byte

4 bytes 2 bytes

4 bytes 3 bytes

11 bytes 5 bytes

Page 31: Gumi study7 messagepack

Embedded type information

type body...

type + value

typevalue length

type + length

非コンテナ型 コンテナ型

よく使う(小さいデータ)は、型情報+値/長さ を1バイトで保存

body...

Page 32: Gumi study7 messagepack

Type information0x000xc20xc30xca0xcb0xcc0xcd0xce0xcf0xdf...

nil false true float double uint8 uint16 uint32 uint64 int8 ...

Types

0xc00xe0

Type information

Page 33: Gumi study7 messagepack

Type information

Positive FixNum

Negative FixNum

FixMapFixArray

FixRaw

0x00

0xc0

0x800x900xa0

0xe0

0x000xc20xc30xca0xcb0xcc0xcd0xce0xcf0xdf...

nil false true float double uint8 uint16 uint32 uint64 int8 ...

Type information Types

Page 34: Gumi study7 messagepack

JSONとの比較{“msgpack”:“json”, “hello”:“world”}

24%削減

MessagePack26 bytes

JSON34 bytes

別の事例:ある日のTwitterのpublic_timeline:JSON 31KB => MessagePack 25KB(19%削減)

Page 35: Gumi study7 messagepack

多言語対応の問題

• 言語間の差異を吸収する必要がある> 型システムの違い 文字列とバイト列の区別がない 配列と連想配列の区別がない クラスがない> クラス名や変数名の命名規則が違う

Page 36: Gumi study7 messagepack

“MessagePackの型”

• “MessagePackの型”を導入> JSON互換 整数, 浮動小数点数, Boolean, nil, 文字列, 配列, 連想配列> “MessagePackの型”を表現するクラスを導入 Java:MessagePackObject C++:msgpack::object> MessagePackの型 と 言語の型 を相互に変換する機能をライブラリで実装

Page 37: Gumi study7 messagepack

MessagePackC++の型 Rubyの型

MessagePackの型

Javaの型

msgpack::object

MessagePackObject

多言語対応

Page 38: Gumi study7 messagepack

高度な型変換

• テンプレート(Java版, C++版)> デシリアライズされたオブジェクトの型を検査> 型の変換や型チェックするコードが不要になる

• Optionalフィールド(Java版)> クラスのデシリアライズ時に、値の省略を許して、デフォルト値を使う

• 高速化> コンパイル時コード生成(C++版)> 実行時コード生成(Java版)

Page 39: Gumi study7 messagepack

Optionalフィールド

@MessagePackMessagepublic static class MyClass { public String str; public double num;

@Optional public int flag = 0;}

Page 40: Gumi study7 messagepack

ストリーミング

require 'msgpack'

u = MessagePack::Unpacker.new($stdin)

u.each do |obj|

puts obj.to_json

end

Page 41: Gumi study7 messagepack

msgpack json protobuf avro thrift

形式

型情報

スキーマ記述

ストリーミング

RPC

シリアライザ単体で利用

binary text binary binary binary

埋め込み 埋め込み 外部 外部(添付) 外部

コード内に記述Thrift互換形式の

IDLも実装中

JSON Schema?

必須(独自DSL)

必須(JSON形式)

必須(独自DSL)

対応 できるはず 非対応 非対応 非対応

msgpack-rpc json-rpc (非公開) avro thrift

可能 可能 可能 可能 面倒

Page 42: Gumi study7 messagepack

MessagePack - 高速シリアライザ

> いつ/どこで MessagePack を使うか> MessagePack の手法

背景

> シリアライザの設計手法と MessagePack の選択> フォーマットと Embedded Type Information> MessagePack の型システムと型変換

MessagePack-RPC - 多機能RPC> プロトコルと Parallel Pipelining> 並列イベント駆動I/O> FutureとSessionによる隠蔽

事例

Page 43: Gumi study7 messagepack

MessagePack - 高速シリアライザ

> いつ/どこで MessagePack を使うか> MessagePack の手法

背景

> シリアライザの設計手法と MessagePack の選択> フォーマットと Embedded Type Information> MessagePack の型システムと型変換

MessagePack-RPC - 多機能RPC> プロトコルと Parallel Pipelining> 並列イベント駆動I/O> FutureとSessionによる隠蔽

事例

Page 44: Gumi study7 messagepack

プロトコルJSON-RPCをベースにしたプロトコル設計

[0, msgid, method, params]

[1, msgid, error, result]

[2, method, params]

Request

Response

Notify

メッセージID→Parallel Pipelining

Page 45: Gumi study7 messagepack

並列性

クライアント サーバ パイプライン化応答が帰ってくる前に立て続けに複数の要求を発行することで高速化を図る

実装例:・HTTP/1.1 pipelining・Thrift・SOAP

Page 46: Gumi study7 messagepack

クライアント サーバ

並列性

重いタスク軽いタスク

実装例:・HTTP/1.1 pipelining・Thrift・SOAP

重いタスクが軽いタスクを待たせる

> 並列性が低下

順番を揃える(キュー)

Page 47: Gumi study7 messagepack

クライアント サーバ

並列性

実装例:・MessagePack-RPC

応答の順番を揃える必要が無い早く終わったタスクはすぐに返す

> 並列性が向上 > サーバのリソース消費量を削減

時間短縮

重いタスク軽いタスク

Page 48: Gumi study7 messagepack

並列性ベンチマークテスト

Page 49: Gumi study7 messagepack

並列性

• RPCの要求と応答に”メッセージID”を入れ、クライアント側で要求と応答を対応付ける> サーバで処理する順番は自由> サーバの並列化が容易 全要求を自動的に並列化する(Java, C++版)> 重いタスクが軽いタスクを待たせない

Page 50: Gumi study7 messagepack

MessagePack - 高速シリアライザ

> いつ/どこで MessagePack を使うか> MessagePack の手法

背景

> シリアライザの設計手法と MessagePack の選択> フォーマットと Embedded Type Information> MessagePack の型システムと型変換

MessagePack-RPC - 多機能RPC> プロトコルと Parallel Pipelining> 並列イベント駆動I/O> FutureとSessionによる隠蔽

事例

Page 51: Gumi study7 messagepack

イベント駆動I/Oサーバーサイド イベント駆動I/O

Dispatcher

ServerClient

Client

Loop

multi-threaded event-driven I/O(C++, Java)

大量のクライアントと効率的に通信できる

Page 52: Gumi study7 messagepack

イベント駆動I/O

Client

Session Loop Server

Client

ServerSession Loop

クライアントサイド イベント駆動I/O

Page 53: Gumi study7 messagepack

イベント駆動I/O

sharedevent loop

Client

Client

Server

Server

Loop

Session

Session

クライアントサイド イベント駆動I/O

並列して通信可能

Page 54: Gumi study7 messagepack

イベント駆動I/O

Session PoolServer

Server

pools these connectionsLoop

Session

Session

connection

クライアントサイド イベント駆動I/O

Page 55: Gumi study7 messagepack

Dispatcher

イベント駆動I/O

sharedevent loop

Client

Server

Server

Loop

Session

Session

クライアントサイド イベント駆動I/O

Client

サーバとクライアントを同じイベントループ上で動作

Page 56: Gumi study7 messagepack

sharedevent looptimer, signal handler,

other protocol, etc...

Dispatcher

イベント駆動I/O

Client

Server

Loop

Session

クライアントサイド イベント駆動I/O

Client

サーバとクライアントを同じイベントループ上で動作

Page 57: Gumi study7 messagepack

イベント駆動I/O

• スレッドを使わずにI/Oを並列化> 多数のクライアントと効率よく通信できる

• クライアント側もイベント駆動> 多数のサーバと効率よく通信できる

• 高度な分散システムを効率よく実装可能> 例:多数のサーバ同士が通信しあう分散システム> 例:クラスタの一括制御ツール

Page 58: Gumi study7 messagepack

イベント駆動I/O

• サーバとクライアントのアーキテクチャが対称的> 1つのイベントループに様々なイベントハンドラを追加のせてプログラムを構築できる

> サーバ/クライアント両方の特性を持つシステム 例:プロキシサーバ

• イベントループをプールしてコネクションをプール> 何度もコネクションを張り直す負荷を削減> 高負荷時でもポート番号が足りなくならない

Page 59: Gumi study7 messagepack

MessagePack - 高速シリアライザ

> いつ/どこで MessagePack を使うか> MessagePack の手法

背景

> シリアライザの設計手法と MessagePack の選択> フォーマットと Embedded Type Information> MessagePack の型システムと型変換

MessagePack-RPC - 多機能RPC> プロトコルと Parallel Pipelining> 並列イベント駆動I/O> FutureとSessionによる隠蔽

事例

Page 60: Gumi study7 messagepack

Futureとセッション

• Future> 「未来の結果」を表すオブジェクト 実際に参照されるまで結果の処理を遅延させる> 非同期呼び出しを抽象化> 並列イベント駆動I/Oを隠蔽

• セッション> 「コネクション」の概念を隠蔽> 接続・再接続・接続維持を自動化

Page 61: Gumi study7 messagepack

Future

Future概念提示使い方を軽く

非同期処理を抽象化

require 'msgpack/rpc'

loop = MessagePack::RPC::Loop.new

c1 = MessagePack::RPC::Client.new(host, port, loop)c2 = MessagePack::RPC::Client.new(host, port, loop)

future1 = c1.call_async(:method1, arg)future2 = c2.call_async(:method2, arg)

future2.getfuture1.get

Page 62: Gumi study7 messagepack

Futureクライアント サーバ1 サーバ2

call_async(method1)

call_async(method2)

future1

future2

Page 63: Gumi study7 messagepack

セッションコネクションの隠蔽

sharedevent loop

Server

Server

Loop

Session

Session

connection

Page 64: Gumi study7 messagepack

セッションコネクションの隠蔽

sharedevent loop

Server

Server

Loop

Session

Session

connection

Future

Future

Future

Future

コネクションを隠蔽非同期処理を抽象化

Page 65: Gumi study7 messagepack

セッションコネクションの隠蔽

Session

Session

Future

Future

Future

Future

コネクションを隠蔽非同期処理を抽象化

セッション:コネクションを直接制御させない

> 接続が切れたら自動的に再接続 > コネクションプーリング

Future:非同期処理を直接記述させない

> 記述を簡略化 > バックグラウンドで処理できる 通信は自動的に並列処理

Page 66: Gumi study7 messagepack

Future非同期処理を抽象化

require 'msgpack/rpc'

loop = MessagePack::RPC::Loop.new

c1 = MessagePack::RPC::Client.new(host, port, loop)c2 = MessagePack::RPC::Client.new(host, port, loop)

future1 = c1.call_async(:method1, arg)future2 = c2.call_async(:method2, arg)

future2.getfuture1.get

Page 67: Gumi study7 messagepack
Page 68: Gumi study7 messagepack

MessagePack - 高速シリアライザ

> いつ/どこで MessagePack を使うか> MessagePack の手法

背景

> シリアライザの設計手法と MessagePack の選択> フォーマットと Embedded Type Information> MessagePack の型システムと型変換

MessagePack-RPC - 多機能RPC> プロトコルと Parallel Pipelining> 並列イベント駆動I/O> FutureとSessionによる隠蔽

事例

Page 69: Gumi study7 messagepack

MessagePack - 高速シリアライザ

> いつ/どこで MessagePack を使うか> MessagePack の手法

背景

> シリアライザの設計手法と MessagePack の選択> フォーマットと Embedded Type Information> MessagePack の型システムと型変換

MessagePack-RPC - 多機能RPC> プロトコルと Parallel Pipelining> 並列イベント駆動I/O> FutureとSessionによる隠蔽

事例

Page 70: Gumi study7 messagepack

事例

• Sedue Search Cloud• Amebaなう• kumofs• Sekai Camera• mycached• Ficia

> “kumofs での Data::Model の使い方” http://blog.yappo.jp/yappo/archives/000710.html

• Cassandra?

Page 71: Gumi study7 messagepack
Page 72: Gumi study7 messagepack
Page 73: Gumi study7 messagepack
Page 74: Gumi study7 messagepack
Page 75: Gumi study7 messagepack

MessagePack - 高速シリアライザ

> いつ/どこで MessagePack を使うか> MessagePack の手法

背景

> シリアライザの設計手法と MessagePack の選択> フォーマットと Embedded Type Information> MessagePack の型システムと型変換

MessagePack-RPC - 多機能RPC> プロトコルと Parallel Pipelining> 並列イベント駆動I/O> FutureとSessionによる隠蔽

事例

Page 76: Gumi study7 messagepack

MessagePack - 高速シリアライザ

> いつ/どこで MessagePack を使うか> MessagePack の手法

背景

> シリアライザの設計手法と MessagePack の選択> フォーマットと Embedded Type Information> MessagePack の型システムと型変換

MessagePack-RPC - 多機能RPC> プロトコルと Parallel Pipelining> 並列イベント駆動I/O> FutureとSessionによる隠蔽

事例

Page 77: Gumi study7 messagepack

まとめ - MessagePack

• 高速なシリアライズ形式> バイナリ形式のコンパクトなフォーマット JSONと比べて約20%くらいデータサイズを削減> 中間型システム + 型変換API により多言語に対応> 型情報をデータに埋め込む; 定義ファイルが不要> JSONと相互に変換可能> ストリーミング機能

Page 78: Gumi study7 messagepack

まとめ - MessagePack-RPC

• 多機能なRPCシステム> クライアントサイドイベント駆動I/O;複数のコネクションで通信を並列化

> Parallel Pipelining;1本のコネクション上でも通信を並列化

> Futureにより複雑な並列イベント駆動I/Oを隠蔽> Sessionによりコネクションを隠蔽 コネクションの確立・維持・再接続を自動化

Page 79: Gumi study7 messagepack

まとめ - The MessagePack Project

• 世界で利用拡大中• コミッタ募集中• 利用事例募集中

Page 80: Gumi study7 messagepack

MessagePack

• C++> Sadayuki Furuhashi

• Ruby> Sadayuki Furuhashi

• Java> Muga Nishizawa

• Python> INADA Naoki

• Haskell> Hideyuki Tanaka

• Lua> Nobuyuki Kubota

• Perl> tokuhirom, gfx, ...

• Erlang> UENISHI Kota

• Node.JS> Peter Griess

• JavaScript> uupaa

• PHP> advect

• D> repeatedly

対応言語と開発者の一部

Page 81: Gumi study7 messagepack

MessagePack-RPC

• C++版 - Sadayuki Furuhashi• Erlang版 - UENISHI Kota• Haskell版 - Hideyuki Tanaka• Java版 - Muga Nishizawa• PHP版 - h0x10• Python版 - INADA Naoki• Ruby版 - Sadayuki Furuhashi

対応言語と開発者の一部

Page 82: Gumi study7 messagepack

http://msgpack.org/ http://github.com/msgpack

Twitter: #msgpack msgpack@googlegroups