gRPC trong .NET 10 — Giao tiếp Microservices hiệu năng cao với Protobuf

Posted on: 4/26/2026 9:11:37 AM

3-10x Nhanh hơn JSON (Protobuf serialization)
HTTP/2 Multiplexing — không head-of-line blocking
40+ Ngôn ngữ được hỗ trợ code generation
4 kiểu Streaming: Unary, Server, Client, Bidirectional

Trong kiến trúc microservices, giao tiếp giữa các service là yếu tố quyết định hiệu năng tổng thể của hệ thống. REST API với JSON đã phục vụ tốt trong nhiều năm, nhưng khi hệ thống mở rộng đến hàng trăm service, overhead của text-based serialization và HTTP/1.1 trở thành bottleneck nghiêm trọng. gRPC — framework RPC do Google phát triển — giải quyết chính xác vấn đề này với Protocol Buffers (binary serialization) và HTTP/2 (multiplexed connections).

Bài viết này đi sâu vào cách triển khai gRPC trên .NET 10, từ cơ bản đến nâng cao, bao gồm cả các pattern thực tế trong production.

1. gRPC là gì và tại sao cần nó?

gRPC (gRPC Remote Procedure Call) là một framework RPC open-source, hiệu năng cao, ban đầu được Google phát triển. Thay vì gửi JSON qua HTTP/1.1 như REST, gRPC sử dụng Protocol Buffers (Protobuf) làm Interface Definition Language (IDL) và format serialization, truyền dữ liệu qua HTTP/2.

graph LR
    A[Client App] -->|Protobuf binary| B[gRPC Channel
HTTP/2] B -->|Multiplexed streams| C[gRPC Server
.NET 10] C -->|Contract-first| D[.proto files] D -->|Code generation| A D -->|Code generation| C style A fill:#e94560,stroke:#fff,color:#fff style B fill:#2c3e50,stroke:#fff,color:#fff style C fill:#e94560,stroke:#fff,color:#fff style D fill:#f8f9fa,stroke:#e94560,color:#2c3e50
Kiến trúc tổng quan gRPC: Contract-first với Protobuf + HTTP/2

1.1. Lợi thế cốt lõi của gRPC

  • Contract-first development: Định nghĩa API bằng file .proto, tự động sinh code cho cả server và client — đảm bảo type safety xuyên suốt.
  • Binary serialization (Protobuf): Payload nhỏ hơn 3-10x so với JSON, serialize/deserialize nhanh hơn đáng kể.
  • HTTP/2 native: Multiplexing nhiều request trên một connection, header compression (HPACK), server push.
  • Streaming tích hợp: Hỗ trợ 4 kiểu giao tiếp — không cần WebSocket hay polling riêng.
  • Deadline và cancellation: Tích hợp sẵn cơ chế timeout propagation xuyên service chain.

2. Protocol Buffers — Ngôn ngữ định nghĩa của gRPC

Protobuf là trái tim của gRPC. File .proto định nghĩa cả structure dữ liệu (messages) và operations (services). Compiler protoc sinh ra strongly-typed code cho ngôn ngữ đích.

syntax = "proto3";

option csharp_namespace = "OrderService.Grpc";

package orders;

// Định nghĩa service
service OrderApi {
  // Unary: 1 request → 1 response
  rpc GetOrder (GetOrderRequest) returns (OrderResponse);

  // Server streaming: 1 request → stream responses
  rpc WatchOrderStatus (GetOrderRequest) returns (stream OrderStatusUpdate);

  // Client streaming: stream requests → 1 response
  rpc UploadOrderItems (stream OrderItem) returns (UploadSummary);

  // Bidirectional streaming: stream ↔ stream
  rpc OrderChat (stream ChatMessage) returns (stream ChatMessage);
}

message GetOrderRequest {
  string order_id = 1;
}

message OrderResponse {
  string order_id = 1;
  string customer_name = 2;
  repeated OrderItem items = 3;
  OrderStatus status = 4;
  google.protobuf.Timestamp created_at = 5;
}

enum OrderStatus {
  ORDER_STATUS_UNSPECIFIED = 0;
  PENDING = 1;
  CONFIRMED = 2;
  SHIPPING = 3;
  DELIVERED = 4;
  CANCELLED = 5;
}

message OrderItem {
  string product_id = 1;
  string name = 2;
  int32 quantity = 3;
  double price = 4;
}

💡 Best Practice

Luôn đánh số field từ 1, và không bao giờ reuse field number đã xóa — dùng reserved để đánh dấu. Điều này đảm bảo backward compatibility khi evolve schema.

2.1. Protobuf Scalar Types phổ biến

Protobuf Type C# Type Ghi chú
doubledouble64-bit floating point
floatfloat32-bit floating point
int32intVarint encoding, không hiệu quả cho số âm
int64longVarint encoding
boolbool
stringstringUTF-8 encoded
bytesByteStringArbitrary binary data
google.protobuf.TimestampDateTimeOffsetDùng well-known type cho datetime

3. Bốn kiểu giao tiếp gRPC

Điểm mạnh nhất của gRPC so với REST là hỗ trợ native 4 kiểu communication pattern, tất cả đều được xây dựng trên HTTP/2 streams.

graph TB
    subgraph Unary["1. Unary RPC"]
        UA[Client] -->|1 Request| UB[Server]
        UB -->|1 Response| UA
    end

    subgraph ServerStream["2. Server Streaming"]
        SA[Client] -->|1 Request| SB[Server]
        SB -->|Stream Responses| SA
    end

    subgraph ClientStream["3. Client Streaming"]
        CA[Client] -->|Stream Requests| CB[Server]
        CB -->|1 Response| CA
    end

    subgraph BiDi["4. Bidirectional Streaming"]
        BA[Client] <-->|Stream ↔ Stream| BB[Server]
    end

    style UA fill:#e94560,stroke:#fff,color:#fff
    style UB fill:#2c3e50,stroke:#fff,color:#fff
    style SA fill:#e94560,stroke:#fff,color:#fff
    style SB fill:#2c3e50,stroke:#fff,color:#fff
    style CA fill:#e94560,stroke:#fff,color:#fff
    style CB fill:#2c3e50,stroke:#fff,color:#fff
    style BA fill:#e94560,stroke:#fff,color:#fff
    style BB fill:#2c3e50,stroke:#fff,color:#fff
  
4 kiểu giao tiếp gRPC — từ đơn giản đến phức tạp

3.1. Unary RPC — Request-Response cổ điển

Tương tự REST call thông thường: client gửi 1 request, server trả 1 response. Đây là pattern phổ biến nhất.

// Server implementation
public override async Task<OrderResponse> GetOrder(
    GetOrderRequest request, ServerCallContext context)
{
    var order = await _orderRepository.GetByIdAsync(
        request.OrderId, context.CancellationToken);

    if (order is null)
    {
        throw new RpcException(new Status(
            StatusCode.NotFound,
            $"Order {request.OrderId} not found"));
    }

    return MapToResponse(order);
}

// Client call
var response = await client.GetOrderAsync(
    new GetOrderRequest { OrderId = "ORD-2026-001" },
    deadline: DateTime.UtcNow.AddSeconds(5));

3.2. Server Streaming — Realtime Updates

Client gửi 1 request, server trả về một stream responses liên tục. Lý tưởng cho realtime notifications, progress updates, hoặc live data feeds.

// Server implementation
public override async Task WatchOrderStatus(
    GetOrderRequest request,
    IServerStreamWriter<OrderStatusUpdate> responseStream,
    ServerCallContext context)
{
    while (!context.CancellationToken.IsCancellationRequested)
    {
        var status = await _orderRepository
            .GetStatusAsync(request.OrderId);

        await responseStream.WriteAsync(new OrderStatusUpdate
        {
            OrderId = request.OrderId,
            Status = status,
            UpdatedAt = Timestamp.FromDateTimeOffset(DateTimeOffset.UtcNow)
        });

        if (status == OrderStatus.Delivered
            || status == OrderStatus.Cancelled)
            break;

        await Task.Delay(2000, context.CancellationToken);
    }
}

// Client consumption
using var call = client.WatchOrderStatus(
    new GetOrderRequest { OrderId = "ORD-2026-001" });

await foreach (var update in call.ResponseStream.ReadAllAsync())
{
    Console.WriteLine($"Status: {update.Status} at {update.UpdatedAt}");
}

3.3. Client Streaming — Batch Upload

Client gửi stream data, server nhận xong trả 1 response tổng hợp. Phù hợp cho file upload, batch processing, hoặc telemetry ingestion.

// Server implementation
public override async Task<UploadSummary> UploadOrderItems(
    IAsyncStreamReader<OrderItem> requestStream,
    ServerCallContext context)
{
    var items = new List<OrderItem>();

    await foreach (var item in requestStream.ReadAllAsync())
    {
        items.Add(item);
    }

    var totalPrice = items.Sum(i => i.Price * i.Quantity);

    return new UploadSummary
    {
        TotalItems = items.Count,
        TotalPrice = totalPrice
    };
}

3.4. Bidirectional Streaming — Full Duplex

Cả client và server đều gửi stream độc lập với nhau trên cùng một connection. Đây là pattern mạnh nhất, phù hợp cho chat, collaborative editing, hoặc game multiplayer.

// Server implementation
public override async Task OrderChat(
    IAsyncStreamReader<ChatMessage> requestStream,
    IServerStreamWriter<ChatMessage> responseStream,
    ServerCallContext context)
{
    await foreach (var message in requestStream.ReadAllAsync())
    {
        // Xử lý message và phản hồi
        var reply = await _chatService.ProcessAsync(message);
        await responseStream.WriteAsync(reply);
    }
}

4. Triển khai gRPC Server trên .NET 10

4.1. Setup Project

# Tạo project từ template
dotnet new grpc -n OrderService

# Hoặc thêm vào project có sẵn
dotnet add package Grpc.AspNetCore

Cấu hình trong Program.cs:

var builder = WebApplication.CreateBuilder(args);

// Đăng ký gRPC services
builder.Services.AddGrpc(options =>
{
    options.MaxReceiveMessageSize = 16 * 1024 * 1024; // 16 MB
    options.MaxSendMessageSize = 16 * 1024 * 1024;
    options.EnableDetailedErrors = builder.Environment.IsDevelopment();
    options.CompressionProviders = new List<ICompressionProvider>
    {
        new GzipCompressionProvider(CompressionLevel.Optimal)
    };
    options.ResponseCompressionAlgorithm = "gzip";
});

// Đăng ký gRPC reflection (cho dev tools)
builder.Services.AddGrpcReflection();

// Đăng ký gRPC health checks
builder.Services.AddGrpcHealthChecks()
    .AddCheck("order-db", new SqlHealthCheck(connectionString));

var app = builder.Build();

app.MapGrpcService<OrderApiService>();
app.MapGrpcReflectionService(); // Cho grpcurl, Postman, etc.
app.MapGrpcHealthChecksService();

app.Run();

4.2. Project file (.csproj)

<ItemGroup>
  <Protobuf Include="Protos\orders.proto" GrpcServices="Server" />
</ItemGroup>

<ItemGroup>
  <PackageReference Include="Grpc.AspNetCore" Version="2.68.0" />
  <PackageReference Include="Grpc.AspNetCore.Server.Reflection" Version="2.68.0" />
  <PackageReference Include="Grpc.HealthCheck" Version="2.68.0" />
</ItemGroup>

5. gRPC Client trong .NET 10

5.1. Client Factory Pattern (khuyên dùng)

.NET cung cấp gRPC Client Factory tích hợp với HttpClientFactory, giúp quản lý connection pooling, lifecycle, và DI một cách tự động.

// Đăng ký trong DI
builder.Services.AddGrpcClient<OrderApi.OrderApiClient>(options =>
{
    options.Address = new Uri("https://order-service:5001");
})
.ConfigureChannel(channel =>
{
    channel.MaxReceiveMessageSize = 16 * 1024 * 1024;
    channel.ServiceConfig = new ServiceConfig
    {
        LoadBalancingConfigs = { new RoundRobinConfig() },
        MethodConfigs =
        {
            new MethodConfig
            {
                Names = { MethodName.Default },
                RetryPolicy = new RetryPolicy
                {
                    MaxAttempts = 3,
                    InitialBackoff = TimeSpan.FromMilliseconds(200),
                    MaxBackoff = TimeSpan.FromSeconds(5),
                    BackoffMultiplier = 2,
                    RetryableStatusCodes =
                    {
                        StatusCode.Unavailable,
                        StatusCode.DeadlineExceeded
                    }
                }
            }
        }
    };
})
.AddInterceptor<LoggingInterceptor>()
.EnableCallContextPropagation();

// Sử dụng qua DI
public class OrderController(OrderApi.OrderApiClient grpcClient)
{
    public async Task<OrderDto> GetOrder(string id)
    {
        var response = await grpcClient.GetOrderAsync(
            new GetOrderRequest { OrderId = id });
        return MapToDto(response);
    }
}

6. Interceptors — Middleware cho gRPC

Interceptors trong gRPC tương tự middleware trong ASP.NET Core, cho phép xen vào pipeline xử lý request/response. Chúng lý tưởng cho logging, metrics, authentication, và error handling.

graph LR
    A[Client Request] --> B[Logging
Interceptor] B --> C[Auth
Interceptor] C --> D[Metrics
Interceptor] D --> E[gRPC Service
Handler] E --> D D --> C C --> B B --> F[Client Response] style A fill:#f8f9fa,stroke:#e94560,color:#2c3e50 style B fill:#e94560,stroke:#fff,color:#fff style C fill:#2c3e50,stroke:#fff,color:#fff style D fill:#e94560,stroke:#fff,color:#fff style E fill:#16213e,stroke:#fff,color:#fff style F fill:#f8f9fa,stroke:#e94560,color:#2c3e50
Pipeline interceptors trong gRPC — tương tự middleware chain
public class LoggingInterceptor : Interceptor
{
    private readonly ILogger<LoggingInterceptor> _logger;

    public LoggingInterceptor(ILogger<LoggingInterceptor> logger)
        => _logger = logger;

    public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
        TRequest request,
        ServerCallContext context,
        UnaryServerMethod<TRequest, TResponse> continuation)
    {
        var sw = Stopwatch.StartNew();
        var method = context.Method;

        try
        {
            var response = await continuation(request, context);
            sw.Stop();

            _logger.LogInformation(
                "gRPC {Method} completed in {ElapsedMs}ms",
                method, sw.ElapsedMilliseconds);

            return response;
        }
        catch (RpcException ex)
        {
            sw.Stop();
            _logger.LogError(ex,
                "gRPC {Method} failed with {StatusCode} in {ElapsedMs}ms",
                method, ex.StatusCode, sw.ElapsedMilliseconds);
            throw;
        }
    }
}

7. gRPC-Web và JSON Transcoding

Một hạn chế lớn của gRPC truyền thống là browser không hỗ trợ HTTP/2 trailers, khiến gRPC không dùng trực tiếp từ frontend được. .NET 10 cung cấp 2 giải pháp:

7.1. gRPC-Web

Một protocol adaptation cho phép browser gọi gRPC services thông qua HTTP/1.1 hoặc HTTP/2 mà không cần trailers.

// Server config
builder.Services.AddGrpc();

var app = builder.Build();
app.UseGrpcWeb(new GrpcWebOptions { DefaultEnabled = true });
app.MapGrpcService<OrderApiService>().EnableGrpcWeb();

// JavaScript client (grpc-web)
const client = new OrderApiClient("https://api.example.com");
const request = new GetOrderRequest();
request.setOrderId("ORD-2026-001");

const response = await client.getOrder(request, {});

7.2. JSON Transcoding — RESTful gRPC

Cho phép expose gRPC service dưới dạng RESTful JSON API mà không cần viết thêm controller. Một gRPC service, hai cách gọi.

import "google/api/annotations.proto";

service OrderApi {
  rpc GetOrder (GetOrderRequest) returns (OrderResponse) {
    option (google.api.http) = {
      get: "/api/v1/orders/{order_id}"
    };
  }

  rpc CreateOrder (CreateOrderRequest) returns (OrderResponse) {
    option (google.api.http) = {
      post: "/api/v1/orders"
      body: "*"
    };
  }
}
// Kích hoạt JSON Transcoding
builder.Services.AddGrpc().AddJsonTranscoding();

// Giờ có thể gọi:
// gRPC:  grpcClient.GetOrderAsync(new GetOrderRequest { OrderId = "123" })
// REST:  GET https://api.example.com/api/v1/orders/123

📌 Khi nào dùng gì?

gRPC-Web: Khi bạn muốn giữ nguyên Protobuf binary format cho performance, client là SPA (React, Vue, Angular). JSON Transcoding: Khi bạn cần expose RESTful API cho third-party consumers hoặc mobile apps đã dùng REST, mà không muốn maintain 2 codebase.

8. So sánh gRPC vs REST vs GraphQL

Tiêu chí gRPC REST GraphQL
Serialization Protobuf (binary) JSON (text) JSON (text)
Transport HTTP/2 HTTP/1.1 hoặc 2 HTTP/1.1 hoặc 2
Contract .proto (bắt buộc) OpenAPI (tùy chọn) SDL (bắt buộc)
Streaming Native bidirectional SSE / WebSocket Subscriptions
Code generation Tự động, đa ngôn ngữ Qua công cụ bên ngoài Qua công cụ bên ngoài
Browser support Qua gRPC-Web / proxy Native Native (HTTP POST)
Caching Không có HTTP caching HTTP caching native Cần effort riêng
Payload size Nhỏ nhất (binary) Lớn (verbose JSON) Linh hoạt (chọn field)
Use case chính Service-to-service Public API, CRUD BFF, data aggregation

9. Load Balancing và Resilience

gRPC trên HTTP/2 sử dụng persistent connections, khiến load balancing ở layer 4 (TCP) không hiệu quả vì tất cả requests đi qua một connection duy nhất. Cần load balancing ở layer 7 (application) hoặc client-side balancing.

graph TB
    subgraph ClientSide["Client-Side Load Balancing"]
        C1[gRPC Client] --> DNS[DNS / Service Discovery]
        DNS --> S1[Server 1]
        DNS --> S2[Server 2]
        DNS --> S3[Server 3]
    end

    subgraph ProxyBased["Proxy-Based Load Balancing"]
        C2[gRPC Client] --> LB[L7 Proxy
Envoy / YARP] LB --> S4[Server 1] LB --> S5[Server 2] LB --> S6[Server 3] end style C1 fill:#e94560,stroke:#fff,color:#fff style C2 fill:#e94560,stroke:#fff,color:#fff style DNS fill:#f8f9fa,stroke:#e94560,color:#2c3e50 style LB fill:#2c3e50,stroke:#fff,color:#fff style S1 fill:#16213e,stroke:#fff,color:#fff style S2 fill:#16213e,stroke:#fff,color:#fff style S3 fill:#16213e,stroke:#fff,color:#fff style S4 fill:#16213e,stroke:#fff,color:#fff style S5 fill:#16213e,stroke:#fff,color:#fff style S6 fill:#16213e,stroke:#fff,color:#fff
Hai chiến lược load balancing cho gRPC

9.1. Client-Side Load Balancing trong .NET

// Cấu hình DNS-based client-side load balancing
builder.Services.AddGrpcClient<OrderApi.OrderApiClient>(options =>
{
    // Dùng dns:/// scheme để kích hoạt DNS resolver
    options.Address = new Uri("dns:///order-service.default.svc.cluster.local");
})
.ConfigureChannel(channel =>
{
    channel.ServiceConfig = new ServiceConfig
    {
        LoadBalancingConfigs = { new RoundRobinConfig() }
    };
    channel.Credentials = ChannelCredentials.Insecure; // Trong cluster
});

9.2. Retry Policy

// Retry với exponential backoff
var retryPolicy = new RetryPolicy
{
    MaxAttempts = 5,
    InitialBackoff = TimeSpan.FromMilliseconds(100),
    MaxBackoff = TimeSpan.FromSeconds(5),
    BackoffMultiplier = 1.5,
    RetryableStatusCodes =
    {
        StatusCode.Unavailable,     // Server down
        StatusCode.DeadlineExceeded // Timeout
    }
};

// Hedging — gửi nhiều request song song, lấy response đầu tiên
var hedgingPolicy = new HedgingPolicy
{
    MaxAttempts = 3,
    HedgingDelay = TimeSpan.FromMilliseconds(200),
    NonFatalStatusCodes = { StatusCode.Unavailable }
};

⚠️ Retry vs Hedging

Retry gửi lại request sau khi nhận lỗi — an toàn cho mọi idempotent operation. Hedging gửi request trước cả khi nhận lỗi (speculative execution) — chỉ dùng cho read operations hoặc operations có idempotency key.

10. Performance Optimization

10.1. Connection Management

// Tái sử dụng channel (1 channel = 1 HTTP/2 connection)
// KHÔNG tạo channel mới cho mỗi request
var channel = GrpcChannel.ForAddress("https://order-service:5001",
    new GrpcChannelOptions
    {
        HttpHandler = new SocketsHttpHandler
        {
            // Giữ connection alive
            PooledConnectionIdleTimeout = TimeSpan.FromMinutes(5),
            KeepAlivePingDelay = TimeSpan.FromSeconds(60),
            KeepAlivePingTimeout = TimeSpan.FromSeconds(30),

            // Tăng concurrent streams trên 1 connection
            EnableMultipleHttp2Connections = true
        }
    });

10.2. Compression

// Server: bật compression mặc định
builder.Services.AddGrpc(options =>
{
    options.ResponseCompressionAlgorithm = "gzip";
    options.ResponseCompressionLevel = CompressionLevel.Optimal;
});

// Client: request compression
var callOptions = new CallOptions(
    writeOptions: new WriteOptions(WriteFlags.NoCompress)); // Tắt cho message nhỏ

10.3. Deadline Propagation

// Service A → Service B → Service C
// Deadline tự động propagate qua chain

// Service A đặt deadline ban đầu
var deadline = DateTime.UtcNow.AddSeconds(10);
var response = await clientB.DoWorkAsync(request,
    deadline: deadline);

// Service B đọc remaining deadline và forward
public override async Task<WorkResult> DoWork(
    WorkRequest request, ServerCallContext context)
{
    // context.Deadline chứa deadline từ caller
    // Khi gọi Service C, deadline được tự propagate
    // nếu dùng EnableCallContextPropagation()
    var result = await _clientC.ProcessAsync(subRequest);
    return result;
}

11. Testing gRPC Services

// Integration test với WebApplicationFactory
public class OrderServiceTests : IClassFixture<GrpcTestFixture>
{
    private readonly OrderApi.OrderApiClient _client;

    public OrderServiceTests(GrpcTestFixture fixture)
    {
        _client = new OrderApi.OrderApiClient(fixture.Channel);
    }

    [Fact]
    public async Task GetOrder_ExistingOrder_ReturnsOrder()
    {
        var response = await _client.GetOrderAsync(
            new GetOrderRequest { OrderId = "test-order-1" });

        Assert.Equal("test-order-1", response.OrderId);
        Assert.Equal(OrderStatus.Confirmed, response.Status);
    }

    [Fact]
    public async Task GetOrder_NonExistent_ThrowsNotFound()
    {
        var ex = await Assert.ThrowsAsync<RpcException>(
            () => _client.GetOrderAsync(
                new GetOrderRequest { OrderId = "non-existent" }));

        Assert.Equal(StatusCode.NotFound, ex.StatusCode);
    }
}

// Test fixture
public class GrpcTestFixture : IDisposable
{
    private readonly WebApplicationFactory<Program> _factory;

    public GrpcChannel Channel { get; }

    public GrpcTestFixture()
    {
        _factory = new WebApplicationFactory<Program>();
        var client = _factory.CreateDefaultClient(
            new ResponseVersionHandler());

        Channel = GrpcChannel.ForAddress(
            _factory.Server.BaseAddress!,
            new GrpcChannelOptions { HttpClient = client });
    }

    public void Dispose() => _factory.Dispose();
}

12. Khi nào nên và không nên dùng gRPC?

Nên dùng: Service-to-service communication trong microservices
Nên dùng: Realtime streaming (notifications, live data)
Nên dùng: Polyglot systems (nhiều ngôn ngữ cùng giao tiếp)
Tránh: Public API cho third-party consumers (dùng REST)
Bước 1 — Đánh giá
Xác định xem service communication có phải bottleneck không. Nếu REST + JSON đang đáp ứng tốt, không cần chuyển.
Bước 2 — Proto-first
Thiết kế API bằng file .proto trước khi code. Đây là cơ hội để chuẩn hóa contract giữa các team.
Bước 3 — Hybrid
Triển khai gRPC cho internal services, giữ REST/GraphQL cho external API. JSON Transcoding giúp phục vụ cả hai từ cùng 1 codebase.
Bước 4 — Observability
Thêm interceptors cho logging, tracing (OpenTelemetry), và metrics ngay từ đầu. gRPC reflection giúp debug dễ dàng.

Tổng kết

gRPC trên .NET 10 là lựa chọn mạnh mẽ cho giao tiếp giữa các microservices khi hiệu năng là ưu tiên hàng đầu. Với Protobuf binary serialization nhanh hơn JSON 3-10x, HTTP/2 multiplexing, native streaming, và hệ sinh thái tooling trưởng thành trên .NET, gRPC cho phép xây dựng hệ thống phân tán với latency thấp và throughput cao. Kết hợp với JSON Transcoding và gRPC-Web, bạn không cần hy sinh khả năng tương thích với browser hay REST clients.

Nguồn tham khảo: