Azure Service Fabric を使う（４）Stateful Reliable Service


今までの Azure 関連の記事は以下。

[Azure Container Serviceを使う（１） 基本のデプロイ編](http://qiita.com/derui@github/items/64cc13016c002db69308)
[Azure Container Serviceを使う（２） 自動化してみる編](http://qiita.com/derui@github/items/c0a56dff517817c2e392)
[Azure Service Facricを使う（１）利用するための環境を揃える](http://qiita.com/derui@github/items/d0a0833bd3df5151a85d)
[Azure Service Facricを使う（２）Stateless Service](http://qiita.com/derui@github/items/4f5b8c668479b38de6a6)
[Azure Service Fabric を使う（３）Reliable Actor](http://qiita.com/derui@github/items/3944af28144e9ddac27a)

Service Fabricで定義されているアプリケーションのうち、最後となるStateful Reliable Serviceです

（どうでもいいんですが、Reliable Stateful Service なのか Stateful Reliable Service なのか、どっちかに統一して欲しいです。公式ドキュメントでも混在してるからどっちでもいいんでしょうけど）

## Stateful Reliable Service ##
**Stateful Reliable Service** は、Reliable Serviceの特徴に加えて、 **Reliable Collection** と呼ばれる仕組みによって状態を管理しているアプリケーションを指します（ということにしておきます）。

Reliable Collectionは、以下のように説明されています。

> Reliable Collection は、C# コレクションを使用したことがあるユーザーには馴染みのある可用性が高い一連のコレクション クラスです。これまでは、サービスにおいて確かな方法で状態を管理するには、外部システムが必要でした。Reliable Collection を使用すると、ユーザーのコンピューティングの隣に状態を格納できると同時に、高可用性の外部ストアと同じレベルの高い可用性と確実性を実現できます。また、コンピューティングと状態を併置することで遅延時間も短縮します
https://docs.microsoft.com/ja-jp/azure/service-fabric/service-fabric-reliable-services-introduction

C# コレクションベースということのようです。C#のコレクションって触ったこと無いからよくわかりませんが、LINQとかと組み合わせて利用できるってことでしょうか。

### 本当のStateful Serviceの定義 ###
実際には、Service FabricでのStateful Serviceとは、 **状態の一部が、整合性を維持したまま永続化しておかなければならない** サービス、とされています。つまりは、Azure BLOBとかDBとかも、Stateful Serviceです。

ただ、そうなると今回の記事で書くことが無くなってしまうので、少なくともこの記事の中では、前述した定義で行きたいと思います。

## Stateful Serviceを作ってみる ##
では早速作っていきましょう。今まで使ってきた環境をそのまま利用します。利用するテンプレートはReliable Serviceと同じです。

さて、Reliable Stateful Serviceとなるために、Reliable Collection を利用するのですが、そもそもReliable Collectionとはどういったものでしょうか。

### Reliable Collection ###
Reliable Collectionは、C#のSystem.Collectionsが自然に進化・発展したものです。その特徴として、

* ローカルに状態が永続化される
* 状態が複数のインスタンスにレプリケートされる
* 基本的に操作は非同期
* トランザクションの概念

が挙げられています。トランザクションは、デフォルトではマジョリティ クオラムが利用されているようです。Cassandraとかと一緒ですね。

その他の特徴についても、分散ストレージらしいものになっています。

* 分離レベルの存在
  * 基本的に自動で選択されます
* 行単位のロック
  * ちょうどCassandraのような感じです
* 2-Phase Transaction
* ログとチェックポイント

基本的に、読み込みでも書き込みでもデッドロック検出のために、タイムアウトがデフォルトで設定にされています。この辺はデフォルト挙動を変更しないことを推奨事項としています。

Reliable Collection は、インターフェースにSystem.Collectionを採用した分散ストレージってことですね。

## Staterful Serviceを実装してみる・・・ ##
と思ってサンプル（C#）とJavaのライブラリを見てみると、そもそも存在しないクラスが利用されており、しかもReplicationの方式としてActor用のクラスしか存在していませんでした。

また、StatelessServiceと異なり、 ``StatelessService`` という基底クラスは存在しているのに、 ``StatefulService`` という基底クラスは存在していませんでした・・・。ちなみにStatefulServiceBaseという、明らかに基底クラスっぽい名前のクラスは、ActorServiceの実装としてのみ実装されていました。

つまり、現時点でStateful Serviceを自前で作るという場合、

1. Actor Serviceとして実装する
2. 頑張ってActorStateManager的なものを実装する
   中身をちょっと見てみましたが、普通に頑張って実装している様子でした

という選択肢しか、現状ないようです。残念・・・。

## まとめ ##
Stateful Service on Javaをやってみようとしたけど無理だったよ、っていう結論になっちゃいました。
なんでJava版のSDKに、汎用的なStatefulServiceが実装されてないのか、ということを考えてみると、恐らく Reliable CollectionをJavaで実装するっていうのが非常に辛いからではないか、と想像されます。

C#の場合、非同期処理に関わる言語仕様として、async/awaitがあり、汎用的に利用できますが、Javaにはそういったものはありません。その辺の事情から、元々特定のインターフェースであったActorStateManagerに対しての実装はしたものの、Reliable Collection 自体を実装するのは後回しにしたんではないでしょうか。

実際、ActorとStateless Service、それとAzureのサービスで永続化を行えば、特に困ることもなさそうな気もします。

そんな感じで、特にオチなく終わっておきます。