Go ve gRPC ile Yuksek Performansli Mikroservisler: 2026 Rehberi ve Mulakat Sorulari
Go ve gRPC ile yuksek performansli mikroservis gelistirme rehberi. Protocol Buffers, unary ve streaming RPC'ler, interceptor'lar, uretim ortami desenleri ve backend mulakat sorulari.

gRPC, düşük gecikme süresi ve katı API sözleşmeleri gerektiren Go mikroservisleri için varsayılan iletişim katmanı haline gelmiştir. grpc-go v1.81, Go 1.26 ve go-grpc-middleware ekosisteminin olgunlaşmasıyla birlikte, Go'da üretim kalitesinde gRPC servisleri geliştirmek her zamankinden daha kolaydır. Aynı zamanda gRPC, backend mühendislik mülakatlarında en sık test edilen konulardan biri olmaya devam etmektedir.
gRPC, ikili serileştirme için HTTP/2 ve Protocol Buffers kullanmaktadır. Bu sayede 10 kata kadar daha küçük veri paketleri ve yerel çift yönlü akış desteği sunmaktadır. REST, genel kullanıma açık API'ler için daha uygun bir seçenek olmaya devam etmektedir; gRPC ise performans ve tip güvenliğinin önemli olduğu servisler arası iletişimde öne çıkmaktadır.
gRPC Neden Go Backend Iletisiminde Baskin Konumda
Uç temel özellik, gRPC'yi Go mikroservisleri için doğal tercih haline getirmektedir. Birincisi, Protocol Buffers derleme zamanında güçlü tipli Go kodu üretmektedir ve sözleşme uyumsuzluklarını dağıtımdan önce yakalamaktadır. İkincisi, HTTP/2 çoklama (multiplexing) özelliği head-of-line blocking sorununu ortadan kaldırmakta ve tek bir TCP bağlantısı üzerinden tam çift yönlü akış desteklemektedir. Üçüncüsü, interceptor modeli Go'nun kalıtım yerine kompozisyon felsefesine temiz bir şekilde uyum sağlamakta ve kimlik doğrulama, izleme gibi kesişen ilgilerin (cross-cutting concerns) birleştirilebilir olmasını mümkün kılmaktadır.
Go'daki gRPC ekosistemi, savaşta test edilmiş birkaç kütüphane etrafında konsolidasyona ulaşmıştır. grpc-go çekirdek taşıma katmanı ve kod üretimini yönetmektedir. go-grpc-middleware v2 paketi; günlükleme, metrik, kimlik doğrulama ve kurtarma için üretim düzeyinde interceptor'lar sağlamaktadır. OpenTelemetry'nin gRPC stats handler'ı ise özel interceptor kodu yazmaya gerek kalmadan dağıtık izlemeyi kapsamaktadır.
Protocol Buffers ile Servis Tanimlama
Her gRPC servisi bir .proto dosyasıyla başlamaktadır. Şema; servis sözleşmesini, mesaj tiplerini ve RPC metotlarını tanımlamaktadır. Aşağıdaki örnek, tekli (unary) arama ve sunucu akışlı (server streaming) aktivite akışı metotlarına sahip bir kullanıcı servisini modellemektedir.
syntax = "proto3";
package user.v1;
option go_package = "gen/user/v1;userv1";
service UserService {
// Unary RPC: single request, single response
rpc GetUser(GetUserRequest) returns (GetUserResponse);
// Server streaming: single request, stream of responses
rpc StreamActivity(StreamActivityRequest) returns (stream ActivityEvent);
}
message GetUserRequest {
string user_id = 1;
}
message GetUserResponse {
string user_id = 1;
string email = 2;
string display_name = 3;
int64 created_at_unix = 4;
}
message StreamActivityRequest {
string user_id = 1;
int32 limit = 2;
}
message ActivityEvent {
string event_id = 1;
string action = 2;
string resource = 3;
int64 timestamp_unix = 4;
}protoc --go_out=. --go-grpc_out=. user_service.proto komutu çalıştırıldığında iki dosya üretilmektedir: biri mesaj tiplerini, diğeri gRPC istemci/sunucu arayüzlerini içermektedir. Üretilen sunucu arayüzü, Go implementasyonunun karşılaması gereken sözleşmeyi oluşturmaktadır.
Go'da gRPC Sunucu Implementasyonu
Sunucu implementasyonu, üretilen UnimplementedUserServiceServer yapısını gömmektedir (embed). Bu yaklaşım ileriye dönük uyumluluk sağlamaktadır: proto dosyasına yeni RPC'ler eklendiğinde, mevcut sunucu kodu ilgili metot açıkça implemente edilene kadar bozulmamaktadır.
package server
import (
"context"
"fmt"
"time"
userv1 "myapp/gen/user/v1"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type UserServer struct {
userv1.UnimplementedUserServiceServer
store UserStore // interface for DB access
}
func NewUserServer(store UserStore) *UserServer {
return &UserServer{store: store}
}
// GetUser handles the unary RPC
func (s *UserServer) GetUser(ctx context.Context, req *userv1.GetUserRequest) (*userv1.GetUserResponse, error) {
if req.GetUserId() == "" {
return nil, status.Error(codes.InvalidArgument, "user_id is required")
}
user, err := s.store.FindByID(ctx, req.GetUserId())
if err != nil {
return nil, status.Errorf(codes.Internal, "lookup failed: %v", err)
}
if user == nil {
return nil, status.Error(codes.NotFound, "user not found")
}
return &userv1.GetUserResponse{
UserId: user.ID,
Email: user.Email,
DisplayName: user.DisplayName,
CreatedAtUnix: user.CreatedAt.Unix(),
}, nil
}
// StreamActivity sends activity events as a server stream
func (s *UserServer) StreamActivity(req *userv1.StreamActivityRequest, stream userv1.UserService_StreamActivityServer) error {
events, err := s.store.GetActivity(stream.Context(), req.GetUserId(), int(req.GetLimit()))
if err != nil {
return status.Errorf(codes.Internal, "activity fetch failed: %v", err)
}
for _, evt := range events {
if err := stream.Send(&userv1.ActivityEvent{
EventId: evt.ID,
Action: evt.Action,
Resource: evt.Resource,
TimestampUnix: evt.Timestamp.Unix(),
}); err != nil {
return fmt.Errorf("stream send: %w", err)
}
}
return nil
}Dikkat edilmesi gereken iki temel desen bulunmaktadır: status.Error ve status.Errorf, istemcilerin programatik olarak inceleyebileceği uygun durum kodlarına sahip gRPC-yerel hatalar üretmektedir. UnimplementedUserServiceServer gömme işlemi ise proto evrildikçe derleme zamanı güvenliği sağlamaktadır.
Interceptor'lar ile Uretim Ortami Sunucu Yapilandirmasi
Temel bir gRPC sunucusu istekleri işleyebilmektedir ancak gözlemlenebilirlik, kimlik doğrulama ve panik kurtarma mekanizmalarından yoksundur. Üretim ortamı servisleri bir interceptor zincirine ihtiyaç duymaktadır. go-grpc-middleware v2 kütüphanesi, grpc.ChainUnaryInterceptor ile zincirlenen birleştirilebilir interceptor'lar sunmaktadır.
package main
import (
"log"
"net"
"os"
"os/signal"
"syscall"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging"
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/recovery"
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/ratelimit"
userv1 "myapp/gen/user/v1"
"myapp/server"
)
func main() {
// Interceptor order matters: recovery first, then metrics, then auth
srv := grpc.NewServer(
// OpenTelemetry tracing via stats handler (not interceptor)
grpc.StatsHandler(otelgrpc.NewServerHandler()),
grpc.ChainUnaryInterceptor(
recovery.UnaryServerInterceptor(), // catch panics
ratelimit.UnaryServerInterceptor(limiter), // rate limiting
logging.UnaryServerInterceptor(logger), // structured logging
authInterceptor, // token validation
),
grpc.ChainStreamInterceptor(
recovery.StreamServerInterceptor(),
ratelimit.StreamServerInterceptor(limiter),
logging.StreamServerInterceptor(logger),
),
)
// Register service implementation
userv1.RegisterUserServiceServer(srv, server.NewUserServer(store))
// Enable reflection for grpcurl and debugging
reflection.Register(srv)
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("listen: %v", err)
}
// Graceful shutdown on SIGTERM
go func() {
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGTERM, syscall.SIGINT)
<-sig
log.Println("shutting down gRPC server")
srv.GracefulStop()
}()
log.Printf("gRPC server listening on :50051")
if err := srv.Serve(lis); err != nil {
log.Fatalf("serve: %v", err)
}
}Interceptor sıralaması yürütme önceliğini belirlemektedir. Recovery ilk sırada çalışarak alt akıştaki herhangi bir interceptor'dan kaynaklanan panikleri yakalamaktadır. Hız sınırlama (rate limiting), kimlik doğrulama katmanını kötüye kullanımdan korumak amacıyla auth'dan önce çalışmaktadır. OpenTelemetry izleme, interceptor yerine StatsHandler kullanmaktadır; bu, grpc-go v1.81 itibarıyla önerilen yaklaşımdır çünkü stats handler'lar interceptor'ların göremediği bayt sayıları ve bağlantı yaşam döngüsü olayları gibi daha düşük seviye taşıma olaylarına erişim sağlamaktadır.
Go mülakatlarında başarılı olmaya hazır mısın?
İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.
Go'da gRPC Hata Yonetimi Desenleri
Doğru hata yönetimi, üretim düzeyindeki gRPC servislerini prototiplerden ayıran temel unsurdur. gRPC, her istemcinin anlayabileceği bir dizi standart durum kodu tanımlamaktadır. Go'nun status paketi bu kodları hatalara eşlemektedir.
Temel desenler aşağıdaki gibidir:
- Hatalı biçimlendirilmiş istekler (istemci hatası) için
codes.InvalidArgumentdöndürülmelidir - Kaynak bulunamadığında
codes.NotFounddöndürülmelidir - Beklenmeyen sunucu hataları için
codes.Internaldöndürülmelidir - Kimlik bilgileri eksik veya geçersiz olduğunda
codes.Unauthenticateddöndürülmelidir - Kimlik bilgileri geçerli ancak yetersiz olduğunda
codes.PermissionDenieddöndürülmelidir
package rpcerr
import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// NotFound wraps a resource-not-found error with a consistent message
func NotFound(resource, id string) error {
return status.Errorf(codes.NotFound, "%s %q not found", resource, id)
}
// InvalidArg wraps a validation error
func InvalidArg(field, reason string) error {
return status.Errorf(codes.InvalidArgument, "%s: %s", field, reason)
}
// Internal wraps an unexpected error, hiding internals from the client
func Internal(err error) error {
// Log the real error server-side; return generic message to client
return status.Error(codes.Internal, "internal server error")
}Hataları alan bazlı yapıcı fonksiyonlarla (constructor) sarmalamak, durum kodlarının tüm RPC'ler boyunca tutarlı kalmasını sağlamaktadır. İstemciler, hata dizelerini ayrıştırmak zorunda kalmadan her durumu işlemek için status.Code(err) üzerinden ayrım yapabilmektedir.
bufconn ile gRPC Servislerini Test Etme
Bir gRPC servisinin entegrasyon testi normalde gerçek bir TCP sunucusunun başlatılmasını gerektirmektedir. bufconn paketi, port tahsisi ve ağ yükünü tamamen ortadan kaldıran bellek içi (in-memory) bir dinleyici sağlamaktadır.
package server_test
import (
"context"
"net"
"testing"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/test/bufconn"
userv1 "myapp/gen/user/v1"
"myapp/server"
)
const bufSize = 1024 * 1024
func setupServer(t *testing.T) userv1.UserServiceClient {
t.Helper()
lis := bufconn.Listen(bufSize) // in-memory listener
srv := grpc.NewServer()
userv1.RegisterUserServiceServer(srv, server.NewUserServer(mockStore{}))
go func() {
if err := srv.Serve(lis); err != nil {
t.Errorf("server exited: %v", err)
}
}()
t.Cleanup(srv.GracefulStop)
// Dial the in-memory listener
conn, err := grpc.NewClient(
"passthrough:///bufconn",
grpc.WithContextDialer(func(ctx context.Context, _ string) (net.Conn, error) {
return lis.DialContext(ctx)
}),
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil {
t.Fatalf("dial bufconn: %v", err)
}
t.Cleanup(func() { conn.Close() })
return userv1.NewUserServiceClient(conn)
}
func TestGetUser_NotFound(t *testing.T) {
client := setupServer(t)
_, err := client.GetUser(context.Background(), &userv1.GetUserRequest{
UserId: "nonexistent",
})
// Verify gRPC status code
st, ok := status.FromError(err)
if !ok || st.Code() != codes.NotFound {
t.Errorf("expected NotFound, got %v", err)
}
}bufconn, serileştirme ve interceptor yürütme dahil tam gRPC bağlantısını TCP olmadan oluşturmaktadır. Testler daha hızlı çalışmakta ve port çakışması olmadan paralel olarak yürütülebilmektedir. Bu, grpc-go deposunun kendi bünyesinde kullanılan standart test desenidir.
mTLS ve Token Kimlik Dogrulama ile gRPC Guvenligi
Üretim ortamı gRPC servisleri taşıma katmanı güvenliği gerektirmektedir. İki yaklaşım baskın konumdadır: her iki tarafın da sertifika sunduğu servisler arası kimlik doğrulama için mTLS ve halihazırda güvenliği sağlanmış bir kanal içinde istemci kimliği için token tabanlı kimlik doğrulama (JWT veya API anahtarları).
mTLS yapılandırması, sunucu başlangıcında sertifikaları yüklemektedir:
package main
import (
"crypto/tls"
"crypto/x509"
"os"
"google.golang.org/grpc/credentials"
)
func loadTLSCredentials(certFile, keyFile, caFile string) (credentials.TransportCredentials, error) {
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return nil, err
}
caPool := x509.NewCertPool()
caPEM, err := os.ReadFile(caFile)
if err != nil {
return nil, err
}
caPool.AppendCertsFromPEM(caPEM)
tlsCfg := &tls.Config{
Certificates: []tls.Certificate{cert},
ClientAuth: tls.RequireAndVerifyClientCert, // enforce mTLS
ClientCAs: caPool,
MinVersion: tls.VersionTLS13, // TLS 1.3 minimum in 2026
}
return credentials.NewTLS(tlsCfg), nil
}TLS 1.3, 2026 yılında gRPC servisleri için temel güvenlik standardıdır. TLS 1.2'ye kıyasla daha hızlı el sıkışma (1-RTT) ve daha güçlü şifre takımları sunmaktadır. TLS üzerine katmanlanan token tabanlı kimlik doğrulama için, bir unary interceptor gRPC meta verilerinden token'ı çıkarmakta ve handler yürütülmeden önce doğrulamaktadır.
Sabit kodlanmış sertifika yolları, rotasyon için sunucu yeniden başlatmalarını gerektirmektedir. Üretim ortamı dağıtımlarında, kesinti yaşanmadan otomatik sertifika yenileme işlemi için tls.Config.GetCertificate kullanılması veya Envoy gibi bir sidecar proxy tercih edilmesi gerekmektedir.
Mulakat Sorulari: gRPC ve Go Mikroservisleri
Aşağıdaki sorular, Go ve dağıtık sistemlere odaklanan backend mühendislik mülakatlarında sıklıkla karşılaşılmaktadır. Her cevap, kıdemli seviyede beklenen derinliği hedeflemektedir.
gRPC'deki dort RPC tipi nelerdir ve her biri ne zaman uygundur?
Unary (tekli istek, tekli yanıt) çoğu CRUD işlemini kapsamaktadır. Sunucu akışı (server streaming), sunucunun birden fazla sonuç ilettiği senaryolara uygundur: aktivite akışları, arama sonuçları ve gerçek zamanlı güncellemeler. İstemci akışı (client streaming), yükleme senaryoları veya istemcinin sunucu yanıt vermeden önce birden fazla mesaj gönderdiği toplu yazma işlemleri için geçerlidir. Çift yönlü akış (bidirectional streaming), sohbet, ortak düzenleme veya her iki tarafın bağımsız olarak mesaj gönderdiği herhangi bir protokol için hizmet vermektedir.
Bir proto alanı kaldırıldığında gRPC geriye dönük uyumluluğu nasıl sağlamaktadır?
Proto3, alan numaralarını asla yeniden kullanmamaktadır. Bir alan kaldırıldığında, eski bir istemci hala bu değeri gönderiyorsa sunucu bunu yok saymaktadır; yanıtı okuyan eski istemciler ise kaldırılan alan için sıfır değerini görmektedir. reserved anahtar kelimesi, alan numaralarının veya adlarının yanlışlıkla yeniden kullanılmasını engellemektedir. Bu durum, alan kaldırmanın deserialization hatalarına neden olabileceği JSON API'lerinden temelden farklıdır.
Mevcut bir alanın tipi veya numarası asla değiştirilmemelidir. Yeni alanlar yeni numaralarla eklenmelidir. Eski numaraları kullanımdan kaldırmak için reserved kullanılmalıdır. Bu kural tüm programlama dillerinde geçerlidir ve sıfır kesinti süreli dağıtımları garanti etmektedir.
Uretim ortami gRPC servisinde interceptor'larin rolunu aciklayiniz.
Interceptor'lar, gRPC'nin middleware katmanıdır. Handler'dan önce ve sonra, kayıt edildikleri sırayla yürütülmektedir. Tipik bir üretim zinciri: recovery (panik yakalama) > hız sınırlama > günlükleme > auth > doğrulama şeklindedir. go-grpc-middleware v2 kütüphanesi bu deseni takip eden birleştirilebilir interceptor'lar sağlamaktadır. Interceptor'lar taşıma katmanını (TLS, portlar) değiştirememektedir; yalnızca RPC seviyesinde çalışmaktadır.
grpc.StatsHandler ile interceptor arasindaki fark nedir?
Interceptor'lar RPC handler'ını sarmalamakta ve uygulama seviyesinde çalışmaktadır. Stats handler'lar ise taşıma seviyesi olaylarını almaktadır: bağlantı başlangıçları, mesaj gönderme/alma ve RPC tamamlanma olayları. OpenTelemetry, interceptor'ların göremediği bayt sayıları ve bağlantı yaşam döngüsü olayları gibi metrikleri yakaladığı için stats handler'ları kullanmaktadır. grpc-go v1.66+ itibarıyla resmi öneri, gözlemlenebilirlik için stats handler'ların, iş mantığı için interceptor'ların kullanılması yönündedir.
Bir gRPC sunucusu icin graceful shutdown nasil uygulanir?
GracefulStop(), yeni bağlantıları kabul etmeyi durdurmakta ve devam eden RPC'lerin tamamlanmasını beklemektedir. Desen şu şekildedir: bir goroutine'de SIGTERM dinlenmekte, GracefulStop() çağrılmakta ve ardından Serve() çağrısı geri dönmektedir. Süresiz çalışabilecek streaming RPC'ler için, context iptal ile bir son tarih belirlenmeli veya kapatma başlamadan önce SERVING durumunu döndürmeyi bırakan bir sağlık kontrolü kullanılmalıdır. Bu sayede yük dengeleyicilere trafiği boşaltmaları için süre tanınmaktadır.
Dahili servisler icin bir ekip gRPC'yi REST yerine ne zaman secmelidir?
gRPC, şu durumlarda daha güçlü bir seçimdir: servisler derleme zamanında uygulanan katı API sözleşmelerine ihtiyaç duyduğunda; sistem akış gerektirdiğinde (sunucu push, çift yönlü); gecikme süresi önemli olduğunda ve ikili serileştirme veri paketi boyutunu küçülttüğünde; ekip hem istemci hem de sunucu kodunu yönettiğinde. REST ise şu durumlarda tercih edilmektedir: tarayıcılar tarafından tüketilen genel API'ler (yerel JSON, proxy gerekmez), HTTP semantikleri ile yoğun önbellek kullanan API'ler veya maksimum araç uyumluluğuna ihtiyaç duyan ekipler için. Birçok mimari her ikisini birlikte kullanmaktadır: dahili iletişim için gRPC, harici tüketiciler için REST gateway.
Pratik yapmaya başla!
Mülakat simülatörleri ve teknik testlerle bilgini test et.
Sonuc
- Protocol Buffers, API sözleşmelerini derleme zamanında uygulamaktadır; bozucu değişiklikler çalışma zamanında değil, kod üretimi sırasında ortaya çıkmaktadır
UnimplementedServerdeseni, gelişen bir servise yeni RPC'ler eklendiğinde ileriye dönük uyumluluk sağlamaktadır- Interceptor sırası kritik öneme sahiptir: önce recovery, ardından hız sınırlama, sonra auth; go-grpc-middleware v2 kütüphanesi zincirlemeyi yönetmektedir
- İzleme için
grpc.StatsHandlerve OpenTelemetry kullanılmalı; auth ve doğrulama gibi iş mantığı için interceptor'lar ayrılmalıdır bufconn, serileştirme ve interceptor'lar dahil tam gRPC yığınını kapsayan hızlı ve port gerektirmeyen entegrasyon testleri sağlamaktadır- TLS 1.3 ile mTLS, 2026'da servisler arası güvenlik için temel standarttır; mesh içinde kimlik doğrulama için üzerine token auth katmanlanmalıdır
- gRPC mulakat sorularina hazirlanirken dort RPC tipi, proto geriye donuk uyumluluk kurallari ve interceptor ile stats handler ayrimi anlasilmalidir
Pratik yapmaya başla!
Mülakat simülatörleri ve teknik testlerle bilgini test et.
Etiketler
Paylaş
İlgili makaleler

Go 1.26 Mulakat Rehberi: Green Tea GC, go fix Araci ve Stack Optimizasyonlari
Go 1.26 surumunde yer alan Green Tea cep toplayici, yenilenmis go fix araci ve stack bellek optimizasyonlari uzerine kapsamli mulakat rehberi. Kod ornekleri ve teknik aciklamalar ile desteklenmistir.

Go Tasarim Desenleri: Go Gelistiricileri icin Temel Desenler ve Mulakat Sorulari
Go tasarim desenlerinin kapsamli rehberi: Functional Options, Strategy, Factory, Observer ve Middleware desenleri. Pratik kod ornekleri ve Go mulakat sorulari.

En çok sorulan 25 Go mülakat sorusu: tam geliştirici rehberi
Go mülakatlarına hâkim olmak için en çok sorulan 25 soru. Goroutine, channel, arayüz ve eşzamanlılık desenleri kod örnekleriyle.