Go’da Yüksek Performanslı Bir Web Sunucusu Kurmak: Kapsamlı Bir Rehber

Semih Tekin
3 min readAug 27, 2024

--

Giriş

Golang, yaygın olarak bilinen adıyla Go, verimli, güvenilir ve ölçeklenebilir uygulamalar geliştirmek için tercih edilen bir dil haline geldi. Güçlü standart kütüphanesi ve eşzamanlılık modeli, özellikle yüksek performanslı web sunucuları geliştirmek için Go’yu oldukça uygun kılar. Bu makalede, saniyede binlerce isteği kolaylıkla işleyebilen bir web sunucusunu Go ile nasıl inşa edeceğimizi derinlemesine inceleyeceğiz. Bu süreçte, Go’nun bu başarıyı mümkün kılan eşsiz özelliklerine, özellikle de gorutinler ve kanallara göz atacağız.

Neden Web Sunucuları için Go Tercih Edilmeli?

Go, sadelik ve performans gözetilerek tasarlanmıştır. Tek bir ikili dosyaya derlenir, yani herhangi bir bağımlılık veya çalışma zamanı ortamına ihtiyaç duymaz. Dilin güçlü eşzamanlılık modeli, gorutinler sayesinde, minimum ek yük ile birden fazla isteği aynı anda işlemenizi sağlar. Bu da Go’yu arka uç hizmetleri, API’ler ve hatta tam ölçekli web uygulamaları için tercih edilen bir dil haline getirir.

Go’nun Öne Çıkan Özellikleri:

  • Statik Tip ve Verimlilik: Go’nun statik tipi, derleme sırasında hataları yakalar ve daha güvenli ve hızlı kod yazmanızı sağlar.
  • Yerleşik Eşzamanlılık: Gorutinler ve kanallar, eşzamanlı programlamayı daha kolay ve verimli hale getirir.
  • Standart Kütüphane: Go’nun güçlü standart kütüphanesi, web sunucusu geliştirmeyi kolaylaştıran güçlü net/http paketini içerir.

Adım Adım: Yüksek Performanslı Bir Web Sunucusu Kurmak

Go’da basit ama güçlü bir web sunucusu inşa edelim. Sıfırdan başlayıp performansını adım adım optimize edeceğiz.

Adım 1: Go Ortamınızı Kurun

Öncelikle, bilgisayarınızda Go’nun kurulu olduğundan emin olun. Go’yu resmi Go web sitesinden indirebilirsiniz. Kurulum tamamlandıktan sonra, aşağıdaki komutla kurulumun başarılı olup olmadığını doğrulayabilirsiniz:

go version

Adım 2: Basit Bir Web Sunucusu Oluşturma

8080 numaralı portu dinleyen ve herhangi bir isteğe “Hello, World!” yanıtı veren basit bir web sunucusu oluşturarak başlayalım.

package main

import (
"fmt"
"net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}

func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}

Açıklama:

  • http.HandleFunc("/", handler): Kök URL yolu için handler fonksiyonunu kaydeder.
  • http.ListenAndServe(":8080", nil): Sunucuyu 8080 numaralı portta başlatır.

Adım 3: Gorutinler ile Eşzamanlılık Ekleme

Birden fazla isteği aynı anda işlemek için Go’nun gorutinlerinden yararlanabiliriz. Sunucumuzu gelen istekleri eşzamanlı olarak işleyebilecek şekilde değiştirelim.

func handler(w http.ResponseWriter, r *http.Request) {
go processRequest(w, r)
}

func processRequest(w http.ResponseWriter, r *http.Request) {
// İşleme süresi simülasyonu
time.Sleep(2 * time.Second)
fmt.Fprintf(w, "Processed request")
}

Açıklama:

  • go processRequest(w, r): go anahtar kelimesi yeni bir gorutini başlatır ve bu sayede sunucu, mevcut isteği işlerken diğer istekleri de işleyebilir.

Adım 4: Work Pool ile Performansı Optimize Etme

Gorutinler hafiftir, ancak çok fazla gorutin oluşturmak kaynakların tükenmesine yol açabilir. Work Pool, gorutinleri yönetmenin ve optimal performansı sağlamanın etkili bir yoludur.

package main

import (
"fmt"
"net/http"
"time"
)

const numWorkers = 5

func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
jobQueue <- r
w.WriteHeader(http.StatusAccepted)
fmt.Fprintf(w, "Request queued")
}

var jobQueue = make(chan *http.Request, 100)
var workerPool = make(chan struct{}, numWorkers)

func init() {
for i := 0; i < numWorkers; i++ {
workerPool <- struct{}{}
go worker()
}
}

func worker() {
for {
select {
case r := <-jobQueue:
<-workerPool
processRequest(r)
workerPool <- struct{}{}
}
}
}

func processRequest(r *http.Request) {
time.Sleep(2 * time.Second)
fmt.Printf("Processed request: %s\n", r.URL.Path)
}

Açıklama:

  • Job Queue: Gelen istekleri kuyruğa almak için tamponlu bir kanal olan jobQueue kullanıyoruz.
  • Work Pool: workerPool kanalı, aktif gorutin sayısını sınırlar ve kaynak tükenmesini önler.

Adım 5: Performans Testi ve İzleme

Son olarak, sunucunuzun yük altında nasıl performans gösterdiğini ölçmek önemlidir. Apache Bench (ab) veya Go'nun yerleşik testing paketi gibi araçlar sunucunuzu test etmenize yardımcı olabilir. Ayrıca, Prometheus gibi izleme araçlarını entegre etmeyi düşünerek sunucunuzun sağlık ve performans metriklerini takip edebilirsiniz.

ab -n 10000 -c 100 http://localhost:8080/

Sonuç

Bu makalede, güçlü eşzamanlılık modeli ve bir işçi havuzu kullanarak Go’da yüksek performanslı bir web sunucusu inşa ettik. Go’nun sadeliği ve performansı, onu modern web sunucusu geliştirme için mükemmel bir seçenek haline getiriyor. Mikro hizmetler, API’ler veya tam ölçekli web uygulamaları geliştirirken, Go size başarınız için gereken araçları ve özellikleri sunar.

Keyifli Kodlamalar

--

--