Jednoargumentowe i strumieniowane RPC po stronie serwera
Implementuj wywołania jednoargumentowe oraz strumieniowanie po stronie serwera, aby przesyłać dane z serwera do klienta w czasie rzeczywistym.
Jednoargumentowe i strumieniowane RPC po stronie serwera to bezpłatna lekcja C# Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C# Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C# Academy zawiera 4 lekcji w sumie.
Typy RPC gRPC
gRPC obsługuje cztery wzorce RPC: Unary (żądanie/odpowiedź), Server Streaming (klient wysyła jedno żądanie, serwer wysyła wiele odpowiedzi), Client Streaming oraz Bidirectional Streaming. W tej lekcji omówiono dwa pierwsze.
Unary RPC: podstawowy wzorzec
Unary to najprostszy wzorzec — jedno żądanie i jedna odpowiedź. Wygląda jak zwykłe wywołanie funkcji, ale jest przesyłany przez HTTP/2 z kodowaniem Protobuf.
// .proto definition
service OrderService {
rpc GetOrder (GetOrderRequest) returns (OrderResponse);
}
message GetOrderRequest { int32 id = 1; }
message OrderResponse { int32 id = 1; string status = 2; double total = 3; }Implementowanie Unary RPC
Należy przesłonić wygenerowaną metodę bazową. ServerCallContext udostępnia metadane, token anulowania, termin wykonania oraz informacje o partnerze komunikacji.
public class OrderService : OrderService.OrderServiceBase
{
private readonly IOrderRepository _repo;
public OrderService(IOrderRepository repo) => _repo = repo;
public override async Task<OrderResponse> GetOrder(
GetOrderRequest request,
ServerCallContext context)
{
var order = await _repo.GetByIdAsync(request.Id, context.CancellationToken);
if (order is null)
throw new RpcException(new Status(StatusCode.NotFound, "Order not found"));
return new OrderResponse
{
Id = order.Id,
Status = order.Status.ToString(),
Total = (double)order.Total
};
}
}Wywoływanie RPC typu unary z klienta
Wygenerowany klient udostępnia zarówno metody wyglądające na synchroniczne, jak i rzeczywiście asynchroniczne. W środowisku produkcyjnym zawsze należy używać wariantu Async.
var client = new OrderService.OrderServiceClient(channel);
// Async call with cancellation
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var reply = await client.GetOrderAsync(
new GetOrderRequest { Id = 42 },
cancellationToken: cts.Token);
Console.WriteLine($"Order {reply.Id}: {reply.Status} - ${reply.Total}");Strumieniowanie po stronie serwera: definicja proto
Strumieniowanie po stronie serwera wymaga dodania słowa kluczowego stream przed typem odpowiedzi. Serwer wysyła wiele komunikatów w ramach tego samego połączenia, zanim zamknie strumień.
service StockService {
// Client sends one symbol, server streams price updates
rpc WatchStock (WatchRequest) returns (stream StockUpdate);
}
message WatchRequest { string symbol = 1; }
message StockUpdate { string symbol = 1; double price = 2; int64 timestamp = 3; }Implementowanie strumieniowania po stronie serwera
Użyj IServerStreamWriter<T> do wysyłania komunikatów. Metoda zwraca Task — zapisuj do zakończenia, a następnie zwróć sterowanie.
public override async Task WatchStock(
WatchRequest request,
IServerStreamWriter<StockUpdate> responseStream,
ServerCallContext context)
{
while (!context.CancellationToken.IsCancellationRequested)
{
var price = await _market.GetPriceAsync(request.Symbol);
await responseStream.WriteAsync(new StockUpdate
{
Symbol = request.Symbol,
Price = price,
Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
});
await Task.Delay(1000, context.CancellationToken);
}
}Odbieranie strumienia serwera po stronie klienta
Użyj await foreach do iteracji po ResponseStream.ReadAllAsync(), aby przetwarzać każdy komunikat w miarę jego nadejścia.
using var call = client.WatchStock(
new WatchRequest { Symbol = "MSFT" });
await foreach (var update in call.ResponseStream.ReadAllAsync())
{
Console.WriteLine($"{update.Symbol}: ${update.Price:F2}");
}
// Continues until server closes the stream or client cancelsAnulowanie strumienia serwera
Przekaż CancellationToken podczas otwierania wywołania, aby zatrzymać strumień po stronie klienta. Serwer otrzymuje sygnał anulowania za pośrednictwem własnego tokenu.
var cts = new CancellationTokenSource();
// Cancel after 30 seconds
cts.CancelAfter(TimeSpan.FromSeconds(30));
using var call = client.WatchStock(
new WatchRequest { Symbol = "AAPL" },
cancellationToken: cts.Token);
try
{
await foreach (var update in
call.ResponseStream.ReadAllAsync(cts.Token))
{
Console.WriteLine($"Price: {update.Price}");
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Stream cancelled.");
}Metadane: nagłówki żądania i trailery
gRPC obsługuje metadane (pary klucz-wartość) wysyłane jako nagłówki przed odpowiedzią i trailery po odpowiedzi. Używaj ich do przekazywania tokenów uwierzytelniania, identyfikatorów śledzenia lub kursorów stronicowania.
// Server: send initial metadata
await context.WriteResponseHeadersAsync(new Metadata
{
{ "x-correlation-id", Guid.NewGuid().ToString() }
});
// Server: set trailing metadata
context.ResponseTrailers.Add("x-total-count", "1500");
// Client: read headers
var headers = await call.ResponseHeadersAsync;
var trailerId = headers.GetValue("x-correlation-id");gRPC-Web dla klientów przeglądarkowych
Przeglądarki nie mogą używać surowego gRPC (trailery HTTP/2 nie są obsługiwane). Użyj Grpc.AspNetCore.Web oraz klienta JavaScript grpc-web albo Grpc.Net.Client.Web w Blazorze.
// dotnet add package Grpc.AspNetCore.Web
app.UseGrpcWeb();
app.MapGrpcService<GreeterService>().EnableGrpcWeb();
// Blazor client:
var handler = new GrpcWebHandler(GrpcWebMode.GrpcWeb,
new HttpClientHandler());
using var channel = GrpcChannel.ForAddress(
"https://localhost:7042",
new GrpcChannelOptions { HttpHandler = handler });Praktyczny przykład: usługa strumieniowania logów
Usługa agregująca logi przesyła wpisy dziennika aplikacji do połączonych klientów monitorujących w czasie rzeczywistym, korzystając ze strumieniowania po stronie serwera.
public override async Task StreamLogs(
LogStreamRequest request,
IServerStreamWriter<LogEntry> responseStream,
ServerCallContext context)
{
await foreach (var log in _logChannel.Reader.ReadAllAsync(
context.CancellationToken))
{
if (log.Level >= request.MinLevel)
{
await responseStream.WriteAsync(new LogEntry
{
Level = log.Level.ToString(),
Message = log.Message,
Timestamp = Timestamp.FromDateTime(log.Timestamp)
});
}
}
}Szybkie sprawdzenie
Jakie słowo kluczowe w pliku .proto wskazuje RPC ze strumieniowaniem po stronie serwera?
Podsumowanie: RPC typu unary i strumieniowanie po stronie serwera
Najważniejsze informacje:
- RPC typu unary: jedno żądanie, jedna odpowiedź — najczęściej stosowany wzorzec
- Strumieniowanie po stronie serwera: jedno żądanie, wiele komunikatów odpowiedzi wysyłanych w czasie
- Strumieniowanie po stronie serwera implementuje się, zapisując do
IServerStreamWriter<T> - Strumienie serwera odbiera się za pomocą
await foreachnaReadAllAsync() - Użyj CancellationToken, aby bezpiecznie zatrzymywać strumienie z dowolnej strony
- gRPC-Web umożliwia klientom przeglądarkowym wywoływanie usług gRPC
Często zadawane pytania
Czy lekcja „Jednoargumentowe i strumieniowane RPC po stronie serwera” jest bezpłatna?
Tak — pełny tekst „Jednoargumentowe i strumieniowane RPC po stronie serwera” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C# Academy, przejdź na CoddyKit PRO. Kurs C# Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Jednoargumentowe i strumieniowane RPC po stronie serwera”?
Implementuj wywołania jednoargumentowe oraz strumieniowanie po stronie serwera, aby przesyłać dane z serwera do klienta w czasie rzeczywistym. Ćwiczysz C# Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć C# Academy?
Nie wymagamy żadnego doświadczenia. C# Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „Jednoargumentowe i strumieniowane RPC po stronie serwera”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji C# Academy?
Tak. Każda lekcja C# Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Podstawy gRPC i Protobuf
- Jednoargumentowe i strumieniowane RPC po stronie serwera
- Strumieniowanie klienta i dwukierunkowe
- Limity czasu, anulowanie i interceptory