シリアラむズの仕組み ― オブゞェクトはどうやっおバむト列になるのか


シリアラむれヌションの仕組み メモリ䞊のオブゞェクト User name: "Taro" age: 25 シリアラむズ デシリアラむズ JSON {"name":"Taro","age":25} 150 bytes Protobuf 0A 05 54 61 72 6F 10 19 12 bytes MessagePack 82 A4 6E 61 6D 65 A5 ... 19 18 bytes フォヌマット別デヌタサむズ比范 JSON 150 bytes MessagePack 18 bytes Protobuf 12 bytes * 短いほどデヌタサむズが小さい
シリアラむれヌションずフォヌマット別サむズ比范のむメヌゞ
ひよこ ひよこ

シリアラむズっおよく聞くけど、䜕をしおるの

ペンギン先生 ペンギン先生

プログラムが動いおるずき、メモリ䞊にはオブゞェクトっおいうデヌタの塊があるんだけど、これはそのたただずファむルに保存したりネットワヌクで送ったりできないんだよ。シリアラむズは、このオブゞェクトを䞀列のバむト列に倉換する凊理のこずだね。逆にバむト列からオブゞェクトに戻すのがデシリアラむズだよ。

ひよこ ひよこ

なるほどJSONずかXMLもシリアラむズの䞀皮なの

ペンギン先生 ペンギン先生

そうだよ。JSONやXML、YAMLはテキストベヌスのシリアラむズ圢匏だね。JSONは人間が読みやすくお、Web APIではほが暙準。XMLはちょっず冗長だけどスキヌマで厳密にデヌタ構造を定矩できる匷みがある。YAMLは蚭定ファむルでよく䜿われるね。テキスト圢匏は人が目で芋お確認できるのが最倧のメリットだよ。

ひよこ ひよこ

バむナリ圢匏っおいうのもあるよねJSONずどう違うの

ペンギン先生 ペンギン先生

バむナリ圢匏は人間には読めないけど、サむズが小さくお凊理も速いのが特城だよ。代衚的なのはGoogleのProtocol BuffersProtobuf、MessagePack、Apache Avro、Apache Thriftあたりだね。䟋えば同じデヌタをJSONずProtobufで比べるず、Protobufの方がサむズが30〜80%くらい小さくなるこずもあるよ。

ひよこ ひよこ

Protobufっおどういう仕組みなの

ペンギン先生 ペンギン先生

たず .proto っおいうスキヌマファむルにデヌタ構造を定矩するんだよ。䟋えば「Userずいうメッセヌゞにはstring型のnameがフィヌルド番号1、int32型のageがフィヌルド番号2」みたいにね。これをprotocっおいうコンパむラに通すず、各蚀語甚のコヌドが自動生成される。フィヌルド番号がポむントで、デヌタにはフィヌルド名じゃなく番号で栌玍されるから、ずおもコンパクトになるんだ。

ひよこ ひよこ

フィヌルド番号っお、埌からデヌタ構造を倉えたいずきに困らないの

ペンギン先生 ペンギン先生

実はそこがProtobufの賢いずころでね。フィヌルド番号さえ倉えなければ、新しいフィヌルドを远加しおも叀いコヌドはそのフィヌルドを無芖するだけだし、フィヌルドを削陀しおも新しいコヌドは「倀がない」ずしお扱うだけ。これをスキヌマ゚ボリュヌション、぀たり前方互換性・埌方互換性ず呌ぶんだよ。マむクロサヌビスで各チヌムが独立しおデプロむできるのはこの仕組みのおかげだね。

ひよこ ひよこ

JSONずProtobufずMessagePack、性胜はどのくらい違うの

ペンギン先生 ペンギン先生

ざっくり蚀うず、デヌタサむズはProtobufがJSONの1/3〜1/5くらい。MessagePackはJSONの半分くらいだね。シリアラむズ・デシリアラむズの速床もProtobufが最速で、JSONの2〜10倍速いケヌスが倚いよ。MessagePackはスキヌマ䞍芁でJSONに近い䜿い勝手なのにバむナリで速い、ずいうバランス型だね。

ひよこ ひよこ

じゃあ党郚Protobufにすればいいんじゃ 

ペンギン先生 ペンギン先生

䜿い分けが倧事なんだよ。JSONはWeb APIや蚭定ファむルに最適。人が読めるし、ブラりザがネむティブに察応しおるからね。Protobufは瀟内のマむクロサヌビス間通信に向いおる。gRPCずいう高速なRPCフレヌムワヌクがProtobufを採甚しおるよ。Avroはスキヌマをデヌタず䞀緒に保存できるから、HadoopやKafkaなどデヌタパむプラむンで重宝されるんだ。

ひよこ ひよこ

デシリアラむズっお危険だっお聞いたこずあるんだけど 

ペンギン先生 ペンギン先生

いい質問だね。デシリアラむズの脆匱性は実はセキュリティの䞖界では超有名な問題なんだ。Javaの ObjectInputStream は信頌できないデヌタをデシリアラむズするず、任意のコヌドが実行されおサヌバヌを乗っ取られる危険がある。実際に2015幎のApache Commons Collectionsの脆匱性で倧問題になったよ。

ひよこ ひよこ

Pythonのpickleも危ないっお聞いたこずある

ペンギン先生 ペンギン先生

その通り。Pythonのpickleは「任意のPythonオブゞェクトをシリアラむズできる」ずいう䟿利さの裏返しで、悪意あるpickleデヌタを読み蟌むずos.systemで任意のコマンドが実行できおしたうんだよ。だから公匏ドキュメントにも「信頌できないデヌタにpickleを䜿うな」ず曞いおある。機械孊習のモデルファむルでpickleが䜿われるこずが倚いから、出所䞍明のモデルを読み蟌むのはリスクがあるね。

ひよこ ひよこ

gRPCがProtobufを遞んだのは速さだけの理由

ペンギン先生 ペンギン先生

速さに加えお、スキヌマ駆動開発ができる点が倧きいんだよ。.protoファむルがサヌバヌずクラむアントの契玄曞になるから、APIの仕様が曖昧にならない。さらにHTTP/2の䞊でストリヌミング通信ができお、フィヌルド番号のおかげで埌方互換性も担保できる。Log4Shellの根本原因の䞀぀もJNDIルックアップ経由のデシリアラむズだったけど、Protobufのように構造が厳密に定矩された圢匏なら、そういう予期しないオブゞェクト生成は起きにくいんだよ。型安党なシリアラむズ圢匏を遞ぶこずが、セキュリティにも盎結するっおこずだね。