しゅがーブログ

技術ネタとか書いていけたらな…

【MongoDB】特定のcollectionをdumpしてrestoreする方法

特定のcollectionのみをdump

下記コマンドを実行するとカレントディレクトリにdumpフォルダが生成される。

mongodump -d hogehoge_db -c hogehoge_collection1 --out dump
mongodump -d hogehoge_db -c hogehoge_collection2 --out dump
mongodump -d hogehoge_db -c hogehoge_collection3 --out dump

こんな感じ

current directory
├── dump
   ├── hogehoge_db
      ├── hogehoge_collection1
      ├── hogehoge_collection2
      ├── hogehoge_collection3

既存collectionを完全に入れ替えたい場合は、--dropオプションを追記する。
詳細は公式リファレンスを参照

mongorestore --drop dump

すると既存のcollectionデータは消えて、新しいデータでrestoreされる。

補足

dockerコンテナ上で動作しているMongoDBにデータを取り込む方法 ホストからコンテナへdumpしたデータをコピー

docker cp dump コンテナID:/dump

参考 https://qiita.com/gologo13/items/7e4e404af80377b48fd5

Elasticsearch 6.8.X に上げるときの注意点

最近書いてなかったので、久しぶりに投稿

TL; DR

  • ヒープサイズのデフォルト値が2GBから1GBに変更になりました。
    • itamaeでjvm.optionsを管理している方は要注意。
    • デフォルト値の指定で書き換えを行っていると、書き換えされずデフォルト値のままElasticsearchが起動されます。
  • like_textからlikeへの変更
  • elasticsearch-railsのmongoidのimport処理で障害になった
    • importo処理を実行する
    • countクエリが走る
    • メタ情報で帰ってこないから素直にカウントしにいく

はじめに

EOLを向かえた5.X系から6.X系の最新までバージョンを上げました。 その時の注意点やクラスタの入れ替え方法をまとめました。

変更概要

ヒープサイズがデフォルト1GBに変更

Elasticsearch 5系のインストール時のデフォルトサイズは2GBとなっています。 しかし6系からデフォルト値は1GBに変更されています。

6系のリファレンスだとこんな感じです。

By default, Elasticsearch tells the JVM to use a heap with a minimum and maximum size of 1 GB. When moving to production, it is important to configure heap size to ensure that Elasticsearch has enough heap available.

基本的にクラスタを組んで一括で管理している方が多数だと思います。(itamaeやchefなどで) そういった方でデフォルト値から書き換えている方は注意してください。 sedで置き換えておりましたが、変更されていることに気づかず1台1GBのクラスタを組んでしまいました。

more_like_thislike_textがサポートされなくなった

シンプルにlike_textがなくなり、likeになりました。

[400] {"error":{"root_cause":[{"type":"parsing_exception","reason":"[mlt] query does not support [like_text]","line":1,"col":96}],"type":"parsing_exception","reason":"[mlt] query does not support [like_text]","line":1,"col":96},"status":400}

公式リファレンスでは見つけられず、そのままクラスタの入れ替えをしてしまいました。 後々GitHub上のIssueで発見しました。(ググっても見つけられなかった、というかページが見つからなかった)

resqueで非同期処理を実行していて、そちらで処理がコケていました。 また、残念なことにエラー検知システムの方でアラートが上がらず、発見したのが翌日でした。 幸いなことに致命的な処理ではなかったので、再実行すれば問題ありませんでした。

elasticsearch-railsのmongoidのimport処理で障害になった

シンプルにこんな処理を流してElasticsearchクラスタにDBにデータを流し込む処理を実行しました。

Hogehoge.__elasticsearch__.import

すると、数分の間にslow queryカウントが急激に増加し、webサーバが処理しきれなくなりサービスが完全ダウンしかけました。

scope.no_timeout.each_slice(batch_size) do |items|
  yield (preprocess ? self.__send__(preprocess, items) : items)
end

このeach_sliceってカウントクエリが走ります。 そのため、メタ情報でカウントが帰ってこない数え方だと純粋に数えに行きレスポンスが帰ってこなくなります。 データ量もそこそこあるcollectionだったので、余計遅くなりサービスダウンの障害となりました。

items = []
scope.no_timeout.each do |item|
  items << item
  if items.count >= batch_size
  yield (preprocess ? self.__send__(preprocess, items) : items)
    items.clear
  end
end

yield (preprocess ? self.__send__(preprocess, items) : items) if items.present?

最終的にはこんな感じのモンキーパッチを当てて対応しました。 バッチのデフォルトサイズ1000件まで配列に追加して、そのままyieldに投げ込むやり方に変更しました。

最後に

Beaking Changeは読みましょう!(読んでいたけど・・) どこで障害に起こっているかわからないため、エラー検知だけを信じず見れるところは見ましょう。

Rails3 + Passenger について

今更ながらRails3 + Passenger + Apacheの環境について調べました。
Railsは3.0.1のためassets pipelineがありません。
そのため、publicディレクトリに置いてあるJavaScriptCSSApacheモジュールのPassengerが圧縮しているみたいです。

Passenger

環境

  • production
  • staging
  • development

基本的に環境はhttpd.confに依存しています。
デフォルトではproductionで動作するようになっているため、production以外の環境はそれぞれ下記のような環境変数を指定してあげるとよさそうです。

httpd.conf

<Directory "/var/www/html">
    Order allow,deny
    Allow from all
    RailsEnv development #ここ
</Directory>

圧縮をかけるコンテンツフィルターはこんな感じで指定できます。

httpd.conf

# Netscape 4.x has some problems...
BrowserMatch ^Mozilla/4 gzip-only-text/html

# Netscape 4.06-4.08 have some more problems
BrowserMatch ^Mozilla/4\.0[678] no-gzip

# MSIE masquerades as Netscape, but it is fine
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

FilterDeclare Compression CONTENT_SET
FilterProvider Compression DEFLATE Content-Type $text/plain
FilterProvider Compression DEFLATE Content-Type $text/css
FilterProvider Compression DEFLATE Content-Type $application/xhtml
FilterProvider Compression DEFLATE Content-Type $application/xml
FilterProvider Compression DEFLATE Content-Type $application/xhtml+xml
FilterProvider Compression DEFLATE Content-Type $application/rss+xml
FilterProvider Compression DEFLATE Content-Type $application/atom+xml
FilterProvider Compression DEFLATE Content-Type $application/x-javascript
FilterProvider Compression DEFLATE Content-Type $image/svg+xml
FilterProvider Compression DEFLATE Content-Type $text/html
FilterProvider Compression DEFLATE Content-Type $application/javascript
FilterChain Compression

あまりにもローカル環境が遅いためPassengerを利用して開発してみようと思い調べてみました。
ローカル環境でシンプルに開発するならやっぱりでWEBrickがいいのかな。
もしくはDockerで各種コンテナを用意して、開発した方が楽そうだな・・

参考

Rails3 事始め: Passenger で development モードで動かす
【Apache】サイトのコンテンツ全てをgzip圧縮する | blog.remora.cx
Apache 2.2 mod_filterを使いこなす – AddOutputFilterByType DEFLATE text/htmlを書き換えてみる – cyano

sessionの有効期限について

使用ツール

Rails 5.1.5
devise 4.4.1

概要

sessionが切れる時の対処法

  • config/initializers/devise.rb
    config.timeout_inの時間を任意の時間に変更

before

  # ==> Configuration for :timeoutable
  # The time you want to timeout the user session without activity. After this
  # time the user will be asked for credentials again. Default is 30 minutes.
  # config.timeout_in = 30.minutes

after

  # ==> Configuration for :timeoutable
  # The time you want to timeout the user session without activity. After this
  # time the user will be asked for credentials again. Default is 30 minutes.
  config.timeout_in = 1.month
  • config/initializers/session_store.rb
    expire_afterを任意の時間で設定する

before

Rails.application.config.session_store :active_record_store, :key => '_app_session'

after

Rails.application.config.session_store :active_record_store, :key => '_app_session', :expire_after => 1.month

参考

Deviseでセッションのタイムアウトまでの時間を延ばす方法 - Qiita

Rails carrierwave fog rmagickで画像アップロード

プロダクト開発でアイコンやバックグラウドイメージをアップロードできるようにしたいので試しに使用してみました。
すでに色々な方々が試しているみたいですが、自分なりの備忘として残しておきます。
環境変数はハードコーディングせずにgem:dotenvを使用して実装しています。

carrierwave

CarrierWave.configure do |config|
  config.fog_credentials = {
    provider: 'AWS',
    aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
    aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
    region: ENV['AWS_REGION'],
    path_style: true
  }
  config.fog_public = true
  config.fog_attributes = {'Cache-Control' => 'public, max-age=86400'}
  config.remove_previously_stored_files_after_update = false
  config.cache_storage = :fog

  case Rails.env
  when 'production'
    config.fog_directory  = ENV['AWS_S3_BUCKET']
  end
end
# 日本語の文字化けを防ぐ
CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/

Uploader

class ImageUploader < CarrierWave::Uploader::Base
  include CarrierWave::RMagick

  storage :fog
  def store_dir
    "images/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  version :thumb do
    process resize_to_fit: [100, 100]
  end

  def extension_whitelist
    %w(jpg jpeg png)
  end

  def filename
    "image_#{model.id}.#{file.extension}" if original_filename
  end
end

Model

class User < ApplicationRecord
  mount_uploader :icon, ImageUploader
end

参考

Rails4.2+carrierwave+fog+rmagickでS3に画像アップロードした話 - Qiita
CarrierWave + Rails 5.1で画像アップローダー | 酒と涙とRubyとRailsと
GitHub - carrierwaveuploader/carrierwave: Classier solution for file uploads for Rails, Sinatra and other Ruby web frameworks

PostgreSQLのversion up

PostgreSQLのversion upを実施した時のメモです。

移行前 version : 9.3.1
移行後 version : 9.5.10

version upすることになった経緯

AWSのEC2上で動作していたDBサーバをRDS上へ移して管理を楽にしたいということがありました。
DMS(Database Migration Service)を利用して移行しようとしましたが、DMSがサポートしているPostgreSQLのversionは9.4以降のため使用できないということが発覚。
そのため、一旦versionを上げてから移行する方針となりました。
9.3系のサポートも2018年9月で切れるということもあり。

実際にやったこと

  1. EC2上のDBインスタンスを完全に停止させて、AMIを取得

  2. 取得したAMIから新規にDBインスンタスを作成

  3. 事前に作成しておいたコマンドを投下

9.3.1で動作しているPostgreSQLの停止して、バックアップとして避けておく。

sudo /etc/init.d/postgresql stop
sudo yum -y update
sudo mv /usr/local/pgsql /usr/local/pgsql.old

今回はソースコードからインストールするためPostgreSQLの公式サイトからインストールしたいバージョンを取得。
sslをサポートさせるために--with-opensslオプションをつけておく。
あとは通常のmake installを実施。

cd /usr/local/src
sudo wget https://ftp.postgresql.org/pub/source/v9.5.10/postgresql-9.5.10.tar.gz
sudo tar zxvf postgresql-9.5.10.tar.gz
cd postgresql-9.5.10
./configure --with-openssl
make
make check
sudo make install

物理ファイル保存用のディレクトリを作成。
postgresユーザに変更してpg_upgradeを実行。
シンボリックリンクで切り替えを行ったため短時間で終わります。

sudo mkdir /usr/local/pgsql/data
sudo chown postgres:root /usr/local/pgsql/data
sudo chmod 700 /usr/local/pgsql/data
sudo su -
su - postgres
export PGDATA=/usr/local/pgsql/data
/usr/local/pgsql/bin/initdb -d /usr/local/pgsql/data
/usr/local/pgsql/bin/pg_upgrade -b /usr/local/pgsql.old/bin -B /usr/local/pgsql/bin -d /usr/local/pgsql.old/data -D /usr/local/pgsql/data -k

9.3.1で使用していたpg_hba.confpostgresql.confはそのまま流用しました。

mv /usr/local/pgsql/data/pg_hba.conf /usr/local/pgsql/data/pg_hba.conf.org
mv /usr/local/pgsql/data/postgresql.conf /usr/local/pgsql/data/postgresql.conf.org
cp -ip /usr/local/pgsql.old/data/pg_hba.conf /usr/local/pgsql/data/pg_hba.conf
cp -ip /usr/local/pgsql.old/data/postgresql.conf /usr/local/pgsql/data/postgresql.conf
./analyze_new_cluster.sh

ついでにslave作ったりと色々足りてなかったことも追加で実施しました。

参考

PostgreSQL 9.5.4文書
PostgreSQL9.4 から PostgreSQL9.5 に pg_upgrade する - Qiita

他ドメインからELBへのルーティング方法

概要

他のサービスでドメインを管理されていたけれど、AWSと併用して使うことになりその移行を実施したのでまとめました。
ELBとWEBサーバ間はひとまずHTTPで通信させるもとのとする。
ドメイン
移行前:www.hogehoge.com
移行後:www.tk-sugar.com

やったこと

  • CNAMEの設定
  • 証明証の差し替え
  • nginx.confの書き換え

CNAMEの設定

元々使用していたドメイン管理サービスでDNSレコードの追加を実施。
www.hogehoge.comに対してレコードを設定する。
レコードの登録が完了しwww.hogehoge.comへアクセスするとwww.tk-sugar.comへルーティングされるようになる。

イメージはこんな感じ

ホスト名 種別 内容
www.hogehoge.com CNAME www.tk-sugar.com

証明証の入れ替え

元々リバースプロキシに設定されてあった証明書をCertificate Managerから登録。
本来は新規にELBを立てたり、Route53を設定しなければならないが、今回は既存で存在していたものを流用する形で設定する。
(実際は少し設定変えたりしましたが、今回は割愛)
また、中間証明書が設定されていた場合は証明書チェーンを設定してやらないとうまくインポートできません。

証明証の登録完了後、該当するELBの443ポートに対して証明書を割り当てます。
※ ELBから振り分けさせたサーバをターゲットさせておくことも忘れずに
あとはhttps通信でアクセスできるか確認しましょう。

nginx.confの書き換え

メンテナンスページの出力用設定 maintainance.htmが存在するなら503を返してメンテナンスページを表示するだけの簡単な仕組みです。
それ以外なら自分で設定したページが出力されます。
メンテナスページとの切り替えは mv maintainance.htm maintainance.html などで簡単に実施できます。

server {
        listen 80;

        省略

        error_page 500 501 502 503 504 /var/www/html/error/maintainance.htm;

        set $maintenance false;
        if ( -f /var/www/html/error/maintainance.htm) {
                set $maintenance true;
        }

        location / {
                if ($maintenance = true) {
                        return 503;
                }
                proxy_pass     http://localhost/;
                proxy_redirect default;
        }

参考URL

【初心者向け】ELBにSSL証明書をインストールする | Developers.IO
SSL Termination(ELB)でアプリ(EC2)がHTTPSのチェックを行えない場合 | cloudpack.media
Nginxでメンテナンスページに編集なしで即時切り替える方法 - Qiita