Forum: D Programlama Dili RSS
Unix domain socket örneği
Sayfa:  1  2  sonraki 
acehreli (Moderatör) #1
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Unix domain socket örneği
std.socket'teki olanaklar denenirken adres olarak UnixAddress kullanıldığında Unix domain sockets denen düzenekten yararlanılabiliyor. Ben de yeni öğrendim. Bu olanak, aynı bilgisayar üzerindeki programlar arasındaki iletişimi işletim sistemi çekirdeği üzerinden yaptırabildiği için TcpSocket ve InternetAddress kullanmaktan daha hızlı oluyor.

Unix domain socket dmd 2.064'ten önce çalışmıyordu. GitHub'daki aday 2.064 ile denediğimde çalıştığını görüyorum.

Aşağıdaki örnek program hem sunucu hem istemci olarak kullanılabiliyor:
import std.stdio;
import std.socket;
import std.getopt;
import std.string;
import std.range;
import std.concurrency;
import core.thread;
 
/* 'Unix doman socket'ler dosya sisteminde dosya olarak
 * beliriyorlarmış. Anladığım kadarıyla kullanıcının bu dosyayla doğrudan bir
 * işi olmuyor.
 *
 * Dosya isminin ilk karakterinin '\0' olması da en azından dosya isim
 * çakışmalarını önlüyormuş. Hatta, böyle isimdeki dosyaların remove() ile
 * silinmeleri de gerekmiyormuş.
 */
enum soketİsmi = "\0/tmp/deneme_soketi";
 
int main(string[] parametreler)
{
    // Sunucu rolünde mi olalım istemci mi
    enum Rol { sunucu, istemci }
    Rol rol;
 
    try {
        // Programın ismi dahil, iki parametre olmalı
        enforce(parametreler.length == 2);
 
        // Rol olamayacak değer geldiğinde hata atar
        getopt(parametreler, "rol", &rol);
 
    } catch {
        stderr.writefln("Kullanım:\n    %s --rol={sunucu|istemci}",
                        parametreler[0]);
        return 1;
    }
 
    final switch (rol) {
    case Rol.sunucu:  sunucuOl(soketİsmi); break;
    case Rol.istemci: istemciOl(soketİsmi); break;
    }
 
    return 0;
}
 
void sunucuOl(string soketİsmi)
{
    auto sunucu = Sunucu(soketİsmi);
    sunucu.hizmetEt();
}
 
void istemciOl(string soketİsmi)
{
    auto istemci = İstemci(soketİsmi);
    istemci.iste();
}
 
/* Bu sunucu her isteğe karşılık farklı bir işçi başlatır, istemcinin
 * bağlantısını ona devreder ve hiç vakit geçirmeden yeni istemci beklemeye
 * başlar.
 *
 * Bu tasarımda işçiler spawn ile başlatılıyorlar ve hemen
 * unutuluyorlar. Dolayısıyla, istemcinin yanıtını göndermek bütünüyle işçinin
 * görevi oluyor.
 */
struct Sunucu
{
    Socket dinleyici;
 
    this(string soketİsmi)
    {
        // Önce bağlantıları karşılayacak olan soketi hazırlıyoruz
        dinleyici = new Socket(AddressFamily.UNIX, SocketType.STREAM);
        auto adres = new UnixAddress(soketİsmi);
 
        dinleyici.bind(adres);
        dinleyici.listen(1);
    }
 
    ~this()
    {
        dinleyici.shutdown(SocketShutdown.BOTH);
        dinleyici.close();
        destroy(dinleyici);
        // Dosyanın silinmesinin gerekip gerekmediğinden aslında emin değilim:
        remove(soketİsmi.toStringz);
    }
 
    /* Sonsuz döngüde istemci bekler ve hiç zaman geçirmeden onun isteğini
     * yerine getirecek olan bir işçi başlatır. */
    void hizmetEt()
    {
        while (true) {
            // İstemci bekliyoruz
            writeln("Bekliyorum...");
 
            // Şimdi o sokette bağlantı kabul ediyoruz. Bu Socket nesnesinin
            // sahipliğini sunucuİşlev devralacak.
            Socket istemci = dinleyici.accept();
 
            writefln("İstemci bağlandı: %s", istemci.remoteAddress());
 
            /* Eş zamanlı işleyecek olan bir işçi başlatıyoruz ve hemen tekrar
             * beklemeye dönüyoruz. Burada işçi sayısında hiçbir kısıtlama
             * getirilmiyor. İstendiğinde başka tasarımlar da
             * düşünülebilir. */
            auto işçi = spawn(&sunucuİşçi, cast(shared)istemci);
        }
    }
}
 
/*
 * İstemcilere eş zamanlı olarak hizmet eden işlev. Parametre olarak bir
 * istemci alır ve ona hizmet eder. Bu tasarımda kendisini başlatan ana iş
 * parçacığı ile hiçbir iletişimi olmuyor. Yanıtını gönderdikten sonra hemen
 * sonlanıyor.
 */
void sunucuİşçi(shared(Socket) istemci_)
{
    /* Bu tasarımda istemcinin sorumluluğu bu işleve ait; çıkarken
     * sonlandıralım. */
    scope (exit) {
        destroy(istemci_);
    }
 
    /* std.concurrency modülü henüz shared ile tam uyumlu olarak
     * çalışmıyor. Şimdilik en iyisi parametreyi yukarıda yaptığımız gibi
     * shared olarak almak ve işlev içinde kullanmadan önce tür dönüşümü ile
     * shared'i kaldırmak: */
    auto istemci = cast()istemci_;
 
    string istek = istemci.tekParçaOlarakOku();
 
    enum saniye = 2;
    writefln("İsteği aldım. Yapay olarak %s saniye bekleyeceğim", saniye);
 
    foreach (i; saniye.iota) {
        Thread.sleep(1.seconds);
        writef(" .");
        stdout.flush();
    }
    writeln();
 
    enum başlık =
        "HTTP/1.0 200 OK\nContent-Type: text/html; charset=utf-8\n\n";
 
    string yanıt = başlık;
    yanıt ~= "<b>Merhaba Dünya!</b>\n";
 
    istemci.send(yanıt);
}
 
/* Socket.receive'in aksine, okunan parçaları birleştirir ve tek string olarak
 * döndürür. */
string tekParçaOlarakOku(Socket soket)
{
    string okunan;
 
    // Okunan veriyi parça parça bu belleğe alacağız
    ubyte[1000] parça;
    bool bütünVeriOkundu_mu = false;
 
    while (!bütünVeriOkundu_mu) {
        const adet = soket.receive(parça);
 
        if (adet == Socket.ERROR) {
            stderr.writeln("OKUMA HATASI");
            break;
        }
 
        okunan ~= parça[0..adet];
 
        bütünVeriOkundu_mu = (adet < parça.length);
    }
 
    return okunan;
}
 
struct İstemci
{
    Socket soket;
 
    this(string soketİsmi)
    {
        soket = new Socket(AddressFamily.UNIX, SocketType.STREAM);
        soket.connect(new UnixAddress(soketİsmi));
    }
 
    ~this()
    {
        soket.shutdown(SocketShutdown.BOTH);
        soket.close();
        destroy(soket);
    }
 
    void iste()
    {
        string mesaj = format("%s%s%s", "merhaba", 42, "dünya");
        const adet = soket.send(mesaj);
        writefln("%s bayt gönderdim", adet);
 
        string yanıt = soket.tekParçaOlarakOku();
        writefln("Yanıt aldım: %s", yanıt);
    }
}
Ali
darkofpain #2
Üye Ağu 2013 tarihinden beri · 58 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Çok teşekkürler acehreli,

Kodu baştan sona okudum inceledim ancak dikkatimi çeken birşey var port olarak hangi port üzerinden çalışıyor yoksa düşündüğüm gibi.

unix:/tmp/datalar şeklinde mi ?

Tabi benim düşüncem direk Ön tarafda Nginx/Apache gibi sunucu bulunarak kullanmak. :)

Yanlış bilgiye sahip değilsem FastCGI - uWSGI yazılımlarıda unix domain socket üzerinden veri alışverişi yapıyordu.
Bu mesaj darkofpain tarafından değiştirildi; zaman: 2013-09-17, 14:49.
acehreli (Moderatör) #3
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
batuhangoksu:
port olarak hangi port üzerinden çalışıyor yoksa düşündüğüm gibi.

unix:/tmp/datalar şeklinde mi ?

Ben bu konuyu çok yeni öğrendim ama evet, öyleymiş. Veri alış verişi dosya sisteminde beliren bir dosya üzerinden yapılıyor ama biz o alt düzey bilgiyle ilgilenmiyoruz. Yine de socket arayüzü ile send() ve receive() ile veri gönderiyoruz. Her şey çekirdek (kernel) üzerinden hızlıca gelişiyor.

unix domain socket üzerinden veri alışverişi yapıyordu.

Mantıklı. Herhalde Nginx'e hangi dosya isminin kullanılacağını bildirmek gerekiyordur. Ayar dosyalarında öyle bir yer olmalı. (?)

Ali
acehreli (Moderatör) #4
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yukarıda verdiğim örnek her istemci yanıtı için tek işçi başlatıyordu. O tek işçi bütün yanıtı kendisi adım adım oluşturuyor ve istemciye gönderiyordu. (Tabii örnekte "oluşturma" diye bir kavram yoktu; hep aynı sonucu alıyorduk.)

Eğer yanıtın kendisi birden fazla işçi tarafından aynı anda oluşturulabiliyorsa, o tek işçi kendisi başka alt işçiler başlatabilir. Aşağıdaki örnek bunu gösteriyor.

Yaptığım temel değişiklik, sunucuİşçi()'de. sunucuİşçi kendisi dört alt işçi başlatıyor ve istemcinin yanıtını dört işçiye aynı anda parça parça oluşturtuyor.
import std.stdio;
import std.socket;
import std.getopt;
import std.string;
import std.range;
import std.concurrency;
import core.thread;
import std.algorithm;
 
/* 'Unix doman socket'ler dosya sisteminde dosya olarak
 * beliriyorlarmış. Anladığım kadarıyla kullanıcının bu dosyayla doğrudan bir
 * işi olmuyor.
 *
 * Dosya isminin ilk karakterinin '\0' olması da en azından dosya isim
 * çakışmalarını önlüyormuş. Hatta, böyle isimdeki dosyaların remove() ile
 * silinmeleri de gerekmiyormuş.
 */
enum soketİsmi = "\0/tmp/deneme_soketi";
 
int main(string[] parametreler)
{
    // Sunucu rolünde mi olalım istemci mi
    enum Rol { sunucu, istemci }
    Rol rol;
 
    try {
        // Programın ismi dahil, iki parametre olmalı
        enforce(parametreler.length == 2);
 
        // Rol olamayacak değer geldiğinde hata atar
        getopt(parametreler, "rol", &rol);
 
    } catch {
        stderr.writefln("Kullanım:\n    %s --rol={sunucu|istemci}",
                        parametreler[0]);
        return 1;
    }
 
    final switch (rol) {
    case Rol.sunucu:  sunucuOl(soketİsmi); break;
    case Rol.istemci: istemciOl(soketİsmi); break;
    }
 
    return 0;
}
 
void sunucuOl(string soketİsmi)
{
    auto sunucu = Sunucu(soketİsmi);
    sunucu.hizmetEt();
}
 
void istemciOl(string soketİsmi)
{
    auto istemci = İstemci(soketİsmi);
    istemci.iste();
}
 
/* Bu sunucu her isteğe karşılık farklı bir işçi başlatır, istemcinin
 * bağlantısını ona devreder ve hiç vakit geçirmeden yeni istemci beklemeye
 * başlar.
 *
 * Bu tasarımda işçiler spawn ile başlatılıyorlar ve hemen
 * unutuluyorlar. Dolayısıyla, istemcinin yanıtını göndermek bütünüyle işçinin
 * görevi oluyor.
 */
struct Sunucu
{
    Socket dinleyici;
 
    this(string soketİsmi)
    {
        // Önce bağlantıları karşılayacak olan soketi hazırlıyoruz
        dinleyici = new Socket(AddressFamily.UNIX, SocketType.STREAM);
        auto adres = new UnixAddress(soketİsmi);
 
        dinleyici.bind(adres);
        dinleyici.listen(1);
    }
 
    ~this()
    {
        dinleyici.shutdown(SocketShutdown.BOTH);
        dinleyici.close();
        destroy(dinleyici);
        // Dosyanın silinmesinin gerekip gerekmediğinden aslında emin değilim:
        remove(soketİsmi.toStringz);
    }
 
    /* Sonsuz döngüde istemci bekler ve hiç zaman geçirmeden onun isteğini
     * yerine getirecek olan bir işçi başlatır. */
    void hizmetEt()
    {
        while (true) {
            // İstemci bekliyoruz
            writeln("Bekliyorum...");
 
            // Şimdi o sokette bağlantı kabul ediyoruz. Bu Socket nesnesinin
            // sahipliğini sunucuİşlev devralacak.
            Socket istemci = dinleyici.accept();
 
            writefln("İstemci bağlandı: %s", istemci.remoteAddress());
 
            /* Eş zamanlı işleyecek olan bir işçi başlatıyoruz ve hemen tekrar
             * beklemeye dönüyoruz. Burada işçi sayısında hiçbir kısıtlama
             * getirilmiyor. İstendiğinde başka tasarımlar da
             * düşünülebilir. */
            auto işçi = spawn(&sunucuİşçi, cast(shared)istemci);
        }
    }
}
 
/*
 * İstemcilere eş zamanlı olarak hizmet eden işlev. Parametre olarak bir
 * istemci alır ve ona hizmet eder. Bu tasarımda kendisini başlatan ana iş
 * parçacığı ile hiçbir iletişimi olmuyor. Yanıtını gönderdikten sonra hemen
 * sonlanıyor.
 */
void sunucuİşçi(shared(Socket) istemci_)
{
    /* Bu tasarımda istemcinin sorumluluğu bu işleve ait; çıkarken
     * sonlandıralım. */
    scope (exit) {
        destroy(istemci_);
    }
 
    /* std.concurrency modülü henüz shared ile tam uyumlu olarak
     * çalışmıyor. Şimdilik en iyisi parametreyi yukarıda yaptığımız gibi
     * shared olarak almak ve işlev içinde kullanmadan önce tür dönüşümü ile
     * shared'i kaldırmak: */
    auto istemci = cast()istemci_;
 
    string istek = istemci.tekParçaOlarakOku();
 
    /*
     * ...
     *
     * Burada isteği ayrıştırdığımızı ve tam olarak ne istendiğini
     * anladığımızı varsayalım.
     *
     * Ek olarak, bu isteğe karşılık gönderilecek olan yanıtın dört parçadan
     * oluştuğunu ve bu dört parçanın birbirlerinden bağımsız olarak
     * oluşturulabileceğini varsayalım. Örneğin, bu dört parçadan birisi veri
     * tabanına erişerek oluşturulabilir, bir başkası başka bir sunucudan
     * edinilecek olan bilgidir, vs.
     *
     * Bu parçalar birbirlerinden bağımsız olduklarından onları eş zamanlı
     * olarak dört alt işçiye oluşturabiliriz. Görevleri dağıttıktan sonra
     * bize kalan, sonuçları beklemek ve yanıtı oluşturmaktır.
     *
     * ...
     */
 
    string[4] parçalar;
 
    /* Bu örnek görevleri başlatırken her işçiye isteğin tamamını
     * gönderiyor. Onun yerine istekten ayrıştırılmış olan bilgiler de
     * gönderilebilir. */
    spawn(&başlıkHazırlayıcı, istek, 0U);
    spawn(&veriTabanındanBirŞeylerToplayıcı, istek, 1U);
    spawn(&birSunucuİleKonuşucu, istek, 2U);
    /* Farklı parametreli bir örnek olsun diye buna fazladan bir bilgi daha
     * gönderelim. */
    spawn(&birHesapYapıcı, istek, 3U, "fazladan biraz daha bilgi", 1.5, "vs.");
 
    /* Bu yerel işlev bütün parçaların hazır olup olmadığını bildirir. */
    bool bütünParçalarHazır_mı()
    {
        return !parçalar[].canFind!(parça => parça.empty);
    }
 
    /* Şimdi sonuçların gelmelerini bekliyoruz. */
    while (!bütünParçalarHazır_mı()) {
        /* İşçilerden sonuç bekliyoruz. Her işçi, parça numarasından ve
         * sonuçtan oluşan bir çokuzlu gönderiyor. Her sonucu 'parçalar'
         * dizisinde ait olduğu yere yerleştireceğiz. */
        auto işSonucu = receiveOnly!(size_t, string)();
        auto parçaNumarası = işSonucu[0];
        auto parça = işSonucu[1];
 
        /* Daha önceden aldığımız bir sonucu almadığımızı denetleyelim. */
        assert(parçalar[parçaNumarası].empty);
 
        /* Parçayı yerine yerleştirelim. */
        parçalar[parçaNumarası] = parça;
    }
 
    /* while sonlandığına göre bütün parçalar hazır. Sonucu oluşturalım. */
    string yanıt;
    foreach (parça; parçalar) {
        yanıt ~= parça;
    }
    istemci.send(yanıt);
}
 
void başlıkHazırlayıcı(string istek, size_t parçaNumarası)
{
    ownerTid.send(
        parçaNumarası,
        "HTTP/1.0 200 OK\nContent-Type: text/html; charset=utf-8\n\n");
}
 
void veriTabanındanBirŞeylerToplayıcı(string istek, size_t parçaNumarası)
{
    string veriler = "<p>veri tabanından bir şeyler toplamış olalım</p>";
    ownerTid.send(parçaNumarası, veriler);
}
 
void birSunucuİleKonuşucu(string istek, size_t parçaNumarası)
{
    string sunucudanGelenVeri = "<p>bunu da bir sunucudan edinmiş olalım</p>";
    ownerTid.send(parçaNumarası, sunucudanGelenVeri);
}
 
void birHesapYapıcı(string istek,
                    size_t parçaNumarası,
                    string fazladanKullanacağımızBirParametre,
                    double başkaBirParametre,
                    string dahaBaşkaBirParametre)
{
    auto sonuç = fazladanKullanacağımızBirParametre.length
                 + başkaBirParametre
                 + dahaBaşkaBirParametre.length;
    string hesapSonucu =
        format("<p>şöyle bir değer hesaplamış olalım: %s</p>", sonuç);
    ownerTid.send(parçaNumarası, hesapSonucu);
}
 
/* Socket.receive'in aksine, okunan parçaları birleştirir ve tek string olarak
 * döndürür. */
string tekParçaOlarakOku(Socket soket)
{
    string okunan;
 
    // Okunan veriyi parça parça bu belleğe alacağız
    ubyte[1000] parça;
    bool bütünVeriOkundu_mu = false;
 
    while (!bütünVeriOkundu_mu) {
        const adet = soket.receive(parça);
 
        if (adet == Socket.ERROR) {
            stderr.writeln("OKUMA HATASI");
            break;
        }
 
        okunan ~= parça[0..adet];
 
        bütünVeriOkundu_mu = (adet < parça.length);
    }
 
    return okunan;
}
 
struct İstemci
{
    Socket soket;
 
    this(string soketİsmi)
    {
        soket = new Socket(AddressFamily.UNIX, SocketType.STREAM);
        soket.connect(new UnixAddress(soketİsmi));
    }
 
    ~this()
    {
        soket.shutdown(SocketShutdown.BOTH);
        soket.close();
        destroy(soket);
    }
 
    void iste()
    {
        string mesaj = format("%s%s%s", "merhaba", 42, "dünya");
        const adet = soket.send(mesaj);
        writefln("%s bayt gönderdim", adet);
 
        string yanıt = soket.tekParçaOlarakOku();
        writefln("Yanıt aldım: %s", yanıt);
    }
}
Ali
darkofpain #5
Üye Ağu 2013 tarihinden beri · 58 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
teşekkürler şimdi uwsgi nginx ile yapılandırmasına baktığım zaman unix socket üzerinden veri alışverişi yaptığını anlayabiliyoruz ve ayarlaması şu şekilde.

http {
  uwsgi_cache_path   /path/to/cache  levels=1:2
                       keys_zone=NAME:10m
                       inactive=5m;
 
  server {
    location / {
      uwsgi_pass          unix:/var/run/example.com.sock;
      uwsgi_cache         NAME;
      uwsgi_cache_key     $host$request_uri;
      uwsgi_cache_valid   200 302  1h;
      uwsgi_cache_valid   301      1d;
      uwsgi_cache_valid   any      1m;
      uwsgi_cache_min_uses  1;
      uwsgi_cache_use_stale error  timeout invalid_header http_500;
    }
  }
}

klasik unix socket için yapılandırma yanlış öğrenmediysem şu şekilde.

upstream backend  {
  server backend1.example.com weight=5;
  server backend2.example.com:8080;
  server unix:/tmp/backend3;
}
 
server {
  location / {
    proxy_pass  http://backend;
  }
}

sanırım verdiğiniz örnek ile önünde Nginx olduğu zaman harika bir performans elde edilebilir diye düşünüyorum.

Yaptığınız örnekte birtane hata var port üzerinden okuma yapmıyor buda şöyle sorun teşkil eder 1 tane ön tarafta duran Nginx serverımız olsun ve gelen tüm istekleri karışlasın ve gelen istekleri sunuculara dağıtmak istediği zaman şöyle olacaktır.

upstream cluster {
     server 127.0.0.1:9001;
     server 192.168.100.101:9001;
     server 192.168.100.102:9001;
     server 192.168.100.103:9001;
     server 192.168.100.104:9001;
}

bu sunucularda uygulamamız hazır bekliyor olacak ve bu adreslere istekler gittikçe görevini yapacak ancak yaptığınız uygulamada ölçeklenebilirlik yok ve nginx ile daha test edemedim Github üzerinden phobosun son halini indirip yükledim ama hata veriyor çözemedim bir türlü.

birde sizden ricam unix socket olayını en basit hali saf hali ile kullanımı hakkında bilgi vermeniz bu örnek baya detaylı çünkü
Bu mesaj 2 defa değişti; son değiştiren: darkofpain; zaman: 2013-09-18, 05:34.
acehreli (Moderatör) #6
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
batuhangoksu:
örnekte birtane hata var port üzerinden okuma yapmıyor

Unix domain sockets'te port olmadığını yazmamış mıyım? O yüzden hata diyemeyiz herhalde.

gelen istekleri sunuculara dağıtmak istediği zaman

Kusura bakma, herhalde üzerinden hızlıca geçmişim ama Unix doman sockets aynı bilgisayar üzerinde çalışan programların haberleşmeleri için. (Daha doğru olarak, aynı işletim sistemi üzerinde çalışan.)

Eğer Nginx sunuculardan farklı bilgisayardaysa tabii ki TcpSocket ve InternetAddress kullanmak gerekecek.

Ali
darkofpain #7
Üye Ağu 2013 tarihinden beri · 58 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
ozaman şöyle anlıyorum.

unix socket sunucular sadece var oldukları bilgisayar içinde bir birleri ile iletişim kurarlar doğrumu ?. Mesela chat uygulamalarını ele alırsak böyle bir uygulama için Unix Socket kullanmak doğru olmayacaktır.

Ama Sunucular arasında dağıtım yapmak istediğimiz de şöyle yapabiliriz ozaman,

(Ana Bilgisayar Nginx) -> (1. Bilgisayar Nginx ile birlikte Unix Socket 192.158.2.1:8080)
                               -> (1. Bilgisayar Nginx ile birlikte Unix Socket 192.158.2.20:8080)
                               -> (1. Bilgisayar Nginx ile birlikte Unix Socket 192.158.2.30:8080)

Gibi dağıtım yapabiliriz yani gelen istekleri nginx karşılayacak hep unix socket üzerinden bize paslayacak bizde işlemleri yapıp sonucu nginxe vereceğz oda yayınlayacak.

Bu mantık doğru ise zaten gelen yükün en büyüğünü Nginx alıyor resimleri javascriptleri filan hep Nginx yüklüyor aktarıyor biz sadece saf html cıktısını üretip Nginx tarafına paslıcaz.

Ozaman Nginx ile unix socket yapılandırması yapmak kalıyor geriye.

Ama Nasıl.... :)
Bu mesaj darkofpain tarafından değiştirildi; zaman: 2013-09-18, 08:38.
acehreli (Moderatör) #8
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
batuhangoksu:
unix socket sunucular sadece var oldukları bilgisayar içinde bir birleri ile iletişim kurarlar doğrumu ?

Evet ama o tür bağlantının adı Unix domain socket.

Mesela chat uygulamalarını ele alırsak böyle bir uygulama için Unix Socket kullanmak doğru olmayacaktır.

Doğru. İnternet üzerinden bağlanmak istiyorsak TCP bağlantısı iyi olur. (UDP de olur.)

Gibi dağıtım yapabiliriz yani gelen istekleri nginx karşılayacak hep unix socket üzerinden bize paslayacak

Hayır, öyle değil. Burada şu cümleyi anlamak şart: Unix domain socket, aynı bilgisayar üzerinde çalışan programların haberleşmeleri için.

Söylemek istenen şu: Nginx 192.168.1.1 üzerinde ve benim ona yardım eden sunucu programım da 192.168.1.1 üzerinde. Anlaştık mı? Aynı bilgisayar...

bizde işlemleri yapıp sonucu nginxe vereceğz oda yayınlayacak.

Bu durumda ilkemiz şu: Eğer işlemleri yapan programın Nginx ile aynı bilgisayardaysa Unix domain socket kullan, değilse TCP socket kullan.

Bu mantık doğru ise zaten gelen yükün en büyüğünü Nginx alıyor resimleri javascriptleri filan hep Nginx yüklüyor aktarıyor biz sadece saf html cıktısını üretip Nginx tarafına paslıcaz.

Nginx ile deneyimim yok ama gelen yükün büyüğü sayfasına göre değişir. Eğer sayfaya yerleşecek bir bilgi uzun hesaplar gerektiriyorsa o zaman gelen yükün büyüğü bizim programa aittir.

Ozaman Nginx ile unix socket yapılandırması yapmak kalıyor geriye.

Eğer senin program Nginx ile aynı bilgisayardaysa öyle olsun, değilse öyle olmasın. ;)

Ali
darkofpain #9
Üye Ağu 2013 tarihinden beri · 58 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
evet benimde anlatmak istediğim buydu aslında yani

her ip ye ait bilgisayar içinde Nginx de var Unix Socket uygulamasıda yani Nginx ile Unix socket aynı bilgisayar içinde haberleşicekler böylece Nginx gelen istekleri okuyacak ve gerekli olanları unix socket üzerinden bize pas edecek böylece her ikiside güzelce arkadaşca işlemlerini yapacaklar.

bir sorum olacak Mac OSX üzerinde dmd2 kullanıyorum Github üzerinden phobosun son sürümünü indirip dmd klasöründeki lib klasöründeki phobos klasörüne yükledim kütüphaneleri.

indirdiğim adres: https://github.com/D-Programming-Language/phobos

ancak mesala yaptığınız unix socket uygulamasını derlemek istediğimde böyle hatalar diziyor ekrana.

Ben doğru yaptımda kütüphane demi sıkıntı var ben mi yanlış yaptım acaba ?

/usr/local/dmd2/lib/phobos/std/utf.d(1113): Error: found '.' when expecting ';' following return statement
/usr/local/dmd2/lib/phobos/std/utf.d(1225): Error: found '.' when expecting ';' following return statement
/usr/local/dmd2/lib/phobos/std/utf.d(1226): Error: found 'else' instead of statement
/usr/local/dmd2/lib/phobos/std/utf.d(1279): Error: found '.' when expecting ';' following throw statement
/usr/local/dmd2/lib/phobos/std/utf.d(1285): Error: found '.' when expecting ';' following throw statement
/usr/local/dmd2/lib/phobos/std/utf.d(1562): Error: found '.' when expecting ';' following throw statement
/usr/local/dmd2/lib/phobos/std/utf.d(1581): Error: found '.' when expecting ';' following throw statement
/usr/local/dmd2/lib/phobos/std/utf.d(1617): Error: found '.' when expecting ';' following throw statement
/usr/local/dmd2/lib/phobos/std/utf.d(1632): Error: found '.' when expecting ';' following throw statement
/usr/local/dmd2/lib/phobos/std/utf.d(1688): Error: found '.' when expecting ';' following throw statement
/usr/local/dmd2/lib/phobos/std/utf.d(1708): Error: found '.' when expecting ';' following throw statement
/usr/local/dmd2/lib/phobos/std/utf.d(1771): Error: found '.' when expecting ';' following throw statement
/usr/local/dmd2/lib/phobos/std/utf.d(1788): Error: found '.' when expecting ';' following throw statement
/usr/local/dmd2/lib/phobos/std/utf.d(1820): Error: found '.' when expecting ';' following throw statement
/usr/local/dmd2/lib/phobos/std/regex.d(6048): Error: unexpected ( in declarator
/usr/local/dmd2/lib/phobos/std/regex.d(6048): Error: basic type expected, not alias
/usr/local/dmd2/lib/phobos/std/regex.d(6048): Error: found 'alias' when expecting ')'
/usr/local/dmd2/lib/phobos/std/regex.d(6048): Error: no identifier for declarator isReplaceFunctor(int)
/usr/local/dmd2/lib/phobos/std/regex.d(6048): Error: semicolon expected following function declaration
/usr/local/dmd2/lib/phobos/std/regex.d(6048): Error: no identifier for declarator fun
/usr/local/dmd2/lib/phobos/std/regex.d(6048): Error: semicolon expected, not ')'
Bu mesaj darkofpain tarafından değiştirildi; zaman: 2013-09-18, 12:19.
acehreli (Moderatör) #10
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Ben dmd ve arkadaşlarını GitHub'dan doğrudan alıp kurmadım hiç. Onun yerine şu projeyi öneririm:

  https://github.com/carlor/dlang-workspace

Hiç OSX'te denemedim ama orada açıklandığı gibi:

  • dmd, druntime, ve phobos'u ayrı ayrı bu projenin altına 'git clone' edin.

  • Herşeyi bash posix/gen.sh diye oluşturun. (Alt projeleri git pull yaptıktan sonra önce bash posix/gen.sh clean yapmanız hararetle önerilir.)

  • Oluşan dmd'nin adı dmd değil, wbd oluyor. Programınızı o komutla derleyin: wbd deneme.d gibi...

Ali
darkofpain #11
Üye Ağu 2013 tarihinden beri · 58 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
teşekkür ederim güzel bir dlang çalışma alanı oluşturma aracı ancak farkı nedir ?
acehreli (Moderatör) #12
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
darkofpain:
farkı nedir ?

Kolaylık. dmd, druntime, ve phobos üç farklı proje. Onları tek tek kendi Makefile'larıyla oluşturmak yerine tek bir ortamda hepsini birden oluşturuyoruz.

Ali
darkofpain #13
Üye Ağu 2013 tarihinden beri · 58 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
ufak bir araştırma sonucu bilgilendirme.

Nginx ile Unix Domain Socket kullanımını araştırırken şöyle bir yapılandırma ile karşılaştım.

upstream backend
{
    server backend2.example.com:8080;
    server unix:/tmp/backend3;
 
    server backup1.example.com:8080   backup;
    server backup2.example.com:8080   backup;
}
 
server
{
    location /
    {
        proxy_pass http://backend;
    }
}

Yapacağımız uygulamada TCP socket ile boğuşmak yerine güzelce Unix Domain Socket yapısı üzerine uygulamamızı yazarız.

Sonra uygulamanın çalışacağı makinaya Nginx kurup yapılandırmasını yaptığımız zaman yaptığımız uygulama Nginx uygulamasını bir uzantısı olarak çalışacaktır. Böylece ve performanslı bir yapı olacak hemde Cluster yapısı oluşturabiliriz.

Şöyle seneryo cizelim.

5 tane sunucumuz var. ve 5 tane ip adresimiz var.
Sunucularımız Nginx + Unix Socket Uygulamamızı kurduk yapılandırmalarını yaptık şuanda 5 sunucuda Nginx ile göreve hazır bekliyorlar.

Domain adresimizi birtane ip adresine yönlendirdik. Yönlendirdiğimiz ip adresinde sunucumuz hazır bekliyor daha sonra Nginx ile yaptığımız cluster yapısı ile 5 tane makina birbiri ile iletişim halinde gelen istekleri karşılıyor.

Böylece hem performanslı hemde ölçeklebilir yapı elde ederiz.

Bunun yanına güzel veritabanı yapısı ve cacheleme yaptığımız zaman kesinlikle yaslanın arkanıza bakın keyfinize :D

Daha detaylı bilgi için: http://tutarticle.com/linux/nginx-web-server-cluster/
Bu mesaj darkofpain tarafından değiştirildi; zaman: 2013-09-19, 03:11.
darkofpain #14
Üye Ağu 2013 tarihinden beri · 58 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
acehreli verdiğinizi örneği sonunda derledim derleme sırasında hata yok ancak çalıştırmak istediğimde hata veriyor.

./test --rol=sunucu olarak çalıştırmak istediğim zaman bu hatayı veriyor

std.socket.SocketOSException@std/socket.d(2495): Unable to bind socket: No such file or directory
----------------
5   test                                0x000000010f8caf68 ref test.Sunucu test.Sunucu.__ctor(immutable(char)[]) + 100
6   test                                0x000000010f8cae77 void test.sunucuOl(immutable(char)[]) + 51
7   test                                0x000000010f8cadc6 _Dmain + 250
8   test                                0x000000010f8ec331 extern (C) int rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).void runMainWithInit().void __lambda1() + 33
9   test                                0x000000010f8ebaa5 extern (C) int rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).void tryExec(scope void delegate()) + 45
10  test                                0x000000010f8ec2c4 extern (C) int rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).void runMainWithInit() + 52
11  test                                0x000000010f8ebaa5 extern (C) int rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).void tryExec(scope void delegate()) + 45
12  test                                0x000000010f8eba21 _d_run_main + 449
13  test                                0x000000010f8cae30 main + 20
14  test                                0x000000010f8cacc4 start + 52
15  ???                                 0x0000000000000002 0x0 + 2
----------------



./test --rol=istemci olarak çalıştırmak istediğim zaman bu hatayı veriyor

std.socket.SocketOSException@std/socket.d(2527): Unable to connect socket: No such file or directory
----------------
5   test                                0x00000001045bd3c8 ref test.İstemci test.İstemci.__ctor(immutable(char)[]) + 100
6   test                                0x00000001045bced7 void test.istemciOl(immutable(char)[]) + 51
7   test                                0x00000001045bcdde _Dmain + 274
8   test                                0x00000001045de331 extern (C) int rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).void runMainWithInit().void __lambda1() + 33
9   test                                0x00000001045ddaa5 extern (C) int rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).void tryExec(scope void delegate()) + 45
10  test                                0x00000001045de2c4 extern (C) int rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).void runMainWithInit() + 52
11  test                                0x00000001045ddaa5 extern (C) int rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).void tryExec(scope void delegate()) + 45
12  test                                0x00000001045dda21 _d_run_main + 449
13  test                                0x00000001045bce30 main + 20
14  test                                0x00000001045bccc4 start + 52
15  ???                                 0x0000000000000002 0x0 + 2
acehreli (Moderatör) #15
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Dosya ismiyle ilgili bir sorun gibi görünüyor. Ben olsam öncelikle dosya yolunun başındaki '\0' karakterini kaldırarak denerdim. Doğru hatırlıyorsam, '\0' yalnızca Linux'un bir olanağı olabilir.

Bir de, OS X'te /tmp klasörü var mı? Yani, dosya yolu geçerli olmalı...

Ali
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Sayfa:  1  2  sonraki 
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-11-18, 22:42:49 (UTC -08:00)