AWSのSQS FIFOキューをプロダクションで利用してみた感想とか
SQS について
AWSのサービスの一つでメッセージキューイングのマネージドサービス。 FIFOキューを選択するとメッセージの取り出しがFIFO(先入れ先出し)が保証されます。
安価に性能保証されたFIFOのメッセージキューが利用できたので、かなり良かったです。
FIFOとスケール
メッセージがFIFOだと大量にエンキューしても1個ずつしか処理されない(FIFOなので当然)のでスループット全然出ない状況になります。。
これはメッセージに適切なグループIDをつけることで解決できます。 このグループID単位でFIFOが保証されるので、リソースの更新キューであれば、リソースIDなどを設定しておけば、そのリソースに対する更新処理はFIFOで処理されるのでとても便利でした。
例えば、商品Aの価格を更新するキューがあるとして、キャンペーン価格の100円に更新するメッセージAと通常価格の200円に更新するメッセージBがあるときに、 A -> B の順番にエンキューされたら A -> B の順番に取り出されて更新されないと最終的に商品Aは200円になってくれません。(標準キューでは B -> A の順番に取り出される可能性があり、その場合商品Aは古い価格の100円のままになってしまいます、、) なので、A,Bは商品AのIDをグループIDに指定して、このグループ単位でFIFOを保証されるように指定するのがよいのです。
また、開発中はこのグループIDの概念を理解しておらずすべてにランダムなIDを振ったところ、あたりまえですが全くFIFOにならなかったので注意が必要です。(後述の重複呼出削除機能だけ使いたければ、そうすればいいと思います。)
重複呼出削除機能
同じ内容のメッセージを送ってしまったときに削除してくれる機能です。デフォルトの設定では5分以内にそのように操作した際に最初のメッセージ以外をキューから削除してくれます。
仕様としてわかっていても、テスト中に2回送ったのに1度しか処理されなかった場面に直面したときにちょっとパニックになりました。(単体テストNGか、、、?スケジュールがやばい、など)
メッセージ数の制限について
FIFOキューでは2万メッセージが限界とドキュメントに書いてありましたが、オレゴンのFIFOキューをつかってみたところ、10万目メッセージくらい入りました。仕様外の動作なのでまったくおススメできないですが、障害発生時でメッセージ取得側が止まってエンキューだけ大量にされて、メッセージがたまっちゃったときに2万以上溜まっててくれたので復旧作業が楽でした。
For FIFO queues, there can be a maximum of 20,000 inflight messages per queue. If you reach this limit, Amazon SQS returns no error messages.
開発中の参考ページなど
公式のドキュメントのほかに、クラスメソッドさんのブログ記事が参考になりました。
デザイナーから受領したSVGをSVGKitでiOSアプリで使えるようにするまで
TL; TR
- SVGKitで表示できるかどうかをシンプルなプロジェクトであらかじめ調べる
- SVGOで最適化してみる
- SVGOMGはブラウザで利用できて便利
- SVGOMG - SVGO's Missing GUI
- inkspaceのパスの簡略化(simplify)でうまく表示できないパスを変換する
- 余裕があればパスをシェイプ(図形)に書き直すのもよい
SVGのメリット・デメリット
メリット
デメリット
SVGKitについて
SVGファイルをパースしてiOSのネイティブ機能(CoreGraphics CoreImageなど)で描画するライブラリです。
SVGKitの利用のしかた
iOSでSVGKitを使う方法は以下のページを参考にしました。
SVGKitでillustratorで書き出したSVGを表示みる
今回はillustratorで書き出した検索アイコンを表示してみようとしてみます。
以下のようにうまく表示できていません。
SVGKitでillustratorで書き出したSVGのプレビュー
SVGKitの表示
SVGOで最適化してみる
SVGOはSVGファイルを最適化するためのものですが、副次的な作用でパスデータを単純なものに書き直すため、表示できるようになることがあるようです。
SVGOMGはブラウザで利用できるので手軽です。
Show original
のスイッチで元データと最適化データを見比べながらSVGファイルが変化していないかどうかをチェックしながら進められます。
各最適化オプションや Precision
でどの程度最適化するかをコントロールできます。
inkspaceの単純なパスに変更する
inkspaceのパスの簡略化機能で単純なパスすることもできます。
大体はこれで対応できそうです。
inkscapeの使い方を覚える必要がありますが、うまく表示できなかったパスのみにフォーカスをあてて簡略化したり、シェイプ(図形)に置き換えたりする作業を手作業で行えば確実にSVGKitで表示できます。
検索アイコンはinkscapeでパスを修正し、SVGKitでも表示できるようになりました。
今回の検索アイコンの例だと、SVGKitのエラー出力を見る感じだと clippath
の表示でうまく行かなかったようですが、inkscapeを利用してclippathを利用せずパスのみにしたり、circle
(円のシェイプ)に変更したりするとSVGKitでも表示できるようになるようです。
SVG仕様について
今回、そもそものSVGの仕様を理解するために色々調べたのですが、mozillaが公開しているSVGのチュートリアルが分かりやすかったです。
illustratorはSVG書き出しディスられている、、
実際にSVGKitで表示できる形式にする作業をした所感
SVGKitでSVGが正しく表示されるかどうかチェックするためのプロジェクトを作成して、イメージ通りに表示されるかチェックする作業をしました。
実際に開発中のアプリをビルドして確認していくのはビルドに時間がかかるためです。
macを利用しているデザイナーさんであればアプリエンジニアが手助けしてあげればなんとか自前でビルドして確認するのは難しくなさそうです。
表示できないSVGの対応ですが、SVGOMGとinkscapeのパスの簡略化の2つで大体解決できたと思います。
inkscapeできれいなSVGファイル(xmlファイル的な観点で)を目指していくこともできますが、最終的な見た目はそんなに変わらないと思いますので、こだわりすぎずに進めていくのが作業時間の節約になりそうです。
Docker Composeで起動したコンテナの時刻をコンテナ内で変更する
背景
日付に依存したバッチ処理のテストをするのにDocker Composeで起動したコンテナの時刻をコンテナ内で変更しようとしたら、rootユーザなのに operation not permitted
と表示され変更できませんでした。
原因
DockerはLinux Capabilitiesの仕組みを使って、デフォルトではできることが制限されていました。
https://docs.docker.com/engine/security/security/#/linux-kernel-capabilities
対応
Dockerコンテナ起動時に権限を渡してあげるオプションがありました。
docker run -it --rm --privileged example:image bash
https://docs.docker.com/engine/reference/run/#/runtime-privilege-and-linux-capabilities
docker-composeではコンテナの設定に privileged: true
を追加しました。
version: '2' services: sample: image: centos6:centos6 privileged: true
Docker ComposeでRails開発
最近はDocker for Windowsでの開発がいい感じにできるようになったのでメモ。
サンプルプロジェクト
GitHub - fly1tkg/rails_docker: docker composeの開発構成サンプル
Dockerfile
Dockerfileは開発用イメージでは bundle install
しないほうがいいと思います。
これを含めてしまうと Gemfile
が変更されるたび、このコマンドからイメージのビルドが始まるので、すべてのgemのインストールし直しが発生してしまうからです。
なので僕はdocker-composeでローカルのフォルダとリンクしてから vendor/bundle
にgemをインストールするようにしています。
FROM ruby:2.3.3 RUN apt-get update -qq && apt-get install -y build-essential nodejs RUN mkdir /myapp WORKDIR /myapp ADD Gemfile /myapp/Gemfile ADD Gemfile.lock /myapp/Gemfile.lock #開発向けはbundle installしない #RUN bundle install ADD . /myapp
Docker Compose
docker-compose.ymlの設定項目については以下のQiita記事が詳しいです。
僕はdocker-compose.yml
は以下を使っています。
version: '2' services: # Databaseのコンテナ db: image: mysql:5.7 # Mysqlコンテナは以下の環境変数でrootのパスワードを指定できる environment: MYSQL_ROOT_PASSWORD: password # ホストOSの3306番ポートとコンテナ内の3306番ポートを設定 ports: - "3306:3306" # ローカルのボリュームとフォルダを共有してしてデータを永続化する volumes: - db-data:/var/lib/mysql # railsのコンテナ web: # DBとは違って、こっちはカレントディレクトリでdocker buildしてイメージを作成 build: . # コンテナ実行時のコマンドを指定 command: bash -c "rm -f ./tmp/pids/server.pid && (bundle check || bundle install -j4 --retry 3) && bundle ex rails s -b 0.0.0.0 -p 3000" environment: BUNDLE_PATH: vendor/bundle # ホストOSのカレントディレクトリをコンテナ内の/myappと共有させる volumes: - .:/myapp # ホストOSの3000番ポートとコンテナ内の3000番ポートを設定 ports: - "3000:3000" # 以下設定しておくとコンテナ内のホスト名dbがdbコンテナのIPアドレスとして引けるようになる links: - db # ローカルのボリュームの設定 volumes: db-data: driver: local
webコンテナのコマンドは以下の感じになっています。
rm -f ./tmp/pids/server.pid
コンテナが正常終了しなかったときにpidが残っちゃうのであったら削除します。
bundle check || bundle install -j4 --retry 3
必要であればbundle installします。
bundle ex rails s -b 0.0.0.0 -p 3000
最後はrails起動コマンドです。
頑張って1行で納めてるけど、別途シェルスクリプトを準備してそれを呼び出したほうが可読性は高そうです、お好みで。
database.yml
docker-compose.yml
の設定で
db
は db
ホストに起動していて、
root
のパスワードは password
なので、database.ymlを以下のように設定します。
default: &default adapter: mysql2 encoding: utf8 database: myapp_development pool: 5 username: root password: password host: db development: <<: *default database: myapp_development
開発開始
docker-compose up
出力が読みづらければ -d
で呼び出して tail -f log/development.log
とかでもいいと思います。
docker-compose up -d
rakeやrailsのコマンドなどコンテナ内での作業
docker-compose exec
でできます。
僕はcygwinのターミナル利用してるのでwinpty
を挟んで実行してます。
winpty docker-compose exec web bundle exec rails g model user name:string
railsジェネレーター。
winpty docker-compose exec web rake db:create db:migrate
dbマイグレーション。
winpty docker-compose exec web bash
コンテナのシェルにも入れます。
その他
linksでコンテナのホストが引けるようになっている
上のdocker-compose.yml
の例だとwebコンテナ内でdb
のホスト名でdbコンテナのIPが引けるようになっている。
root@f69a3de1fdf2:/myapp# ping db PING db (172.18.0.2): 56 data bytes 64 bytes from 172.18.0.2: icmp_seq=0 ttl=64 time=0.072 ms 64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.197 ms 64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.329 ms
エディタ設定
Windowsで開発してると文字コード utf-8
と改行コード LF
の設定をエディタに忘れずするようにしないといろいろ混ざります、、、
Docker for Windows利用メモ
事前準備
Windows 10 Proを購入しましょう。
Docker for Windows
Hyper-Vの有効化
Docker for windowsを利用するにはHyper-Vを有効化する必要があります。
Install Hyper-V on Windows 10 | Microsoft Docs
インストール
アプリは公式サイトからダウンロードしてインストールします。
Get started with Docker for Windows - Docker
共有フォルダの設定
Docker for WindowsはボリュームのマウントにSambaを利用するため、以下の設定が必要です。
トレイを右クリックして Settings... > Shared Drives
から マウントに使うパスを設定します。
一番上のフォルダが設定されていれば、配下のどこのフォルダもマウントできるので、特にこだわりがなければ C
でよいと思います。(2016.12.26削除: できなかった、、)(この設定だとCドライブが丸々SambaでWindowsの共有フォルダになってしまうのでセキュリティが気になる人はもっと絞った場所が良いと思います。)
利用してみた感想
LinuxやMacで動かしたときよりはインタラクティブモード周りがちょっとイケてない感ありますが、Ruby on Rails開発は一通りできる感じです。
Docker for Macよりは共有フォルダのアクセス速度が体感で早いと思いました。(Windowsのほうが設定がやや面倒ですが)
備考
Cygwinからdocker execを利用する
docker execをするときにCygwinからだとうまく動作しないのでwinptyを挟んで実行できるようにします。
winpty docker exec -it 123 bash
docker-compose run がインタラクティブに使えない
-d
オプションで使うこともできますが、使い勝手が悪かったので、 docker-compose up
した状態で docker exec
でbashにはいって必要なことをしています。
buildなどで異様に時間かかってるときウイルス対策ソフトのリアルタイムスキャンをOffにする(2016.12.26追記)
Hyper-Vマネージャを開いてDockerのVMのCPU使用率が0%なのに、build等が遅い場合はウイルス対策ソフトのリアルタイムスキャンがボトルネックになっている場合があります。
タスクマネージャーを開いて、リアルタイムスキャンのプロセスのCPU使用率が上がっていたらそうだと思います。
一時的にリアルタイムスキャンをOffにすることをおすすめします。