.NET Core ã«ãªã㨠WCF ã®ãµã¼ãã¼ãµã¤ããæ¶ãã¦ç§»è¡å ã¨ã㦠gRPC ãããããã¦ãã®ãä½å¦ãã§è¦ãæ°ããã¾ããOSS ã® WCF ããã£ãæ°ããããã©ããã£ã¡ã¯ããè¦ã¦ãªãã
ã¨ãããã¨ã§ãASP.NET Core 3.0 Preview 㧠gRPC 試ãã¦ã¿ããã¨æãã¾ãã
ããã¸ã§ã¯ãã®ä½æ
ä»æ¥ã¯åºå ã®ã«ãã§ã§ã³ã¼ãã¼é£²ã¿ãªãã Surface Go ã§æ¸ãã¦ã¾ãããªã®ã§ Visual Studio 2019 ã¯å ¥ã£ã¦ãªãï¼Surface Go ã«ã¯éãããï¼ã®ã§ãVisual Studio Code ã§ããã¾ãã
é©å½ãªãã©ã«ãã¼ã§ç©ºã® Web ã¢ããªãä½ãã¾ãã
$ dotnet new web -o GrpcServer
ã½ãªã¥ã¼ã·ã§ã³ãä½ã£ã¦è¿½å ãã¦ããã¾ãããã
$ dotnet new sln $ dotnet sln add GrpcServer/GrpcServer.csproj
Visual Studio Code ã§ã½ãªã¥ã¼ã·ã§ã³ã®ãããã©ã«ãã¼ãéã㦠task.json ã¨ããçæã㦠Ctrl + Shift + B
ã§ãã«ãããã F5
ã§ãããã°ã§ããããã«ãã¾ããã便å©ã
gRPC ã®ããã®ããã±ã¼ã¸ã追å ãã¾ãã
$ dotnet add .\GrpcServer\GrpcServer.csproj package Grpc.AspNetCore -v 0.1.22-pre3
ããã¦ã.proto
ãã¡ã¤ã«ãçæãã¾ããããããã dotnet new
ã§çæã§ãã¾ããå¾ã§ä½æããã¯ã©ã¤ã¢ã³ãã§ã使ãäºå®ãªã®ã§ãã½ãªã¥ã¼ã·ã§ã³ã®ãããã©ã«ãã¼ã« Proto/Proto.proto
ã¨ãã¿ãããªæãã§ä½ãã¾ããã
$ dotnet new proto -o Proto
ãµã¼ãã¹ã®å®ç¾©ã追å ãã¾ãã
syntax = "proto3"; option csharp_namespace = "GrpcSample"; service Greeter { rpc Greet (GreetRequest) returns (GreetReply); } message GreetRequest { string name = 1; } message GreetReply { string message = 1; }
ãµã¼ãã¼ããã¸ã§ã¯ãã«è¿½å ããããã« .csproj
ãç·¨éãã¾ãããã
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp3.0</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="Grpc.AspNetCore" Version="0.1.22-pre3" /> </ItemGroup> <ItemGroup> <!-- ããã追å --> <Protobuf Include="../Proto/Proto.proto" LinkBase="Proto/Proto.proto" GrpcServices="Server" /> </ItemGroup> </Project>
ããã§ãã«ãããã㨠GrpcServer/obj/Debug
ã« Proto.cs
㨠ProtoGrpc.cs
ãçæããã¾ãããããç¶æ¿ãã¦ãµã¼ãã¹ãå®è£
ãã¾ãã
GrpcServer
ããã¸ã§ã¯ãã« Services
ãã©ã«ãã¼ãä½ã£ã¦ãããã« GreeterService.cs
ãä½ã£ã¦ä»¥ä¸ã®ããã« Greeter.GreeterBase
ãç¶æ¿ããå½¢ã§å¦çãä½ãã¾ãã
using System.Threading.Tasks; using Grpc.Core; using GrpcSample; namespace GrpcService.Services { public class GreeterService : Greeter.GreeterBase { public override Task<GreetReply> Greet(GreetRequest request, ServerCallContext context) { return Task.FromResult(new GreetReply { Message = $"Hello {request.Name}", }); } } }
.proto
ã«å®ç¾©ããã¯ã©ã¹ã¨ãµã¼ãã¹ã®ã¡ã½ããã®ã²ãªåã¯åºæ¬ã¯ã©ã¹ã§å®ç¾©ããã¦ããã®ã§ããããã¨ã¯ã¡ã½ããããªã¼ãã¼ã©ã¤ããã¦å®è£
ããã ãã§ããç°¡åã
Startup.cs
㧠gRPC æ©è½ã®æå¹åã¨ä¸ã§ä½æãããµã¼ãã¹ãç»é²ããå¦çã追å ãã¾ãã
using GrpcService.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace GrpcServer { public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddGrpc(); // ãã㨠} public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapGrpcService<GreeterService>(); // ããã追å endpoints.MapGet("/", async context => { await context.Response.WriteAsync("Hello World!"); }); }); } } }
ããã§ãµã¼ãã¼ã¯å®æãã¾ããã¨ããããã¨ããã§ãããããã¡ãã£ã¨ã ãè¨å®ã⦠gRPC 㯠HTTP/2 ã使ãã®ã§ããã®è¨å®ã追å ãã¾ããappsettings.json
ã«ä»¥ä¸ã®ãããªè¨å®ã追å ãã¾ãã
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", "Kestrel": { "EndpointDefaults": { "Protocols": "Http2" } } }
Kestrel ã®é¨åã追å ãããã®ã«ãªãã¾ãã
ã¯ã©ã¤ã¢ã³ãã®ä½æ
ãµã¼ãã¼ã ãä½ã£ã¦ãã誰ãå¼ãã§ãããªãã¨ä½ãã§ããªãã®ã§ã¯ã©ã¤ã¢ã³ããä½ãã¾ããWPF ã§ããã¾ããããããã£ã¨ããã¸ã§ã¯ããä½ã£ã¦ã½ãªã¥ã¼ã·ã§ã³ã«è¿½å ãã¾ãã
$ dotnet new wpf -o GrpcClient $ dotnet sln add .\GrpcClient\GrpcClient.csproj
ãã㦠gRPC ã®ã¯ã©ã¤ã¢ã³ãå´ã«å¿ è¦ãªããã±ã¼ã¸ãå ¥ãã¾ãã
dotnet add .\GrpcClient\GrpcClient.csproj package Google.Protobuf -v 3.9.1 dotnet add .\GrpcClient\GrpcClient.csproj package Grpc.Net.Client -v 0.1.22-pre3 dotnet add .\GrpcClient\GrpcClient.csproj package Grpc.Tools -v 2.23.0
ããã¦ãGrpcClient.csproj
ã« Protobuf ã¿ã°ã追å ãã¾ããä»åã¯çæãã¦ãããã®ã¯ã¯ã©ã¤ã¢ã³ããªã®ã§ GrpcServices å±æ§ã«ã¯ Client ãè¨å®ãã¦ã¾ããä½è«ã§ããã¯ã©ã¤ã¢ã³ãã¨ãµã¼ãã¼ã®ä¸¡æ¹ãçæãã¦ã»ããã¨ã㯠Both ã¨ããã¿ããã§ãã
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop"> <PropertyGroup> <OutputType>WinExe</OutputType> <TargetFramework>netcoreapp3.0</TargetFramework> <UseWPF>true</UseWPF> </PropertyGroup> <ItemGroup> <PackageReference Include="Google.Protobuf" Version="3.9.1" /> <PackageReference Include="Grpc.Net.Client" Version="0.1.22-pre3" /> <PackageReference Include="Grpc.Tools" Version="2.23.0"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference> </ItemGroup> <ItemGroup> <Protobuf Include="../Proto/Proto.proto" LinkBase="Proto/Proto.proto" GrpcServices="Client" /> </ItemGroup> </Project>
ããã¦ãååãå
¥åããããã® TextBox ã¨ãµã¼ãã¹ãå¼ã¶ããã® Button ãç½®ããç»é¢ã MainWindow.xaml
ã«å®ç¾©ãã¦â¦
<Window x:Class="GrpcClient.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:GrpcClient" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <StackPanel> <TextBox x:Name="textBoxName" /> <Button Content="Call gRPC service" Click="CallGrpcServiceButton_Click" /> </StackPanel> </Window>
ã³ã¼ãããã¤ã³ãã«ãµã¼ãã¹ãå¼ã³åºãã³ã¼ããæ¸ãã¾ãããã
using System; using System.Net.Http; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using GrpcSample; namespace GrpcClient { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private async void CallGrpcServiceButton_Click(object sender, RoutedEventArgs e) { using (var client = new HttpClient { BaseAddress = new Uri("https://localhost:5001") }) { var greetServices = Grpc.Net.Client.GrpcClient.Create<Greeter.GreeterClient>(client); var response = await greetServices.GreetAsync(new GreetRequest { Name = textBoxName.Text, }); MessageBox.Show(response.Message); } } } }
ããããã¨ã³ã³ãã¤ã«ã¨ã©ã¼ï¼ï¼
MainWindow.xaml.cs(16,7): error CS0246: The type or namespace name 'GrpcSample' could not be found (are you missing a using directive or an assembly reference?) [c:\Users\k_ota\source\repos\GrpcLab\GrpcClient\GrpcClient_teh220ey_wpftmp.csproj]
èµ·ãã¦ãã¨ã©ã¼ã¨ãã¦ã¯ä»¥ä¸ã® Issue ã¨ä¼¼ã¦ããã©ããã£ã¡ã¯ã¯ã©ã·ãã¯ãã¼ã«ãã§ã¼ã³â¦
試ãã« WPF ãããªãã¦ã³ã³ã½ã¼ã«ã¢ããªã§åãæé ãè¸ãã§å¼ã³åºãå¦çãæ¸ãããã³ã³ãã¤ã«ã¨ã©ã¼ã«ãªããªãã®ã§ WPF on .NET Core ç¨ã®ãã¼ã«ã¾ããã®ãã°ããªï¼ã¨ããããã®åé¿æ¹æ³ã¯ã¯ã©ã¤ã¢ã³ãã³ã¼ãã®çæãã¯ã©ã¹ã©ã¤ãã©ãªã«ãã¤ããã¨ã§ãã
ããã¸ã§ã¯ããä½æãã¦ãå¿ è¦ãªåç §ã追å ããããã¾ãã
$ dotnet new classlib -o GrpcClientLib $ dotnet sln add .\GrpcClientLib\GrpcClientLib.csproj
çæãããã®ã¯ .NET Standard 2.0 ã®ããã¸ã§ã¯ããªã®ã§ãããGrpc.Net.Client 0.1.22-pre3 㯠.NET Standard 2.1 ï¼ã¿ã¼ã²ããã«ãã¦ãã©ã¤ãã©ãªå§ãã¦ã¿ãï¼ï¼ãªã®ã§ GrpcClientLib.csproj ã® netstandard2.0 ã netstandard2.1 ã«æ¸ãæãã¦ããä¸è¨ã³ãã³ãã§ã©ã¤ãã©ãªã追å ãã¾ãã
$ dotnet add .\GrpcClientLib\GrpcClientLib.csproj package Google.Protobuf -v 3.9.1 $ dotnet add .\GrpcClientLib\GrpcClientLib.csproj package Grpc.Net.Client -v 0.1.22-pre3 $ dotnet add .\GrpcClientLib\GrpcClientLib.csproj package Grpc.Tools -v 2.23.0
ãã㦠GrpcClientLib.csproj
ã«ãProtobuf ã¿ã°ã®å®ç¾©ã追å ãã¾ãã
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>netstandard2.1</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="Google.Protobuf" Version="3.9.1" /> <PackageReference Include="Grpc.Net.Client" Version="0.1.22-pre3" /> <PackageReference Include="Grpc.Tools" Version="2.23.0"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference> </ItemGroup> <ItemGroup> <Protobuf Include="../Proto/Proto.proto" LinkBase="Proto/Proto.proto" GrpcServices="Client" /> </ItemGroup> </Project>
WPF å´ãã㯠Protobuf ã®ã¿ã°ãåé¤ãã¦ããã¾ãããã
ããã¦ãGrpcClient ã« GrpcCLientLib ã¸ã®åç §ã追å ãã¾ãã
$ dotnet add .\GrpcClient\GrpcClient.csproj reference .\GrpcClientLib\GrpcClientLib.csproj
ããã§ã³ã³ãã¤ã«ã¨ã©ã¼ãªãã§ãã«ããéãããã«ãªãã¾ãã
ã¾ã ä¸åº¦ãå ¥ãããã¨ããªã人㯠.NET Core ã®éçºç¨ã®è¨¼ææ¸ãã¤ã³ã¹ãã¼ã«ãã¦
$ dotnet dev-certs https --trust
dotnet run
ã§ãµã¼ãã¼ã¨ã¯ã©ã¤ã¢ã³ããèµ·åãã¦è©¦ãã¦ã¿ã¾ãããã
ã¾ãã¯ããµã¼ãã¼
$ dotnet run --project .\GrpcServer\GrpcServer.csproj
ããã¦ãã¯ã©ã¤ã¢ã³ã
$ dotnet run --project .\GrpcClient\GrpcClient.csproj
é©å½ã« TextBox ã«ä½ãå ¥ãã¦ãã¿ã³ãæ¼ãã¨ç¡äºåãã¾ãã
Azure ã«ãããã¤ï¼ï¼
Azure ã® App Service ã« gRPC ã®ãµã¼ãã¹ããããã¤ãã¦åãããã¨ã¯ã§ããªãã¿ããã§ããæ®å¿µã
AKS 使ãã°åºæ¥ããã§ãããããã«æ¸ãã«ã¯ã¡ãã£ã¨ããã¼ãªã®ã§ãã¾ãä»åº¦ãã©ã¤ãã¦ã¿ã¦æ¸ãã¾ãã
ã¾ã¨ã
ASP.NET Core ã® gRPC å²ã¨ãµã¯ãã¨ä½ãã¦ããæãã§ãã LTS çã® .NET Core 3.1 ãåºãã使ã£ã¦ã¿ãããªããã§ã App Service ã®å¯¾å¿ã¯æ©ããã¦ã»ããã¨ããã
ã½ã¼ã¹ã³ã¼ãã¯ãGitHub ã«ããã¦ããã¾ããã