$30 off During Our Annual Pro Sale. View Details »

.NET のための通信フレームワーク MagicOnion 入門 / Introduction...

.NET のための通信フレームワーク MagicOnion 入門 / Introduction to MagicOnion

.NET のための通信フレームワーク MagicOnion 入門

- MagicOnion で Unary API を実装するデモ: https://youtu.be/LoL_pRjC2sU
- サーバーとクライアントを一つの IDE でステップ実行するデモ: https://youtu.be/aioFKsX1GuA
- StreamingHub でリアルタイムにクライアントへ配信するデモ: https://youtu.be/Vj18oXv5LgM

Mayuki Sawatari

November 18, 2024
Tweet

More Decks by Mayuki Sawatari

Other Decks in Programming

Transcript

  1. About Me Mayuki Sawatari @mayuki http://github.com/mayuki Working at Cysharp, Inc.

    MagicOnion Maintainer Microsoft MVP for Developer Technologies
  2. .NET/C# IDL / .NET C# IDL C# ? (MagicOnion )

    C# interface C# Client C# Server C# interface .NET .NET interface API interface
  3. .NET/C# IDL API C# C# interface namespace ApiService1; public interface

    IGreeterService { string SayHello(string name); } IGreeterService SayHello string string
  4. .NET/C# IDL C# // var client = Client.Create<IGreeterService>(); var result

    = client.SayHello("Alice"); Console.WriteLine(result); // => Hello Alice // public class GreeterService : IGreeterService { public string SayHello(string name) => $"Hello {name}"; } // public interface IGreeterService { string SayHello(string name); }
  5. .NET/C# IDL MagicOnion // var client = MagicOnionClient.Create<IGreeterService>(channel); var result

    = await client.SayHelloAsync("Alice"); Console.WriteLine(result); // => Hello Alice // public class GreeterService : ServiceBase<IGreeterService>, IGreeterService { public async UnaryResult<string> SayHelloAsync(string name) => $"Hello {name}"; } // public interface IGreeterService : IService<IGreeterService> { UnaryResult<string> SayHelloAsync(string name); }
  6. =

  7. SignalR MagicOnion SignalR (= ) MagicOnion .NET (.NET, Unity) (=

    ) Strongly-typed MagicOnion .NET interface object
  8. .NET Runtime ASP.NET Core Grpc.AspNetCore.Server MagicOnion.Server OS (Windows, Linux, macOS)

    OS (Windows, Linux, macOS, iOS, Android) .NET Runtime Unity SocketsHttpHandler YetAnotherHttpHandler HttpClient Grpc.Net.Client MagicOnion.Client gRPC HTTP/2 MessagePack TCP/IP TLS UDS/Named Pipe
  9. Unary: IService<T> Task<T>/Task UnaryResult<T>/UnaryResult MagicOnion Protocol Buffer public interface IGreeterService

    : IService<IGreeterService> { UnaryResult<string> SayHelloAsync(string name); } UnaryResult Task/ValueTask
  10. Unary: ServiceBase ASP.NET Core MVC Web API Controller public class

    GreeterService : ServiceBase<IGreeterService>, IGreeterService { public async UnaryResult<string> SayHelloAsync(string name) => $"Hello {name}"; }
  11. Unary: MagicOnionClient.Create<IService> // var channel = GrpcChannel.ForAddress("https://localhost:7127"); var client =

    MagicOnionClient.Create<IGreeterService>(channel); var result = await client.SayHelloAsync("Alice"); Console.WriteLine(result); // => Hello Alice
  12. Unary: Web → MagicOnion ( ) public class MyFilterAttribute :

    MagicOnionFilterAttribute { public override async ValueTask Invoke(ServiceContext context, Func<ServiceContext, ValueTask> next) { // var request = context.GetRawRequest(); // … // await next(context); // var response = context.GetRawResponse(); // … context.SetRawResponse(response); // … } }
  13. Unary: ASP .NET Core HTTP RateLimiting Authorize RateLimitingMiddleware (ASP.NET Core)

    AuthorizeMiddleware (ASP.NET Core) MetricsFilter MyFilter SayHelloAsync
  14. StreamingHub: IStreamingHub ValueTask/ValueTask<T> ( ) // public interface IGreeterHub :

    IStreamingHub<IGreeterHub, IGreeterHubReceiver> { ValueTask<string> HelloAsync(string name); } // ( ) public interface IGreeterHubReceiver { void OnMessageReceived(string message); } void
  15. StreamingHub: StreamingHubBase Unary Controller SignalR Hub Client public class GreeterHub

    : StreamingHubBase<IGreeterHub, IGreeterHubReceiver>, IGreeterHub { public async ValueTask<string> HelloAsync(string name) { // _ = Task.Run(async () => { await Task.Delay(1000); Client.OnMessageReceived($" {name}"); }); return $"Hello {name}"; } } Client.OnMessageReceived vNext
  16. StreamingHub: StreamingHubClient.ConnectAsync & var channel = GrpcChannel.ForAddress("https://localhost:7127"); var receiver =

    new GreeterHubReceiver(); var hub = await StreamingHubClient.ConnectAsync<IGreeterHub, IGreeterHubReceiver>(channel, receiver); var result = await hub.HelloAsync("Alice"); Console.WriteLine(result); // => Hello Alice // 1 " Alice" ( ) class GreeterHubReceiver : IGreeterHubReceiver { public void OnMessageReceived(string message) => Console.WriteLine(message); }
  17. StreamingHub: (JoinAsync) (SendMessageAsync) OnMessage public interface IChatHub : IStreamingHub<IChatHub, IChatHubReceiver>

    { ValueTask JoinAsync(string roomName, string name); ValueTask SendMessageAsync(string message); } public interface IChatHubReceiver { void OnMessage(string name, string message); }
  18. StreamingHub: v6.x public class ChatHub : StreamingHubBase<IChatHub, IChatHubReceiver>, IChatHub {

    private IGroup? _group; private string? _name; public async ValueTask JoinAsync(string roomName, string name) { // roomName _group = await Group.AddAsync(roomName); _name = name; } public ValueTask SendMessageAsync(string message) { // OnMessage Broadcast(_group).OnMessage(_name, message); return default; } }
  19. StreamingHub: v7 public class ChatHub : StreamingHubBase<IChatHub, IChatHubReceiver>, IChatHub {

    private IGroup<IChatHubReceiver>? _group; private string? _name; public async ValueTask JoinAsync(string roomName, string name) { // roomName _group = await Group.AddAsync(roomName); _name = name; } public ValueTask SendMessageAsync(string message) { // OnMessage _group.All.OnMessage(_name, message); return default; } } ( All) vNext
  20. Demo: StreamingHub public class BroadcastHub(ILogger<BroadcastHub> logger) : StreamingHubBase<IBroadcastHub, IBroadcastHubReceiver>, IBroadcastHub

    { private IGroup? _group; protected override async ValueTask OnConnected() { logger.LogInformation($"Client: {ConnectionId} Connected. (User-Agent: {Context.CallContext.GetHttpContext().Request.Headers.UserAgent})"); _group = await Group.AddAsync("All"); } public async ValueTask CompleteAsync(string message) { logger.LogInformation($"Begin CompleteAsync: Input={message}"); var client = new OpenAIClient("<OpenAI API Token>").AsChatClient(modelId: "gpt-4o-mini"); var stream = client.CompleteStreamingAsync([new ChatMessage(ChatRole.User, message)]); Broadcast(_group).OnCompleteStarted(message); await foreach (var response in stream) { Broadcast(_group).OnMessageReceived(response.Text); } Broadcast(_group).OnCompleteFinished(); logger.LogInformation($"Finished CompleteAsync"); } }
  21. .NET RPC C# API Unary StraemingHub API C# API .NET

    ASP .NET Core ASP.NET Core grpc-dotnet Source Generator Metrics API
  22. MagicOnion - C# .NET Core/Unity | Cygames Engineers' Blog https://tech.cygames.co.jp/archives/3181/

    NextGen Server/Client Architecture - gRPC + Unity + C# https://www.slideshare.net/slideshow/nextgen-serverclient-architecture-grpc-unity-c/72604810