Upgrade to Pro — share decks privately, control downloads, hide ads and more …

XML-RPC : Pythonが電池付属と呼ばれる理由

Avatar for Ransui Iso Ransui Iso
September 13, 2014

XML-RPC : Pythonが電池付属と呼ばれる理由

Avatar for Ransui Iso

Ransui Iso

September 13, 2014

Other Decks in Technology

Transcript

  1. Copyright (c) 2014 Ransui Iso, All rights reserved. XML-RPC Pythonが電池付属と呼ばれる理由

    2014-09-13 Python Conference JP 2014 Ransui Iso Strategic Technology Group / X-Listing Co, Ltd.
  2. Copyright (c) 2014 Ransui Iso, All rights reserved. おまえ誰よ? http://www.facebook.com/ransui

    @ransui Ransui Iso (磯 蘭水) Work at X-Listing Co, Ltd. http://www.xlisting.co.jp/ Pythonは1998年から使っています。E-Commerceエンジンやサーチエンジンの開 発、Zopeを用いたWebサイト開発、その他色々を経て、今はネット広告配信シス テムについての研究開発をしています。最近はCommon Lispでシステム開発をし ていますが、Pythonもヘビーに使っています。
  3. Copyright (c) 2014 Ransui Iso, All rights reserved. 有名どころ •

    Sun RPC – NFSの基盤として開発された – XDRという形式で情報をシリアライズする • なんとPython標準モジュールにでXDRを取り扱える – 現役で色々と使われている • その他にも – DCE/RPC – OMG CORBA – DCOM
  4. Copyright (c) 2014 Ransui Iso, All rights reserved. そも、RPCとは? •

    言語が提供する「呼び出し規約」を拡張する – 利用者はRPCをサポートする言語でプログラミングをす るとき、ほとんどRPCの存在を意識する必要がない。 Local Remote ham spam egg ham spam egg この時ローカルから result = spam(args) という感じでリモート のメソッドを呼び出せるということ
  5. Copyright (c) 2014 Ransui Iso, All rights reserved. Client もうすこし細かく見てみる

    • 魔法は存在しないのでタネがある – インタフェースの定義からStubライブラリを作成しそれ を利用することでリモート呼び出しの詳細を隠蔽する RPC Library IDL Client Stub Server RPC Library Server Stub IDL Compiler Application Code Server Code
  6. Copyright (c) 2014 Ransui Iso, All rights reserved. メッセージ形式がXMLなRPC •

    通信そのものはHTTPが使われることが多い – HTTPのbody部分に呼び出しや戻り値についての情報を XML形式で記述してメッセージとして交換する – 当然のことながらXMLの冗長性のおかげでオーバーヘッ ドが大きくてパフォーマンス的には不利 – バイナリプロトコルに対してHuman Readableだという 部分くらいしか利点が思いつかない……
  7. Copyright (c) 2014 Ransui Iso, All rights reserved. PythonでのXML-RPC •

    標準ライブラリにある – クライアント・サーバモデル – xmlrpc.servsr サーバ側 – xmlrpc.client クライアント側 • PurePythonによる実装 – cPythonが動く環境であればまずどこでも使える – 改造も簡単。色々できる。
  8. Copyright (c) 2014 Ransui Iso, All rights reserved. Hello World

    : Server側 • まずはサーバを準備 • SimpleXMLRPCServerを継承したクラスを作る • このクラスは通信担当で公開メソッドとかに関与しない import xmlrpc.server class HelloServer(xmlrpc.server.SimpleXMLRPCServer): allow_reuse_address = True request_queue_size = 1024 def __init__(self, *args, **kw): super().__init__(*args, **kw) import xmlrpc.server class HelloServer(xmlrpc.server.SimpleXMLRPCServer): allow_reuse_address = True request_queue_size = 1024 def __init__(self, *args, **kw): super().__init__(*args, **kw)
  9. Copyright (c) 2014 Ransui Iso, All rights reserved. Hello World

    : Server側 • 公開する機能を準備する • SimpleXMLRPCRequestHandlerを継承したクラスを作る • このクラス内で「メソッド名」と「機能」の対応を作る class HelloRequestHandler(xmlrpc.server.SimpleXMLRPCRequestHandler): def __init__(self, *args, **kw): super().__init__(*args, **kw) def _dispatch(self, method_name, args): return getattr(self, method_name)(*args) def greeting(self, name): return "Hello, %s" % name class HelloRequestHandler(xmlrpc.server.SimpleXMLRPCRequestHandler): def __init__(self, *args, **kw): super().__init__(*args, **kw) def _dispatch(self, method_name, args): return getattr(self, method_name)(*args) def greeting(self, name): return "Hello, %s" % name
  10. Copyright (c) 2014 Ransui Iso, All rights reserved. Hello World

    : Server側 • 組み合わせてサーバとして起動する • サーバクラスとハンドラクラスのインスタンスを作成して組み 合わせる。その後、サーバインスタンスのループを開始。 def main(): server = HelloServer(("127.0.0.1", 9999), requestHandler=HelloRequestHandler, logRequests=None, allow_none=True) server.serve_forever() def main(): server = HelloServer(("127.0.0.1", 9999), requestHandler=HelloRequestHandler, logRequests=None, allow_none=True) server.serve_forever()
  11. Copyright (c) 2014 Ransui Iso, All rights reserved. Hello World

    : Client側 • ServerProxyクラスを使うだけ • サーバ側に比べてとっても簡単 import xmlrpc.client def main(): proxy = xmlrpc.client.ServerProxy("http://127.0.0.1:9999/", allow_none=True) print(proxy.greeting("spam")) import xmlrpc.client def main(): proxy = xmlrpc.client.ServerProxy("http://127.0.0.1:9999/", allow_none=True) print(proxy.greeting("spam"))
  12. Copyright (c) 2014 Ransui Iso, All rights reserved. ServerとClient分離問題 •

    見通しの悪さを改善する – サーバもクライアントも1つのモジュールをimportする – 下のような状態を維持しやすくする ServiceClient RequestHandler ham spam egg ham spam egg
  13. Copyright (c) 2014 Ransui Iso, All rights reserved. もっと結合性を上げる •

    Pythonの動的な性質をもっと使う – MetaClassを使うなどして、サービスの定義を行うとと 自動的にStubが生成されるようにして、コードはそれを 継承して書くとかする Client RPC Library Service Definition Client Stub Server RPC Library Server Stub Metaclass Application Code Server Code
  14. Copyright (c) 2014 Ransui Iso, All rights reserved. サーバのスレッド化 •

    簡単にスレッド化ができる – SimpleXMLRPCServerはSocketServerを利用して構築 されていることを利用する。 import xmlrpc.server import socketserver class HelloServer(Socketserver.ThreadingMixIn, xmlrpc.server.SimpleXMLRPCServer): allow_reuse_address = True request_queue_size = 1024 def __init__(self, *args, **kw): super().__init__(*args, **kw) import xmlrpc.server import socketserver class HelloServer(Socketserver.ThreadingMixIn, xmlrpc.server.SimpleXMLRPCServer): allow_reuse_address = True request_queue_size = 1024 def __init__(self, *args, **kw): super().__init__(*args, **kw)
  15. Copyright (c) 2014 Ransui Iso, All rights reserved. 複雑なデータ •

    インスタンスとかの送受信 – デコレータ化すればもっとかっこよくできる import pickle from xmlrpc.client import Binary def encode_to_binary(target_object): return Binary(pickle.dumps(target_object, protocol=2)) def decode_from_binary(binary_image): return pickle.loads(binary_image.data) import pickle from xmlrpc.client import Binary def encode_to_binary(target_object): return Binary(pickle.dumps(target_object, protocol=2)) def decode_from_binary(binary_image): return pickle.loads(binary_image.data) def server_side_method(self, args): return encode_to_binary(blahblah(decode_from_binay(args)) def client_side_method(self, args): result = decode_from_binary( self.proxy.server_side_method(encode_to_binary(args)) def server_side_method(self, args): return encode_to_binary(blahblah(decode_from_binay(args)) def client_side_method(self, args): result = decode_from_binary( self.proxy.server_side_method(encode_to_binary(args))
  16. Copyright (c) 2014 Ransui Iso, All rights reserved. Application Viewer

    Search MonkeypodTreeServer MonkeyPod ディレクトリ • データベースと検索に使用 Tree maintainer Get Node Get Review etc. SiteData Data Manage
  17. Copyright (c) 2014 Ransui Iso, All rights reserved. Application Rule

    Builer RuleEngine Stats / Report RuleServer ターゲティングルール • 広告配信のターゲティングルールの管理 Object Storage Create New Rule Get Rule Set Rule Storage File Remove Rule
  18. Copyright (c) 2014 Ransui Iso, All rights reserved. 使い所と注意 •

    ちょっとしたサービスが必要なときに – とにかくPythonがインストールされていれば使える – 変な設定ファイルとかサーバプロセスとかいらない – サービス側のコードを書く際に、お作法とか無いので何 でもやり放題 • 気をつけたいところ – pickleとか無節操に使うとPython縛りに – 真の意味でパフォーマンスが必要なときは使っちゃダメ
  19. Copyright (c) 2014 Ransui Iso, All rights reserved. Thank you

    for listening. Happy Hacking with Python!