Debian + Nginx 0.7.x + mod_wsgi + pythonでthriftを動かす
Google App Engine(Python)でThriftを動作させるこれが上手くいったので、wsgiな環境なら、どんなサーバーでも動作可能なはず。
ということで、Nginx 0.7.x + mod_wsgiでthriftのサーバーを動かしてみました。
Nginx 0.7.xとmod_wsgiのモジュール取得
Nginx + WSGI + Pylons環境の構築方法
こちらを参考にしました。
Nginxのダウンロードは、以下のURLから行えます。
http://nginx.org/en/download.html
今回は、最新の安定版nginx-0.7.64を使用しました。
またmod_wsgiは、以下のURLからダウンロードできます。
http://hg.mperillo.ath.cx/nginx/mod_wsgi/archive/tip.tar.gz
必須ライブラリのインストール
ビルドには以下のライブラリが必要となるので、事前にインストールしておきます。
apt-get install gcc make libc6-dev python python-dev libpcre3-dev libssl-dev
ソースの展開と修正
/usr/local/srcにモジュールをダウンロードし、展開します。
# wget http://nginx.org/download/nginx-0.7.64.tar.gz
# wget http://hg.mperillo.ath.cx/nginx/mod_wsgi/archive/tip.tar.gz
# tar zxf nginx-0.7.64.tar.gz
# tar zxf mod_wsgi-8994b058d2db.tar.gz
# mv mod_wsgi-8994b058d2db mod_wsgi
mod_wsgiはしばらくメンテナンスされておらず、Nginx 0.5.xでのみビルドが通るようです。
Nginxの関数名がいくつか変更されているので、修正しておきます。
1.ngx_garbage_collector_temp_handlerという関数はNginx0.7で廃止されたようです。
※何に変更されたかまでは調べ切れていません・・・
wsgiのテンポラリ指定時に使用しているようで、wsgi_temp_pathというパラメータを
使用しなければ、削っても問題ないはず。(たぶん)
mod_wsgi/src/ngx_http_wsgi_module.cをエディタで開き、ngx_garbage_collector_temp_handlerを
使用している箇所をコメントしてしまいます。
■154行目
/*
{ ngx_string("wsgi_temp_path"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
ngx_conf_set_path_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_wsgi_loc_conf_t, temp_path),
(void *) ngx_garbage_collector_temp_handler },
*/
■345行目
/*
ngx_conf_merge_path_value(conf->temp_path,
prev->temp_path,
NGX_HTTP_WSGI_TEMP_PATH, 1, 2, 0,
ngx_garbage_collector_temp_handler, cf);
*/
2.ngx_http_discard_bodyという関数名は、0.6からngx_http_discard_request_bodyに
変更されています。
mod_wsgi/src/ngx_http_wsgi_handler.cを開き、関数名を修正します。
■74行目付近
if (r->method == NGX_HTTP_GET || r->method == NGX_HTTP_HEAD) {
/* XXX not sure */
/* rc = ngx_http_discard_body(r); */
rc = ngx_http_discard_request_body(r);
インストール
インストールはお決まりのcongifure,make,make installで実行します。
今回実行したのはこんな感じ。
※--add-module=/usr/local/src/mod_wsgi/で、mod_wsgiを有効にするのを忘れずに。
###実際は一行
# ./configure --add-module=/usr/local/src/mod_wsgi/ --sbin-path=/sbin/nginx
--conf-path=/usr/local/nginx/nginx.conf --pid-path=/usr/local/nginx/nginx.pid
--with-http_ssl_module --with-md5=auto/lib/md5 --with-sha1=auto/lib/sha1
Configuration summary
+ using system PCRE library
+ using system OpenSSL library
+ md5: using OpenSSL library
+ using sha1 library: auto/lib/sha1
+ using system zlib library
nginx path prefix: "/usr/local/nginx"
nginx binary file: "/sbin/nginx"
nginx configuration prefix: "/usr/local/nginx"
nginx configuration file: "/usr/local/nginx/nginx.conf"
nginx pid file: "/usr/local/nginx/nginx.pid"
nginx error log file: "/usr/local/nginx/logs/error.log"
nginx http access log file: "/usr/local/nginx/logs/access.log"
nginx http client request body temporary files: "client_body_temp"
nginx http proxy temporary files: "proxy_temp"
nginx http fastcgi temporary files: "fastcgi_temp"
# make
# make install
nginx.confの修正
まず、nginxに渡すパラメーターファイルをmod_wsgiのソースの中からコピーしておきます。
#mkdir /usr/local/nginx/conf
#cp /usr/local/src/mod_wsgi/conf/wsgi_vars /usr/local/nginx/conf/
次に、/usr/local/nginx/nginx.confを修正します。
■nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name sv01;
include conf/wsgi_vars;
location / {
root html;
index index.html index.htm;
}
location /thrift {
wsgi_pass /opt/thrift/nginx.py;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
設定ファイルのポイントは、
include conf/wsgi_vars;
の行を追加して、wsgiの設定を読み込む。
location /thriftの設定でサーバにhttp://server.com/thrift/とアクセスしたときに
/opt/thrift/nginx.pyのプログラムを実行する
という点でしょうか。
/opt/thrift/nginx.pyにサンプルプログラムを作成してみます。
サンプルプログラム
/opt/thrift/nginx.pyの内容はこんな感じになりました。
# -*- coding:utf-8 -*-
import cStringIO
#Thriftを使用するため、importを追加
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.transport import TIOStreamTransport
from sample import Calculator
from sample.ttypes import *
#Calculatorの実装
class CalculatorHandler:
def add(self, n1, n2):
return n1+n2
def application(environ, start_response):
handler = CalculatorHandler()
processor = Calculator.Processor(handler)
#自作したTIOStreamTransportをtransportとして指定する
input_stream = environ['wsgi.input']
output_stream = cStringIO.StringIO()
transport = TIOStreamTransport.TIOStreamTransport(input_stream, output_stream)
protocol = TBinaryProtocol.TBinaryProtocol(transport, True, True)
transport.open()
processor.process(protocol, protocol)
transport.close()
#シーク位置を先頭に戻す
output_stream.seek(0)
headers = [('Content-Type', 'application/x-thrift')]
start_response('200 OK', headers)
return output_stream
また、/opt/thriftにthriftコマンドで作成したgen-pyフォルダをコピーします。
そして、thrift\lib\py\src以下のファイルを/opt/thrift/thrift以下に配置しました。
TIOStreamTransportを使用するため、
Google App Engine(Python)でThriftを動作させる
ここで作成したTIOStreamTransportを
/opt/thrift/thrift/transport/TIOStreamTransport.pyに配置します。
最終的な、/opt/thriftの構成はこんな感じ。
nginx.py
/gen-py
__init__.py
/sample
__init__.py
Calculator.py
Calculator-remote
constants.py
ttypes.py
/thrift
__init__.py
Thrift.py
TSCons.py
/protocol
__init__.py
TBinaryProtocol.py
TProtocol.py
/server
__init__.py
THttpServer.py
TNonblockingServer.py
TServer.py
/transport
__init__.py
THttpClient.py
TIOStreamTransport.py
TSocket.py
TTransport.py
TTwisted.py
※今思えば、thriftのライブラリをpython setup.py installで
インストールしたほうが早かったかも。
クライアントプログラム
テストに使用したクライアントのプログラムは、以前と同様の内容です。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import sys
sys.path.append('./gen-py')
#sampleは雛形に指定したthriftファイルの名前になる模様
from sample import Calculator
from sample.ttypes import *
#お決まりのimport
from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.transport import THttpClient
try:
transport = THttpClient.THttpClient("http://sample.com/thrift/")
protocol = TBinaryProtocol.TBinaryProtocol(transport)
client = Calculator.Client(protocol)
transport.open()
#指定したaddメソッドを呼び出す
num1 = 1
num2 = 10
sum = client.add(num1, num2)
#計算結果を表示
print '[client print] %d+%d=%d' % (num1, num2, sum)
#後始末
transport.close()
except Thrift.TException, tx:
print '%s' % (tx.message)
これで無事動いてくれました。
【参考URL】
第2回 WSGIを使ったもう少し複雑なアプリケーションの作成
- 関連記事
-
- Apache + phpの環境でThriftサーバーを動かす
- Thriftでphpの雛形を生成するときのオプションについて
- Debian + Nginx 0.7.x + mod_wsgi + pythonでthriftを動かす
- プロキシサーバー越しにPythonでThriftのTHttpClientを使用する
- Google App Engine(Python)でThriftを動作させる
コメント