Gönderen: yuxel  Son güncelleme :2010-04-18 22:57:08 Sayaç : 165959

Thrift ile ölçeklenebilir Web

Bu belgede anlatılan tüm kodları http://github.com/yuxel/thrift-examples/ adresinden inceleyebilirsiniz.

Nedir?

Thrift, Facebook tarafından geliştirilen, C++, C# , Cocoa , Erlang , Haskell , Java, OCaml, Perl, PHP , Python, Ruby, Smalltalk dilleri ile istekler yapıp cevaplar alabileceğiniz bir RPC framework'üdür. Örneğin, PHP kodu içinde, PHP methodlarını kullanarak arka tarafta çalışan bir Python uygulamasına istek gönderip cevap alabilirsiniz.

Binary bir protokol kullandığı için SOAP gibi alternatiflerinden daha performanslı bir iletişim katmanı sunar.

Ayrıca en güzel özelliklerinden birisi de asenkron işlemlere izin veren yapısıdır.

 

Kullanım alanları

Thrift, desteklediği diller arasındaki esnek geçişlerle, bir dil ile karşılaştığımız kısıtları başka bir dil ile yazdığımız arka plan servislerinin çözmesine imkan veriyor. Örneğin, PHP'nin en zayıf olduğu multithread gerektiren bir işlem düşünün. 10 farklı veritabanından veri çekmeniz gerekiyor ve her verinin gelmesi 1'er saniye sürüyor. Tek thread üzerinden bu işlemi yapmanız 10*1 = 10 saniye sürecektir. Ama bu işlemi thread desteği daha iyi olan bir dil ile 10 thread'de paralel olarak 1 saniyede yapabiliriz. Thrift'i bu tip işlemler için kullanabilirsiniz.



Thrift aynı zamanda "oneway", yani asenkron işlemlere de izin vermektedir. Asenkron görevler ise zaman zaman çok işimize yarar. Örneğin, kullanıcının yüklediği bir resmi 10 farklı boyutta, üzerlerine filigran basark, 10 farklı sunucuya yedekleyerek ve bu yükleme işlemini belli yerlere e-posta atarak bildiren bir servisiniz olsun. Yaptığınız her optimizasyona rağmen de bu işlemin 10 saniye sürdüğünü düşünün. Böyle bir işlemde kullanıcı resmi gönderdikten sonra 10 saniye beklemek zorunda kalır. Ama aslında kullanıcının, resmi gönderdikten sonra ve belki resmin ilk kopyası bir sunucuya gönderildikten sonra beklemesine gerek yoktur. Diğer işlem arka planda çalışabilir. Thrift bu tip işlemler için askenkron işlem desteğini sunar.



 

Kurulum

http://www.yuxel.net/?module=my&id=12 adresinden Debian GNU/Linux için anlatımı bulabilirsiniz.

 

Tanımlama Dosyası

Thrift kod üretme araçları, tanımlama dosyalarını kullanarak yukarıda belirtilen diller ile ilgili dosyaları oluşturmanıza yardımcı olur. Bu dosya ile ilgili kodları implemente edeceğiniz PHP, Python, C++, Java interface'lerini oluşturabilirsiniz.



Tanımlama dosyalarında, http://wiki.apache.org/thrift/ThriftTypes adresinde belirtilen tiplerdeki verilerle, servis arayüzünüzü yazabilirsiniz.



 

Kod oluşturma

Yukarıda da bahsettiğim gibi, Thrift aslında bir "kod oluşturma kütüphanesi" olarak da tanımlanabilir. Hazırladığınız Thrift tanımlama dosyasından, istediğiniz dil ile sunucu ve istemci tarafını implemente edebileceğiniz kodları oluşturabilirsiniz.



 

Örnek Uygulama

Az laf çok kod :) Şimdi de basit bir Thrift servisi oluşturalım. Servisin 2 tane methodu olsun. Birinci method senkron olarak mevcut zamanı unix time stamp formatında geri döndürsün. İkinci method da alt tarafta çok uzun sürecek bir işlemi (örneğin bir resmin çeşitli boyutlarda 10 kopyasını oluşturup her birini farklı sunuculara upload eden, 10 saniye süren bir işlem) asenkron olarak yapsın. Bunu da bir PHP istemci(client) ve Python sunucu(server) ile yapsın.

 



Öncelikle bu servisi thrift dosyamızda hazırlamalıyız.

namespace php Example
service Example {
    string showCurrentTimestamp()
    oneway void asynchronousJob()
}



Bu dosyada Example  isimli bir servisimiz var. showCurrentTimestamp methodu string türünden bir veri dönüyor. asynchronousJob methodu da askenkron (oneway) olarak bir islem yapıyor.

Asenkron methodların bir veri döndürmeyeceğini unutmayın. Dolayısıyla her oneway method void türünden veri dönmelidir.



Bu dosyayı Example.thrift olarak kaydettikten sonra PHP ve Python arayüzlerini oluşturmalıyız.

thrift --gen php Example.thrift
thrift --gen py Example.thrift

Bu komutlardan sonra gen-php ve gen-py dizinleri içinde Example sınıfları oluşmuş olmalı.

Oluşturulan php dosyasında (gen-php/Example/Example.php) Example_types.php dosyasının "include_once" ile cagirildigi yolun dogru olduguna emin olun veya o satırı yorum satırı haline getirin.

Bundan sonra ise artık istemci ve sunucu kodlarımızı implemente etmemiz gerekiyor. Bir Python sunucu ve PHP istemci kod örneği görelim.

 PythonServer.py

#!/usr/bin/env python

port = 9090

import sys
# Burada gen-py dizininizi belirtin
sys.path.append('../gen-py')

import time

# Olusturulan dosyalari import et 
from Example import *
from Example.ttypes import *

# Thrift kutuphanesi
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer

# Burada sunucu implementasyonumuz basliyor
class ExampleHandler:
    # mevcut zamani donen
    def showCurrentTimestamp(self):
        timeStamp = time.time()
        return str(timeStamp)

    # sunucuda 10 saniye suren bir islem
    # asenkron olarak calisacak
    def asynchronousJob(self):
        print 'Burada sunucuda 10 saniye suren bir islem basliyor'
        time.sleep(10)
        print 'Ama istemci 10 saniye beklemiyor'


# Sunucuyu baslat
handler = ExampleHandler()

processor = Example.Processor(handler)
transport = TSocket.TServerSocket(port)
tfactory = TTransport.TBufferedTransportFactory()
pfactory = TBinaryProtocol.TBinaryProtocolFactory()


server = TServer.TThreadedServer(processor, transport, tfactory, pfactory)

print 'Sunucu baslatiliyor'
server.serve()


PhpClient.php

// Thrift kutuphanesi dosyalari 
$GLOBALS['THRIFT_ROOT'] = '../lib/';

require_once $GLOBALS['THRIFT_ROOT'].'/Thrift.php';
require_once $GLOBALS['THRIFT_ROOT'].'/protocol/TBinaryProtocol.php';
require_once $GLOBALS['THRIFT_ROOT'].'/transport/TSocket.php';
require_once $GLOBALS['THRIFT_ROOT'].'/transport/THttpClient.php';
require_once $GLOBALS['THRIFT_ROOT'].'/transport/TBufferedTransport.php';


// gen-php dizini
$GEN_DIR = '../gen-php';

// Example dosyalarimiz
require_once $GEN_DIR . '/Example/Example.php';
require_once $GEN_DIR . '/Example/Example_types.php';

// Baglanilacak sunucu host ve portu
$host = "localhost";
$port = 9090;


try {

     //Thrift baglantisi
     $socket = new TSocket( $host , $port );
     $transport = new TBufferedTransport($socket, 1024, 1024);
     $protocol = new TBinaryProtocol($transport);

     // Istemciyi baslat
     $client = new ExampleClient($protocol);
     $transport->open(); 

     // Sunucudan mevcut zamani al
     $currentTimeStamp = $client->showCurrentTimestamp();
     echo $currentTimeStamp;

     // Sunucuda 10 saniye surecek bir islemi asenkron olarak cagir
     $client->asynchronousJob();

    $transport->close();

} catch (TException $tx) {
    print 'Hata: '.$tx->getMessage()."n";
}

 



Simdi olusan Python ve PHP arayuzleri ile istemci ve sunucumuzu implemente ettik. python PythonServer.py komutu ile Python ile hazirladigimiz sunucuyu baslattiktan ve PhpClient.php dosyamizi tarayicimizla açtıktan sonra, ekranda mevcut zamanı göreceğiz ve askenkron isteğimizi sunucuya göndermiş olacağız.

 

 

 Kaynakça

http://wiki.apache.org/thrift/

Konular
Opera {39}
Müzik {70}
Qt {12}
Ben {122}
Debian {26}
Sinema {24}
php/web {44}
Link {58}
KDE {7}

[_lang_topics]


Takvim
<  Ocak 2018  >
PSÇPCCtPz
1234567
891011121314
15161718192021
22232425262728
293031


Temalar
xmas
yesilozAskerEdition
yellos
yesiloz
uira
yesilozHtml5
darksight
greeny
opera
default
dx

Es Dost
Altan
Tuğrul
Selçuk
Timu
Mehmet
Ünal
Gökhan
Koray Taylan
Yaşar
Özgür
Orhan
Kemali
Ahmet
Emrah
Kıvanç
BilgiFrekans
Bünyamin
Bedava Site

Gez Gör Arpacık
Opera Türkiye
Uira
Ma"Cess"teleri


Projeler
Beedon
sozluQ
qPod
SourPHP
Ekşigator
Ekşigator-qt
Soccer Madness