Web Projesi Yapıyorum, Nasıl Çalışıyor Bilmiyorum”

Türerkan İnce
9 min readApr 25, 2017

--

Soğan gibi katman katman üst üste binmiş frameworkleri, kütüphaneleri, platformları, protokolleri birer birer soymak.

Framework’ler çağında yaşıyoruz. Bir çok yazılım projesi bir kütüphaneyi alıp diğerini bağlamaktan ibaret olmuş. Bir soruna çözüm bulmak deyince akla algoritmalar veya veri yapıları gelmiyor. Onların yerini internetin tozlu köşelerinde terk edilmiş bir zamazingo.js’nin dökümante edilmemiş hatalarını debug etmek almış. (baktım, zamazingo.js diye bir proje yok. İşte size framework piyasasına girme fırsatı!)

Şikayet etmeyelim, günün koşulları hep aynı olacak değil. Ama ortada büyük bir boşluk olduğunu kabul edelim: Ne olup bittiğini bilmek.

İman gücü ve seloteyple tutturup bir kez testi geçtiği anda canlıya attığımız şu web projeleri yarım yamalak çalışıyor çalışmasına ama içimizde hep bir burukluk var. Patladığında neden patladığını, çalıştığında neden çalıştığını anlamıyoruz. Sürecin çoğunluğuna hakim değiliz.

İnsan bilmediğinden korkarmış. Yazılım projeleri gün geçtikçe daha korkunç hale geliyor. Daha büyük işler yaptığımız için değil. Daha opak, daha bilinmez, daha incelenmez hale geldikleri için. Ben bu yeni dünyada eski kafalı birisi olarak bu belirsizliklere katlanmayı reddediyorum. En azından proje kapsamları el verdiğince.

Korkunun üstüne yürümek demek, bir soğan gibi katman katman üst üste binmiş frameworkleri, kütüphaneleri, platformları, protokolleri birer birer soymak demek.

Dünya ve Makine

Bir web projesine en soyut, en yüksekten bakış dünyayı projenin içi ve dışı olmak üzere iki kümeye bölmekle elde edilebilir. Kabaca, kodun çalıştığı makine ve dünyanın geri kalanı. Şimdilik uygulama kodunuz bir HTTP isteğini bir HTTP cevabına dönüştüren kapalı bir kutudan ibaret olsun. Yolculuğumuza en dışarıdan başlayalım.

Internet Protokolü

İnternet Protokolü internet üzerindeki her bilgisayara bir numara, IP numarası verilmesi üstüne kuruludur. Mümkün olan tüm IP numaraları ülkelere ve servis sağlayıcılara göre bölünmüştür. Her bir servis sağlayıcı (örneğin TTNET) internete giren kullanıcılarına bir IP numarası atar. İnternete bağlı iki bilgisayara arasındaki iletişim iki IP numarası arasındaki iletişim şeklinde soyutlanır.

Peki IP, IP’yi nerede bulur?

Tekil bilgisayarlar servis sağlayıcılarına bağlı, servis sağlayıcılar ise dünya çapında bir ağ ile birbirine bağlı. Bir IP’ye istek gönderdiğinizde servis sağlayıcınız bu IP kendi müşterisiyse doğrudan bağlantıyı kurar. Bir telefon santrali gibi düşünün: “Ahmet bey mi? Hemen bağlıyorum efendim, bizi aradığınız için teşekkür ederiz!”.

Eğer istediğiniz IP servis sağlayıcımıza ait değilse şöyle bir senaryo gerçekleşir: “Yok, burada Justin Bieber diye birisi yok. Kusura bakmayın. Ama isim bir Kanadalı ismine benziyor. İsterseniz kanada konsolosluğu ile bir konuşun, belki onlar bilir. Kanada konsolosluğuna aktarıyorum…” Daha sonra Kanada konsolosluğundan Justin Bieber’ın Amerika’da yaşadığını öğrendiğiniz vb. kısımları es geçiyorum.

Bilgisayarınız bu telefon bürokrasisini milisaniyeler içinde hallederken size hiç ses etmez. Ama merak ediyorsanız terminalinizi açıp traceroute google.com yazıp iç çekerek seyredebilirsiniz. (Windows kullanıyorsanız tracert google.com olacak, dikkat)

192.168.112.213 gibi gösterilen 12 haneli IP numaralarının dünya çapında tükenmek üzere olduğunu not edelim. IPv4 adındaki bu eski gösterimin yerine IPv6 adında yeni bir IP numarası biçimi geliyor. İncelemenizi tavsiye ederim: https://tr.wikipedia.org/wiki/IPv6

Bir bilgisayarın birden fazla IP numarası olabildiğini, çoğunlukla en azından bir yerel ağ, bir de internet IP’niz olduğunu unutmayın. http://whatismyipaddress.com/tr/ip-im adresinden internete çıkan IP numaranızı görebilirsiniz.

Alan Adı Sistemi

Bu noktada şöyle bir sorunuz olabilir: “İnternete bağlı makinelere numara verildi dedin, ama biz Justin Bieber’ın numarasını nereden bulacağız?”. Çok haklı bir soru, hepimizin birer T.C. Kimlik numarası var ama hala birbirimize Ahmet, Mehmet diye isimlerle sesleniyoruz. İnternette de bazı makinelerin isimlerinin olması önemli. Bunun için DNS (Domain Name System, Alan Adı Sistemi) denilen bir protokol icat edilmiş. Böylece Justin Bieber’ın bilgisayarının IP numarasını değil, o bilgisayara atanmış “www.justinbiebermusic.com” adını bilmemiz yeterli oluyor.

DNS’den faydalanmak için bir DNS sunucusunun IP numarasını en baştan bilmeniz lazım. Bir de DNS istemcisi gerekli ki, tüm işletim sistemlerinin içinde zaten var. Servis sağlayıcıları da otomatik olarak bir DNS sunucusu verdiği için rahatsınız. İsterseniz elle DNS sunucunuzu değiştirebilirsiniz ama bu konumuzun dışında.

Alan adları sağdan sola doğru incelenir. Yukarıdaki adresi incelersek “com” en üst düzey alan adıdır. Bunun bi altında “justinbiebermusic.com”, onun da altında “www.justinbiebermusic.com” gelir.

Bir alan adını açmak istediğinizde öncelikle bilgisayarınız önceden IP’sini bildiği DNS sunucusuna sorar: www.justinbiebermusic.com diye birini tanıyor musun?”. Sunucu yakın zamanda bu adresi gördüyse önbelleğinden cevabı yapıştırır, bir IP numarası olarak. Görmediyse “com” üst alan adının kaydını tutan sunuculara sorar, “justinbiebermusic.com’un DNS sunucusu nedir?” cevabı alınca o sunucuya da www.justinbiebermusic.com’un sunucusu nedir?” diye sorar. Tıpkı İnternet Protokolünde olduğu gibi bir bürokratik geliş gidişler sonucunda doğru IP adresi makinenize döner.

Burası DNS, Buradan Çıkış Yok

Tahmin edeceğiniz gibi DNS protokolü çok sık kullanılan bir protokol, her tür internet iletişiminin öncesinde bir DNS sorgusu yapılıyor. Hatta yukarıdaki traceroute örneği sinsice bir DNS çağrısı yapıyor olmasaydı ‘traceroute google.com’ yazamazdık, IP’sini bilmemiz gerekirdi. IP protokolüne örnek vereyim derken bile önce bir DNS sorgusu yapmaktan kaçamamışız. Neyse ki DNS sorgusunun kendisi de IP protokolü üzerinden gittiği için rahatız.

Bu yoğun kullanım yüzünden DNS sonuçları şiddetle önbelleklenir. Ne kadar önbellekleneceği DNS kayıtlarında alan adı sahibi tarafından belirtilir. DNS değişikliklerinden sonra herşeyin normale dönmesi için bazen saatlerce beklemek zorunda kalmamız bu önbellekleme yüzündendir.

Eğer merak ediyorsanız Windows, Mac OS, Linux farketmeksizin `nslookup google.com` komutu ile alan adı çözümleyemeyi deneyebilirsiniz.

DNS’leri Ayarlamak Benim Başıma Kaldı! Offf…

Alan adı satın aldığınızda bir DNS sunucusunu bu alan adı için asıl sunucu olarak belirtmeniz gerekir. İnternetin her yerindeki diğer DNS sunucuları bu asıl sunucudaki kayıtları kopyalar. Genellikle alan adını satın aldığınız yer size DNS sunucusu hizmetini de sağlar. Ama kendi makinenize “bind9” kurarak kendi kendinizin DNS sunucusu da olabilirsiniz. Veya üçüncü parti bir DNS sunucusu kullanırsınız (Örneğin Amazon AWS veya Digitalocean gibi sanal makine sağlayıcıları aynı zamanda müşterilerine DNS hizmeti de veriyor). Her durumda alan adını satın aldığınız yerde (Domain Registrar) kullandığınız DNS sunucularının belirtilmiş olması gerekir.

DNS kayıtlarını çoğunlukla bir web sayfasındaki form üzerinden yönetiyoruz. Bu form her Domain Registrar’da farklı. Ama ayarlardaki konseptler hep aynı. bind9 DNS sunucu yazılımının konfigürasyon dosyalarındaki biçimin aynısı.

Aman diyeyim kendi hiç bind9’ımı kurayım ayarlayayım demeyin, konfigürasyonu saç baş yoldurur. Bırakınız sizin yerinize yapsınlar. Yapsınlar derken, en otomatiği bile ayarların yarısını size yazdırıyor. O yüzden elimiz mahkum biraz bakacağız. Digitalocean DNS girişi ekranı şöyle görünüyor:

Önemli DNS kayıt türleri şöyle oluyor;

  • A: bir alanadına denk düşen IP numarası. Bir nevi kayıtların en hası. Bu kayıt bir alt alan adı ile bir IP numarasını eşleştirir. Genellikle alt alan adını boş bırakır veya `@` yaparsanız alan adının kendisine IP vermiş olursunuz.
  • AAAA: aynısının IPv6 için olanı. Bir süre daha bunu kullanmadan idare edebileceğiz, ama ha bugün ha yarın mecburen AAAA kayıtlarını doldurmak zorunda kalacağız, bunu da unutmayalım.
  • CNAME: bir alt alan adını başka bir alt alan adına yönlendirir. En yaygın kullanımı www alt alan adını asıl alan adına yönlendirmek şeklindedir.
  • MX: bu alan adına gönderilen e-postaları işleyen eposta sunucusunun adresi.
  • NS: bu alan adının DNS sunucusunun adresini verir.

İşlevsel bir sitenin DNS kayıtları yaklaşık şuna benzer:

alanadim.com A 192.168.112.123 (sunucunu IPsi)
www CNAME @
MX 10 eposta-sunucum.com
NS ns1.dns-sunucum.com
NS ns2.dns-sunucum.com

Zeki Müren De Bizi Görecek Mi?

Bu kadar yazıyı bizi bulabilsinler diye yazdık. O yağlı ballı web frameworkümüz, kurtarıcımız, kıymetlimiz daha ufukta bile görünmedi. Gelse ve sizi güvenilir kollarınıza alsa nasıl da rahat ederdiniz, değil mi? Gelmeyecek, hiç beklemeyin. Ama biz ona doğru emin adımlarla yürüyoruz. İlk gördüğümüz yerde bir şaplak indirmeyi de aklımızdan çıkartmıyoruz.

Birilerinin bize ulaşmasının yolunu açtık, ama bakalım biz onlara cevap verecek miyiz? Her gelen telefona uzun uzun cevap verseydik herhalde ömür geçmezdi. “Aaa, yeni kredi kartı mı vermek istiyorsunuz? Cidden mi? Tabi ki anlatabilirsiniz! Bütün gün yapacak başka işim mi var, hadi anlatın bu yeni kredi kartının özelliklerini!”

Firewall diye adını sıkça duyduğumuz şey aslında IP’mize gelen istekleri inceleyip bazılarını reddetmeye yarayan bir güvenlik sistemi. Tıpkı bir gece kulübünün önündeki güvenlik gibi, görevi tipini beğenmediğini, damsız geleni almamak. Yüzeysel bir kontrolden ibaret. Firewall sizi rezil de etmez vezir de etmez. Var diye rahatlamayın, yok diye üzülmeyin. En önemli katkısı sadece yerelden erişilebilmesi gereken bazı uygulamaların hatayla tüm internete açılmasını engellemektir.

Linux altında “iptables” komutu firewall ayarlarını yapmaya yarar. Bunun yanında AWS gibi sanal makine sağlayıcısı kullanıyorsanız size web arayüzünden yönetilen ek bir firewall daha sağlıyor olabilirler. Eğer sadece hosting hizmeti satın alıyorsanız firewall ayarlarını hosting firması sizin yerinize yapar, size bırakmaz.

Temel bir web projesi için makineninizin 22, 80 ve 443 portlarının dışarıdan erişime açık olması yeterlidir. Bunlar sırası ile SSH, HTTP ve HTTPS protokollerine denk gelir. Firewall ayarlarına ilişkin örnek vermiyorum, özel olarak ilgilenmeyenlerin detayına girmesine gerek olmayan bir konu.

Port Nedir Açıklamadın?

Çünkü port denilen kavram TCP (Transmission Control Protocol) protokolünün bir parçası. TCP’den henüz bahsetmemiştik. TCP/IP şeklinde internet protokolü ile birlikte anıldığına çok rastlarsınız. O kadar temeldir yani. Sitemize gelen istekler tamamen TCP’den ibaret olacak ama bizim TCP’ye dair pek bilgi sahibi olmamız gerekmiyor. (TCP’nin haricinde UDP diye bir şey de var, merak edenler için)

Bir makineyi IP protokolü ile bulup aradaki iletişimi sağladıktan sonra TCP ile belirli bir “port”una erişmek isteriz. “Port” bir bilgisayarın birden fazla konuda hizmet verebilmesi için icat edilmiş TCP’ye dair bir kavram. Her port numarası genel olarak bir protokolle ilişkilendirilmiştir. Boşta olan veya sizin açınızdan önemsiz olan protokollerin numaralarını serbestçe kullanabilirsiniz, kimse kızmaz.

Bu port numaraları ayrımı olmasa, aynı bilgisayar hem web sunucusu, hem mail sunucusu, hem DNS sunucusu olamazdı. Olabiliyor, dolayısı ile teşekkürler TCP.

Devam etmeden önce, eğer ki projemiz birden fazla makinede çalışacak kadar büyürse tanışmak zorunda kalacağımız bir kavramın adını söyleyeyim: Network Load Balancer. Basitçe gelen istekleri birden fazla makineye, yük dağılımının eşit olmasını gözeterek dağıtan bir sistem. Girmiyorum, lazım olursa nasıl olsa mecburen öğreneceğiz. Ama bugün o gün değilse rahatız:)

(Hidayet Doğan arkadaşın eleştirisi doğrultusunda ufak bir ekleme yapayım: Ben burada özet yapayım derken bazı şeyleri eksik bıraktım. Port aslında bir transport layer kavramı, sadece TCP’ye özel değil. UDP’de de portlar var mı, evet var:) Anlatmaya çalıştığım şey port kavramının paket yönlendirmesinden tamamen bağımsız ve daha yüksek seviyeli olduğu, sadece multiplexing sağlamak için tasarlandığı. Yoksa TCP’nin adını bu makale dahilinde telafuz etmeye gerek yoktu, hatta keşke etmeseymişim.)

Dinlemeye Takılmak — Web Sunucusu

Bir bilgisayara bir TCP portundan istek geldiğinde “o portu dinleyen” bir uygulama bulunması gerekir. İşletim sistemi gelen isteği hiç ellemeden portu dinleyen uygulamaya yönlendirir, ki ilgili uygulama cevap verebilsin. Yoksa karşı tarafa sadece bir hata gider. Biz genellikle HTTP ve HTTPS portlarını dinlemek için bir web sunucusu uygulaması kullanırız.

Aslında yazacağımız kodun doğrudan HTTP portunu dinleyerek çalışmasını engelleyen bir şey yok. Ama bazı pratik sebeplerden ötürü gerçek hayatta %99 böyle olmadığını görürüz. Piyasanın en yaygın web sunucuları Nginx, Apache ve Microsoft IIS’dir.

Bir web sunucusu bize şu faydaları sağlar:

  • Birden fazla web projesini aynı makineden yayınlıyorsak bunlara gelen istekleri ilgili uygulamalara yönlendirir.
  • HTTPS kullanıyorsak bizim için güvenli iletişimi sağlar. Böylece güvenlikle ilgili kodu kendimiz yazmamış oluruz (Yazacak olsak kesin hacklenirdik, garanti.)
  • Web sitemizin sabit dosyalarına bir istek geldiğinde (örneğin resim dosyaları) bunları yayınlayabilir. Böylece sabit dosyaları yayınlamak için kendi kodumuzu işletmemiş oluruz (emin olun web sunucusunu yazanların kodu sizinkinden çok daha hızlı çalışıyor).

Dikkat ederseniz web sunucusu en fazla sabit dosyalarımız yayınlamaya kadar yardımcı olabiliyor. Sitemiz tamamen sabit dosyalardan ibaretse işimiz bitti demektir. Ama Eğer dinamik bir içeriğimiz varsa, yani gelen isteğe özel cevap üreteceksek, isteği uygulamamıza yönlendirmemiz gerekecektir.

Eğer işi büyütmeyi kafanıza koyduysanız uygulama katmanında sık üretilen cevapları önbellekleyip zaman kazanabilirsiniz. Bunun için bir Reverse Proxy Cache kullanabilirsiniz (Varnish vs.)

Fikir vermesi açısından ufak bir Nginx konfigürasyon dosyası:

server {
listen 80;
server_name alan-adi.com;
location /static {
root /home/www-data/alan-adi/;
}
location / {
include /etc/nginx/uwsgi_params;
uwsgi_pass unix:///home/www-data/alan-adi/alan-adi.sock;
}
}

Bu konfigürasyon 80 portundan alan-adi.com’a gelen istekleri /home/www-data/alan-adi/ dizinindeki siteye yönlendirir. Eğer istek /static dizinine ise doğrudan Nginx tarafından işlenir. /static haricine gelen istekler uWSGI uygulama sunucusuna aktarılır.

Uygulama Sunucusu

Web sunucuları uygulamanız ile bir kaç yolla iletişim kurabilir:

  • Özel Protokol: Uygulamanız FastCGI, WSGI gibi özel bir protokol ile çalışır, web sunucu aynı protokolü destekler, gelen istekle ile ilgili veri bu protokol ile aktarılır.
  • HTTP: Uygulamanız sadece yerel erişime açık bir TCP portundan HTTP isteklerini dinler, web server gelen isteği uygulamanıza doğrudan aktarır.
  • Plugin: Web sunucusunun bir plugin’i doğrudan projemizin kodunu işletir.

Bunlardan en performanslısı WSGI, FastCGI gibi bir protokol ve Unix soketleri kullanmaktır. Uygulamanızı bir Apache plugini ile işletmeyi ise hiç tavsiye etmiyorum.

Bunun yanında uygulamanızı nasıl başlatıp durduracağınız, patlarsa nasıl tekrar başlatacağınız, ne kadar RAM ayıracağınız, loglarını nereye yazacağınız gibi envai çeşit soru da mevcut. Birileri bu soruların cevabı olarak uygulama sunucularını keşfetmiş. Soğanımıza bir halka daha ekledik böylece.

Uygulama sunucuları genelde belirli bir dil veya web sunucusuna bağlıdırlar. Örnek olarak Python için uWSGI, PHP için PHP-FPM verilebilir. Windows sunucularda bu işlev IIS’e dahildir, eğer .NET yazıyorsanız tabi ki.

Bağımsız bir uygulama sunucusu kullanmak tamamen isteğe bağlı. Uygulamamızı başlatmanın başka yollarını da bulabilirsiniz. Ama kullandığımız dil, araçlar vb. için bir uygulama sunucusu varsa onu da kullanmakta fayda var. Böylece bellek, proses ve log yönetimi adına birçok tatlı dokunuşu emek vermeden edinmiş olursunuz. Kaçırmayın derim.

Uygulamanın Kendisi

Canımız, bir tanemiz Framework’ümüze geldik. Bütün bu saydığımız şeylerin üstüne bir tek URL yönlendirmesi ekledi, hepsinin üstüne bayrağı dikti. Meşhur oldu, fenomen oldu. Kimileri ona taraftar oldu. Oysaki tek bir HTTP isteğini cevaplayana kadar dökülen terin, gözyaşının yüzde birine bile ortak olmadı. İşte böylesine nankördür kendileri.

Dışarıdan bakan göz için uygulama kodunuz bir HTTP isteğini bir HTTP cevabına dönüştüren kapalı bir kutu. Hemen hemen her platformda standart HTTP sınıfları, metotları mevcut. İster bir web framework’ü kullanmış olun, ister olmayın; bundan sonrası hikayenin en çok anlatılmış kısmı. O yüzden soğanımızın bahsi geçen halkalarını sayarak bitiriyorum. Geçmeyenler de var mı? Evet var. Fiber optik kablolara, onu döşeyen işçi abilere kadar gidebilirdik. Umarım tadında bırakmışızdır.

Soğanın Halkaları

  • IP
  • DNS *
  • TCP
  • Firewall
  • Network Load Balancer **
  • Proxy Cache **
  • Web Sunucusu
  • Uygulama Sunucusu
  • Web Framework
  • Uygulama Kodu

* DNS’nin bu listede bulunması ve yeri tartışılabilir, biliyorum.
** Sadece görece büyük projelerde.

Türerkan İnce
turerkan@houseofapps.com

--

--