ameba piggの裏側

125

Click here to load reader

Upload: yusaku-watanabe

Post on 06-May-2015

12.617 views

Category:

Documents


10 download

TRANSCRIPT

Page 1: Ameba Piggの裏側

AmebaPiggの裏側

2011年5月16日月曜日

Page 2: Ameba Piggの裏側

自己紹介

2011年5月16日月曜日

Page 3: Ameba Piggの裏側

渡辺 雄作(32) / @waysaku株式会社サイバーエージェントアメーバ事業本部所属

2006年中途入社前職は金融•証券系のSIerのプログラマーアメーバ関連開発を経て、現在はAmebaPiggのシステム開発責任者

2011年5月16日月曜日

Page 4: Ameba Piggの裏側

渡辺 雄作(32) / @waysaku株式会社サイバーエージェントアメーバ事業本部所属

2006年中途入社前職は金融•証券系のSIerのプログラマーアメーバ関連開発を経て、現在はAmebaPiggのシステム開発責任者

2011年5月16日月曜日

Page 5: Ameba Piggの裏側

AmebaPiggとは?

2011年5月16日月曜日

Page 6: Ameba Piggの裏側

2009年2月に開始した仮想空間サービス

現在は400万人以上のユーザーが利用する仮想空間へと成長

2011年5月16日月曜日

Page 7: Ameba Piggの裏側

2011年5月16日月曜日

Page 8: Ameba Piggの裏側

2011年5月16日月曜日

Page 9: Ameba Piggの裏側

2011年5月16日月曜日

Page 10: Ameba Piggの裏側

6割の売上を占める主要サービス

2011年5月16日月曜日

Page 11: Ameba Piggの裏側

システムアーキテクチャ

•求められている要件•システム仕様

2011年5月16日月曜日

Page 12: Ameba Piggの裏側

求められている要件

2011年5月16日月曜日

Page 13: Ameba Piggの裏側

求められている要件大量リクエスト処理

2011年5月16日月曜日

Page 14: Ameba Piggの裏側

求められている要件大量リクエスト処理スケーラビリティ

2011年5月16日月曜日

Page 15: Ameba Piggの裏側

求められている要件

リアルタイム性

大量リクエスト処理スケーラビリティ

2011年5月16日月曜日

Page 16: Ameba Piggの裏側

求められている要件

リアルタイム性イベント駆動(Push配信)

大量リクエスト処理スケーラビリティ

2011年5月16日月曜日

Page 17: Ameba Piggの裏側

求められている要件

リアルタイム性イベント駆動(Push配信)

大量リクエスト処理スケーラビリティ

ブラウザで動く

2011年5月16日月曜日

Page 18: Ameba Piggの裏側

求められている要件

リアルタイム性イベント駆動(Push配信)

大量リクエスト処理スケーラビリティ

ミニマムスタート(予算的な意味で)

ブラウザで動く

2011年5月16日月曜日

Page 19: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 20: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

swfやimgの配信

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 21: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 22: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

ユーザー情報のやり取り

2011年5月16日月曜日

Page 23: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 24: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

チャットデータのやり取り

2011年5月16日月曜日

Page 25: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 26: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

チャット+

ゲーム情報のやりとり

2011年5月16日月曜日

Page 27: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 28: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

ピグの基盤DB

2011年5月16日月曜日

Page 29: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 30: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

ユーザーswfなどを格納

2011年5月16日月曜日

Page 31: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 32: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

ログデータの簡単な解析

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 33: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 34: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 35: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 36: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 37: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 38: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 39: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 40: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 41: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 42: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 43: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 44: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 45: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 46: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 47: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 48: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 49: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 50: Ameba Piggの裏側

システム仕様

2011年5月16日月曜日

Page 51: Ameba Piggの裏側

クライアント

2011年5月16日月曜日

Page 52: Ameba Piggの裏側

クライアント

ActionScript3+

独自開発フレームワーク

2011年5月16日月曜日

Page 53: Ameba Piggの裏側

クライアント

ActionScript3+

独自開発フレームワーク複数人開発を意識したモジュール化

Dynamic Module LoadingDependency Injection

各種ライブラリのチューニング(LinkedListのチューニングなど)

2011年5月16日月曜日

Page 54: Ameba Piggの裏側

main.swf

core.swcソケット通信などのフレームワーク

profile.swf

room.swf

casino.swf

fishing.swf

shop.swf

main.swf各モジュールへのインターフェースを

定義

2011年5月16日月曜日

Page 55: Ameba Piggの裏側

main.swf

core.swcソケット通信などのフレームワーク

profile.swf

room.swf

casino.swf

fishing.swf

shop.swf

main.swf各モジュールへのインターフェースを

定義

イベント発生時に動的にswfをロードする

2011年5月16日月曜日

Page 56: Ameba Piggの裏側

サーバ(socket)

2011年5月16日月曜日

Page 57: Ameba Piggの裏側

サーバ(socket)

Java+

独自開発フレームワーク

2011年5月16日月曜日

Page 58: Ameba Piggの裏側

サーバ(socket)

Java+

独自開発フレームワークノンブロッキングIOを使った軽量データ(コマンド)処理サーバ

独自プロトコルによるステートフル通信

2011年5月16日月曜日

Page 59: Ameba Piggの裏側

<interface>Command

コマンド処理

<interface>Command

コマンド処理

送信したいデータをバイトデータにシリアライズ

AS3、pythonで実装済

server client

2011年5月16日月曜日

Page 60: Ameba Piggの裏側

データストア

2011年5月16日月曜日

Page 61: Ameba Piggの裏側

データストア

IndexPersister(Java)+

MySQL

2011年5月16日月曜日

Page 62: Ameba Piggの裏側

データストア

IndexPersister(Java)+

MySQL

オブジェクトをバイナリでMySQLに保存MySQLはKeyValueストアとして利用するのみ

2011年5月16日月曜日

Page 63: Ameba Piggの裏側

IndexPersister@Persistable("address")

public class Address {

private int userId; private String name;; private byte enable;

@IndexKey @Store(index=0) public int getUserId() { return userId; } @Store(index=1) public String getName() { return name; } @Store(index=2) public byte getEnable() { return status; }

2011年5月16日月曜日

Page 64: Ameba Piggの裏側

IndexPersister@Persistable("address")

public class Address {

private int userId; private String name;; private byte enable;

@IndexKey @Store(index=0) public int getUserId() { return userId; } @Store(index=1) public String getName() { return name; } @Store(index=2) public byte getEnable() { return status; }

Key : ValueuserId : userId + name + enable

シリアライズ

2011年5月16日月曜日

Page 65: Ameba Piggの裏側

IndexPersister@Persistable("address")

public class Address {

private int userId; private String name;; private byte enable;

@IndexKey @Store(index=0) public int getUserId() { return userId; } @Store(index=1) public String getName() { return name; } @Store(index=2) public byte getEnable() { return status; }

Key : ValueuserId : userId + name + enable

シリアライズ

2011年5月16日月曜日

Page 66: Ameba Piggの裏側

IndexPersister@Persistable("address")

public class Address {

private int userId; private String name;; private byte enable;

@IndexKey @Store(index=0) public int getUserId() { return userId; } @Store(index=1) public String getName() { return name; } @Store(index=2) public byte getEnable() { return status; }

Key : ValueuserId : userId + name + enable

シリアライズ

2011年5月16日月曜日

Page 67: Ameba Piggの裏側

IndexPersister@Persistable("address")

public class Address {

private int userId; private String name;; private byte enable;

@IndexKey @Store(index=0) public int getUserId() { return userId; } @Store(index=1) public String getName() { return name; } @Store(index=2) public byte getEnable() { return status; }

Key : ValueuserId : userId + name + enable

シリアライズ

2011年5月16日月曜日

Page 68: Ameba Piggの裏側

IndexPersister@Persistable("address")

public class Address {

private int userId; private String name;; private byte enable;

@IndexKey @Store(index=0) public int getUserId() { return userId; } @Store(index=1) public String getName() { return name; } @Store(index=2) public byte getEnable() { return status; }

Key : ValueuserId : userId + name + enable

シリアライズ

2011年5月16日月曜日

Page 69: Ameba Piggの裏側

IndexPersister

2011年5月16日月曜日

Page 70: Ameba Piggの裏側

IndexPersister

複数の型のシリアライズに対応

2011年5月16日月曜日

Page 71: Ameba Piggの裏側

IndexPersister

複数の型のシリアライズに対応データ互換性保持

2011年5月16日月曜日

Page 72: Ameba Piggの裏側

IndexPersister

複数の型のシリアライズに対応データ互換性保持中間キャッシュ

2011年5月16日月曜日

Page 73: Ameba Piggの裏側

IndexPersister

複数の型のシリアライズに対応データ互換性保持中間キャッシュデータ圧縮

2011年5月16日月曜日

Page 74: Ameba Piggの裏側

IndexPersister

複数の型のシリアライズに対応データ互換性保持中間キャッシュデータ圧縮複合キー生成

2011年5月16日月曜日

Page 75: Ameba Piggの裏側

IndexPersisterバイナリで保存するメリット

2011年5月16日月曜日

Page 76: Ameba Piggの裏側

IndexPersisterバイナリで保存するメリット

データストアに依存しない

indexPersister Interface

NDIpersister

MySQL persister

MongoDB persister

その他

byte[] : byte[]

varbinary : longblob

バイナリ形式が保存できればOK

Application

2011年5月16日月曜日

Page 77: Ameba Piggの裏側

MySQLの利用方法Key Valueストアとして利用

`key` varbinary(255) NOT NULL`value` longblob NOT NULL

2011年5月16日月曜日

Page 78: Ameba Piggの裏側

MySQLの利用方法Key Valueストアとして利用

`key` varbinary(255) NOT NULL`value` longblob NOT NULL

Amebaで実績のあるMySQLの安定性•信頼性社内のMySQLの運用ノウハウを利用可能

I/O性能対策にI/O Accerarator(FusionIO)を採用

2011年5月16日月曜日

Page 79: Ameba Piggの裏側

運用•工夫について•開発体制•システムパフォーマンス•サーバの物理設計•行動ログの保存•永続化レイヤーのリプレイス

2011年5月16日月曜日

Page 80: Ameba Piggの裏側

開発体制(立ち上げ)プロデューサ

エンジニア

Flashクリエイター

デザイナー

2011年5月16日月曜日

Page 81: Ameba Piggの裏側

開発体制(現在)

プロデューサ

エンジニア

Flashクリエイター

デザイナーイラストレータークリエイティブディレクター

2011年5月16日月曜日

Page 82: Ameba Piggの裏側

パフォーマンスなど

2011年5月16日月曜日

Page 83: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

2011年5月16日月曜日

Page 84: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

ソケットサーバへの同時接続数

10万同時接続(ピーク時)

2011年5月16日月曜日

Page 85: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

ソケットサーバへの同時接続数

10万同時接続(ピーク時)トラフィック

2.2Gbps(ピーク時)

2011年5月16日月曜日

Page 86: Ameba Piggの裏側

Flash(ActionScript3)

web-app server info-socket-server chat-socket-server game-socket-server

hadoop cluster

memcached

File Store Cluster

memcached

MySQL

ソケットサーバへの同時接続数

10万同時接続(ピーク時)トラフィック

2.2Gbps(ピーク時)

秒間クエリ(Query Per Second)

14万QPS

30万QPS

2011年5月16日月曜日

Page 87: Ameba Piggの裏側

サーバ物理設計

2011年5月16日月曜日

Page 88: Ameba Piggの裏側

サーバ物理設計

2011年5月16日月曜日

Page 89: Ameba Piggの裏側

サーバ物理設計

CPU性能はあまり必要ない

2011年5月16日月曜日

Page 90: Ameba Piggの裏側

サーバ物理設計

CPU性能はあまり必要ない省電力

2011年5月16日月曜日

Page 91: Ameba Piggの裏側

サーバ物理設計

CPU性能はあまり必要ない省電力省スペース

2011年5月16日月曜日

Page 92: Ameba Piggの裏側

サーバ物理設計

安い

CPU性能はあまり必要ない省電力省スペース

2011年5月16日月曜日

Page 93: Ameba Piggの裏側

2011年5月16日月曜日

Page 94: Ameba Piggの裏側

2011年5月16日月曜日

Page 95: Ameba Piggの裏側

2011年5月16日月曜日

Page 96: Ameba Piggの裏側

2011年5月16日月曜日

Page 97: Ameba Piggの裏側

2011年5月16日月曜日

Page 98: Ameba Piggの裏側

2011年5月16日月曜日

Page 99: Ameba Piggの裏側

ユーザー行動ログの保存

2011年5月16日月曜日

Page 100: Ameba Piggの裏側

保存しているログの種類

ログイン•ログアウト移動チャット手紙•メッセンジャー着替え•顔変更ぴぐとも

部活カメラ•アイテム消費ペットゲームetc...

2011年5月16日月曜日

Page 101: Ameba Piggの裏側

保存しているログの種類

ログイン•ログアウト移動チャット手紙•メッセンジャー着替え•顔変更ぴぐとも

部活カメラ•アイテム消費ペットゲームetc...

取得している行動ログは100種類程度約3GB/dayのログを収集

デイリーでラボチームにもデータ転送

2011年5月16日月曜日

Page 102: Ameba Piggの裏側

永続化レイヤーのリプレイス

2011年5月16日月曜日

Page 103: Ameba Piggの裏側

web-app server info-socket-server chat-socket-server game-socket-server

MySQLhadoop cluster File Store Cluster

Flash(ActionScript3)2011年5月16日月曜日

Page 104: Ameba Piggの裏側

web-app server info-socket-server chat-socket-server game-socket-server

MySQLhadoop cluster File Store Cluster

Flash(ActionScript3)2011年5月16日月曜日

Page 105: Ameba Piggの裏側

web-app server info-socket-server chat-socket-server game-socket-server

MySQLhadoop cluster File Store Cluster

Flash(ActionScript3)

独自実装の分散KVS

2011年5月16日月曜日

Page 106: Ameba Piggの裏側

独自実装の分散KVS

Namura Distributed Index(NDI)名村が2008年頃に開発した分散KVS

2011年5月16日月曜日

Page 107: Ameba Piggの裏側

独自実装の分散KVS

Namura Distributed Index(NDI)名村が2008年頃に開発した分散KVS

range search by keyauto shardingauto failoveron memory

2011年5月16日月曜日

Page 108: Ameba Piggの裏側

独自実装の分散KVS

Namura Distributed Index(NDI)名村が2008年頃に開発した分散KVS

range search by keyauto shardingauto failoveron memory

最終的にサーバは200台近くまで増設管理コスト肥大化

開発•検証環境のメンテナンス大変

2011年5月16日月曜日

Page 109: Ameba Piggの裏側

NDIからMySQLへのリプレイス

200台近くのノードでさばいていた参照クエリをMySQL × 4台でさばく

2011年5月16日月曜日

Page 110: Ameba Piggの裏側

NDIからMySQLへのリプレイス

200台近くのノードでさばいていた参照クエリをMySQL × 4台でさばく

MySQLのディスクI/O

問題

2011年5月16日月曜日

Page 111: Ameba Piggの裏側

FusionIOの導入

NANDコントローラのあるカードに、専用のメモリモジュールを装着して利用するSSD(I/O Accerarator)

ReadでHDの5倍ぐらい WriteでHDの7~8倍ぐらいのパフォーマンス

2011年5月16日月曜日

Page 112: Ameba Piggの裏側

Fusion-io社の製品ページ

2011年5月16日月曜日

Page 113: Ameba Piggの裏側

SAS RAID5

FusionIO

2011年5月16日月曜日

Page 114: Ameba Piggの裏側

MySQL QPS CPU

Load Average Traffic

2011年5月16日月曜日

Page 115: Ameba Piggの裏側

MySQL QPS CPU

Load Average Traffic

2011年5月16日月曜日

Page 116: Ameba Piggの裏側

スケールアウトからスケールアップへ

2011年5月16日月曜日

Page 117: Ameba Piggの裏側

スケールアウトからスケールアップへ

•スケールアウト自体はミニマムスタートには超有効•安価なサーバ•スケーラブルなソフトウェア設計

2011年5月16日月曜日

Page 118: Ameba Piggの裏側

スケールアウトからスケールアップへ

•スケールアウト自体はミニマムスタートには超有効•安価なサーバ•スケーラブルなソフトウェア設計

システムの成長が早い場合には管理コストの増大に追いつくのが大変※管理コストに追われて機能追加が遅れる

2011年5月16日月曜日

Page 119: Ameba Piggの裏側

AmebaPiggの今後の課題

2011年5月16日月曜日

Page 120: Ameba Piggの裏側

ダウンタイムの削減

ユーザーによる不正行為の防止

とはいえ、増え続けるサーバの管理

2011年5月16日月曜日

Page 121: Ameba Piggの裏側

ダウンタイムの削減

ユーザーによる不正行為の防止

とはいえ、増え続けるサーバの管理

リリース時のサービス停止の削減監視機能強化

2011年5月16日月曜日

Page 122: Ameba Piggの裏側

ダウンタイムの削減

ユーザーによる不正行為の防止

とはいえ、増え続けるサーバの管理

リリース時のサービス停止の削減監視機能強化

低年齢層や女性ユーザーも引き続き安心して使えるようにゲームでの不正行為防止

2011年5月16日月曜日

Page 123: Ameba Piggの裏側

ダウンタイムの削減

ユーザーによる不正行為の防止

とはいえ、増え続けるサーバの管理

リリース時のサービス停止の削減監視機能強化

低年齢層や女性ユーザーも引き続き安心して使えるようにゲームでの不正行為防止

自作サーバの組み立て外注各種設定の更なる自動化

2011年5月16日月曜日

Page 124: Ameba Piggの裏側

興味のある方は是非使ってみてください

2011年5月16日月曜日

Page 125: Ameba Piggの裏側

ご清聴ありがとうございました

2011年5月16日月曜日