XML-RPC で簡易分散環境を構築する
大量のファイルを処理するタスクがあるので、めちゃ適当な分散システムを構築してみた。本当は SGE (Sun N1 Grid Engine) を使えばいいんだろうけど、使い方が悪いのかえらく遅くなったので。
で、普通はスケジューラデーモンが各マシンにタスクを割り振るんだろうけど、面倒なのでマスタサーバにキューを入れて、各マシンから polling するように。
サーバは Python の SimpleXMLRPCServer でさくっと。
#!/usr/bin/env python import sys import SimpleXMLRPCServer import optparse import Queue import socket _DEFAULT_HOST = socket.gethostname() _DEFAULT_PORT = 10010 parser = optparse.OptionParser() parser.add_option('--host', dest='host', default=_DEFAULT_HOST) parser.add_option('--port', dest='port', type='int', default=_DEFAULT_PORT) (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) queue = Queue.Queue() for line in sys.stdin: queue.put(line.rstrip()) server = SimpleXMLRPCServer.SimpleXMLRPCServer((options.host, options.port)) server.register_instance(queue) try: server.serve_forever() except KeyboardInterrupt: pass
キューを取り出すクライアントも xmlrpclib.ServerProxy でさくっとかける。
#!/usr/bin/env python import sys import optparse import xmlrpclib import socket _DEFAULT_HOST = socket.gethostname() _DEFAULT_PORT = 10010 parser = optparse.OptionParser() parser.add_option('--host', dest='host', default=_DEFAULT_HOST) parser.add_option('--port', dest='port', type='int', default=_DEFAULT_PORT) (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) url = "http://%s:%d/" % (options.host, options.port) server = xmlrpclib.ServerProxy(url) try: item = server.get(True, 1) print item except xmlrpclib.Fault, fault: print >>sys.stderr, "queue is empty" sys.exit(2)
で、キューを取り出して処理する shell script はこんなの。
#!/bin/bash host=$(hostname) port=10010 while getopts "h:p:" option; do case "$option" in h) host="$OPTARG" ;; p) port="$OPTARG" ;; esac done [ $OPTIND > 1 ] && shift $((OPTIND - 1)) while queue=$(./get_queue.py --host "$host" --port "$port"); do hogehoge $queue done
用途によってはこんなんでも十分役に立つかな。マシンの数が少なくて、プロセッサを占有できることが前提だけど。