Monday, April 09, 2007

Thrift

Note:
ไปเจอจาก bookmark ของ bact' บน del.icio.us
น่าสนใจดี ตรงตามที่อยากได้
เลยชิงเขียนถึงก่อน

Thrift มีแนวคิดคล้ายๆ COBRA นั่นคือ เข้ามาช่วยเราในเรื่อง Distributed Application
แต่ไม่ over spec เหมือน COBRA
ตัวมันจะเล็กๆ เบาๆ กว่า

ที่ผมชอบก็คือ มันเปิดโอกาสให้ผม เชื่อม ruby, python, java, php
เข้าหากันในลักษณะ remote procedure call ได้

วิธีการใช้ ก็คือ เราต้องเขียน definition ของ interface, parameter ที่เราต้องการใช้ ด้วย syntax ของ Thrift เองก่อน
(แบบเดียวกับที่เราต้องเขียน IDL file ใน COBRA)
จากนั้นก็สามารถจะ generate stub สำหรับฝั่ง server หรือฝั่ง client
บนภาษาที่เราต้องการได้
โดยขณะนี้ Thrift support การ generate java,cpp,php,python,ruby

ลองดูตัวอย่าง
เริ่มด้วยการเขียน definition file
#!/usr/local/bin/thrift -cpp -java -py -php -rb -r

struct Address {
1: string province
2: string zipCode
}

struct Person {
1: i32 id,
2: string name,
3: Address address
}


service PersonService {
Person getById(1:i32 id),
void create(1:Person person)
}


ลอง implement server ด้วย java
public class MyServer implements PersonService.Iface {

static Hashtable<Integer, Person> map = new Hashtable<Integer, Person>();

public void create(Person person) throws TException {
map.put(person.id, person);
}

public Person getById(int id) throws TException {
return map.get(id);
}

public static void main(String[] args) throws TTransportException {
PersonService.Processor proc = new PersonService.Processor(new MyServer());
TServerSocket tss = new TServerSocket(9090);
TThreadPoolServer server = new TThreadPoolServer(proc, tss);
server.serve();
}
}


ลอง implement client ด้วย ruby
#! /usr/bin/env ruby

require 'thrift/transport/tsocket'
require 'thrift/protocol/tbinaryprotocol'

require 'PersonService'

transport = TBufferedTransport.new(TSocket.new('localhost',9090))
protocol = TBinaryProtocol.new(transport)
client = PersonService::Client.new(protocol)

transport.open()

p = Person.new
a = Address.new
a.zipCode = '10900'
a.province = 'Bangkok'
p.address = a
p.name = 'pok'
p.id = 1

client.create(p)

np = client.getById(1)
puts np.name
puts np.address.zipCode


สุดท้ายลอง implement client ด้วย python
#!/usr/bin/env python

import sys
sys.path.append('..')

from person import PersonService
from person.ttypes import *

from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol


transport = TSocket.TSocket('localhost',9090)
transport = TTransport.TBufferedTransport(transport)
protocol = TBinaryProtocol.TBinaryProtocol(transport)

client = PersonService.Client(protocol)

transport.open()

p = client.getById(1)
print p.name, p.address.zipCode

Related link from Roti

2 comments:

Anonymous said...

มันต่างกับ Web service ยังไงอ่ะครับ

PPhetra said...

ไม่ต่างกันนะ
แต่ชอบตัวนี้มากกว่า ตรงข้อจำกัดของ thrift
ที่ขีดวงไว้ชัดเจนแล้ว ว่าใช้อะไรได้ หรือไม่ได้
(เพราะมันเล็ก เลยรู้ขอบเขตได้ง่าย)