2014年9月11日RabbitMQ-RabbitMQtutorial-Remoteprocedurecall(RPC)
http://www.rabbitmq.com/tutorials/tutorial-six-python.html1/2
Wheretogethelp
Ifyou''rehavingtroublegoingthrough
thistutorialyoucancontact
usthroughthediscussionlistor
directly.
Remoteprocedurecall(RPC)
(usingthepika0.9.8Pythonclient)
InthesecondtutorialwelearnedhowtouseWork
Queuestodistributetime-consumingtasksamong
multipleworkers.
Butwhatifweneedtorunafunctiononaremote
computerandwaitfortheresult?Well,that''sa
differentstory.Thispatterniscommonlyknown
asRemoteProcedureCallorRPC.
Inthistutorialwe''regoingtouseRabbitMQtobuildanRPCsystem:aclientandascalableRPC
server.Aswedon''thaveanytime-consumingtasksthatareworthdistributing,we''regoingto
createadummyRPCservicethatreturnsFibonaccinumbers.
Clientinterface
ToillustratehowanRPCservicecouldbeusedwe''regoingtocreateasimpleclientclass.It''s
goingtoexposeamethodnamedcallwhichsendsanRPCrequestandblocksuntiltheansweris
received:
fibonacci_rpc=FibonacciRpcClient()
result=fibonacci_rpc.call(4)
print"fib(4)is%r"%(result,)
AnoteonRPC
AlthoughRPCisaprettycommonpatternincomputing,it''softencriticised.Theproblems
arisewhenaprogrammerisnotawarewhetherafunctioncallislocalorifit''saslowRPC.
Confusionslikethatresultinanunpredictablesystemandaddsunnecessarycomplexityto
debugging.Insteadofsimplifyingsoftware,misusedRPCcanresultinunmaintainable
spaghetticode.
Bearingthatinmind,considerthefollowingadvice:
Makesureit''sobviouswhichfunctioncallislocalandwhichisremote.
Documentyoursystem.Makethedependenciesbetweencomponentsclear.
Handleerrorcases.HowshouldtheclientreactwhentheRPCserverisdownforalong
time?
WhenindoubtavoidRPC.Ifyoucan,youshoulduseanasynchronouspipeline-insteadof
RPC-likeblocking,resultsareasynchronouslypushedtoanextcomputationstage.
Callbackqueue
IngeneraldoingRPCoverRabbitMQiseasy.Aclientsendsarequestmessageandaserverreplies
2014年9月11日RabbitMQ-RabbitMQtutorial-Remoteprocedurecall(RPC)
http://www.rabbitmq.com/tutorials/tutorial-six-python.html2/2
witharesponsemessage.Inordertoreceivearesponsetheclientneedstosenda''callback''
queueaddresswiththerequest.Let''stryit:
result=channel.queue_declare(exclusive=True)
callback_queue=result.method.queue
channel.basic_publish(exchange='''',
routing_key=''rpc_queue'',
properties=pika.BasicProperties(
reply_to=callback_queue,
),
body=request)
#...andsomecodetoreadaresponsemessagefromthecallback_queue...
Messageproperties
TheAMQPprotocolpredefinesasetof14propertiesthatgowithamessage.Mostofthe
propertiesarerarelyused,withtheexceptionofthefollowing:
delivery_mode:Marksamessageaspersistent(withavalueof2)ortransient(anyother
value).Youmayrememberthispropertyfromthesecondtutorial.
content_type:Usedtodescribethemime-typeoftheencoding.Forexamplefortheoften
usedJSONencodingitisagoodpracticetosetthispropertyto:application/json.
reply_to:Commonlyusedtonameacallbackqueue.
correlation_id:UsefultocorrelateRPCresponseswithrequests.
Correlationid
InthemethodpresentedabovewesuggestcreatingacallbackqueueforeveryRPCrequest.
That''sprettyinefficient,butfortunatelythereisabetterway-let''screateasinglecallback
queueperclient.
Thatraisesanewissue,havingreceivedaresponseinthatqueueit''snotcleartowhichrequest
theresponsebelongs.That''swhenthecorrelation_idpropertyisused.We''regoingtosetitto
auniquevalueforeveryrequest.Later,whenwereceiveamessageinthecallbackqueuewe''ll
lookatthisproperty,andbasedonthatwe''llbeabletomatcharesponsewitharequest.Ifwe
seeanunknowncorrelation_idvalue,wemaysafelydiscardthemessage-itdoesn''tbelongto
ourrequests.
Youmayask,whyshouldweignoreunknownmessagesinthecallbackqueue,ratherthanfailing
withanerror?It''sduetoapossibilityofaraceconditionontheserverside.Althoughunlikely,it
ispossiblethattheRPCserverwilldiejustaftersendingustheanswer,butbeforesendingan
acknowledgmentmessagefortherequest.Ifthathappens,therestartedRPCserverwillprocess
therequestagain.That''swhyontheclientwemusthandletheduplicateresponsesgracefully,
andtheRPCshouldide
|
|