読者です 読者をやめる 読者になる 読者になる

Amazon Elastic Beanstalk でデプロイ時に database.yml に database.example.yml をsymlinkする方法

database.yml をgitにcommitしたくないよね... そんな時に

先に方法

files:
  "/opt/elasticbeanstalk/hooks/appdeploy/pre/01a_symlink_database_yml.sh":
    mode: "000777"
    content: |
      #!/bin/bash
      cd /var/app/ondeck/config
      ln -sf database.example.yml database.yml
  • ~/.ebextensions/20_symlink_database_yml.config

概要

デプロイ処理の途中で、database.ymldatabase.example.yml をsymlinkしている

どうやっているの?

~/.ebextensions について

  • Elastic Beanstalkでは、コードの ~/.ebextensions/ に、のデプロイ前後に実行するコマンドや、ファイルを追加するための設定を格納できる
    • ただし、デプロイの途中に何かを挟むことはできない
  • files: は、コードが展開される前に、指定したpathに、content の内容のファイルを設置する

/opt/elasticbeanstalk/hooks/appdeploy/pre/01a_symlink_database_yml.sh について

  • /opt/elasticbeanstalk/hooks/appdeploy/ は、デプロイ時に実行されるシェルが格納されているディレクト
  • 辞書順にシェルが実行されるので、適切な名前のシェルを追加することで、任意の処理をデプロイ処理の途中に紛れ込ませることができる
  • pre/01a_symlink_database_yml.sh の場合、コードを展開した後に実行される
  • /var/app/ondeck は、コードが最初に展開されるディレクト
    • デプロイ処理に成功すると、 /var/app/current に mv される
  • 上記方法は、オフィシャルなドキュメントに明示されている方法ではないので、今後の更新で使えなくなるかも

雑記

  • Elastic Beanstalk的には、 database.yml をcommitして欲しい様子
  • heroku だと、heroku環境用の database.yml を生成してくれる

参考

ロードバランシングしている場合、サーバまたいでもRailsのcookie sessionって保持されるか不安になった時に見るページ

いつもはkey-valueストアでやっているので、cookie sessionを使うとなった時に心配になったのでメモ

先に結論

sessionは保持される

理由

cookie sessionは、ブラウザ側でsessionの情報を保持して、サーバ側に情報を持たないから

cookieおさらい

cookie : webサーバと、ブラウザ間で情報を管理するプロトコル(RFC6265)

  • key=value で情報を保持
  • リクエスト/レスポンスヘッダでやりとりする
  • 適用範囲 : path, domainを指定可能
    • domain 未指定の場合、発行したdomain上でだけ受信可能
  • 有効期限 : 未指定の場合ブラウザを閉じたら終了

session

webサーバとブラウザで情報を管理する仕組み ログイン情報とか、カートに何が入っているかとか

cookie session

  • sessionの情報をcookieを使って管理する
  • railsでのsessionの管理方法のデフォルト
  • valueは暗号化されて格納される

欠点

  • cookieのサイズ上限は4Kbyte(safariの場合)
  • 大量のデータを保持した場合、通信量が増える
  • ブラウザ側でデータを改変できる

cookie以外のsession管理方法

(やや別件) ロードバランシングした場合、複数サーバを跨ると困るところは?

  • /tmp ディレクトリに一時ファイルを生成して、そのpathをcookieに入れて処理している場合
  • メモリにsession情報を入れている場合(cookieにはsession idのみ)

参考リンク

Amazon Elastic Beanstalk で t2.micro で Rails をデプロイすると、gem install に失敗する件

先に結論

原因

bundle install 時に メモリが不足が原因で native extension のビルドに失敗している

エラーメッセージ

An error occurred while installing nokogiri (1.6.8.1), and Bundler cannot
continue.
Make sure that `gem install nokogiri -v '1.6.8.1'` succeeds before bundling.

eb-activity.log

  Installing nokogiri 1.6.8.1 with native extensions

  Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

      current directory: /opt/rubies/ruby-2.3.1/lib/ruby/gems/2.3.0/gems/nokogiri-1.6.8.1/ext/nokogiri
  /opt/rubies/ruby-2.3.1/bin/ruby -r ./siteconf20161205-3296-zuwti1.rb extconf.rb 
  Cannot allocate memory - /opt/rubies/ruby-2.3.1/bin/ruby -r ./siteconf20161205-3296-zuwti1.rb extconf.rb 2>&1

swap を大きくするとか回避する方法もあるけれど、お金を惜しんで手間を掛けるのは、PaaS の精神に反しているとおもったので、お金で解決

HerokuのDBにAmazon Elastic Beanstalkからアクセスする

これは何?

Herokuで運用しているアプリを、ふとAmazon Elastic Beanstalkに移行したくなった

けれど、軽く試すためだけのために、DBを移行するの大変

そんな時にお手軽に試す為の方法の記録

Heroku から DB の情報を取得する

heroku では、database.yml に接続するDBの情報を書かなくても良い感じに繋ぐけど、Amazon Elastic Beanstalk から heroku のDBに接続するためには、接続情報が必要

heroku config で調べる場合

$ heroku config

=== ***** Config Vars
DATABASE_URL:             postgres://#{username}:#{password}@#{hostname}:5432/#{db_name}

rails config で調べる場合

$ heroku run rails console

irb(main):001:0> ActiveRecord::Base.connection_config
=> {:adapter=>"postgresql", :pool=>5, :timeout=>5000, :database=>"*****", :username=>"*****", :password=>"*****", :port=>5432, :host=>"*****"}

それぞれ、出てきた情報をメモする

database.yml に設定を追記する

直接書くのはよろしくないので、以下のようにして、環境変数から値を取るようにする

production:
  <<: *default
  database: <%= ENV['DB_NAME'] %>
  username: <%= ENV['USERNAME'] %>
  password: <%= ENV['PASSWORD'] %>
  host: <%= ENV['HOSTNAME'] %>
  port: 5432

Elastic Beanstalk に環境変数を設定する

eb setenv DB_NAME=******
eb setenv USERNAME=******
eb setenv PASSWORD=******
eb setenv HOSTNAME=******.amazonaws.com

以上

slack に書かれた内容を Amazon Polly で読み上げてみた

この記事は feedforce Advent Calendar 2016の6日目です!!

www.adventar.org

昨日は、tjinjinドラッカー風エクササイズをチームで試してみました でした

cross-black777.hatenablog.com

期待マネジメント大事ですね。 ウチのチームも一度やってみたら面白いかもしれないですね...

さて、実用的な記事はやってもらえたので、私の方は技術ネタでお茶を濁したいと思います!

Amazon Polly で遊ぼう!

先日の AWS re:Invent 2016 では、色々なサービスがローンチされてすごかったですね!

今日はその中から、音声読み上げサービスである Amazon Polly で遊んでみようと思います!

Amazon Polly ってなあに?

公式blogに詳しい解説がありました

Amazon Polly – 文章から音声へ、47の声と24の言語 | Amazon Web Services ブログ

特徴をかいつまむとだいたいこんな感じです

  • クラウド音声読み上げサービス
  • 今までの音声読み上げサービスよりも精度が高く、よりネイティブに近い発音なのが特徴
  • 毎月500万文字までは無料(!) 以降は1文字 $0.000004 生成される音声1分あたり$0.004

pollyコンソール で 簡単に試すことができるので、色々遊んでみると良いと思います。 主観ですが、今までの音声読み上げと比べるとだいぶ違和感が減ったなぁと感じました

既に sdk も使えるようですので、なにか面白い使いみちを考えてみましょう...

Amazon Polly の使い道を考える

slackの流れは追っておきたいけれど、そのために作業を中断するのはしたくない。そんな時ありませんか?

そんなときに、そう。読み上げてもらえば...!

でき上がったものがこちらになります

youtu.be

しくみ

ソースコード

こちらになります。 ruby で実装しています。また afplay を使っている関係上 macOS のみで動作します

github.com

ハマったポイント

APIを使ってslackのchannelのメッセージをリアルタイムに取得する方法が分からずにハマりました

  • slack の Real Time Messaging API には Bot 用のAPIキーが必要
  • Botが所属している channel のメッセージしか取れない
    • channel に呼ぶには Bot をメンションする

まとめ

入力した文章が読み上げられるってそれだけで結構楽しいですね!

半分ネタで作ってみたのですが、コンテキストスイッチを乱されずに情報が追えるので、あれ? 意外に実用度高くない...? などと思っているところです

参考リンク

明日は、フィードフォースボドゲ部部長 および 日本酒会会長 の kano-e の 「RailsエンジニアがFacebook広告を出稿してみた」です!

tech.feedforce.jp

Ad業界エンジニア必見!!! あと手書きのスライド資料が温かみがあって良い感じです!

負荷テストについて思ってることをポエムする

色々知見が溜まってきたのでポエムします

言いたいこと

  • 「なにをもってゴールとするか?」の合意を取ろう
  • まず実測
  • 本番環境にできうる限り近い環境でやろう
  • 実測ツール紹介
  • 中央値も見よう

「なにをもってゴールとするか?」の合意を取ろう

やろうと思えばどこまでも高速化できてしまうので、最初に、なるべく実際の負荷に近いと思われる条件の元、 どんな条件で、どのような結果ならばOKか? の合意をチーム内で取りましょう

どんな条件での例

  • アクセス方法(どのページにどんな頻度でアクセスするか?なるべく実際のユーザの挙動に近いほうが良い
  • キャッシュの有無(厳密にやるならば、実際のキャッシュヒット率に近くなるようにやるべき。ページキャッシュやら、SQLキャッシュやら

どのような結果ならばOKか? の例

  • 限界テスト : 何アクセス数まで、サーバが落ちないこと
  • 性能テスト : 何アクセス数まで、平均レスポンスタイムがn秒以内であること

まず実測

計算上耐えられる負荷に耐えられることは100%無いです。 何かがボトルネックになって、計算上耐えられる負荷より前にサーバが悲鳴を上げます。本番でそれが起こると目もあてられないので、さっさと実測しましょう。 可能ならば、CIとかに組み込んでメトリクスを取ると更に良いです。

本番環境にできうる限り近い環境でやろう

可能ならば本番サーバでやるのが良いですが、無理ならば 可能な限り本番環境に環境を近づけて測定しましょう。 本番でだけproxyサーバを挟んでいる? それがボトルネックになって、本番環境だと負荷に耐えられないと思いましょう。 最近はAWSとか仮想環境に環境を構築している場合が多いと思うので、面倒臭がらずに同様の環境を1つ用意しましょう。あと、データも本番と同様にね!

実測ツール紹介

簡単に単一URLで負荷試験をしたい場合は、Apache Bench が楽に色々なデータが取れるのでオススメです。

複数URLで負荷試験したい場合は、apachebench-for-multi-url というツールも見つけましたが、自分は使わなかったので、誰か使ってみて下さい。

自分の場合は、色々制約や条件があったので、最終的にrubyで負荷ツールを自作しました。ただ、 自作ツールの場合、ツールそのものがボトルネックになる可能性も否定できない ので気をつけて下さい。

中央値も見よう

実測した結果を見てガッカリする前に、平均値だけでなく中央値も見てみましょう。

中央値 : 有限個のデータを小さい順に並べたとき中央に位置する値

平均値だけ高い場合と、中央値も平均値も高い場合とでは、対策が異なるので、平均値だけ見ていると無駄な努力をする羽目になります。

中央値も平均値も高い場合

  • 全体のレスポンスタイムを下げる施策が必要

平均値だけ高い場合

  • 特定のリクエストの場合のみ遅いのであれば、その原因を調査して取り除く
  • リクエスト数によってタイムアウトや待ちが発生している場所を探す

そんなかんじです。良き計測ライフを!

参考

自分の考えるリファクタリング指針

なにこれ?

文書化して明確にしてみよう

目次

  1. 何故リファクタリングをするか?
  2. リファクタリングの優先順位
  3. 性能改善との兼ね合い
  4. どこまでリファクタリングすべきか?

1. 何故リファクタリングをするか?

  • 可読性を上げるため
    • 何故可読性を上げるか?
      • 品質を上げるため
      • 開発速度を上げるため
  • 可読性の高いコードの利点
    • バグを発見しやすい(品質up)
    • 不具合発覚時に修正がし易い(品質up)
    • 機能の追加がしやすい(開発速度up)
    • 再利用しやすい(開発速度up)

ぶっちゃけもう二度と機能追加/修正をしないコードはリファクタリングする必要はない

  • でもなんだかんだ手を入れる事になるんだよね...

2. リファクタリングの優先順位

テスト -> リファクタリング -> 機能追加

3. 性能改善との兼ね合い

  • 可読性を上げたために速度が遅くなった! なんてことはあんまりないので、そこまで気にしなくて良いと思う
    • 理想をいえばCIに性能計測を仕込んで、リファクタリング前後で計測できると良いのだけど...
  • リファクタリングと性能改善は別の作業なので、同時に行わない

4. どこまでリファクタリングすべきか?

個人的な指針なので異論はあると思う

自己満足のリファクタリングはしない

必要に応じたリファクタリングをすべき

リファクタリング前に問うこと

リファクタリングをすべきとき

  • 機能追加の前
    • 積極的にすべき
    • コードを理解するために
    • 追加すべきコードの量を減らすために(品質/生産性up)
  • 機能追加の後
    • コードレビュー時など
    • リファクタリングが行われる最後のチャンスと思っても良いかもしれない
  • 汚いコードを見つけた時
    • ただし、他の作業との優先度は兼ね合うべき
  • 性急な機能追加が一区切りついた時
    • 一区切りつく前に、生産性や品質について課題が発生している場合は絶対にやるべき
    • プロダクトオーナーに了承を取って、一定の期間をリファクタリングに費やす
      • これ以降の生産性や品質が上がります! という形で説得する
      • 課題感を共有できていれば説得できるはず