SPARQL-proxy
提供:TogoWiki
SPARQL-proxy は、クライアントと SPARQL エンドポイントの間で動作するミドルウェアで、 山中さんが SPARQLthon で作成されたオリジナルを改訂したものです。
目次 |
主な機能
- SPARQL クエリをパースし、更新系のクエリを実行できないようにする
- SPARQL クエリをジョブスケジューリングしてからトリプルストアに投げる(負荷集中の低減)
- ジョブのタイムアウトを指定できる
- 同時に実行するジョブの数を指定できる
- 管理画面からジョブを確認したり削除したりできる
- SPARQL 検索結果をキャッシュして2度目からトリプルストアを使わずに結果を返す(レスポンスの向上)
- キャッシュは memory, file, redis, memcached を選択して利用できる
- キャッシュを圧縮してサイズを抑えることができる
- クエリのログを取得できる
実験的な機能
- 大量な結果が返る SPARQL クエリを LIMIT/OFFSET を自動的につけて分割実行する
最近の追加機能
- Virtuoso 独自の拡張「DEFINE sql:select-option "order"」などを許容するように変更
- ただし、SELECT などで sql:hogehoge とか option() などを使っている場合には対応していない
- 180323 ver.
- [ ] を使ったクエリは SPARQL パーザーが _:b0 形式のブランクに書き換えるが、ブランクにクエリを超えて連番つけるので、これまでは [ ] を使うクエリでキャッシュが効かなかった。パーザーを毎回リセットすることで、キャッシュが効くようになりました
レポジトリ
インストール
node.js の安定版をインストール(展開して bin/node, bin/npm を ~/local/bin などにリンクする)
$ wget --no-check-certificate https://nodejs.org/dist/v6.10.0/node-v6.10.0-linux-x64.tar.xz
sparql-proxy の現状版をダウンロードしてインストール
$ git clone https://github.com/dbcls/sparql-proxy.git $ cd sparql-proxy $ npm install
一部の依存ライブラリが GCC 4.8 以降の新しいものを必要とするので注意。
起動
$ cat startup.sh #!/bin/sh PREFIX=/opt/proxy export PATH="$PREFIX/bin:$PREFIX/local/bin:$PATH" # REDIS_URL=localhost:6379 \ # MEMCACHE_SERVERS=localhost:11211,localhost:11212 \ # JOB_TIMEOUT=300000 \ # DURATION_TO_KEEP_OLD_JOBS=60000 \ # COMPRESSOR=snappy \ ( cd $PREFIX/git/sparql-proxy QUERY_LOG_PATH=$PREFIX/log/proxy.log \ CACHE_STORE=file \ CACHE_STORE_PATH=$PREFIX/cache \ MAX_CONCURRENCY=3 \ TRUST_PROXY=true \ PORT=3000 \ SPARQL_BACKEND=http://dev.togogenome.org/sparql \ ADMIN_USER=admin \ ADMIN_PASSWORD=hogehoge \ $PREFIX/bin/npm start 2>&1 >> $PREFIX/log/server.log & )
これで http://localhost:3000/ を開くと SPARQL を実行する画面が表示される。
- http://localhost:3000/sparql をエンドポイトとして公開すれば OK。
- http://localhost:3000/admin にログインすると実行待ちや実行の終わったジョブの一覧が見られる
foreverでdaemon化
$ npm install -g forever $ PORT=3000 SPARQL_BACKEND=http://aaa.bbb.ccc/sparql forever start -c "npm start" /path_to_sparql-proxy_dir $ forever list # forever 稼働中リスト $ forever stop NNN # list で確認したuidを用いて停止
/opt/proxy/git/sparql-proxy にインストールし、npmやforeverが/opt/proxy/local/binにある場合
% cat startup.sh #!/bin/sh PREFIX=/opt/proxy ( cd $PREFIX/git/sparql-proxy QUERY_LOG_PATH=$PREFIX/log/proxy.log \ CACHE_STORE=file \ CACHE_STORE_PATH=$PREFIX/cache \ MAX_CONCURRENCY=3 \ TRUST_PROXY=true \ PORT=14990 \ SPARQL_BACKEND=http://example.org/sparql-backend \ ADMIN_USER=admin \ ADMIN_PASSWORD=togo \ $PREFIX/local/bin/forever --workingDir $PREFIX/git/sparql-proxy $PREFIX/local/bin/npm start )
- Defaultでは 10,000 binidngs まで
- 環境変数 MAX_LIMIT で設定
デプロイ
これまでどおりの URL たとえば http://example.org/sparql を sparql-proxy を使ったものに差し替えたい場合、 sparql-proxy を localhost:3000 などで起動しておいて、
server { listen 80; server_name example.org location /sparql { add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Headers X-Requested-With; proxy_pass http://localhost:3000/sparql; proxy_redirect default; } }
のようにすれば OK。
もし sparql-proxy のトップページや /admin を localhost:3000 ではなく外からもアクセスできるように、 同じドメイン 80 番ポートのサブパス、たとえば /proxy で公開する形でホストしたい場合は、 http://example.org/proxy/ でトップページを、http://example.org/proxy/sparql でエンドポイントを、 http://example.org/proxy/admin/ で管理画面を表示することになるが、 管理画面の更新が WebSockets で行われていることと、管理者ログインのクッキーへの対応ため、 下記のような書き換えが必要。
location ~ ^/proxy/(.*)$ { proxy_pass http://localhost:3000/$1$is_args$args; proxy_redirect / /proxy/; proxy_cookie_path / /proxy/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }
以上、いずれも Nginx の場合の設定例。 関連する情報
タイムアウト設定(nginxデフォルトは60秒)
proxy_read_timeout 3m;
SPARQLパース関連
- Sparqlパース機能はもっと単純にならないか?
- proxy 経由したときだけ遅くなるクエリがある
- かなり重いクエリが下記のエラー
- (node:15438) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 10): TypeError: Cannot read property 'map' of undefined
- virtuoso で空白ノードをアンダーバーコロン形式 (例 '_:blank')や変数に入れた後で、OPTIONAL join を行うと遅くなる場合がある。[ ] 形式だと問題ない
- _:b1, _:b2, _:b3 と数が多いほど遅くなる
- SPARQL-proxy の SPARQL パーザーは [ ] 形式を '_:b' 形式に書き換えて実効するので、結果、遅くなる
- かなり重いクエリが下記のエラー
// virtuoso で問題ない ?s hoge:p [ a ?type ; rdf:value ? value ] . OPTIONAL { ?s hoge:p2 ? o .} ===========パーザーが書き換え============ // virtuoso で遅い ?s hoge:p _:b1 . _:b1 rdf:type ?type . _:b1 rdf:value ?value . OPTIONAL { ?s hoge:p2 ? o .}
- 解決法:可能なら、OPTIONAL join を先にする
DEFINE sql:select-option "order" OPTIONAL { ?s hoge:p2 ? o .} ?s hoge:p [ a ?type ; rdf:value ? value ] .
- 空白ノード、プロパティ・パス関連でパースエラー (最新版では解決済み)
- 主語を省略しつつ、空白ノード省略でプロパティ・パス (/,*,+ など) を使うとエラー
- 主語か空白ノードの省略をやめると通る
s p o ; p [ p/p o ] .
- サブクエリに FROM 行を入れるとパースエラー