Slide 1

Slide 1 text

出張!Railsウォッチ
 in 銀座Rails#17
 森 雅智 / @morimorihoge 2020/01/16 1
 特集:~リソース管理スコープについて~


Slide 2

Slide 2 text

About Me
 ● 森 雅智: @morimorihoge
 ● BPS株式会社でRailsの受託開発チームをやってたり、週1大学非常勤で Web開発を教えてたりします
 ● Ruby/Rails歴は10年くらい。Web開発は16年くらい
 ● 銀座Ralis #10でActiveRecordでVIEWを使おうという話をしました
 About BPS & TechRacho
 ● Web受託開発や電子書籍製品開発をやっている会社です
 ● TechRachoという自社技術Blogを運営しています
 ○ 3年ほど前から平日毎日更新してます
 ○ https://techracho.bpsinc.jp/ ● お仕事相談、転職相談、TechRachoへのご意見など気軽にどうぞ
 ○ https://www.bpsinc.jp/ 2


Slide 3

Slide 3 text

Railsウォッチとは?
 技術ブログTechRachoで毎週連載しているRails / Ruby界隈を中 心とした雑多な情報を提供する技術雑談マガジン
 3


Slide 4

Slide 4 text

これまでの出張Railsウォッチのピックアップテーマ
 ● Rails6新機能特集
 ○ 銀座Rails#12: 複数DB対応
 ○ 銀座Rails#13: ActionText、Trix
 ○ 銀座Rails#14: ActionMailbox
 ● Railsアプリケーション開発に関する雑多なテーマ
 ○ 銀座Rails#15: production、development、staging環境につ いて
 ○ 銀座Rails#16: 機能開発の設計レビューについて
 4
 ※過去のスライドはTechRachoにて公開しています。「TechRacho 銀座Rails」あたりで 検索するとヒットしますので興味のある方はどうぞ


Slide 5

Slide 5 text

Ruby 2.7.0リリース
 ● 無事2019/12/25にリリースされました
 ● 新機能の解説については公式およびその他の解説サイトをどうぞ
 ○ https://www.ruby-lang.org/ja/news/2019/12/25/ruby-2-7-0-released/ 
 ● Ruby3に向けてキーワード引数とpositional引数の自動変換が非推奨になり、 deprecation warningsが出るようになった
 ○ 
 5


Slide 6

Slide 6 text

Rails: 6.0.2.1リリース
 ● 12/19にCVE-2019-16782に対応したセキュリティアップデートが出ています ○ Cookieに保存されるsession_idとサーバーサイドのsession_idが同じだと、タイミングによってセッ ションハイジャックが発生することがあったのが修正されています 6


Slide 7

Slide 7 text

Railsエンジニアが知っておきたい
 リソース管理スコープの話
 7


Slide 8

Slide 8 text

リソース管理スコープ?
 8
 ● 僕の造語です(注意)。適切な用語が思い浮かばなかったので、もし正しい用語を 知ってる人いたら教えて下さい
 ● サーバーサイドアプリケーション開発者から見た時に、アプリケーションで保存・参 照するデータ(ファイルやメモリ上に展開されているデータ)がどこに保持されてい て、それらがどういう特性を持つのかという話
 ○ クライアントサイドも含めると説明することが膨大になるので今回cookieやlocalStorageは範囲外と します
 ● 昔からWebアプリ開発をしている人には自明かも知れませんが、社内外のコードを レビューしたりしていると意外と見落としているケースを見るのでまとめてみました
 ● コードレビューやアプリケーション設計に役立つはず!


Slide 9

Slide 9 text

よくあるRailsシステムのポンチ絵
 9


Slide 10

Slide 10 text

よくあるRailsシステムのポンチ絵
 10
 (ほぼ)嘘です
 ※少なくともリソース管理スコープの視点では、情報が足りなすぎる 


Slide 11

Slide 11 text

実態
 11
 実際には更にCDNやmultiple DBなどもあれば増えるので、これでも小さい方だと思います 


Slide 12

Slide 12 text

こういうハマり方したことのある人向けです
 ● クラス変数をアプリケーションコードで上書きしてしまい、謎のバグを仕込んでしまっ たことがある
 ● サーバー1台構成では大丈夫だったが、本番で複数台に冗長化したらバグったこと がある
 ● 1-process/1-thread設定のunicornをマルチプロセス動作のpuma/unicornに変更し たらバグったことがある
 12


Slide 13

Slide 13 text

リソース管理の各スコープレベル
 ● サービスインフラ全体レベル
 ● サーバーホストレベル
 ● プロセスレベル
 ● スレッドレベル
 ● リクエストレベル
 ● ブロック内変数スコープレベル
 13
 サービスアーキテクチャ
 Linux OS
 Ruby/Railsコード


Slide 14

Slide 14 text

サービスインフラ全体レベル
 ● DBサーバーやRedis/Memcached、AWS S3などのオブジェクトストレージ
 ● 利点
 ○ どのリクエストから更新・参照を行っても同じ結果になる 
 ○ 更新・削除が直ちに他のリクエストの処理結果に反映される 
 ○ リソース側に排他制御の仕組みがあれば、排他制御は自前実装不要 
 ● 欠点
 ○ 全サーバースレッドがリソース共有するため、性能劣化の原因になりやすい 
 ○ ネットワーク越しのアクセスになるため大きな遅延が発生する 
 14


Slide 15

Slide 15 text

サーバーホストレベル
 ● ファイルシステムやOSファイルキャッシュなど
 ● 利点
 ○ ネットワーク通信不要なのでDB等に比べて高速 
 ○ fseekなどを使い、ファイルの特定位置だけアクセスするなどが可能 
 ● 欠点
 ○ サーバーホストを跨ぐとデータが共有されないので、サービス全体で使いたい場合は別途同期処 理などが必要になる(排他制御も!) 
 ○ ロードバランサレベルでブラウザとWebサーバーを紐付けるような機能の併用が必須(AWS ALBの Sticky Sessionなど) 
 ○ Webサーバーのリソースを消費するので、ディスク空き容量などは監視が必要 
 15


Slide 16

Slide 16 text

プロセスレベル
 ● クラス変数やグローバル変数、環境変数など
 ● 利点
 ○ 全てのスレッドで共有できるデータ(ライブラリデータやconfig)をメモリ効率良く扱うことができる 
 ○ 固定データであればfork前にマスタープロセスで展開しておくと、プロセス間でもメモリ共有が可能 (OSの持つcopy on write機能) 
 ● 欠点
 ○ 配下スレッドがデータを変更すると他のスレッドにも影響が伝搬してしまう 
 ○ メモリ解放漏れがあるとゴリゴリ消費メモリが増えていく 
 16


Slide 17

Slide 17 text

スレッドレベル
 ● スレッドローカル変数など
 ● 利点
 ○ fiberに分割しない限りは1リクエストを処理する間他のリクエストに影響されず、安全にデータを保 持できる(マルチfiberなサーバーであるfalconが主流になると変わる可能性あり) 
 ● 欠点
 ○ スレッドが再利用される際に前のリクエストのデータが残っていると問題が起きる可能性 
 ○ メモリ解放漏れがあるとゴリゴリ消費メモリが増えていく(プロセスレベルと同じ) 
 17


Slide 18

Slide 18 text

リクエストレベル
 ● ActiveSupport::CurrentAttributesなど
 ● 利点
 ○ 1リクエスト内でのみ有効なグローバル変数の様な扱い方ができる 
 ● 欠点
 ○ どこからでもアクセスできるSingletonなので、プログラムとしては行儀が悪くなりがち 
 ○ メモリ解放はRailsがやってくれるので、値で保存する限りは解放漏れを心配しなくて良い 
 18
 ※厳密にはスレッドレベルより更に詳細な区分けになる
 (スレッドの寿命 > リクエストの寿命)


Slide 19

Slide 19 text

ブロック内変数スコープレベル
 ● これも勝手に命名したが、要はRubyのブロック内で宣言した変数のこと
 ● 利点
 ○ ブロック内で宣言した変数は(一般的な方法では)外からアクセスできないので、排他制御が簡単 
 ○ ブロックを脱出すれば適切なタイミングでRubyがGCしてくれる(はず) 
 ● 欠点
 ○ 他のメソッドに引き渡したり、別のスレッドから参照させたいと思った場合には使うことはできない (オブジェクト参照を引数で渡したりする必要がある) 
 19
 ※この図だと表現しにくい(説明むずかしい)


Slide 20

Slide 20 text

リソース管理スコープ別比較
 20


Slide 21

Slide 21 text

こう考えると大体OKかな?
 ● サービスで永続化・共有する必要のあるデータはサービス・インフラ全体レベルで 管理する
 ● キャッシュや処理するデータのうち、アクセスユーザー単位で偏らせると処理できそ うなデータはサーバーホストレベルで管理する
 ○ OSのファイルアクセスがどうしても必要な場合もこれ 
 ● アプリケーション設定など、アプリケーションコード全体で共有され、実行中に変更 されないデータはプロセスレベルで管理する
 ● スレッドレベルは使わず、プロセスレベルかリクエストレベルを使うべき
 ● どうしてもSingletonを扱いたいときにはリクエストレベルで管理する
 ● 上記に該当しないものはなるべくブロック内変数レベルに閉じて管理する
 21


Slide 22

Slide 22 text

DBアクセスは早いのか?
 アクセス速度だけ見るならメモリアクセスと比較すると明らかに遅い
 22
 参考: https://colin-scott.github.io/personal_website/research/interactive_latency.html 
 ※データ処理などはDBにやらせたほうが結果として早くなることはある
 参考


Slide 23

Slide 23 text

まとめ
 ● Railsアプリケーションコードを書くバックエンドエンジニアが知っていて欲しいリソー ス管理スコープについてまとめました
 ● 僕の中で温めていたことを書き出してみたv1的な内容なので、懇親会・Twitter等で ぜひツッコミ歓迎です
 ● 各管理レベルに応じて向き・不向きがあるので適切なデータ管理方法を選択する 参考にしてもらえると幸いです
 23


Slide 24

Slide 24 text

宣伝:週刊Railsウォッチ 公開つっつき会
 ● 毎月第一木曜日、社外の方も参加できる公開つっつき会を開 催してます
 ○ 次回は2020/2/6(木)19:30~@西新宿 BPS会議スペース にて
 ● TechRachoの週刊Railsウォッチの最新記事、または「週刊 Railsウォッチ公開つっつき会」でぐぐってご参加下さい!
 ○ https://techplay.jp/event/767484
 24


Slide 25

Slide 25 text

次回以降もブラッシュアップしていきます
 感想・リクエストなどあればTwitter
 #ginzarails
 @morimorihoge
 @hachi8833
 までお声かけください
 25