kasei_sanのブログ

かせいさんのIT系のおぼえがきです。胡乱の方はnoteとtwitterへ

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

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

言いたいこと

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

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

やろうと思えばどこまでも高速化できてしまうので、最初に、なるべく実際の負荷に近いと思われる条件の元、 どんな条件で、どのような結果ならば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)
  • 機能追加の後
    • コードレビュー時など
    • リファクタリングが行われる最後のチャンスと思っても良いかもしれない
  • 汚いコードを見つけた時
    • ただし、他の作業との優先度は兼ね合うべき
  • 性急な機能追加が一区切りついた時
    • 一区切りつく前に、生産性や品質について課題が発生している場合は絶対にやるべき
    • プロダクトオーナーに了承を取って、一定の期間をリファクタリングに費やす
      • これ以降の生産性や品質が上がります! という形で説得する
      • 課題感を共有できていれば説得できるはず

Serverspec本どくしょかんそうぶん

Serverspec

Serverspec

読書メモ

かんそう

  • set_property, property 大事
  • set で使える設定の一覧って、公式ドキュメントのどこにあるの?

作者のスタンス

  • テストを実行することに注力していて、どのサーバに行うとか、サーバ毎の違いを吸収するとかは自分でなんとかしてね!
    • その「自分でなんとかしてね」を実現するライブラリっていろいろありそうだけどどうなのだろう
  • 構成管理ツールとの連携はしない
    • サーバの構成のテストはするけど、構成管理ツールが正しく動作しているかは知らない
    • 構成管理ツールの設定をする人が間違えていないか? 意図しない変更を発生させていないか? を保証する

課題

  • linux系で理解が足りていないことが多い
  • Infratasrer, test kitchen 気になる
  • consul 理解が足りていない
  • Dockerも手を付けたい

【持ってきてよかったもの】4泊6日のオーストラリア旅行に行って【持っていった方がよかったもの】

家庭の用事で4泊6日のオーストラリア旅行に行ってきました

次回の備忘のために、持ってきてよかったものと、持って行ったほうが良かったものを記します

良かったもの

ファーストクラスラウンジのチケット

  • ヤフオクで1枚3500円程度で購入
  • ラウンジ以外に、ちょっとしたレストランでディナーが食べれる
  • 親同伴だったので、ちょっとした親孝行風ができて良かったw
  • ラウンジチケットを見せる前に、エコノミーの航空券を提出したら「お前のラウンジはここじゃねえよ」と遠回しに言われて悲しかった...

SIMフリーのモバイルルータ

  • 海外で気兼ねなくネットができるのはすごく良い!
  • GL04Pジモティーにて5000円弱で購入
  • SIMはOptusを使用。設定方法はSIMが梱包されている紙に書いてある
  • 1日2$で500MBまでのプランがあると、いくつかのblogにあったが、見つけられず(&尋ねても不明だった)
  • 仕方なく1G/10$のプランを選ぶが、何かしらのソフトウェアアップデートが起動し、600M近くを浪費...
  • その後、追加で3G(30$)を購入
  • SMSを使った残額確認や、持ち歩く機器が1個減るので、可能ならSIMフリーのスマートフォンの方が便利

モバイルバッテリー

  • モバイルルータと、iPhoneが1日出歩いてると持たないので必須
  • 多少重くても大容量であればあるだけ良いと思っている
  • 自分は、Anker Astro M3 13000mAhを使用中

iPhone (google Maps!)

  • バス乗車時、目的地と現在地が一発で判断できるのは精神にとても良い
  • 公共交通機関が発達している街の場合、ルート検索がとても便利!
  • ホテルまで迷わず到着
  • あと、現在地の近くの観光地やレストランを一覧表示してくれる機能を初めて知った...

ゴミ袋

  • 100円ショップの20枚位入っているものを1袋
  • 何かと使いみちが
  • 飛行機内等でゴミ袋に
  • 着終わった服入れに
  • おみやげ入れに
  • まるめて割れ物のガードに

歯ブラシ

  • 飛行機に持ち込んで寝る前に使用
  • 後海外のホテルでは大抵歯ブラシが無いので注意!

100円ショップの物干し

  • 靴下や下着は最低限持って行って、洗面台で洗濯して干した
  • あと寝る前にジーンズを干しておくと、後日履くときに少しさっぱり

(シドニー限定)Operlカード

  • suica的なプリペイドSIM
  • 電車、バス、路面電車、フェリーがこれ1枚
  • 駅近くのお店でタダで貰えて、その場でデポジット可能(最低10$
  • 料金キャップ制なのでお得
    • 平日15$、休日2.5$!
    • 空港に電車で行くときは、空港税が別料金
  • 時間によってはバスはOperlカード限定らしい

持ってくれば良かったと思ったもの

スリッパ

  • 機内、ホテル(備え付けが無かった!) であると便利
  • シャワーの後も履くので、サンダル的なものの方がよいかも

給電可能なusbハブ

  • 変換プラグ2個では足りず
  • モバイルルータとモバイルバッテリーと、iPhoneをまとめて充電したかった

長めのUSBケーブル

  • 飛行機の充電ポートが大体変な位置にあるので長いほうが便利

英語力(だいじ

そんな感じでした

【1日1gem】 rspec3 でも its が使いたい! rspec/rspec-its

1日1gemとは

最近好きなgemってありますか? という質問に自分が答えられるように始めたgemを紹介する記事

rspec/rspec-its

https://github.com/rspec/rspec-its

何をするの?

rspec3 で core から無くなった、 its を復活させる gem

  • 正確には、 its が別gemに分離した

サンプル

require_relative '../lib/hoge'

RSpec.describe Hoge do
  let(:message){ 'hello' }
  subject { Hoge.new(message) }

  # こんな風に書き換えられる
  #it { expect(subject.message).to eq(message) }
  its(:message) { is_expected.to eq(message) }

  # ネストできる
  its('say.hello') { is_expected.to eq('hello') }

  describe '#saids' do
    before do
      @hoge = Hoge.new(message)
      @hoge.say.hello
      @hoge.say.hoo
    end
    subject { @hoge }
    # 複数型なら `are_expected`
    its('saids') { are_expected.to eq(%w[hello hoo]) }

    describe 'array' do
      subject { @hoge.saids }
      # 配列の要素指定
      its([1]) { is_expected.to eq('hoo') }
    end
  end
end

そもそもなんで its が core から無くなったの?

ここに、rspec の中の人のコメントがある

Explanation for why `its` will be removed from rspec-3 · GitHub

要約すると、 its を使った場合に、rspecの出力結果が直感的でなくなって、デバッグに支障がでると思うので辞めたとのこと ただ、個人的にはあんまり納得いってない

  • コメントにある it { expect(subject.name).to eq "Bob" } みたいに書いた場合、 its と変わんないのに、ただコードが長くなるだけでないの? という疑問への回答が無い
  • 悪い例が書かれているけど、良い例が無いので、「じゃあどうするのが理想なの?」への回答が無い
  • そもそも、rspec って、テストコードを英文と一致させることを諦めてなかったっけ?

ActiveRecordeの関連付けで、class名と異なる関連名を使いたい場合、 class_name オプションを使う

こんな場合

class Item < ActiveRecord::Base
  has_one :item_detail, dependent: :destroy
end
class ItemDetail < ActiveRecord::Base
  belongs_to :item
end

ItemDetail を参照するとき、記述が冗長になってしまう

# item って単語が重複するのがキモい
item.item_detail.description

こういう時には、class_name オプション

class Item < ActiveRecord::Base
  has_one :detail, dependent: :destroy, class_name: ItemDetail
end

こうすることで、関連名は、 detail。 実際に使用する model は、 ItemDetail になる

item.detail.description

便利!

paperclip の写真の格納先をS3に変更する

やりたいこと

paperclip の写真の格納先をS3にしたい

方法

Paperclip に S3 用のオプションがあるので、それを使う

aws-sdk のインストール

Gemfile

gem 'aws-sdk'

paperclip のデフォルトの設定を追加

config/application.rb

  class Application < Rails::Application
    config.active_record.raise_in_transactional_callbacks = true

    config.paperclip_defaults = {
      storage:        :s3,
      bucket:         ENV['S3_BUCKET'],
      s3_region:      ENV['AWS_REGION'],
      s3_credentials: {
        access_key_id:     ENV['AWS_ACCESS_KEY'],
        secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
      },
      hash_secret:    'uO4l0IJA5hWKPo3kDgXj/Oo9H1KvDt912jDkzOIpP2ecaBMQgejN0MtVdkCee0FMOooNAnqIyMzIbb9BINVMbVza8Xbu8LT7Ee1vu538JzRtUKpLlB6hOezs/FzCBSmmmch4pDUemROm7iS8O8GAKs9jNkLUJydbqXHBvWX2qJM',
      path:           ':attachment/:style/:hash.:extension',
    }
  end
end
  • storage: S3を使いたい場合は :s3
  • bucket: 格納先のbucket名
  • s3_credentials: S3の認証情報
    • access_key_id と、secret_access_key が必要
  • s3_region: S3のリージョン
    • S3の管理画面にアクセスした時に home?region=us-east-1 みたいに URLに表示されるやつを指定すればよい...はず...
  • s3_host_name: S3のホスト名
    • S3の管理画面の適当なオブジェクトのプロパティを開いて「リンク」を見れば分かる
  • hash_secret: ファイル名にhash(後述)を使いたい場合のhashのキー
    • secret とあるけど、まぁ別にhash名から元のファイル名を復元されても困らないので直書き
  • path: S3のup先のpath
    • attachment: has_attached_file で指定した attachment_name
    • style: has_attached_file で指定した style
      • medium とか thumb とか。後オリジナル画像は、original
    • hash: ファイル名をhashにしたもの
      • ファイル名が2バイト文字とかの時に困らないように
    • extension: ファイルの拡張子

参考 : https://github.com/thoughtbot/paperclip#defaults

トラブルシューティング

endpoint を指定しろ的なエラーが出る

The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint
  • s3_host_name の設定漏れ

環境変数 AWS_REGION を設定しろ的なエラーが出て、設定してもおんなじエラーが出る

Aws::Errors::MissingRegionError (missing region; use :region option or export region name to ENV['AWS_REGION']):
  • s3_region を設定する
  • 環境変数を設定しても paperclip の s3_region を優先するらしく、反映されない