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

用途によってはこんなんでも十分役に立つかな。マシンの数が少なくて、プロセッサを占有できることが前提だけど。