Duyuruyu Kapat
Facebook Gözat
Twitter Gözat

ddili ile socket okuma/veri gönderme ve "non-blocking i/o"

Konu, 'D Dili' kısmında netwalker tarafından paylaşıldı.

  1. netwalker

    netwalker Üye

    Kayıt:
    20 Kasım 2011
    Mesajlar:
    60
    Beğenilen Mesajlar:
    0
    Haklısınız önerilerinizi dikkate alıyorum düşünüyorum güzel bir şey olacak gibi geliyor acehreli ile yapacağız sanırım :) herkes içinde güzel örnek olabilir.

    son yaptığımız örnekte 10 saniye bekleme olayını kaldırıp siege ile http stress testi yaptım önüne nginx koydum şuanda nginx ile birlikte çalışarak bu sonuçları elde ettim.

    Kod:
    siege aborted due to excessive socket failure; you
    can change the failure threshold in $HOME/.siegerc
    
    
    Transactions:               33125 hits
    Availability:               96.84 %
    Elapsed time:              182.31 secs
    Data transferred:          846.80 MB
    Response time:                0.08 secs
    Transaction rate:          181.70 trans/sec
    Throughput:                4.64 MB/sec
    Concurrency:               13.75
    Successful transactions:       33125
    Failed transactions:            1082
    Longest transaction:           20.71
    Shortest transaction:            0.00
     
    FILE: /usr/local/var/siege.log
    You can disable this annoying message by editing
    the .siegerc file in your home directory; change
    the directive 'show-logfile' to false.
    
    ekte nginx access ve error log kayıtları var incelemek isterseniz diye ekledim.

    Eki Görüntüle 12534

    Şema (1)

    Eki Görüntüle 12535


    Şema (2)
    Eki Görüntüle 12536
     
  2. Atakan Erbaþ

    Atakan Erbaþ Aktif Üye

    Kayıt:
    11 Mayıs 2012
    Mesajlar:
    459
    Beğenilen Mesajlar:
    0
    Şehir:
    Bursa
    Netwalker, aslında kendin yazabilirsin. İlk şema işe yarar gibi gözüküyor.
     
  3. netwalker

    netwalker Üye

    Kayıt:
    20 Kasım 2011
    Mesajlar:
    60
    Beğenilen Mesajlar:
    0
    Haklısınız ama yetemedim. Denedim biraz elime yüzüme bulaştırdım :D
     
  4. Atakan Erbaþ

    Atakan Erbaþ Aktif Üye

    Kayıt:
    11 Mayıs 2012
    Mesajlar:
    459
    Beğenilen Mesajlar:
    0
    Şehir:
    Bursa
    Programı kafada kurabilmek en az yazmak kadar önemlidir bence. Ben işi hobi olarak yaptığım için kodlara rastgele dalarım, kurmam kafamda. Ama proje hafif büyüdüğü zaman problem oluyor. Çünkü kuracak çok şey oluyor ve ayrıntılara takılıyorken bütüne odaklanamıyorsun. Şahsen bir program yazarken en çok yaşadığım problem bu. Mesela "Bir program olsun portları dinlesin. Bir istemci bağlanınca bunu bir yapı dizinde tutsun. Sonra bir dosya yollasın." denirse bana kolay kolay yaparım. Ama iş karmaşıklaştığı zaman, o dizideki yapının elemanları arttıkça veya işi tümüyle kendim kurmam gerektiğinde iş karışıyor. Nereden başlayacağımı bilemiyorum. Bu becerinin nasıl kazanıldığını da bilmiyorum. Tahminimce tecrübe ile oluşuyor. O yüzden senin yazmanı tavsiye ettim. Fakat yapamadıysan sana yolunu gösterebilirim. Takıldığın özel bir yer var mı yoksa kafanda mı kuramadın?
     
  5. netwalker

    netwalker Üye

    Kayıt:
    20 Kasım 2011
    Mesajlar:
    60
    Beğenilen Mesajlar:
    0
    İlgi ve alakanız için Atakan sana ve acehreli'ye çok teşekkür ederim sonsuz minnet duyarım.

    Şimdi kafamdakini tam olarak sırası ile anlatim en altta şema cizdim onu resmide var.

    Aslında kısacası bu sistemin adı non-blocking i/o oluyor. Yapmak istediğim bu fikir var ancak koda dökemedim dökmek istedim elime yüzüme bulaştırdım.

    Bunu halledebilirsek gerisini getirebiliceğimi düşünüyorum nedir bunlar mesala; girilen sayfayı cachleyeceğim eyerki sayfada güncelleme yok ise direk cache üzerinden okuyacağım filan bir kaç şey var kafamda ancak önce yukarıdaki bahsettiklerimi yapabilmemiz lazım şahsen ben beceremedim.

    Şema.

    Eki Görüntüle 12545
     
  6. acehreli

    acehreli Ali Çehreli

    Kayıt:
    19 Ekim 2002
    Mesajlar:
    4,973
    Beğenilen Mesajlar:
    2
    O madde dışındakiler zaten örnek programda var. Havuz kavramı için de D'nin dizilerinden ve dilimlerinden yararlanabilirsin.

    Yukarıdaki örnek kod da non-blocking.

    Yukarıda bahsettiklerin arasından yalnızca havuz kavramı eksik. O kavramı da herhalde fazla istemci olmasın diye düşünüyorsun. Öyle bir kısıtlamayı spawn ile başlatılan işçi adedini kısıtlayarak başarabilirsin. Sayaçı her spawn'da bir arttır.

    Örnek programda eksik olan bir şey var: İşçiler sahiplerine "işim bitti" diye mesaj göndermiyorlar. Verseler, her işi biten için sayacını bir azaltırsın ve böylece havuz kavramını gerçekleştirmiş olursun.

    Şu bölüm çok yardımcı olacak:

    http://ddili.org/ders/d/es_zamanli.html

    İlgisiz olarak: netwalker, senin mesajının başında "Atakan Erbaş Demiş ki" diye başlayan bir bölüm var. Orada Atakan Erbaş hemen yukarıda yazdıklarının aynıları var. O kopya gereksiz.

    Ali
     
  7. Atakan Erbaþ

    Atakan Erbaþ Aktif Üye

    Kayıt:
    11 Mayıs 2012
    Mesajlar:
    459
    Beğenilen Mesajlar:
    0
    Şehir:
    Bursa
    Netwalker,
    1)Nginx'in sistemdeki işi nedir?
    2)Havuzdan kastın ne?
     
  8. netwalker

    netwalker Üye

    Kayıt:
    20 Kasım 2011
    Mesajlar:
    60
    Beğenilen Mesajlar:
    0
    Teşekkür ederim acehreli söylediklerinizde haklısınız; Bugün dinlenicem yarın üzerinde çalışıp buraya sonuçlarını yazıcağım. Başka önerileriniz varsa söyleyin lütfen.

    Atakan;

    1) Nginx sadece statik dosyaları okumak için ve proxy_pass etmek için geçiş kapısı yukarıdaki yaptığınız örnek sadece gelen istedeği okur sonuca göre datayı nginxe gönderir gerisini nginx halleder.
    3) her porta ait istek havuzu ve bu isteklerin işlendiği havuz belki orda mantığı yanlış kurmuş olabilirim.

    Önerilerin varsa söyle lütfen.
     
  9. Atakan Erbaþ

    Atakan Erbaþ Aktif Üye

    Kayıt:
    11 Mayıs 2012
    Mesajlar:
    459
    Beğenilen Mesajlar:
    0
    Şehir:
    Bursa
    Nginx konusunda epey bir cahil olduğum için malesef yapmak istediğini de anlayamıyorum. Nginx bir web sunucusu değil mi? "İstek" dediğin şeyler HTTP isteği gibi şeyler mi? "Statik dosya" derken kastettiğin html gibi dosyalar mı? Proxy pass ne demek :D
    Ayrıca select yerine epoll, poll veya kqueue kullanabilirsin. Select/Poll level triggered çalışır, epoll ise edge triggered çalışır. Çok istek varsa epoll daha avantajlıdır.
     
  10. netwalker

    netwalker Üye

    Kayıt:
    20 Kasım 2011
    Mesajlar:
    60
    Beğenilen Mesajlar:
    0
    Selam Atakan,

    Nginx bir http sunucusudur. Nginx Apache uygulamasına göre daha hızlıdır ve statik dosyalar (image,css,javascript,video,mp3 vs) dosyalarını daha hızlı okur. İstekler ise evet HTTP yani GET,POST istekleri. Proxy Pass olayı Apache uygulamasında nasıldır bilmiyorum ama Nginx'de şöyledir.

    Gelen istek örn(http://localhost/yenikonu/yaz) yada örn(http://localhost/yenikonu.html?islem=yaz) şeklinde olsun Nginx bu isteği belirlediğin IP:pORT adres(lerine) gönderir acehrelinin yaptığı uygulama zaten bu IP:pORT adresini dinliyor olacağı için Nginx üzerinden gelen datayı hemen okur ve sonucunda programın yaptığı işlemden çıkan datayı tekrar Nginx uygulamasına gönderir.

    Nginx uygulamasından gelen HTTP / GET bilgileri
    Kod:
    GET / HTTP/1.0
    Request: GET / HTTP/1.1
    X-Real-IP: 127.0.0.1
    X-Forwarded-For: 127.0.0.1
    Host: localhost
    Connection: close
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36
    Accept-Encoding: gzip,deflate,sdch
    Accept-Language: en-US,en;q=0.8
    
    Nginx uygulamasından gelen HTTP / POST bilgileri
    Kod:
    POST / HTTP/1.0
    Request: POST / HTTP/1.1
    X-Real-IP: 127.0.0.1
    X-Forwarded-For: 127.0.0.1
    Host: localhost
    Referer: http://localhost/
    Content-Type: application/x-www-form-urlencoded
    Connection: close
    Content-Length: 38
    Cache-Control: max-age=0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Origin: http://localhost
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36
    Accept-Encoding: gzip,deflate,sdch
    Accept-Language: en-US,en;q=0.8
    Post: test1=Baslik&test2=Tarih&test3=Aciklama
    
    Sonra şöyle bir seneryo ile programın çalıştığını farz edelim;

    Kullanıcı Yeni Konu düğmesine bastı gelen sayfada Başlık,Tarih,Açıklama bunların HTML tarafında input isimleri test1,test2,test3 'dür. Şimdi yukarıdaki kod bakalım orada ( Post: ) bilgisi yer alıyor. Örnek (test1=Baslik) diyor bu HTML tarafında test1 inputundan gelen Baslik isimli veri;
    Bizim program input içeriklerini alıyor veritabanına belirlediğimiz gibi yazıyor sonrasında ise işlem başarılı olduğunda biz Nginx tarafına şöyle bir data veriyoruz.

    Kod:
    HTTP/1.1 200 OK
    Content-Type: text/html; charset=utf-8
    Content-Length: 200
    -- standart html başlıkları (kodları) --
    <center><b>Yeni Konu Başarıyla Açılmıştır <a href="#">(Konuya gitmek için tıklayın)</a></b></center>
    
    
    Nginx uygulaması ile bizim uygulamamız belirlenen IP:pORT adresi üzerinden sürekli iletişim halindeler zaten. Yukarıdaki datayı bizim uygulamamız Nginx uygulamasına gönderiyor Nginx datayı alıp tarayıcıya yansıtıyor bizim uygulama üzerinden giden tek şey html datalarıdır.

    Nginx (image,css,javascript,video,mp3 vs) dosyalarını belirlediğimiz klasörden okuyarak işler.

    Nginx statik dosya yapılandırması. (hangi dosyaları static klasöründen okunacağı ise nginxe ait mime.type.conf dosyasında liste halinde mevcut)
    Kod:
    location /static/ {                autoindex on;    
                root   /users/netwalker/wwwroot/;    
             } 
    Nginx uygulamasının bize göndereği başlıklar yapılandırması.

    Kod:
    proxy_set_header  Request $request;            
    proxy_set_header  X-Real-IP $remote_addr;
    proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
    proxy_set_header  Host $http_host;
    proxy_set_header  Referer $http_referer;
    proxy_set_header  Content-Type $content_type;
    proxy_redirect off;
    proxy_pass http://127.0.0.1:8085;
    Olay budur benim yapmak istediğim ise sadece gelen isteklere cabuk okuyup / yazarak cabuk yanıt vermesi ve tıkanma olmaması (non-blocking).

    Tüm işleyiş bu şekilde yani Nginx üzerinde gelen istekleri IP:pORT adresine yönlendirme proxy_pass olarak geçiyor.
     
  11. Atakan Erbaþ

    Atakan Erbaþ Aktif Üye

    Kayıt:
    11 Mayıs 2012
    Mesajlar:
    459
    Beğenilen Mesajlar:
    0
    Şehir:
    Bursa
    Az çok anladım. Bu programı D'de soket programlamayı öğrenmek için mi yoksa işlevsel olarak kullanmak için mi yazıyorsun?
     
  12. netwalker

    netwalker Üye

    Kayıt:
    20 Kasım 2011
    Mesajlar:
    60
    Beğenilen Mesajlar:
    0
    Öncelikle soket programlamayı anlamak için sonra işlevsel olarak kullanabiliceğim bir yapı yapmak için.
     
  13. Atakan Erbaþ

    Atakan Erbaþ Aktif Üye

    Kayıt:
    11 Mayıs 2012
    Mesajlar:
    459
    Beğenilen Mesajlar:
    0
    Şehir:
    Bursa
    Eğer istek geldiği anda cevap verilecekse havuza gerek olmaz sanırım. Azami istek boyutu kadar bir tampon açarsın. İsteğe cevap verirsin ve aynı bölgeyi tekrar kullanırsın.
     
  14. netwalker

    netwalker Üye

    Kayıt:
    20 Kasım 2011
    Mesajlar:
    60
    Beğenilen Mesajlar:
    0
    Selam Atakan,

    Havuz dedim ama Tampon esasında o anda aklıma bir türlü gelmemişti ismi. Tampon olayı tam olarak nedir ?

    Şuanda acehreli örneği üzerinde çalışıyor geliştiriyorum ancak tek sıkıntım var nedense 1048 byte ve üzeri veri geldiği zaman çöküyor :/

    HTTP/1.1 502 0.06 secs: 1048 bytes ==> GET /
     
  15. Atakan Erbaþ

    Atakan Erbaþ Aktif Üye

    Kayıt:
    11 Mayıs 2012
    Mesajlar:
    459
    Beğenilen Mesajlar:
    0
    Şehir:
    Bursa
    Bir veri bölümü açarsın, gelen veri oraya yazarsın ve işlemini yaparsın. Her istemci için teker teker açmak çok masraflı olabilir, 1024 istemci ve 1024 bayttan hesap edersek durağan olarak açılmış bu alan yığıtta 1MB yer kaplar. Ama tek bir alan olursa 1 KB ile işi kapatabilirsin. Ama boyutu iyi ayarlamalı ve oluşabilecek sorunlara karşı hazırlıklı olmalısın. Bir isteğin kaplayacağı maksimum alan kadar olmalı tampon büyüklüğü. Ama şöyle bir olay da var, senin göndereceğin cevapları da bir yerde tutman gerekiyor. Ve bütün cevaplar aynı anda "gönderilemeyebilir" . Senin veya karşıdaki kişinin ağ tamponu dolarsa beklememelisin. O yüzden her istemci için bir dosya da açabilirsin. Veya yine tampon kullanabilirsin. D'yi bilmiyorum ama C'de send ve recv işlevleri okudukları kadar döner. Mesela bir dosyaya yazdın cevabı, bunu göndermek için send işlevini kullandın. Dosya boyutu 3000 bayt ama send 1000 byte gönderebildi. Senin bu değeri alıp bir dahaki sefere dosyanın kalan kısmını göndermen gerekir. Bunun için de her bağlantı için tuttuğun bir yapı olmalı. Ne kadar kaldığını, veya ne kadar okuyacağını anlaman için. Evet, okurken de aynı sorunla karşılaşabilirsin.
     
  16. acehreli

    acehreli Ali Çehreli

    Kayıt:
    19 Ekim 2002
    Mesajlar:
    4,973
    Beğenilen Mesajlar:
    2
    D'de de öyle ve ben de o yüzden örnekte receive()'in döndürdüğü değeri kullanmıştım. ;)

    Ama send()'in dönüş değerine bakmamışım. O da ayrıca Socket.ERROR döndürüyormuş:

    http://dlang.org/phobos/std_socket.html#.Socket.send

    netwalker, 'bellek' isimli diziye her adımda 1000 bayt okunuyordu. Sonra 'bellek'i 'istek'in sonuna ekliyorduk. Hatayı programın çöktüğü durumda o değişkenlerin durumunu filan yazdırarak bulabilirsin.

    Forum "--- Ekleme ---" yanlışlığına düşmesin diye ben netwalker'a başka bir yanıt yazayım:

    netwalker, nginx bilgileri için teşekkürler ama bu programın onunla doğrudan bir ilgisi yok, değil mi? Sonuçta biz belirli bir porttan gelen isteğe karşılık bir sonuç üretiyoruz. İsteğin nginx'ten, wget'ten, vs. gelip gelmemesi bu programı ilgilendirmiyor.

    Ali
     
  17. Atakan Erbaþ

    Atakan Erbaþ Aktif Üye

    Kayıt:
    11 Mayıs 2012
    Mesajlar:
    459
    Beğenilen Mesajlar:
    0
    Şehir:
    Bursa
    Ali Bey nginx'i ben sorduğum için yazdı. Aslında önemli bir ayrıntı olması gerekmez mi?
     
  18. acehreli

    acehreli Ali Çehreli

    Kayıt:
    19 Ekim 2002
    Mesajlar:
    4,973
    Beğenilen Mesajlar:
    2
    Ben de yanıtını ilgiyle okudum ve aydınlandım. :)

    Bence hayır. nginx bir protokol tanımlıyor: Belirli işlemleri kendim yapmayacağım; ayarladığınız sunucu ve porta istem göndereceğim ve yanıtını kullanacağım.

    Anlaşılan nginx özel HTTP başlıkları da kuruyor. O da tamam; istersek kullanırız...

    Ama o noktadan sonra bizim programımızın nginx ile işi kalmıyor. Biz porttan gelen isteğe yanıt yazıyoruz. Bizim işimiz o ve bence bu çok yararlı bir şey. Bizim işimizi basitleştiriyor.

    Ali
     
  19. netwalker

    netwalker Üye

    Kayıt:
    20 Kasım 2011
    Mesajlar:
    60
    Beğenilen Mesajlar:
    0
    Evet acehreli çok iyi anlamış biz Nginx bizimle ilgili olan bilgileri ip:port adresimize gönderiyor. Biz gelen istek sonucunda gereken işlemleri yapıyor sonra çıktıyı Nginxe veriyoruz gerisini Nginx hallediyor.

    Aslında tüm trafiği işlemleri Nginx hallediyor. Statik dosyalarına kadar Nginx üstleniyor bize düşen görev Nginx üzerinden bize gelen isteğe cevap vermektir okadar.

    Ayrıca acehrelini yaptığı program sadece Nginx ile değil Apache ile de çalışabilir isterseniz Lightpd yada Chrokee HTTP ile çalıştırabilirsiniz.
     
  20. Atakan Erbaþ

    Atakan Erbaþ Aktif Üye

    Kayıt:
    11 Mayıs 2012
    Mesajlar:
    459
    Beğenilen Mesajlar:
    0
    Şehir:
    Bursa
    Netwalker,
    hangi çözümde karar kıldın?