30
gevent + protobuf = ab gevent + protobuf = ab u.rpc u.rpc 基基基基基 基基基基基 RPC RPC 基基 基基 赖赖赖 http://laiyonghao.com http://techparty.org 2011.5.14

abu.rpc intro

  • Upload
    -

  • View
    2.397

  • Download
    0

Embed Size (px)

Citation preview

Page 1: abu.rpc intro

gevent + protobuf = abu.rpcgevent + protobuf = abu.rpc基于协程的基于协程的 RPCRPC 实现实现

赖勇浩http://laiyonghao.com

http://techparty.org

2011.5.14

Page 2: abu.rpc intro

升级版

Page 3: abu.rpc intro

RPCRPC

Page 4: abu.rpc intro

RPC

• Remote Procedure Call

• Application level protocol

• TCP/UDP

• HTTP

Page 5: abu.rpc intro

abu.rpcabu.rpc

Page 6: abu.rpc intro

特性• 更小(得益于 google protobuf )• 更快(得益于 libevent )• 同步 API (利益于 greenlet )• 并行管线• 双向调用• TCP only

Page 7: abu.rpc intro

google protobufgoogle protobuf

Page 8: abu.rpc intro

Jeff Dean, Google fellow

• Protocol description language is a must.

• http://outerthought.org/blog/410-ot.html

Page 9: abu.rpc intro

google protobuf

• http://code.google.com/p/protobuf/

• 协议描述语言• C++ 、 java 、 Python and more

• service interface

Page 10: abu.rpc intro

Quick Example

message Person {

required int32 id = 1;

required string name = 2;

optional string email = 3;

}

Page 11: abu.rpc intro

Quick Example

person = Person()

person.id = 10

person.name = 'laiyonghao'

person.email = '[email protected]'

with open('person.data', 'wb') as f:

f.write(person.SerializeToString())

Page 12: abu.rpc intro

Quick Example

service SearchService {

rpc Search (SearchRequest) returns (SearchResponse);

}

Page 13: abu.rpc intro

geventgevent

Page 14: abu.rpc intro

greenlet + libeventgreenlet + libevent

Page 15: abu.rpc intro

greenlet

• green thread– user space– pseudo-concurrently– scheduled by VM– http://en.wikipedia.org/wiki/Green_threads

• Python 的 green thread

Page 16: abu.rpc intro

PEP 342

def echo_handler(sock): while True: try: data = yield nonblocking_read(sock) yield nonblocking_write(sock, data) except ConnectionLost: pass # exit normally if connection lost

Page 17: abu.rpc intro

libevent

• 提供指定文件描述符事件发生时调用回调函数的机制

• timeouts, signals

Page 18: abu.rpc intro

ExamplesExamples

Page 19: abu.rpc intro

echoecho

Page 20: abu.rpc intro

echo.proto

• message Packet{• required string text = 1;• }

• service EchoService{• rpc echo(Packet)returns(Packet);• }

Page 21: abu.rpc intro

s_echo.py

• @abu.rpc.check_service• class EchoService(echo.EchoService):• @abu.rpc.send_return• def echo(self, controller, request, done):• return request

• service = EchoService()• services = (service,)• server = abu.rpc.Server(('0.0.0.0', 10086), services)• print 'serving...'• server.serve_forever()

Page 22: abu.rpc intro

c_echo.py

• channel = abu.rpc.Channel(('127.0.0.1', 10086), ())• server = abu.rpc.Proxy(echo.EchoService_Stub(chann

el))

• for i in xrange(10):• req = echo.Packet()• req.text = 'hello'• print 'send:%s' % req.text• resp = server.EchoService.echo(req)• print 'recv:%s' % resp.text

Page 23: abu.rpc intro

chat roomchat room

Page 24: abu.rpc intro

chat.proto• message HelloReq{• required string name = 1;• }

• message HelloResp{• required string name = 1;• required bool succ = 2;• optional string info = 3;• }

• message ByeReq{• required string name = 1;• }

• message ByeResp{• required string name = 1;• required bool succ = 2;• optional string info = 3;• }

• message SayReq{• required string name = 1;• required string text = 2;• }

• message SayResp{• required string name = 1;• required bool succ = 2;• optional string info = 3;• }

Page 25: abu.rpc intro

• message Message{• required string name =

1;• required string text = 2;• }

• service ChatClientService{• rpc say(Message)retur

ns(abu.rpc.Void);• }

chat.proto

• service ChatServerService{• rpc hello(HelloReq)ret

urns(HelloResp);• rpc bye(ByeReq)return

s(ByeResp);• rpc say(SayReq)return

s(SayResp);• }

Page 26: abu.rpc intro

s_chat.py:ChatServerService.hello

• @abu.rpc.send_return• def hello(self, controller, request, done):• name = request.name• resp = chat.HelloResp()• resp.name = name• if name in self._clients:• resp.succ = False• resp.info = u' 用户名( %s )已经有人使用了。 ' %

name• return resp• self._clients[name] = Client(controller.socket)• resp.succ = True• return resp

Page 27: abu.rpc intro

s_chat.py:ChatServerService.say• @abu.rpc.send_return• def say(self, controller, request, done):• name = request.name• resp = chat.SayResp()• resp.name = name• if name not in self._clients:• resp.succ = False• resp.info = u' 无效的用户名( %s ) ' % name• return resp• msg = chat.Message()• msg.name = name• msg.text = request.text• for n, client in self._clients.iteritems():• client.proxy.ChatClientService.say(msg)• resp.succ = True• return resp

Page 28: abu.rpc intro

c_chat.py:ChatClientService.say

• @abu.rpc.check_service• class ChatClientService(chat.ChatClientService):• @abu.rpc.send_return• def say(self, controller, request, done):• print u'%s 说: %s' % (request.name, re

quest.text)• return

Page 29: abu.rpc intro
Page 30: abu.rpc intro

Thx~Thx~

twitter.com/laiyonghaoweibo.com/gzlaiyonghao