リゾームの開発OJTでの学びと成長ポイント

株式会社リゾーム 業務ソリューション事業部 企画開発課の梶谷です。

今年入社し、5月から12月頭まで開発OJTに参加しましたので、今回はその具体的な内容をご紹介します。

私はIT系の専門学校を卒業してはいるものの、コードを自力で書いた経験はあまりなく実務スキルがほとんどない状態でOJTをスタートしました。

ほぼ未経験で弊社の開発OJTに参加して成長したことや、特にありがたかった点もお伝えしますので、就職活動中の方や開発系のOJTに関わる方の参考になれば幸いです。

開発OJT概要

まずは具体的にどのような取り組みを行ったか紹介していきます。 OJTの取り組みは、大きく3つのカテゴリに分けられます。

  • 通期で継続して行った内容
  • 期間を区切って集中的に取り組んだ内容
  • 個人で自主的に進めた内容

この3つに分けて、具体的にご紹介します。

通期で取り組んだこと

OJT全体を通して継続して行った取り組みです。

昼会

毎日、昼休み後に実施しました。 当日の取り組み内容を自分の言葉で解説する形で先輩に報告し、理解度を確認してもらう時間として活用していました。 報告の中で不明点が明らかになった場合はその場で先輩から説明を受け、疑問を解消しました。

OJTフィードバック

毎週金曜日に実施しました。先輩から今週の課題に対するフィードバックを受け、理解度や改善点を確認した後、次週の予定を確認し目標を設定していました。

日報の記入

毎日、その日の作業内容や理解できたこと、課題を記録しました。記入後、先輩からアドバイスをコメントしてもらい、改善点や次の取り組みを確認しました。

メンター面談

月に一回ほど実施しました。OJTで技術面をサポートする先輩とは別に、メンターの先輩と業務やキャリア、働き方など幅広い相談ができる場で、学習以外の不安も解消できました。

期間を区切って取り組んだこと

特定の期間で集中的に進めた学習です。 製品で使用している技術を中心に学んでいます。

ZENStudy:Webアプリケーション開発(5月頭~7月半ば)

www.nnn.ed.nico

こちらの学習ツールを使ってプログラミングの基礎文法やWebアプリケーションの仕組み、アルゴリズムなどについて学び、プログラミングについての基礎知識を実際に手を動かしながら身につけました。

プロを目指す人のためのRuby入門(7月半ば~8月半ば)

こちらの本を読み弊社製品の開発言語であるRubyについて学習しました。

1冊ですべて身につくHTML & CSSとWebデザイン入門講座(7月半ば~8月半ば)

こちらの本を読んで、読書会として開発OJT参加メンバーで感想を発表することでHTMLとCSS、Webデザインについての知識を身につけました。

Railsチュートリアル(8月半ば~10月半ば)

railstutorial.jp

こちらの教材を利用し、教材を見ながら実際にサンプルアプリケーションを作成することでRailsについての基礎知識を身につけました。

RSpecによるRailsテスト⼊⾨(10月半ば~10月末)

leanpub.com

こちらの教材を進めることを通してRSpecでのテストについてやテスト駆動開発の知識を身につけました。

オリジナルアプリケーション制作(11月頭~12月頭)

設計から自分で考えてアプリケーションを実装し、作成したものを部内で発表しました。

個人での取り組み

その他、個人で取り組んでいた取り組みについても紹介します。

タッチタイピング練習

私はタッチタイピングがあまりできなかったので業務内で時間を決めてタイピングソフトでタッチタイピングの練習をしていました。

未経験としてありがたかったこと

ほぼ未経験で研修を受けてみて特にありがたかったことについて挙げていきます。

毎日の昼会で質問できる環境

OJT開始直後は「わからないところがわからない」といった状態になっていました。

昼会で自分の言葉で説明する際に初めて分からないことが発覚することが多かったのですが、先輩に理解度を把握してもらえたことで適切なサポートを受けられ、分からない部分をその場で解消できました。また、学習内容以外にも業務に関する悩みも相談できたので安心して学習に集中できました。

課題を最後までやり切る方針

学習進度が同期よりも遅れてしまうことがありましたが、途中で中断することなく最後までやり切るための時間を確保していただきました。 その結果、基礎からしっかり理解でき、後々の応用力につながりました。

定期的なフィードバック

毎週の振り返りで、今週の課題と次週の目標が明確になりました。自分の進捗を客観的に確認でき、モチベーションを維持できたと思います。

初歩的な内容から学習を始められたこと

ZENStudyやRuby入門など、基礎から段階的に学べる教材が用意されていたので未経験でも取り組みやすく、理解を積み重ねながら進められました。 また、タッチタイピングの練習時間を設けて貰えたりと業務に直結する基礎的なスキルを身につける機会があったこともありがたかったです。

一から自力でアプリ開発を行い、成果を大人数の前で発表する機会があったこと

オリジナルアプリケーション制作で読書会用の書籍と感想登録ツールを開発したのですが、設計から開発まで初めて自力で完成させることができたので貴重な経験となりました。

これまで実用性のあるアプリケーションを作ったことはありませんでしたが、実際に使用を想定したものを制作できたことで、新しい視点を得られたと思います。 また、発表という明確なゴールと制作期限があったことで、開発にメリハリをつけて取り組めました。

成長したこと

研修を通して成長できた点についても挙げていきます。

理解度を言語化し、質問できるようになった

昼会で説明する習慣により、分からない部分を明確化できるようになりました。毎日先輩に説明することで説明力と論理的な整理力が向上したと思います。

疑問をすぐ解消する姿勢が身についた

毎日の昼会で分からないところを先輩に相談できたこともあり、疑問を放置せず、早めに相談する習慣が定着しました。 学習効率が上がり、課題を着実に進められるようになったと思います。

焦りをコントロールし、着実に進める力を得た

学習進度に遅れをとってしまった際、同期との進捗差に焦りを感じても、優先度を整理しキャッチアップする方法を学びました。 理解を優先する重要性を実感し、落ち着いて学習に取り組めるようになりました。

チームコミュニケーション力の向上

毎日の昼会や週次フィードバックで、進捗共有や相談の習慣が身につきました。 チームで協力しながら進める意識が強まったと思います。

おわりに

ほぼ未経験からのスタートでしたが、OJTを通じて基礎から応用まで幅広く学ぶことができました。

「わからないところがわからない」という段階から始まったOJTでしたが、少しずつできることが増えました。 オリジナルアプリケーション制作の際に、自力で開発を進められるようになっていたことは大きな成長だと思っています。

今後は製品に関するOJTが始まり、実際の開発に関わる機会も増えていくと思います。これまでに身につけた知識を生かし、さらに成長できるよう努力していきます。

同じように挑戦する方にとって、この記事が少しでも参考になれば嬉しいです。

新卒エンジニアがリモートワークをやるうえで気づいた工夫

株式会社リゾーム 業務ソリューション事業グループの富田です。 今回は、2025年4月入社の私がリモートワークをやる上で気づいた社内での工夫、やって良かったことを紹介します。リモートワーク勤務に興味のある方や、弊社に興味を持っていただいた方の参考になればと思います。

リモートワークで気づいた工夫

私がリモートワークで気づいた、社内で行われている工夫について紹介します。

コミュニケーションの工夫

リモートワークは人と話す機会が少ないと思っていたのですが、実際は人と話す機会が多く、会議が業務時間の半分以上を占めることもありました。また、コミュニケーションの大半が通話やテキストチャットを使っているため通常以上にコミュニケーション能力が必要だと感じました。その問題の対策として、リアクションやビデオ通話が活用され、文字や音声だけでは伝わらない感情を表現でき、効果的な取り組みだと思いました。私も他の人の投稿に「いいね」をたくさん押して、自分の気持ちを伝えるようにしています。

自己管理の難しさと日報の役割

リモートでは、作業を直接確認できないため、自分で仕事やスケジュールを管理する必要があります。また、自宅で作業をしているので、仕事とプライベートの切り替えが難しいと感じるときがあります。私の部署では、朝会で予定を共有し、夕会で日報を作成してチームメンバー全員が進捗を確認しています。予定や日報を書くことで、進捗の整理ができるだけではなく、アドバイスや新しい気づきを得られ、気分の切り替えにもつながるので、とても助かっています。

孤独感を感じたときに助かること

一人で作業をすることが多いため、孤独感を感じることがあります。特にアイデアが出てこないときや、自分の作業が間違っていないか不安になるときに、孤独感を強く感じます。そんなとき、私の部署で取り組んでいる「分報」を活用しています。「分報」とはチャット上で自分の作業内容や感じていることをリアルタイムに書き込む仕組みです。これによって、自分の作業内容を客観的に整理できたり、つぶやきにリアクションをもらえることで、孤独感が和らぎ安心します。

チームメンバーのサポート

私が新人研修から配属されたときに感じたことですが、チームメンバーのサポートが強く印象に残っています。どんな質問にも丁寧に答えていただき、分からないことを分報に書き込むとアドバイスをいただけるので非常に助かりました。こうした助け合いが結局、一番大切なのかもしれないと思いました。

リモートワークでやって良かったこと

私がリモートワークで意識している所、やって良かったと思っている所を紹介します。

積極的な自己開示

『自己開示?』と思うかもしれませんが、私はこれがとても重要だと考えています。出社時と違い、自分を知ってもらえる機会が少ないため、特に新入社員はどんな人で何を考えているのかが分かりにくいです。相手にとって不安を与えないように、自己開示の機会を見つけて、自分のことを知ってもらえるように意識しました。開示する内容は、基本的になんでも良いと思います。「好きなもの」、「興味のあるもの」、「過去の経験」などポジティブに伝えました。積極的な自己開示をしたことで、共通の話題が広がり、チームメンバーとの距離が縮まりました。

適度に休憩をとる

私は作業に集中しすぎると、休憩を忘れがちになります。特に、一人で作業をしていると、つい長時間作業してしまい、その後の集中力が途切れてしまうことがあります。そうならないために、適度な休憩を取りながら、効率的に作業を進めることが大切だと思います。私の場合、少し歩いて体を動かす、カフェオレを飲む、音楽を聴くなどのリフレッシュをして、気分を切り替えています。

快適な作業環境づくり

一日の大部分を過ごすリモート環境を快適にすることは大事なことだと思っています。特にリモート環境は、自由に作ることが出来るからこそ、こだわりたい部分です。私の場合、モバイルモニターや専用の机と椅子を用意し、気分転換に音楽を聴ける環境を作っています。さらに、椅子に座り続けて疲れたときは座椅子に移動できるようにしており、こうした工夫で常に快適な状態で作業できています。

終業後の運動習慣

リモートワークでは、外出する機会が少なくなり、座りっぱなしで作業することが多くなりがちです。私も運動不足を感じました。長く健康に仕事を続けるためには、意識的に体を動かすことが大事だと思います。私は仕事終わりに、エアロバイクを使い、運動不足を解消するようにしています。エアロバイクは、ゲームや動画を楽しみながらできるので、無理なく続けられ、とてもおすすめです。

終わりに

入社してから気づいたリモートワークの工夫、やって良かったことを紹介しました。まだ入社して一年も経っていない新人ですが、これからリモートワークを始める方や興味のある方にとって、少しでも参考になれば嬉しいです。最後まで読んでいただき、ありがとうございました。今後も気づきを発信していきたいと思います。

サポート役としての新人育成体験

株式会社リゾーム 業務ソリューション事業グループの土井です。 今回は、2024年度に新人が同じ部署に配属された際、OJTトレーナーではなくサポート役として関わった経験をご紹介します。 新たにOJTに関わる可能性が出てきた方や就職活動中に弊社に興味を持っていただいた方の参考になればと思います。

新入社員研修の概要

まず最初に2024年度の新入社員が入社からどのような流れで研修を受けていったかを簡単に紹介します。

新入社員研修(4月)

ビジネスマナー、自社製品、SC業界についてなどの、今後仕事をしていくうえでの基礎的な内容を他部署の新入社員と一緒に研修を受けてもらいました。

開発部門の研修(5月~10月)

開発の業務を行っていくうえで必要なプログラミングの基礎知識や、実務で使用していく言語やフレームワークについて書籍やEラーニング教材を使用して学習してもらいました。

実務(10月~)

実際の業務にサポートをしつつ慣れていってもらいました。

OJTの概要

OJTでの取り組みは先ほど紹介した開発部門での研修以降行っていました。具体的にどのような取り組みを行っていたかをこちらも簡単に紹介します。

出社でのフォロー

所属する部署は基本的には在宅勤務でのリモートワークですが、最初の1か月間は慣れてもらうことや質問のしやすさ等を考慮して、出社での勤務とフォローを行いました。

昼会

日々の進捗、疑問点などを共有してもらうために毎日お昼休みの後に、新人、OJTトレーナーの先輩、私の3人で昼会を開催していました。特に在宅勤務になってからはコミュニケーションの場としても役立ったと感じています。

週次のふりかえりMTG

その週での取り組みのふりかえりや、次週のタスクの計画をする会を毎週金曜日の定時前1時間ほど昼会と同じく3人で行っていました。昼会とは異なり毎回レジュメを作成し、OJTでの活動全体を振り返ることで進捗や課題を整理していました。

モブプログラミング

Visual Studio CodeのLive Share機能を使用してモブプログラミング*1を実施しました。同じコードを共有して操作することで指導がしやすくなり、リアルタイムで相談しながらコーディングを進めることができました。

Live Share機能については以下リンクをご参照ください。 learn.microsoft.com

実施してよかったと思うこと

ここからは、実際にやってみて「これは良かった!」と思った取り組みをご紹介します。 OJTトレーナーではなくあくまでサポートという立場で以下2点は特にうまくいったと思うので紹介します。

先輩の負担を減らす

OJTをスムーズに進めるために、会議室の予約やteams会議の作成など雑用的な部分は実施するようにしていました。 ただ新人にもできるようになってもらう必要があるので、余裕が出てきたタイミングで予約や会議作成自体を依頼するようにしていました。

書記的な役割

週次のふりかえりMTGなどで事務的な記述を行う作業は出来るだけ実施するようにしていました。 MTGの進め方として会話をしながら書いていく場面も多く、そのような場面ではOJTトレーナーの先輩や新人に記入してもらっていました。

特に効果的だったと個人的に思っているのはモブプログラミングの際です。 モブプログラミングの進行上、どうしてもコードを記述→相談→またコードの記述といった流れになります。新人はメモを取る余裕はないと思い、裏でメモの作成を行っていました。会話をしながら作成したコード自体に加えて、こちらで作成したメモを使うことでモブプログラミングのふりかえりの助けになったのではと思います。 

反省点

振り返ってみて、改善できたと思う点が1つあります。OJTで使用するドキュメントの整理をOJTトレーナーの先輩が作成してくださっていたのですが、私も作成にもっと関わるべきだったと思います。負担の分散はもちろんですが、書記的な役割を果たすうえでドキュメント化をするところまで念頭に置いておくべきだったという反省があります。

実際の評価

今回のブログ執筆を機に改めてOJTの先輩と新人から以下のようなフィードバックを頂きました。 自ら考えて実施した「先輩の負担を減らす」こと「書記的な役割」が実際に役に立てていたようでよかったです。 一方で新人と比較的近い立場であることがメンタル面で役立っていたのは新たな気づきでした。

OJTトレーナーの先輩から

  • 会議でのメモ取りが非常に助かった
    • 話の流れや重要なポイントを記録してくれたことで、振り返りがしやすくなった
    • 教えながら同時にメモを取るのは難しいため、サポーターの恩恵を強く感じた
  • 会議予約などの率先した対応
    • 「次は○日の×時に会議室Bでやりましょうか」という会話をキャッチしてすぐに予約してくれることで、予定の抜け漏れが防止され安心できた
  • メンター的な役割
    • 年齢・キャリア的に新人の目線に近く、メンタリング的なサポートも果たしていた
  • チーム全体への効果
    • チームとしてフロントエンド技術を改めて学ぶことが出来たため、結果的にチーム全体のレベルアップにつながった

新人から

  • 入社時期の近い先輩の意見を聞けた点
    • ReactやNext.jsの学習で、過去に同じように勉強した人の目線で助言をもらえたのが良かった
    • 特にNext.jsは難しく感じていたが、「自分も難しかった」と私から一言もらえるだけでメンタル的に楽になった
  • モブプログラミングで複数の視点を得られた点
    • 「コードはどこから読むのがいいか?」といった議題で、OJTトレーナーの先輩からだけでなく複数の意見を聞けたことで、考え方を学ぶ上で非常に助かった
  • 書記・メモのサポート
    • メモを取っていたが、より詳細な手順を記録してくれていたため、聞き直しが減った
    • 新人自身で作成したメモと私が作成したメモを見比べることで、認識の間違いに気づけた場面もあった

おわりに

OJTトレーナーではなくサポート役として新人育成に関わった経験を振り返ってみると、直接教える立場ではなくとも貢献できる場面がたくさんあると感じました。周囲をサポートし、仕事のしやすい環境を整えることは、通常業務でも求められる大切な役割だと改めて感じました。 今後OJTに関わるとなるとサポートとしてではなく、OJTトレーナーとしてかかわると思うのでこの経験を活かしていければと思います。

*1:モブプログラミングは複数人で同じコードに対してコーディングを行うこと。同じコードを見ながら作業を進めるためコミュニケーションを密にとりながら作業を行える。

ActiveJobの優先度制御にNice値を使用する

株式会社リゾーム 業務ソリューション事業グループの原です。

弊社ではショッピングセンター向けの製品の自社開発を行っており、私はBOND GATEという製品の開発に携わっています。 こちらはRuby on Railsで開発しており、その中の管理者用の機能の一つとして、ログの内容をCSVファイルにして出力する機能があります。

今回は、この機能を一部の環境で使用した際に、処理が重くなり動作しなくなる……という事象が発生しました。 そのときの対応・検証についてまとめたので、似たような問題が起きた際の解決策となると思い、記事にしています。

経緯

ログ内容のCSVファイルを出力するActiveJobを実行した際に、ある環境だけメモリ使用率が100%まで達し、処理ができなくなるという状態が発生しました。

原因を調べたところ、大量のActiveRecordeachで処理しており、環境によっては100万件以上になってしまうためメモリが足りなくなってしまう……という状態でした。

これに関してはfind_eachを使うことでメモリ使用率は抑えられる……のですが、今度はCPU使用率が90%前後になっていました。 BOND GATEはAPサーバとワーカーを1台サーバーで動かしているので、ワーカーがCPUを90%も使っていたらAPサーバが動けなくなってしまいます。

この負荷への対処方法を検討していた際、当初はActiveJobのCPU使用率が高いことから、リソースの制限を加える方向で考えていました。

チームで調査を進める中で、「プロセスの優先度を下げれば、他の処理に影響を与えずに済むのでは?」というアイデアが出ました。調べてみると、Linuxには「Nice値」というプロセスの優先度を調整する仕組みがあることがわかりました。これを使えば、他の処理に影響を与えずに負荷をコントロールできそうです。

本当に効果があるのかを確かめるため、検証を行うことにしました。

Nice値の設定

webkaru.net

0を標準として、-20~19の範囲で数字を大きくするほど優先度は低く、下げると高くなります。逆にしないように注意。

ActiveJobアダプタにはsidekiqなどがありますが、BOND GATEではqueというgemを使用しています。

github.com

queのプロセスはsystemdで設定しているので、Nice値もここから設定できました。

[Service]
Type=forking
WorkingDirectory=#{current_path}
ExecStart=/opt/bondgate/bin/que_#{File.basename(deploy_to)}.sh
PIDFile=#{shared_path}/pids/que.pid
User=********
Group=********
Nice=19

これでデプロイするとqueのNice値が19になったので、ここからstress-ngコマンドを使って負荷をかけていきます。

まずはstress-ngの負荷を色々変えてみて、topコマンドでジョブ実行中のqueがどのくらいのCPU使用率になるのかを見てみます。 (COMMAND列は長くなり見づらくなったため書き換えています)

  • stress-ng 100%
    • queはほとんど使われなくなる
stress-ng --cpu 0 --cpu-load 100
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                     
2703937 ********  20   0   84508   7736   4016 R  93.4   0.2   1:43.14 stress-ng 100                                            
2703938 ********  20   0   84508   6220   4020 R  92.1   0.2   1:42.42 stress-ng 100                                            
2424664 ********  39  19 1745624 483748  11368 S   1.0  12.3  38:38.20 que
  • stress-ng 50%
    • queの使用率は70~80%
    • 負荷なしのときより多少使用率は減るが、あまり変わらない印象
stress-ng --cpu 0 --cpu-load 50
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                     
2424664 ********  39  19 1745624 483752  11368 R  78.7  12.3  40:13.35 que
2704125 ********  20   0   84508   6424   4232 S  46.8   0.2   0:52.49 stress-ng 50
2704126 ********  20   0   84508   6424   4236 R  45.5   0.2   0:52.48 stress-ng 50                                             
  • stress-ng 80%
    • queの使用率は45%前後
 stress-ng --cpu 0 --cpu-load 80
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                     
2704529 ********  20   0   84508   7612   3884 R  76.7   0.2   0:54.29 stress-ng 80                                             
2704530 ********  20   0   84508   7612   3888 R  75.1   0.2   0:54.32 stress-ng 80                                             
2424664 ********  39  19 1745624 483740  11368 S  42.5  12.3  43:41.81 que
  • stress-ng 80% + abコマンド
    • abコマンド(Apache Bench)を使って並列で100アクセスさせる負荷を追加でかけてみました
    • queの使用率は20~30%程度
stress-ng --cpu 0 --cpu-load 80
ab -c 100 -n 1000 https://********
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                 
2706435 ********  20   0   84508   6300   4100 R  56.1   0.2   1:35.51 stress-ng 80                         
2706434 ********  20   0   84508   6300   4096 R  54.5   0.2   1:35.82 stress-ng 80                         
2424664 ********  39  19 1745624 484084  11368 S  22.3  12.3  45:59.07 que

その後Nice値を変えて結果が変わるのかも見てみました。reniceコマンドで実行中のプロセスのNice値を変更できます。

renice 0 -p <PID>

queの優先度が高くなるのだから、先程よりCPU使用率は上がるはずです。

しかしqueのNice値を0にしてみても特に結果が変わりませんでした。 stress-ngの負荷が高すぎてこうなるのかわかりませんが、Nice値の設定は本当に効いてるの?と少し不安になります。 そこで逆にqueのNice値を0、stress-ngのNice値を上げてみました。

こちらはreniceではなく、実行時にNice値指定すればOKです。

  • Nice値10
nice -n 10 stress-ng --cpu 0 --cpu-load 100
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                
3138372 ********  30  10   84508   7808   4096 R  93.0   0.2   0:25.72 stress-ng 100                                       
3138371 ********  30  10   84508   7808   4092 R  90.7   0.2   0:25.48 stress-ng 100                                       
2424664 ********  20   0 1703336 383344  10660 S  14.6   9.7  91:41.96 que
  • Nice値19
nice -n 19 stress-ng --cpu 0 --cpu-load 100
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                
3138439 ********  39  19   84508   8140   4164 R  82.0   0.2   0:17.98 stress-ng 100                                       
3138440 ********  39  19   84508   6360   4168 R  76.3   0.2   0:18.31 stress-ng 100                                       
2424664 ********  20   0 1703336 383304  10660 S  40.0   9.7  92:03.43 que

10、19と変えてみるとちゃんとstress-ngのCPU使用率が減り、queは増えました。 それでも大半はstress-ngが占めているので、元々の処理の重さで変わりそうですが、ちゃんと効いてそうです。 ちなみにNice値を1上げるだけだと特に変わらないように見えたので、ある程度大きく変更したほうが良いかもしれません。

queue_with_priority を設定する

これでOK……とはいかず、そもそも原因となったジョブが7~8分かけてCSV出力していたので、そこに他のジョブが入ってくるとその間は処理を待つことになります。 可能性は低いとは思いますが、CSV出力処理を連打して複数個queに登録されてしまったら、30分ほど他のジョブが捌けない、という状態になってしまいます。

幸い、このジョブは裏でCSV生成・出力処理を行い、後ほどダウンロードできるようになったらお知らせします、というものなので後回しになっても良いものです。 ということでqueに登録するジョブそのものの優先度を設定することにしました。

railsguides.jp

queue_with_priorityでジョブの優先度を設定することができます。 既に設定されているところはないかとコードを確認してみると、どうやらメール送信のジョブでqueue_with_priority(200)に設定されていたので、同様に設定してみました。

class CreateCsvJob < ApplicationJob
  # CSV出力は優先度を下げるため、200に設定
  queue_with_priority(200)

これで他のジョブより後に実行されるようになるはずです。

確認方法としてはまずこのジョブを数回queに登録しておきます。 その間に別のジョブ(今回は別のデータのzipファイル出力処理)を実行します。 優先度が同じならばCSV出力がすべて終わった後にzip出力処理が行われるはずですが、優先度を下げてるので現在のCSV出力が終わったら、残っているCSVの前にzip出力処理が実行されるはずです。 この方法で無事優先度が下がっていることを確認しました。今度こそ問題なさそうです。

まとめ

今回は優先度周りの設定をすることで処理の重いジョブを上手く捌くことができました。

私自身はこういった対応方法に疎く、「ジョブが重いなら処理をどうにかして軽くするしか無い」……という方向に行きがちなのですが、チームメンバーから対応方法についてのアプローチを頂き、今回の対応をしました。

今回の対応のように、別の視点からの解決方法がないか、探せるように知識をつけていければ良いなと思う出来事でした。

AWS WAF統合でコスト削減 マネージドルール料金を最適化した方法

株式会社リゾーム 業務ソリューション事業グループのあめぎです。

定期的にAWS費用の内訳と睨めっこして、「どこか削減できるんじゃないか?」と考えてしまうところがあるのですが、今回はそれが実を結んだ。というお話です。 結果として、毎年パソコンが何台も買える経費削減につながりました。

もしALBとWAFをお客様ごとに用意して、マネージドルールを使用しているなら、同様の経費削減ができるかもしれません。

WAFのマネージドルールに着目した経緯

利用しているマネージドルールの料金体系をよく見ると、月額サブスクリプションが環境ごとにかかる事に着目しました。そこで「できるならWAFをまとめてしまおう」という発想に至りました。

きっかけは、WAFのバージョンアップについて調べていたときに、ふと目にした「AWSのWAFは複数のリソースを割り当て可能」という情報です。そこから「これは使えるかも?」と思い、詳しく調べてみました。

参考:Web ACL を AWS リソースに関連付ける - AWS WAF

WAFとは?

WAF(Web Application Firewall)は、ウェブアプリケーションを悪意ある攻撃から保護する機能です。AWSはこれをサービスとして提供しており、クラウド環境で簡単に導入できます。 リゾームでも一部の製品でこのWAFを利用しています。

主な特徴は以下の通りです。

Webアプリは常に攻撃のリスクにさらされています。そこでWAFが攻撃を防ぐ門番として活躍します。

WAFにおけるマネージドルールとは?

マネージドルールとは、AWSやセキュリティベンダーが事前に作成したセキュリティルールセットで、AWS WAFに簡単に適用できます。これを使えば、専門知識がなくても高度なセキュリティを導入できます。

特徴

  • 専門知識不要で導入可能
  • 最新の脅威に対応(ベンダーが随時更新)
  • 数クリックで設定完了

料金体系は、月額サブスクリプション+リクエスト単位の従量課金が一般的です。サードパーティ製のルールはAWS Marketplaceで提供され、目的に応じて選べます。

WAFをまとめたらコスト削減できる?発想のきっかけ

この発想に至った理由は、採用していたマネージドルールの料金体系と、自社製品のAWS環境構成にありました。 ある製品では、ALB(このリソースにWAFを割り当てます)を「お客様ごと」に構築していました。

そして、利用していたWAFのマネージドルールの料金体系は

という仕組みでした。この「月額サブスクリプション料金」が環境数ごとにかかってしまう。 つまり、環境が増えるほどコストが膨らむ構造だったのです。

まとめても大丈夫と判断した理由は3つ

ではどうやって「まとめてもよい」と判断したのか?詳しく説明します。 まとめるということは、ポリシーやログなど、WAFに関するあらゆる要素が1つに統合されるということです。今回は次の3つが理由となりました。

1. お客様ごとにWAFのカスタム設定をしていなかった

調査した結果、細かいカスタマイズはなく、全て同一の設定でした。対象の製品は「環境が異なっても共通の品質を維持する」という運用ポリシーがあり、今回のWAF統合を後押しするものとなりました。

2. ログからお客様ごとの環境が識別できた

WAFのログについて改めて調べたところ、通信ごとに関連するALBがログに記載される事がわかりました。WAF統合後はこのALBの情報を頼りにお客様を識別すればよいとわかりました。

参考:保護パック (ウェブ ACL) トラフィックのログフィールド
※ httpSourceIdが該当します

3. WAFリクエスト数の上限を超えなければ良い

WAFにはリクエスト数の上限が設けられています。引き上げリクエストにより拡張が可能で、最大は1秒当たり100,000です。この数値を下回る範囲で統合作業を行えば、利用するお客様に影響はないとわかりました。

参考:AWS WAF クォータ

WAFリクエスト数の計測方法

検討した方法は2つです。

1. Athenaを使う方法

WAFのログをS3に保存しているので、Athenaを使って分析する。 Web ACLsの件数がリクエスト数に相当するので、1秒単位のログ件数を算出する。

2. CloudWatchの活用

リクエストに相当する以下のメトリクスの合計を利用する。

  • AllowedRequests
  • BlockedRequests
  • CaptchaRequests
  • ChallengeRequests

メトリクスの集計期間を工夫し、およそのリクエスト数を把握する。

検討した結果

Athenaを使う方法がより正確な数値を出せそうでしたので、今回はそちらを採用しました。 計測をした結果を元に、お客様をいくつかのグループに分け、リクエスト数が確実に上限を下回るよう統合を進める事になりました。

徐々に統合を進めていく

最初はかなり慎重に動きました。統合先となるWAFを新規作成して、まずは2社をWAFに統合し、1週間ほど経過観察を行いました。 Athenaを使った計測結果を元に、リクエスト数がおよそ2社の合計に収まっている事や、お客様の環境に変化がない事を確認しました。

ここまで確認が出来たら、あとはミスなく進めるだけでした。利用するお客様に合わせ、製品利用に影響のないスケジュールを立て徐々に移行していきました。 結果として、「お客様に提供する環境の品質を維持したまま」、「コスト削減のみ実現」できました。

まとめ

ひょんな閃きからWAFの統合について調査を始めましたが、運よく条件が重なり統合を行う事ができました。同じような課題をお持ちの方にとって、お役に立つ情報になりましたら幸いです。

「スッキリわかるSQL入門」読書会レポート vol.12

株式会社リゾーム 技術部 システム開発 第1グループの小田です。今回は「スッキリわかるSQL入門」読書会の第12回レポートです。 過去のレポートはこちらからご覧いただけます。

tech.rhizome-e.com

書籍について

前回に引き続き「スッキリわかるSQL入門 第3版」を題材としています。

第12回レポート

今回は第12章「テーブルの設計」の後半部分(5~7節)のレポートになります。 前回は正規化の概要について触れましたが、今回は正規化の具体的な手順やテーブルの物理設計について学習しました。

参加者は5名でした。

12.5 正規化の手順

正規化によってテーブルが適切に分割された状態を正規形と言います。 正規形は第1正規形から第5正規形まで存在しますが、本書では通常のシステム開発業務で求められる第3正規形までを解説されていました。 第1~第3正規形に変形するための具体的な手順は以下になります。

  • 非正規形 → 第1正規形:繰り返し列の排除
  • 第1正規形 → 第2正規形:複合主キーの一部への関数従属の排除
  • 第2正規形 → 第3正規形:間接的な関数従属の排除

また、正規化後にはER図を作成するのが一般的です。 ER図にはお客様の理想・要件を起点とする設計の流れで作成するものと、お客様の今の現実を起点とする設計の流れで作成するものの2種類があり、それぞれ「トップダウン・アプローチ」と「ボトムアップ・アプローチ」と呼ばれています。 前者のER図を基本にしつつ後者のER図から得られる情報を適切に取り込んでいくことで、新たな要件を満たしつつも可能な限り仕様漏れを防ぐことが出来ます。

参加者の意見・感想
  • 「きたない関数従属*1」は2種類あって、それぞれを解消するのが第2正規形と第3正規形という説明が図で整理されていてわかりやすかった
  • 今まで「ここ、冗長だから別テーブルにしたほうが良いのでは?」という感じで正規化をやっている部分があった。「ここが部分関数従属で~」とか、「ここが推移関数従属で~」とかはあんまり考えていなかったので、今後は意識してみようと思う
  • トップダウン・アプローチとボトムアップ・アプローチはどちらも重要。理想と現実をうまくすり合わせていくことが大事なんだな

12.6 物理設計

物理設計とは論理設計後に行う工程です。物理設計では論理モデルを元に、使用するDBMS製品独自の制約を考慮しつつ全テーブルの物理モデルを作成します。 また、作成した物理モデルはそのままDDL(主にCREATE文)に変換できる内容になります。 具体的には以下のような内容を確定させていきます。

  • テーブルやカラムの物理名の決定
  • カラムの型や制約の決定
  • インデックスの決定
参加者の意見・感想
  • 数値なら精度、文字列なら長さを決める必要があるし、DBMSによって型の仕様も違ったりする。よく考えて決めなければ
  • テーブル名、列名を英語で名前付けする際、たとえ意味が正しくてもマイナーな単語を使うとかえって分かりづらくなることがある。名前の正確さとわかりやすさのバランスを取るのが難しい
  • 書籍に書いてある「性能のためにあえて正規化を崩す」というのは聞いたことがある。参照頻度の高いカラムなどはキッチリ正規化して別テーブルに持たせるより、ある程度正規化を崩して同一テーブルに持たせた方がJOINの回数を減らせるので結果的にパフォーマンスが上がることもあるらしい

12.7 正規化されたデータの利用

整合性を維持しつつ効率よくデータを管理するためには、データを複数のテーブルに分けて格納する必要があります。 一方でデータを便利に利用してもらうためには、複数のテーブルの内容を1つの結果として見せたり、それをさらに集計したりする必要があります。 それら2つの形態を変換する技術が正規化と結合です。 正規化や結合といった技術を駆使することで、データベース上では整合性を保ちやすい効率的で安全なデータ管理ができ、お客様からはデータを見やすく分かりやすいシステムを作ることができます。

参加者の意見・感想
  • データの管理は複数テーブルで行い、利用時には1つのテーブルに見える形にするのがよい
  • 書籍の「そもそも私たち人間は、曖昧で、ある程度の冗長を含む情報に取り囲まれて生活しています。(...) 人間にとってはあまり正規化されていない情報のほうが取り扱いやすいのでしょう。」という内容について、Excelシートの結合を見かけるたびにうすうすそんな気がしていた
  • Excelや紙だと集計しにくくなるのを承知の上で見やすさや把握しやすさ優先のキタナイ表にすることもあるが、DBの場合はビューなどを使用した人間向けの画面と、正規化された中身で分けて運用できる

まとめ

今回は論理設計や物理設計の具体的な手順について学習しました。 この辺りの内容については体系的に学習したことのない参加者も居たため、非常に良い機会となりました。 また、書籍に書かれていた「性能のためにあえて正規化を崩す」というのは、SQLのパフォーマンス面で躓いた際に手段の1つとして思い出せるようにしておこうと思いました。

今回の第12回レポートで「スッキリわかるSQL入門」の内容は終了となります。 他にも本書の巻末には陥りやすいエラーや落とし穴とその対処法であったり、SQLのドリルも付いています。 それらも含め、特にSQL初学者には非常にオススメできる1冊だったように思います。 今後私が新入社員教育を担当することがあれば、SQLの学習にはぜひ本書を採用したいと思います。

*1:本書独自の言い回し。第2正規形の場合は複合主キーの一部への関数従属、第3正規形の場合は主キーへの間接的な関数従属がそれぞれ「きたない関数従属」に当たる。

「スッキリわかるSQL入門」読書会レポート vol.11

株式会社リゾーム 技術部 システム開発 第1グループの岩﨑です。今回は「スッキリわかるSQL入門」読書会の第11回レポートです。

過去のレポートはこちらからご覧いただけます。

tech.rhizome-e.com

書籍について

前回に引き続き「スッキリわかるSQL入門 第3版」を題材としています。

第11回レポート

第12章「テーブルの設計」の前半部分(1~4節)のレポートになります。前回まで様々なSQLの文法やDBMSの機能について学んできましたが、今回は少し異なり「概念設計」「論理設計」などのテーブル設計の手順について学習しました。

参加者は4名でした。

12.1 システムとデータベース

まずデータベース設計作業の一通りの流れをざっくりと学習しました。データベース設計は多くの場合、以下の流れで行われます。

  1. お客様の要望聴取
  2. 概念設計
  3. 論理設計
  4. 物理設計
  5. DDLDBMSの設定に落とし込む

実際にSQLを書くのは5番目の段階であることから、これまでに学習したSQL文法やDBMSの機能を理解し扱えることとシステムを適切に設計できるということは、関連があるにしてもイコールではないということがわかりました。

参加者の意見・感想
  • テーブルを設計するにはSQLの知識とともに、その業務のドメイン知識が必要不可欠
  • 今後新しい製品や機能を作る際には「今、自分はデータベース設計のどの段階にいるのか?」ということを意識するようにしたい

12.2 家計管理データベースの要件

システムには利用者がいるため、利用者側の要件をしっかりと洗い出すことが大切です。本節では「家計管理データベース」という具体的な例から、要件の聞き取りにおいての注意点を学習できました。

参加者の意見・感想
  • 関係者間の意識合わせをしておかないと、後々仕様が大きく変わる可能性がある
    • 複数の要件間で矛盾が出ないよう注意する
  • 「お客様の要望=お客様が本当に必要なもの」とは限らないため、難しいけど注意する必要がある

12.3 概念設計

概念設計では、要件を実現するためにデータベースで管理する情報を抽象化します。概念設計は結局どうすれば正解なのかとつい考えてしまいますが、唯一の正解があるわけではないため、練習や実践を重ねたり実例を沢山見て慣れていくことが重要そうです。

参加者の意見・感想
  • 資格試験で学習したときには概念的なもののイメージを掴むのにかなり苦戦した覚えがあるが、本書で書かれているヒントをもとにイメージしていくことで理解が進んだ
  • 最初の頃はエンティティが何を指しているのか理解するのが大変だった思い出
    • 本書では「情報の塊」「テーブルの原石」という表現で書かれており、イメージしやすい
  • 各エンティティの関係を明らかにしておくと全体の構造が分かりやすくなる
  • 形のない概念をエンティティにするのが難しそう……
  • 二重構造エンティティ(エンティティの中に別のエンティティを作ること)はできない
    • 今まで自然とやっていたが、そういう場合は別のエンティティとして外部に取り出す必要があるということを改めて学んだ

また、意見交換ではデータベースからER図を自動生成するツール「A5:SQL Mk-2」についての話も挙がりました。ER図を一から書かなくとも良いというのはとても便利ですね!

12.4 論理設計

論理設計では、概念設計で抽象化したものをデータベースが扱いやすい構造に変換するため、キーの整理、正規化(詳しくは次回レポート)などを行います。本節では「主キーは重複しないだけでなく、非NULL性、不変性も満たす必要がある」など、普段自然とやってきたことを例をもとに改めて学習することができました。

参加者の意見・感想
  • きれいに正規化されたテーブルだとアプリ画面での操作も楽なはず
  • 多対多になっているエンティティは中間テーブルを追加することで1対多になるよう変換する
  • 主キーはちゃんと考えて付けないと、いざ運用が始まってから主キーを変えるとなるとかなり大変
  • RailsはデフォルトでIDが主キーになるので主キーを考える手間が省ける

まとめ

今回はデータベース設計の要望聴取~論理設計を学習しました。「SQLの学習」といえばどうしても文法ばかりになってしまうため、今回の範囲でデータベースの設計作業を学習することができて良かったです。今後データベースの設計作業に関わることもあるかと思いますが、苦手意識を持たずポジティブな気持ちで挑みたいと思います。
次回の範囲は第12章「テーブルの設計」の後半(5~7節)です。