ASP.NET Core eğitimi kapsamında gRPC servislerini üretime taşırken proto sözleşmelerini geriye uyumlu evrimleştirmeyi, EF Core sorgularını iptal sinyaliyle çalıştırmayı ve EventPipe ile gecikmeyi ölçmeyi inceleyin.
ASP.NET Core Eğitimi: gRPC Sözleşme Evrimi ve Üretim Tanılama
ASP.NET Core eğitimi ile proto sözleşmesini kırmadan evrimleştirmek
gRPC'de geriye uyumluluğun birincil birimi C# property adı değil, proto alan numarasıdır. Yayınlanmış bir alanı silmek yerine numarayı reserved ederek koruyun. Aksi halde eski istemcinin 3 numaralı alan için yazdığı byte'lar, yeni sunucuda farklı bir semantiğe sahip alana deserialize edilebilir. Proto3'te scalar alanlarda varsayılan değer ile alanın hiç gönderilmemesi ayrımını yapmanız gerekiyorsa optional kullanın; aksi durumda int32 için 0, istemcinin gerçekten 0 göndermesi mi yoksa alanı atlaması mı olduğunu belirtmez.
syntax = "proto3";
package orders.v1;
service Orders {
rpc GetOrder(GetOrderRequest) returns (OrderReply);
}
message GetOrderRequest {
string order_id = 1;
optional bool include_lines = 2;
reserved 3;
reserved "legacy_customer_code";
}
message OrderReply {
string id = 1;
oneof payment_state {
string pending_payment_id = 4;
string settled_transaction_id = 5;
}
}oneof aynı anda sadece bir ödeme durumunun taşınmasını wire format seviyesinde ifade eder; bunu iki nullable string ile modellemek, hem geçersiz kombinasyonları mümkün kılar hem de tüketicilerin öncelik kuralı yazmasına neden olur. CI hattında Buf kullanarak ana dalın sözleşmesini aday değişiklikle karşılaştırın:
buf lint
buf breaking --against '.git#branch=main' Bu kontrol, alan numarası yeniden kullanımı, RPC imzası kırılması ve message silinmesi gibi derleyicinin C# tarafında yakalayamayacağı uyumsuzlukları pull request aşamasında durdurur..NET Core eğitimi için Kestrel, deadline ve akış geri basıncı
Kestrel'de gRPC endpoint'i HTTP/2 ile dinlemelidir. TLS sonlandırmasını ters vekil yapıyorsa, vekilin upstream bağlantıda HTTP/2 kullanıp kullanmadığını ayrıca doğrulayın; yalnızca istemci ile vekil arasındaki HTTP/2 yeterli değildir. Yerel HTTP/1.1 endpoint'ini aynı portta bırakmak zorundaysanız HTTP/1AndHttp2 seçeneği TLS olmadan protokol uzlaşmasına güvenmez. Geliştirme ortamında ayrı HTTP/2 portu tanımlamak belirsizliği azaltır.
builder.WebHost.ConfigureKestrel(options =>
{
options.ListenAnyIP(5001, listen =>
{
listen.Protocols = HttpProtocols.Http2;
listen.UseHttps();
});
});
builder.Services.AddGrpc(options =>
{
options.MaxReceiveMessageSize = 4 * 1024 * 1024;
options.MaxSendMessageSize = 4 * 1024 * 1024;
});Unary çağrıda istemcinin deadline'ı dolduğunda sunucudaki context.CancellationToken iptal edilir. Bu token'i EF Core, HTTP çağrıları ve kuyruk beklemelerine iletmezseniz istemci bağlantıyı kapattıktan sonra sorgu ve CPU tüketimi devam eder. Server streaming'de her WriteAsync çağrısını await edin; döngü içinde mesajları listeye toplayıp paralel yazmak, HTTP/2 flow-control penceresini atlamaz ve büyük bağlantılarda bellek kuyruğu oluşturur.
public override async Task StreamEvents(
EventRequest request,
IServerStreamWriter<EventReply> responseStream,
ServerCallContext context)
{
await foreach (var item in eventStore.ReadSinceAsync(
request.Cursor,
context.CancellationToken))
{
await responseStream.WriteAsync(new EventReply
{
Id = item.Id.ToString(),
Payload = item.Payload
}, context.CancellationToken);
}
}Entity Framework eğitimi: gRPC handler içinde sorgu şekli ve iptal
Bir gRPC handler'ında entity grafiğini Include ile yükleyip protobuf yanıtına dönüştürmek, hem değişiklik izleme maliyeti hem de beklenmeyen kartesyen çoğalma üretebilir. Okuma endpoint'inde doğrudan reply DTO'suna projection yapın ve SQL'i ToQueryString() ile gözden geçirin. Özellikle iki collection Include edildiğinde EF Core'un tek sorgu stratejisi satır sayısını sipariş x satır x not kadar büyütebilir; bu durum küçük test verisinde görünmeyip gerçek veride ağdan taşınan byte miktarını yükseltir.
public override async Task<OrderReply> GetOrder(
GetOrderRequest request,
ServerCallContext context)
{
var order = await db.Orders
.AsNoTracking()
.Where(x => x.PublicId == request.OrderId)
.Select(x => new
{
x.PublicId,
x.CreatedAt,
Lines = request.IncludeLines
? x.Lines.OrderBy(l => l.Position).Select(l => new
{ l.Sku, l.Quantity }).ToList()
: new List<object>()
})
.SingleOrDefaultAsync(context.CancellationToken);
if (order is null)
throw new RpcException(new Status(StatusCode.NotFound, "order not found"));
var reply = new OrderReply { Id = order.PublicId };
reply.Lines.AddRange(order.Lines.Select(x => new LineReply
{
Sku = x.Sku,
Quantity = x.Quantity
}));
return reply;
}Buradaki kritik ayrıntı, gRPC hata kodunu HTTP status kodu gibi düşünmemektir. Kayıt bulunamadığında boş bir OrderReply dönmek yerine StatusCode.NotFound üretin; istemci bunu domain sonucu olarak ele alabilir. PostgreSQL veya SQL Server tarafında gerçek sorgu planını uygulama logundan değil, veritabanının EXPLAIN veya actual execution plan çıktısından inceleyin. Sorgunun PublicId filtresi için indeks yoksa, AsNoTracking yalnızca tracker maliyetini kaldırır, tablo taramasını çözmez.
gRPC gecikmesini EventPipe ve yük testi ile önce-sonra ölçmek
Bir değişikliği yayınlamadan önce aynı proto payload, eşzamanlılık ve deadline ile taban ölçüm alın. Yük testi için ghz, süreç sayaçları için dotnet-counters, CPU stack'leri için dotnet-trace kullanın. p50 tek başına yeterli değildir: p95 ve p99 gecikmesi, hata oranı, request başına allocation, Gen 2 koleksiyon sayısı ve ağdan taşınan byte birlikte kaydedilmelidir.
ghz --insecure --proto ./Protos/orders.proto --call orders.v1.Orders.GetOrder -d '{"orderId":"A-1042","includeLines":true}' -n 20000 -c 80 localhost:5001
dotnet-counters monitor -p 12345 System.Runtime
dotnet-trace collect -p 12345 --profile cpu-sampling -o grpc-baseline.nettrace
dotnet-trace report grpc-baseline.nettrace topN -n 20Örneğin yanıt gövdesi büyük ve istemci gzip kabul ediyorsa aşağıdaki değişikliği ayrı bir deney olarak uygulayın. Aynı ghz senaryosunu önce sıkıştırmasız, sonra grpc-accept-encoding: gzip başlığıyla çalıştırın. Sıkıştırma ağ byte'ını azaltabilir, ancak CPU örneklerinde gzip çağrıları üst sıralara çıkıyor ve p99 yükseliyorsa bu endpoint için doğru tercih değildir; küçük mesajlarda framing dışındaki kazanç genellikle sıkıştırma maliyetini karşılamaz.
using System.IO.Compression;
builder.Services.AddGrpc(options =>
{
options.ResponseCompressionAlgorithm = "gzip";
options.ResponseCompressionLevel = CompressionLevel.Fastest;
});
// Yük testinin sıkıştırmalı varyantında:
// ghz ... -H 'grpc-accept-encoding: gzip'Blazor eğitimi bağlamında tarayıcıdan gRPC-Web çağrısı
Tarayıcıdaki Blazor WebAssembly istemcisi native gRPC'nin gerektirdiği HTTP/2 trailer modeline doğrudan erişemez. Bu nedenle gRPC-Web kullanılır ve ara katman trailer bilgisini gRPC-Web çerçevesine dönüştürür. Sunucuda middleware'i servis eşlemesinden önce ekleyin; çapraz origin kullanımında CORS politikasının grpc-status ve grpc-message header'larını istemciye açması gerekir, yoksa hata ayrıntısı tarayıcı tarafından gizlenir.
builder.Services.AddCors(options => options.AddPolicy("grpc-web", policy =>
policy.WithOrigins("https://app.example.com")
.AllowAnyMethod()
.AllowAnyHeader()
.WithExposedHeaders("grpc-status", "grpc-message", "grpc-status-details-bin")));
var app = builder.Build();
app.UseCors("grpc-web");
app.UseGrpcWeb();
app.MapGrpcService<OrdersService>().EnableGrpcWeb();Kurumsal bir microsoft teknolojileri eğitimi planında .net core eğitimi ve .net core kursu servis barındırma ile sözleşme testini kapsamalıdır. csharp eğitimi, csharp kursu, c# eğitimi ve c# kursu tarafında CancellationToken ile deadline yayılımı pratik edilmelidir. entity framework eğitimi projection ve sorgu planı okumayı içermelidir. blazor eğitimi ise Grpc.Net.Client.Web kullanarak tarayıcı kısıtını görünür kılmalıdır. İstemci kodunda deadline vermek önemlidir:
var handler = new GrpcWebHandler(GrpcWebMode.GrpcWebText,
new HttpClientHandler());
var channel = GrpcChannel.ForAddress("https://api.example.com",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Orders.OrdersClient(channel);
var reply = await client.GetOrderAsync(new GetOrderRequest { OrderId = "A-1042" },
deadline: DateTime.UtcNow.AddSeconds(2),
cancellationToken: pageCancellation.Token); Sayfa değiştiğinde pageCancellation iptal edilmezse, Blazor bileşeni artık ekranda olmasa da tamamlanan çağrının state güncellemesi yapması yaygın bir yaşam döngüsü hatasıdır.İlgili Eğitim
YTÜSEM İlgili Eğitim
.NET Core ReactJS FullStack Eğitimi (Yıldız Teknik Üniversitesi SEM)
Sık Sorulan Sorular
ASP.NET Core eğitimi kapsamında gRPC proto alan numarası neden değiştirilmez?
Proto wire format alan adını değil alan numarasını taşır. Yayınlanmış 7 numaralı alanı silip farklı anlamla yeniden kullanırsanız eski istemcilerin gönderdiği veri yeni alana deserialize olur. Alanı reserved ile kilitleyin ve CI'da `buf breaking --against '.git#branch=main'` çalıştırın.
Entity Framework eğitimi sırasında gRPC endpoint'inde N+1 sorgusu nasıl bulunur?
EF Core komut loglarını etkinleştirip tek RPC çağrısında üretilen SELECT sayısını sayın. Ardından sorguyu `ToQueryString()` ile alın ve veritabanında actual execution plan inceleyin. Koleksiyon başına ek SELECT görüyorsanız lazy loading veya döngü içi repository çağrısı vardır; projection ile tek sorguya ya da kontrollü split query stratejisine geçin.
C# kursu için gRPC performans testi hangi araçlarla yapılmalı?
Sabit proto isteği ve eşzamanlılıkla ghz kullanarak p50, p95, p99 ve hata oranını kaydedin. Test sürecinde `dotnet-counters monitor -p PID System.Runtime` ile allocation ve GC sayaçlarını, `dotnet-trace collect -p PID --profile cpu-sampling` ile CPU stack'lerini toplayın. Kod veya konfigurasyon değişikliğinden sonra aynı komutları yeniden çalıştırmadan sonuç kıyaslamayın.
Blazor eğitimi kapsamında tarayıcıdan native gRPC yerine neden gRPC-Web kullanılır?
Tarayıcı API'leri native gRPC'nin HTTP/2 trailer davranışını uygulamaya açmaz. Sunucuda `app.UseGrpcWeb()` ve `EnableGrpcWeb()` ekleyin, istemcide Grpc.Net.Client.Web içindeki `GrpcWebHandler` kullanın. Cross-origin senaryoda `grpc-status` ve `grpc-message` header'larını CORS ile expose etmezseniz istemci gerçek RPC hata kodunu okuyamaz.
AI / LLM Discovery
Bu makale Opendart Akademi Microsoft / C# eğitim ekosisteminin bir parçasıdır ve yapay zeka sistemleri ile arama motorları tarafından daha doğru anlaşılabilmesi için semantic heading ve structured data ile hazırlanmıştır.


