More Related Content
Similar to NS study8 DDD Microservices Azuer Service Fabric (20)
NS study8 DDD Microservices Azuer Service Fabric
- 3. 自己紹介
• 会社
株式会社ネクストスケープ
• 名前
上坂貴志(うえさかたかし)Twitter:@takashiuesaka
• 年齢
44歳
• 好き・興味あり
Azure(Microsoft MVP for Microsoft Azure)、
Scrum(認定スクラムマスター)
DDD、ソフトウェアアーキテクチャ、機械学習
• 講演活動
• 2016年
de:code 2016 DDD & Azure Service Fabric 登壇
NS Study No.6 Azure IoTHub紹介
アプレッソ 最新IT事例セミナー Azure Machine Learning セミナー登壇
SANSAN DDD勉強会発表
• 2015年
FEST2015 (Channel9で動画公開)
MSxNextscape合同 Azure Machine Learningセミナー開催
Developers Summit 2015
QCon 2015
CloudDays2015東京・大阪 3
• 執筆活動
• 人工知能アプリケーション総覧 寄稿(日経BP社、2015年9月30日発売)
• ITPro:クラウドで機械学習を手近に、Azure Machine Learningの概要
www.nextscape.net 3
- 6. 会社紹介
www.nextscape.net 6
タワーレコード様
「NO MUSIC, NO LIFE.」のキャッチフレーズでおなじみの、音楽エンタメ・小売り事業の大手。
250万点もの商品を取り扱うオンラインショップ「TOWER RECORDS ONLINE」のCMSをSitecoreで構
築。
2010年当時に1日当たり100万強だったPVは、2014年4月時点で205万強まで倍増。
https://www.sitecore.net/ja-jp/customers/e-commerce/towerrecords.aspx
エイベックス通信放送様( dTV powerd by BeeTV )
「dビデオ powered by BeeTV」は、スマートフォン利用者向けに映画、ドラマなどを視聴可能な国内最大
規模の動画配信サイトとして注目を集めている。
Microsoft Azureにて、高負荷・ハイパフォーマンスに耐えうるスケーラブルな配信インフラを構築。
http://special.nikkeibp.co.jp/as/201207/mpncompetency/cs01.html
400万会員を超える動画サイトの配信インフラを構築
EC売上を3年間で2倍以上にしたタワーレコードの成長を支えたCMS基盤を導入
- 30. ハードルを越えよう
www.nextscape.net 30
要件定義中からモデルを書きましょう
• モデリングをする、ということは業務フロー=モデル、となるはずです
• 逆にいうと、基本設計以降のフェーズだけでDDD採用は見送った方が良いです(負担ばかりが多くて価値が出にくい)
コンテキストマップを書きましょう
• これを軽視すると1つのコンテキストでモデリングしがちです。巨大なモデル群を作り上げてしまいます
最初からテーブル設計を絶対にしないこと
• DDDを採用すると開発プロセスが変わります。
• モデリングという作業が強要され、要件定義=モデリングしつつ実装も進めます。
• ER図の作成開始はモデリングが完了してからです。が、モデリングは要件定義なのでなかなか固まりません。
• だからER図の作成は後回しにするしかないはずなのです。
• RDBMSで保存するなら最終的にテーブル設計は必要ですが、最初からやろうとしてはいけません。無駄になるだけなら
いいですが、最悪モデリングしないで工程が進んでいきます。(もはやDDDではない)
私が感じた、実践したほうが良いプラクティス
大事!
- 32. Azure Service Fabricとは
www.nextscape.net 32
スタンドアロンアプリのクラスタ化PaaSです。
• クラスタリングとは?
多数の低廉なコンピュータを、特別なソフトウェア・ハード
ウェアを用いて、あたかも1つの大きなコンピュータとして利
用できるように接続すること。(Wikipedia)
1. 負荷分散・・・複数のマシンで処理を分散
• クラスタの特徴とは?
2. 高可用性・・・1台のマシンが停止しても、待機系マシンがすぐ立ち上がる
- 37. Azure Service Fabricとは
www.nextscape.net 37
スタンドアロンアプリは2種類に大別されます。
1. Exe, Javaアプリなどのスタンドアロ
ンアプリをホスティング
2. ServiceFabricのSDKを使ったアプリ
をホスティング(実はこれもスタン
ドアロン
ゲスト実行可能ファイル
ステートレス
サービス
ステートフル
サービス
という名称です。でもServiceFabricは
として起動します。
2種類のタイプのサービスを作ることが
できます。ステートレスサービス
- 38. Azure Service Fabricとは
MSDNを見るともう1つReliable Actorというものがあります。
これはExe単位ではなくオブジェクト単位のクラスタです。
www.nextscape.net 38
実態は ステートフルサービス です。
つまり、Service Fabricを理解する近道は
ステートレス
サービス
ステートフル
サービス
を理解することです。
※もっと言うと、ステートレスサービスから理解するとわかりやすいです。
ちなみにService FabricはオンプレでもLinuxでも動きます!
別にAzure上だけで動くサービスじゃありません!
- 42. Service Fabric SDKを使った実装
www.nextscape.net 43
ServiceFabricのSDKを使って実装すると
• 外部との通信が実現
• 中止、開始、停止時のイベントをハンドルできる
プログラミングモデルの種類
Reliable Service Reliable Actor
ステートレス Service ステートフル Service
Exe等の実行ファイル
単位のホスティング
Service Fabric
の基本
オブジェクト単位
のホスティング
データを保持しない
StatelessServiceクラス
を継承したクラスに実
装していく
データを保持する
StatefullServiceクラスを
継承したクラスに実装
していく
- 45. Service Fabricの外部と通信する
www.nextscape.net 46
StatelessService
RunASync, OnOpenASync, OnCloseASync, OnAbort
MyService
ICommunicationListener
MyListener
protected override IEnumerable<ServiceInstanceListener>
CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[]
{
new ServiceInstanceListener(serviceContext =>
new MyListener ())
};
}
Task<string> OpenAsync(
CancellationToken cancellationToken)
Task CloseAsync(
CancellationToken cancellationToken)
void Abort()
見ての通り、リスナーは複数
返せるのでエンドポイントを
複数用意できます。
1つはhttpで、もう1つもhttpで
Port違い、3つ目はtcpでクラス
タ内通信とかできます
あれ?こっちも
Open,Close,Abo
rtじゃないか
OpenASyncメソッドの戻り値で
返す文字列が重要。
外部からの着信をリッスンす
る場所を返却する
例:http://ホスト名:port/ほげ
ほげ
- 46. Webで通信
IISが動かないので、OWINで自己ホストします
Visual Studioに用意されるテンプレートのService Fabric
WebAPIはMSDNで解説している内容の完全実装です
www.nextscape.net 47
StatelessService
自作クラス
Startup
void ConfigureApp(IAppBuilder appBuilder)
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[]
{
new ServiceInstanceListener(
serviceContext => new OwinCommunicationListener(
Startup.ConfigureApp,
serviceContext,
ServiceEventSource.Current,
"ServiceEndpoint"))
};
}
ICommunicationListener
OwinCommunicationListener
Task<string> OpenAsync(CancellationToken cancellationToken)
OpenASyncでリッスンするURIを組み立てて、
サーバースタートしているだけ
https://azure.microsoft.com/ja-
jp/documentation/articles/service-fabric-reliable-services-
communication-webapi/
MSDN解説のURL
- 48. WCFで通信
www.nextscape.net 49
WCFホスト側の実装
Calculatorの実装がサンプルに見当たりません。適当に作ってください
class Calculator : ICalculator
{
public Task<int> Add(int value1, int value2)
{
return Task.FromResult(value1 + value2);
}
}
<Resources>
<Endpoints>
<Endpoint Name="WcfServiceEndpoint" Protocol="tcp" Port="8515"/>
</Endpoints>
</Resources>
リッスンする場所とプロトコルを定義して名前つけます
internal sealed class WcfHostStateless : StatelessService
{
private ICalculator _calculator;
public WcfHostStateless(StatelessServiceContext context)
: base(context)
{
this._calculator = new Calculator();
}
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[]
{
new ServiceInstanceListener(serviceContext =>
new WcfCommunicationListener<ICalculator>(
wcfServiceObject:this._calculator,
serviceContext:base.Context,
endpointResourceName: "WcfServiceEndpoint",
listenerBinding: WcfUtility.CreateTcpListenerBinding()
))
};
}
- 49. WCFで通信
www.nextscape.net 50
サンプルでServiceUriというオブジェクトが説明なく出てきます。
これはWCFを実装したホストの場所を保持したUriオブジェクトです。
例:”fabric:/アプリ名/サービス名/”
WCFクライアント側の実装
クライアント側にもライブラリをいれてください
private void CallWcf(StatelessServiceContext context, string endpointName)
{
var binding = WcfUtility.CreateTcpClientBinding();
IServicePartitionResolver partitionResolver = ServicePartitionResolver.GetDefault();
var wcfClientFactory = new WcfCommunicationClientFactory<ICalculator>
(clientBinding: binding, servicePartitionResolver: partitionResolver);
var calculatorServiceCommunicationClient = new WcfCommunicationClient(
wcfClientFactory,
new Uri("fabric:/ServiceFabricWcf/WcfHostStateless"),
ServicePartitionKey.Singleton);
var result = calculatorServiceCommunicationClient.InvokeWithRetryAsync(
client => client.Channel.Add(2, 3)).Result;
}
サンプルそのままです
this.CallWcf(this.Context, "WcfServiceEndpoint");
RunAsyncの中でCallWcfメソッドを呼びます
Wcfホストと同じEndpoint
設定を記載します
Editor's Notes
- ここでお話しする「なぜ」に対する答えはあくまで個人的に思うもの
他の人と違うこと言っている
- サービス切り出し指針がなかった
こんな感じ?で切り出してみる
↓
後から要件追加
↓
複数のサービスに関わりそうな要件
↓
サービスの切り出しに失敗した・・・
↓
仕方ないから融合化、結局一つになっていく
サービス間の連携が扱いづらい
SOAPが登場した
↓
仕様が重すぎて扱いづらかった。
↓
WCFなんてどこいった?
サービスの可用性を担保するのが難しかった
サービスが落ちてしまった時の対応は?
↓
クラスタ組むためには専用のソフトが必要。高い。メンテは?誰がする?
↓
オンプレ冗長化も必要。=高コスト。
↓
導入コストが高い。運用コストも。
分散リソースに対する実装が辛すぎた
↓
非同期を前提とした通信となるが
↓
実装量の爆発が辛かった
----------------------------
要するに設計も実装もインフラも全てがSOAに耐えられなかった
今ならできるのかも。
RESTがデファクトに
クラウドによる可用性の担保
非同期実装も簡単になった
残る問題はサービスの切り出し。そこでDDD、という話が多いのかと。
- サービス境界をどうやって引くか。
その一つの解がDDDの「境界付けられたコンテキスト」というのがよく見かけます
でも、SOAのサービスの粒度と、これと同じなの?っていうとそこは人によって色々意見あるようです
境界付けられたコンテキストを理解するためには
・ドメインとはなぜか
・コンテキストとは
から理解が必要。
つまりDDDの世界観に触れて、理解することになる
↓
せっかくDDDに触れるのに、これだけしか理解しない、採用しないのはもったいないので、
少しだけ広げて話します
- DDDには流派があると思っています。
日本にも何人もDDDのエキスパートの方がいて、
色んなところでDDDセミナーやセッションを開催しています。
内容を比べると明確に同じではありません。
もちろん抽象度が高いところでは一致していると思いますが、
セミナー・セッションではやり方(HOW)に着目したものが
多いせいか解釈が異なる箇所もあるようです。
なので、私の今日話す内容についても、あくまで上坂が思うDDD、実践してきたDDD、と思っていたければと思います。
- 矢印を一つずつたどる度に必ず変換が入る。
この変換が悪。
どうして?もちろん開発者にとって大変なのは説明いらないとは思う。
でも顧客にとっては理不尽すぎる現状がある。
- だから設計技法として理解しようとするとよくわからなくなるんです
- コンテキストが違うことを前提にしていれば同じ言葉(モデル)でも異なる意味を持つことに違和感を持つ人はいない
じゃあコンテキストを明確に分けよう。
抽象化するのではなく。
- 後はコンテキスト間の関係性を確認する、という作業と、コンテキスト内部のモデル間のマッピング定義を記述するための
コンテキストマップ、というツールがあります。
これが実に重要。
だから境界付けられたコンテキストの概念でざっくりとサービスをわけて終わりにしないでください
- ESB・・・Enterprise Service Bus。SOA基盤
- Service FabricはオンプレでもLinuxでも動きますよ、という構成系の話は
直樹さんのセッションでたぶんやるんじゃないかなぁ、ということで省略
- ステートレスはStatelessService、ステートフルStafefullServiceというクラスを継承して作るのが基本形
ステートフルの方が少し扱えるイベントが多いだけで使い方は同じ
- RunASync
デプロイされてサービスが準備OKになった後にこのメソッドが1回だけ呼ばれる。
バッチ用と割り切っていいんじゃないでしょうか。テンプレートではここを抜けないようにwhile(true)で実装されている。懐かしいクラウドサービスのWorkerRoleと似ている。
別に実装は必須じゃない。
中止、停止イベント通知を受け取る用仮想メソッド
OnAbort, OnCloseASync, OnOpenASync(RunASyncとほとんど同じだが、 初期化に失敗したら処理中止、ということができる)
- OpenASyncの戻り値でなんでリスニングポイント返すのか?
これが重要なのは、サービスのアドレスが静的でないためです。リソースの分散と可用性のために、サービスはクラスター内を移動します。これは、クライアントがサービスのリッスンしているアドレスを解決できるようにするメカニズムです。
ホスト名はFabricRuntimクラスから取得できるFabricRuntime.GetNodeContext().IPAddressOrFQDN