Cấu trúc Protocol Buffer cơ bản
Để sử dụng kiểu dữ liệu rỗng, cần khai báo thư viện:
import "google/protobuf/empty.proto";
Kiểu dữ liệu rỗng được định nghĩa là google.protobuf.Empty. Với mảng, sử dụng từ khóa repeated.
Mẫu tệp .proto tiêu chuẩn
syntax = "proto3";
option csharp_namespace = "UserManagementService";
package usermgmt;
import "google/protobuf/empty.proto";
service UserManagement {
rpc FetchAllUsers(Empty) returns (UserListResponse);
rpc GetUserProfile(GetUserRequest) returns (UserProfileResponse);
rpc UpdateUserStream(stream UserUpdateRequest) returns (UpdateResult);
rpc CreateBidirectionalStream(stream UserCreationRequest) returns (stream CreationStatus);
rpc StreamUserDetails(Empty) returns (stream UserDetails);
}
message GetUserRequest {
string username = 1;
}
message UserProfileResponse {
UserProfile user = 1;
}
message UserListResponse {
repeated UserProfile users = 1;
}
message UserProfile {
string name = 1;
int32 age = 2;
}
message UserUpdateRequest {
UserProfile profile = 1;
}
message UpdateResult {
bool success = 1;
}
message UserCreationRequest {
string action = 1;
UserProfile data = 2;
}
message CreationStatus {
bool status = 1;
}
message UserDetails {
UserProfile profile = 1;
string info = 2;
}
Cài đặt phía máy chủ
using Google.Protobuf.WellKnownTypes;
using Grpc.Core;
using UserManagementService;
namespace UserApiService.Services
{
public class UserService : UserManagement.UserManagementBase
{
public override async Task StreamUserDetails(Empty request,
IServerStreamWriter<UserDetails> responseStream,
ServerCallContext context)
{
await responseStream.WriteAsync(new UserDetails {
Info = "Dữ liệu mẫu",
Profile = new UserProfile { Name = "Nguyễn Văn A", Age = 30 }
});
}
public override async Task<UpdateResult> UpdateUserStream(
IAsyncStreamReader<UserUpdateRequest> requestStream,
ServerCallContext context)
{
UserProfile latestProfile = null;
await foreach (var update in requestStream.ReadAllAsync())
{
latestProfile = update.Profile;
}
return new UpdateResult { Success = latestProfile != null };
}
public override async Task FetchAllUsers(Empty request,
ServerCallContext context)
{
var response = new UserListResponse();
response.Users.Add(new UserProfile { Name = "User 1", Age = 25 });
response.Users.Add(new UserProfile { Name = "User 2", Age = 35 });
return response;
}
}
}
Cấu hình phía máy khách
Trong tệp dự án client, cập nhật cấu hình:
<ItemGroup>
<Protobuf Include="Protos\usermgmt.proto" GrpcServices="Client" />
</ItemGroup>
Đăng ký dịch vụ trong Program.cs:
builder.Services.AddGrpcClient<UserManagement.UserManagementClient>(options =>
{
options.Address = new Uri("http://localhost:5000");
});
Gọi dịch vụ từ ứng dụng WebAPI
using Microsoft.AspNetCore.Mvc;
using UserManagementService;
using Google.Protobuf.WellKnownTypes;
namespace UserClientApi.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{
private readonly UserManagementClient _client;
public UserController(UserManagementClient client)
=> _client = client;
[HttpGet("all")]
public IActionResult GetAllUsers()
{
var response = _client.FetchAllUsers(new Empty());
return Ok(response.Users);
}
[HttpPost("stream")]
public async Task<IActionResult> CreateUserStream()
{
var call = _client.CreateBidirectionalStream();
await call.RequestStream.WriteAsync(new UserCreationRequest {
Action = "CREATE",
Data = new UserProfile { Name = "Minh", Age = 28 }
});
await call.RequestStream.CompleteAsync();
await foreach (var status in call.ResponseStream.ReadAllAsync())
{
if (status.Status) return Ok("Thành công");
}
return BadRequest();
}
}
}