Redash で 502 Bad Gateway が発生したときに見直すべき Gunicorn のタイムアウト
業務で使い倒している Redash で、あるクエリーの結果をダウンロードすると、「502 Bad Gateway」が発生していたので調査・対応したメモ
発生していた現象
行数約28,000行、列数約70の結果を返すクエリーを Excel ダウンロードしようとすると nginx の 「502 Bad Gateway」エラーが発生しファイルがダウンロードできない。条件を絞って取得行数を減らすとダウンロードできる。
調査
nginx のエラーログには以下のようなメッセージが記録されていた。
... upstream prematurely closed connection while reading response header from upstream, client: xxx.xxx.xxx.xxx ...
また、server
コンテナのログには、ワーカーがタイムアウトしたようなログが記録されていた(詳細は割愛)
ここでの「ワーカー」は Celery 上で動く Redash のワーカーではなく、Redash がアプリケーションサーバーとして使用している Gunicorn のワーカーのこと。
対応
エラーログから Gunicorn がタイムアウトしていると推測し、設定を調査した。
結果として、タイムアウトのオプションがあり、それはデフォルトで 30
秒になっていることがわかった。
また、Gunicorn のオプションはコマンドライン引数として与える以外にも、以下のように環境変数で渡すことができる。
$ GUNICORN_CMD_ARGS="--bind=127.0.0.1 --workers=3" gunicorn app:app
Redash は現在 Docker 環境を推奨しているため、コマンドラインオプションの変更ははイメージの再構築が必要になってしまい、相性が悪い。
その点、GUNICORN_CMD_ARGS
環境変数を使えば docker-compose.yml
の変更のみでオプションを適用できる。
これらを踏まえて、以下の設定を docker-compose.yml
の server
サービス内、 environment
に追加した。
GUNICORN_CMD_ARGS: "--timeout 90"
90秒という設定は適当。
docker-compose.yml
を編集後、docker-compose down
、docker-compose up -d
でコンテナを再起動。
エラーが出ていたクエリをブラウザで表示し、クエリー結果を Excel ダウンロードしたところ、ダウンロード成功。
まとめ
Redash でファイルダウンロード時に 502 エラーが発生した際は、Gunicorn のタイムアウトを見直すことで解決することがある。
この記事では Docker 環境で動作している Redash を扱っているが、レガシー(Ubuntu に直接導入)セットアップでも似たような対応ができるはず。
Mackerel アンバサダーになりました
アンバサダープログラムについては以下の記事に詳しく書いてあります。
Mackerel 関連の活動ふりかえり
アンバサダーに選出していただいたので、これまでの活動をざっくり振り返ってみました。
プラグイン開発への参加
Mackerel はエージェントやプラグインを OSS として公開していますが、私も以下のプラグインの開発に微力ながら参加しました。
- mackerel-plugin-aws-rds
- mackerel-plugin-elasticsearch
- mackerel-plugin-td-table-count
- mackerel-plugin-php-fpm
- mackerel-plugin-aws-ec2-ebs
個人の OSS
個人的にもいくつか Mackerel 関連の OSS を公開しています。実装が中途半端なものも多いですが、以下の2つはそれなりに使える状態になっていると思います。
- GitHub - ariarijp/mackerel-plugin-ping: ICMP Ping RTT custom metrics plugin for mackerel-agent.
- GitHub - ariarijp/mackerel-client-php: mackerel-client-php is an unofficial port of mackerelio/mackerel-client-ruby.
ブログなどでの記事公開
改めて振り返ってみると。意外といろいろ書いていました。
- Raspberry PIでGoとmackerel-agentをビルドして動作させてみる - Qiita
- mackerel-agentのARM版バイナリーはRaspberry PI 2でもさくっと動く - Qiita
- MackerelでEC2スポットインスタンスの価格変動を監視する - ariarijp’s blog
- PHP-FPMのステータスをメトリクスとして収集するMackerelプラグインを作った - ariarijp’s blog
- Raspberry PIとUSBマイクとMackerelを組み合わせて、室内の騒音レベルを可視化する - ariarijp’s blog
- mackerel-agent-pluginsにmackerel-plugin-php-fpmが含まれてないんだけど?と言われて調べた - ariarijp’s blog
- mackerel-client-goを使ったBotを作る - ariarijp’s blog
- Mackerel Meetup #9でPHPerとしてLTしてきました - ariarijp’s blog
- Mackerel UG × IDCFクラウド UG Meetup で半飛び込み LT してきました - ariarijp’s blog
イベントでの LT 登壇
参加者としては以下のイベント意外にも参加したことがありますが、2度ほど LT 枠で登壇したこともありました。
今後の活動について
アンバサダーになったからといって、変に気負って Mackerel 関連の活動をすることは無いと思いますが、Mackerel は気に入っているプロダクトのひとつなので、今後もなんらかの形でコミュニティやエコシステムに関わりたいと思っています。
Happy Monitoring !!
Mac から Windows への移行を試したメモ
モチベーション
去年、Surface Laptop を衝動買いしたことをきっかけに、ここ数年 Mac で開発していたけど Windows に移行できるか試したくなった
やったこと
- Surface Laptop は初期状態が Windows 10 S モード なので、Windows 10 Pro にアップグレード
- WSL を有効にして Ubuntu を Windows ストアからインストール
- Cmder, VSCode, Docker などをインストール。Chocolatey はまだ使っていないけど、Python などをインストールするときに使う予定
- Ctrl2cap で Caps Lock を Ctrl に入れ替え
- WSL で Python を動かしたり、Serverless Framework で AWS にデプロイしたり
今のところの感想
- キーボードの打ち間違いがとにかく多い。特に Mac の Cmd-Tab とか Cmd-S や IME の切り替えを指癖で打とうとすると Win-Tab、Win-S などをタイプしてしまいストレスがたまる、キーマップをいじるべきか悩む
- Mac ではトラックパッドを使っているけど、Surface Laptop のトラックパッドは少し厳しい。物理スイッチのトラックパッドにはもう戻れないと思った
- マウスを使っているけど、4年ぐらいマウス使わない生活をしていたので、これもすごく違和感がある
- キーボードとマウスをしばらく使っていたら、Thinkpad のキーボードが恋しくなった。家のどこかにあるはずなんだけど見当たらないので、Bluetooth 版のやつを買おうか悩んでいる
- WSL があるおかげで CLI 操作が以前の Windows と比べると格段によくなっている
- WSL で Docker が動くようになったけど、Docker Compose はまだ使えないため、今のところ Docker は WSL の外で使うことになりそう
- 開発環境は Windows 側に作るか WSL 内に作るか悩む。今は WSL に寄せてるけど、VSCode を使うとなると Window 側にも Python や Nodejs を導入する必要がありそうな気がしている
- Mac でできて Windows でできないことはいくつかある(Xcode 使えないとか)が、だいたいのことは Windows でも慣れればなんとかなるかなと思い始めた
- 以前使っていた Windows は前職で貸与されていた DELL のラップトップだったんだけど、最近のものはどれも見た目とか質感がいいなと思った。Surface Laptop もかなり気に入ってる
- Surface 製品全般に言えることかもしれないけど、製品の特性上修理ではなく交換になることが多いらしいので、故障のリスクはちょっと怖い
- とりあえず、まずはプライベートでなにかするときは Surface Laptop を使い続けてみることにした
今後やること
- Redash の開発環境を整えてみる
- PyCharm など JetBrains 製品をいくつかインストールする
レノボ・ジャパン ThinkPad Bluetooth ワイヤレス・トラックポイント・キーボード - 日本語 0B47181
- 出版社/メーカー: レノボ・ジャパン
- 発売日: 2013/06/25
- メディア: Personal Computers
- この商品を含むブログ (22件) を見る
Ubuntu 上で環境構築していた Redash を Docker 上で動作する環境に移行する手順
この記事は Redash Advent Calendar 2018 25日目。最終日の記事です!
参加いただいたみなさまも、読んでいただいた皆様もありがとうございます!
お題
現在、Redash の環境構築は Docker を使用する方法のみが公式ドキュメントなどでも記載されていますが、古くからの Redash ユーザーにとっては、Ubuntu の上にインストールする形で運用している方も多く、私もそのひとりです。
この記事では、旧来の Ubuntu 上に環境構築された Redash(以降、レガシーセットアップ)を Docker で構築された Redash(以降、Docker セットアップ)に移行する方法を紹介します。
注意事項
この記事で紹介する方法はあらゆる環境を網羅したものではありません。
お使いの環境を移行する際は、必ずご自身で検証してください。
また、この手順は私が業務で Redash を移行する際にも利用しているため、移行作業の結果によって、この記事を加筆修正する場合があります。
前提条件
この記事の検証で使用した Ubuntu と Docker、 Docker Compose のバージョンは以下となっています。
- Ubuntu 16.04.4 LTS
- Docker version 18.09.0, build 4d60db4
- docker-compose version 1.8.0, build unknown
この記事では Docker の導入については割愛しますが、私は以下の記事を参考にして Docker を導入しました。
How To Install and Use Docker on Ubuntu 16.04 | DigitalOcean
手順
PostgreSQL 以外の Redash 関連のサービスを停止
PostgreSQL の DB ダンプを取得する前に、Redash 関連のサービスをすべて停止します。
$ sudo service nginx stop $ sudo service supervisord stop $ sudo service redis_6379 stop
サービス名は Redash をどのバージョンから利用しているかによって異なる場合があります。
既存の Redash から DB ダンプを取得する
Docker セットアップ環境で使用する PostgreSQL にリストアするための DB ダンプを取得します。
レガシーセットアップでは PostgreSQL に redash
ユーザーを作成しますが、Docker セットアップでは postgres
ユーザーを使いますが、そのため、既存環境のダンプファイル取得時にオーナー情報を除去しておきます。
$ sudo -u postgres bash -c "pg_dump --no-owner --no-acl redash | gzip > /tmp/dump.sql.gz"
ダンプファイルの出力先は /opt/docker/redash
として、この記事内では以降の説明でも、このディレクトリ内で作業します
既存の PostgreSQL を停止
ダンプファイルを取得したら、既存の PostgreSQL は不要になるためサービスを停止します。
$ sudo service postgresql stop
docker-compose.yml をダウンロードする
移行先バージョンの docker-compose.production.yml
をダウンロードします。
この記事では移行先に v5.0.2
を使用するため、GitHub 上でタグを指定してダウンロードしています。
$ wget -o /opt/docker/redash/docker-compose.yml https://raw.githubusercontent.com/getredash/redash/v5.0.2/docker-compose.production.yml
docker-compose.yml を書き換える
Docker セットアップで使用するバージョンに合わせて docker-compose.yml
を書き換えます。
バージョンの指定
Docker イメージのタグ一覧 を参照し、利用したいバージョンのタグを指定します。
$ sed -i s/redash\\/redash:latest/redash\\/redash:5.0.2.b5486/g /opt/docker/redash/docker-compose.yml
postgres サービスのボリューム指定
PostgreSQL のデータを保持するボリュームを指定します。
postgres
サービスの volumes
がコメントアウトされているので、これをアンコメントしてホスト側のパスを書き換えます
...省略... postgres: image: postgres:9.5.6-alpine volumes: - /opt/docker/redash/postgres-data:/var/lib/postgresql/data restart: always ...省略...
環境変数を設定する
既存の Redash の .env
から必要な設定を server
, worker
サービスの environment
に設定します。
ここでは詳細な説明を省きますが、メールサーバーの設定などは .env
にで設定することが多いので、忘れずに設定しましょう。
また、server
のみに設定してしまい worker
に環境変数が適用されないというケースもあるので、忘れずに両方の environment
に設定してください。
Docker Compose で起動する
準備ができたら、サービスを起動します。
$ sudo docker-compose up -d
postgres
にダンプファイルをコピーする。
新規インストールの手順であればここで create_db
を実行するところですが、今回は既存環境からの移行なので、データベースの作成はせずに、先程取得したダンプファイルをリストアします。
そのため、ダンプファイルを postgres
サービスが動いているコンテナにコピーします。
$ sudo docker cp /tmp/dump.sql.gz `sudo docker ps|grep postgres|awk '{print $1}'`:/tmp/
DB をリストアする
コピーしたダンプファイルを使って、以下のコマンドでリストアします。
$ sudo docker-compose exec postgres bash -c "zcat /tmp/dump.sql.gz | psql -U postgres"
マイグレーションを実行する
この時点で、DB は作られていますが、古いバージョンのテーブル構造のままになっているため、マイグレーションを実行して移行先のバージョンにあったテーブル構成にします。
$ sudo docker-compose run --rm server manage db upgrade
ここまででレガシーセットアップから Docker セットアップへの移行は完了です。
疎通確認
最後に、curl
で簡単に疎通確認してみます。
$ curl -I localhost/api/config
JSON 文字列が表示されていれば、移行した Redash が動作していることが確認できています。
まとめ
バージョンアップにくらべ、さらに腰が重くなるような移行作業ですが、私も今後のアップグレードも見据えて移行を進めています。移行は計画的に進めましょう。
Redash のクエリ結果がクリーンアップされる仕組み
この記事は Redash Advent Calendar 2018 20日目の記事です。
お題
フォーラムでクエリ結果を使ってごにょごにょされている方の投稿がありました。
私もコメントしてみましたが、Redash のクエリ結果はあるルールで定期的に削除されています。
この記事では、その動きを追ってみようと思います。使用するバージョンは v6.0.0
ブランチです。
動きを追ってみる
server と worker
まず、Redash は大きく server
(Flask) と worker
(Celery) のプロセスがあります。
クエリ結果を削除する仕組みは worker
側で実行されています。
worker が実行される仕組み
Redash の worker
プロセスは Celery を使って実行されます。
エントリポイントは redash/worker.py になっています。
クエリ結果が削除される仕組み。
redash/worker.py
中の以下のコードがクエリ結果の削除に大きく影響します。
if settings.QUERY_RESULTS_CLEANUP_ENABLED: celery_schedule['cleanup_query_results'] = { 'task': 'redash.tasks.cleanup_query_results', 'schedule': timedelta(minutes=5) }
Redash は環境変数でいろいろな設定を変更できるようになっており、 QUERY_RESULTS_CLEANUP_ENABLED
もその設定のひとつです。
文字通り、クエリ結果をクリーンアップするかどうかをこの環境変数で決定しており、デフォルトは True
になっています。
この設定が有効になっていると、redash/tasks/queries.py の cleanup_query_results
が5分に1度実行されます。
@celery.task(name="redash.tasks.cleanup_query_results") def cleanup_query_results(): """ Job to cleanup unused query results -- such that no query links to them anymore, and older than settings.QUERY_RESULTS_MAX_AGE (a week by default, so it's less likely to be open in someone's browser and be used). Each time the job deletes only settings.QUERY_RESULTS_CLEANUP_COUNT (100 by default) query results so it won't choke the database in case of many such results. """ logging.info("Running query results clean up (removing maximum of %d unused results, that are %d days old or more)", settings.QUERY_RESULTS_CLEANUP_COUNT, settings.QUERY_RESULTS_CLEANUP_MAX_AGE) unused_query_results = models.QueryResult.unused(settings.QUERY_RESULTS_CLEANUP_MAX_AGE).limit(settings.QUERY_RESULTS_CLEANUP_COUNT) deleted_count = models.QueryResult.query.filter( models.QueryResult.id.in_(unused_query_results.subquery()) ).delete(synchronize_session=False) models.db.session.commit() logger.info("Deleted %d unused query results.", deleted_count)
ここで QUERY_RESULTS_CLEANUP_MAX_AGE
に指定された日数(デフォルトは 7
日) 以上前に実行されたクエリ結果を QUERY_RESULTS_CLEANUP_COUNT
に指定された件数(デフォルトは 100
)削除されます。
利用の仕方によってはクエリ結果が大きくなってしまい、ディスクなどのリソースを圧迫してしまうことがあるため、実行済みのクエリ結果を多用しない場合は QUERY_RESULTS_CLEANUP_MAX_AGE
を適切に調整するのをおすすめします。
私が業務で運用している Redash インスタンスはクエリパラメータを多用していたり、毎時結果が変わるような特性のデータを扱っていることもあるため、 QUERY_RESULTS_CLEANUP_MAX_AGE
は 3
に設定しています。
この記事で紹介した環境変数以外にもいろいろな項目が設定できるので、以下の記事もぜひ読んでみてください。
まとめ
クエリ結果が削除される仕組みについて改めて調べてみました。
クエリ結果が大きくなるようなクエリを多く運用されている方でこれらの設定を見直したことがないという方がいたら。一度見直してみると良いと思います。
明日は y-tomoyasu さんによる「Python Data Sourceの利用ケースについてなにか」です。
y-tomoyasu さんは Redash Meetup 4.0.2-dev でも少しお話を伺いましたが、Python データソースをガッツリ使われているようです!お楽しみに!