Weitere ähnliche Inhalte Ähnlich wie The Usage and Patterns of MagicOnion (20) Mehr von Yoshifumi Kawai (20) The Usage and Patterns of MagicOnion2. 河合 宜文 / Kawai Yoshifumi / @neuecc
Cysharp, Inc.
Cygames
C#大統一理論
C#
6. Unified Realtime/API Engine for .NET Core and Unity
https://github.com/Cysharp/MagicOnion/
・2017/06 - Ver.1, 「黒騎士と白の魔王(iOS/Android)」
・2018/12 - Ver.2, StreamingHub, Hosting
gRPC(HTTP/2)ベースの統合型ネットワークエンジン
サーバーを通したRPCの提供(のみ)
C#特化、C#フレンドリーなAPIの実現に力を注いだ
ビルトインの超高速で柔軟性の高いシリアライザ(MessagePack for C#)
を、(シリアライザの作者なので)100%活かしきった設計
21. 究極の土管
ネットワーク通信における究極の抽象化で最小公倍数
Client <-> Server RPCさえあれば、なんでも実装できる
Unityに依存しないことであらゆる使い方ができるように
一つのSimpleなやり方で、どこまでも応用が効く
サーバープログラムを透明にしない
サーバーもクライアントもどちらも大事
適切な場所に適切なコードが書けることを最重要視する
(クライアントだけの比重を高めてデータを左から右に流すだけの土管は違う)
そのうえで、余計なものがついてないシンプルさを土管とする
22. 究極の土管
ネットワーク通信における究極の抽象化で最小公倍数
Client <-> Server RPCさえあれば、なんでも実装できる
Unityに依存しないことであらゆる使い方ができるように
一つのSimpleなやり方で、どこまでも応用が効く
サーバープログラムを透明にしない
サーバーもクライアントもどちらも大事
適切な場所に適切なコードが書けることを最重要視する
(クライアントだけの比重を高めてデータを左から右に流すだけの土管は違う)
そのうえで、余計なものがついてないシンプルさを土管とする
世の中のウェブサイトはWordPressだけじゃないでしょ!
WordPressは大事で重宝されるけど、普通に開発だったら誰も
がRailsとか使って書くでしょ!
23. 究極の土管
ネットワーク通信における究極の抽象化で最小公倍数
Client <-> Server RPCさえあれば、なんでも実装できる
Unityに依存しないことであらゆる使い方ができるように
一つのSimpleなやり方で、どこまでも応用が効く
サーバープログラムを透明にしない
サーバーもクライアントもどちらも大事
適切な場所に適切なコードが書けることを最重要視する
(クライアントだけの比重を高めてデータを左から右に流すだけの土管は違う)
そのうえで、余計なものがついてないシンプルさを土管とする
コンポーネント貼っつけてTransform同期みたいなEasyさはいらな
い(どうせそれ以外の要件やパフォーマンス問題で、アプリケー
ション要件に沿った機構を作る)
クライアント-サーバー間RPCをC#としてどれだけ書き味を高め
られるか(要件にあったカスタマイズがしやすいか)を究極的に
追求しているのがMagicOnion
24. Dedicated Server is Good
ってみんな(?)言ってる
P2Pは繋がらない場合リレーサーバー経由で動かす
などなど、実は複雑
「サーバーを通して通信する」で統一して考えるだけで
めっちゃSimpleにすっきりしたりする(応用例もずっと広がる)
インフラ知識やサーバー代に関する話は、後述しますが、世の中ど
んどん良くなっていってるので意外と大丈夫(になるといいなぁ)
29. use CircleCI with AWS ECS(or Azure or GCP)
CIはCircleCIをお薦めしています(無料でも使えますよ!)
version: 2.1
orbs:
aws-ecr: circleci/aws-ecr@3.1.0
aws-ecs: circleci/aws-ecs@0.0.7
workflows:
build-push:
jobs:
# see: https://circleci.com/orbs/registry/orb/circleci/aws-ecr
# AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, AWS_ECR_ACCOUNT_URL
- aws-ecr/build_and_push_image:
repo: magiconionsample
# see: https://circleci.com/orbs/registry/orb/circleci/aws-ecs
# AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION
- aws-ecs/deploy-service-update:
requires:
- aws-ecr/build_and_push_image
family: magiconionsample
cluster-name: magiconionsample-cluster
service-name: magiconionsample-service
container-image-name-updates: 'container=magiconion,tag=latest'
とりあえずこれを置いておけばビルドとデ
プロイが自動化される
AWS_ACCESS_KEY_IDなどを自分のものに設
定してもらうのと、作ったクラスタ名など
を置き換えてもらえればOK
31. Unary API
リクエスト/レスポンス型
public class TestService : ITestService
{
public async UnaryResult<int> Sum(int x, int y)
{
return x + y;
}
}
var client = MagicOnionClient.Create<ITestService>(channel);
var result = await client.Sum(100, 200);
39. public class AuthenticationFilter : MagicOnionFilterAttribute
{
public override ValueTask Invoke(ServiceContext context)
{
var token = context.CallContext.RequestHeaders
.FirstOrDefault(x => !x.IsBinary && x.Key == "auth-token");
if (token != null)
{
var decoder = context.ServiceLocator.GetService<LitJWT.JwtDecoder>();
if (decoder.TryDecode(token.Value,
x => JsonSerializer.Deserialize<int>(x.ToArray()), out var id)
== LitJWT.DecodeResult.Success)
{
context.Items["UserId"] = id;
return Next(context);
}
}
throw new Exception("not found authentication key");
}
}
Headerに埋め込んでサーバー側では
Filterで取り出す
ServiceContext.Itemsに格納
LitJWT
https://github.com/Cysharp/LitJWT
42. public class TelemetryFilter : MagicOnionFilterAttribute
{
public override ValueTask Invoke(ServiceContext context)
{
try
{
// リクエスト開始の記録
return Next(context);
}
catch
{
// Errorの伝達
throw;
}
finally
{
// リクエスト終了の記録
}
}
}
public class TelemetryLogger : IMagicOnionLogger
{
void BeginBuildServiceDefinition();
void EndBuildServiceDefinition(double elapsed);
void BeginInvokeMethod(ServiceContext context, by
void EndInvokeMethod(ServiceContext context, byte
void BeginInvokeHubMethod(StreamingHubContext con
void EndInvokeHubMethod(StreamingHubContext conte
void InvokeHubBroadcast(string groupName, int res
void WriteToStream(ServiceContext context, byte[]
void ReadFromStream(ServiceContext context, byte[
}
FilterとLoggerを使って自分で使っているダッ
シュボードサービス用のAPIに向かって投げる
44. Native gRPC(C Core) is Dead
C Coreは別にいいんだけど標準C#バインディング実装がダメ
性能的に不満しかない(あとUnityではフリーズしやすい)
サーバー側はMicrosoftがMS実装のハイパフォーマンスなウェブ
サーバー(Kestrel)の拡張としてPure C#実装を準備中
Unityで使うクライアント実装を独自に作る
StreamingHubのゼロアロケーションの達成とECSとの親和性の追求
RUDP/QUIC
UNIX domain socketが許されるなら転送方式はなんでもよくね?
Server/Clientが両方Pure C#なら自由に拡張できるのでやりたい放題
46. while(true) { await tick; }
現在のStreamingHubはクライアントのメソッド呼び出し起因でし
か、ブロードキャストイベントを呼べない。
サーバー側でも一定間隔でグループへのアクセスを可能にすること
で、AIがルーム管理したり、コマンドをキューイングしてから処理
するなどが可能になる。
(MagicOnionの実例である「黒騎士と白の魔王」もこの方式)
ゲーム作成に必須と考えていて、今日リリース!したいと思ってた
んですが間に合わなかったのでまだですが近日中には……!
48. Google CloudRun
未来はServerless(Not FaaS, mBaaS)。
インフラ構築大変だし、お高いんでしょ、に対する答え。
接続がある間だけ起動し、接続がなくなったら自動終了
使った分だけ課金
無料Tierあり
まだgRPC対応していないのでただの理想?
でも(Googleだし)近い内に実装されそう
MagicOnionがgRPC(HTTP/2)という標
準プロトコルに乗っかっている強
みの一つ