はじめに レバレジーズシステム本部 NALYSYSグループ テックリードの桐生です。 NALYSYSとは、ピープルマネジメントを支援する「 NALYSYSモチベーション管理 」や労務業務を効率化する「 NALYSYS労務管理 」などの機能を多数持った、人事労務に関わる課題を解決するためのSaaSです。 そんなNALYSYSでは、 今年4月に新たに「NALYSYS従業員ライブラリ」をリリースいたしました 。こちらのプロダクトではマイクロサービスを跨いだ検索を実現する必要があったのですが、これにより今までにない設計上やパフォーマンス面の問題に直面し、また短い納期の中でこの問題を解決する必要がありました。 今回の記事では、これらの問題をNetflixの事例を参考に爆速で解決に導いた取り組みをご紹介いたします。 NALYSYS 従業員ライブラリについて 現在のNALYSYSは、「NALYSYS Admin」に登録された従業員の基本情報を中心として、それにぶら下がる形で「NALYSYSモチベーション管理」や「NALYSYS労務管理」などに追加の情報を保持しています。同じ従業員の情報であっても分野ごとに異なるプロダクトに保存されているため、これらのデータを活用するには複数のプロダクトを行き来する必要があり、ユーザーにとって不便な状態となっていました。 これを解決するために企画されたサービスが NALYSYS従業員ライブラリ です。 従業員ライブラリが新たにNALYSYSに加わることで、複数のプロダクトに分散している情報を集約して閲覧することができ、プロダクトをまたいだ従業員の検索も行うことができるようになります。 全プロダクトのデータを集約するという性質上、権限やパフォーマンスに関して今までにない課題に直面することとなりました。また、今回は企画立案〜リリースまでが3ヶ月という短いスケジュールだったため、その期間で実現可能な方法を選ぶ必要がありました。 本記事では、直面したさまざまな課題の中から「プロダクト横断検索」に関わる部分をピックアップしてお届けします。 マイクロサービス間検索における課題 NALYSYSのバックエンドではマイクロサービスアーキテクチャを採用しており、それぞれのマイクロサービスごとに独立したデータベースを持っています。(マイクロサービスアーキテクチャでは各サービスの独立デプロイ可能性を確保するためにデータベースを分離する必要があります)このため、マイクロサービスを跨いだ検索を行おうとすると、検索に利用したいデータが複数のデータベースに分散しているという点が問題となります。具体的には、愚直に検索を実装する場合、複数のマイクロサービスに対してそれぞれデータ取得操作を行なった後、それらを集約して検索結果を構築する必要があります。特に、特定のマイクロサービスに関する検索条件がゆるい場合には大量のデータをロード・転送しなければならないため、データ量に対してスケールしにくくなってしまいます。実際に既存のプロダクトでも在籍状況+プロダクト固有の情報で検索する場合などに同様の問題に直面し、パフォーマンスが低下していました。 今回は、この問題を根本的に解決するため、単一の検索用データベースに全てのサービスのデータを集約することとしました。具体的には、以下のNetflixの事例を参考に、マイクロサービス間に分散したデータをElasticsearchに集約してインデックス化し、横断的な検索を実現します。 netflixtechblog.com 検索システムの構成 構築した検索システムの概要を以下に示します。 先ほど紹介したNetflixの事例と同様、Elasticsearchの検索インデックスに各サービスからかき集めた従業員の情報を合成して登録していきます。実際にユーザーが検索リクエストを送った際には、従業員ライブラリのマイクロサービスがそれをElasticsearch用の検索クエリに変換して検索を実行します。検索処理は全てElasticsearch内で完結し、DBのスキャンが必要ないため高速な検索処理を実現することができました。 インデックスの更新方法について Elasticsearchに登録されている従業員データは元々のサービスからコピーされたものであるため、元のデータが更新された場合これを随時インデックスに反映していく必要があります。 先ほどのNetflixの事例では、各マイクロサービスが送出するデータ更新イベントをトリガーにしてElasticsearchへのデータ再登録を行うという手法をとっていました。Netflixのシステムでは元々Kafkaに変更イベントを送出する仕組みが整っていたため、このような手法を少ない労力で実装できたようです。 一方、NALYSYSにはNetflixで行われているような変更イベントを流す仕組みがありませんでした。マイクロサービス間を疎結合にするという観点で、Netflixと同様にメッセージベースのやり取りを実装するのが望ましくはあったのですが、開発期間が短い中でそのような仕組みを設計・構築する余裕がなかったため、今回は代わりにLogstashのJDBC Input Pluginを活用した変更検知を実装しています。 JDBC Input Pluginを用いると、データベースに対して定期的にクエリを発行し、データの差分を取り込むことができます。以下の公式ブログに詳しい実装方法が説明されています。 www.elastic.co この方法を用いる場合、Logstashのデプロイおよび必要な設定ファイルの作成を行うだけでインデックスの自動更新を実装することができるため、自前で更新のための仕組み(差分イベント送出・検知)を実装するのに比べて大きく工数を削減することができます。一方で、各サービスのデータベースの構造とLogstashの設定ファイルが密結合になるためメンテナンス性が低下するという問題も抱えています。今回は短納期を実現するために必要な負債としてこれを受け入れることとしました。 まとめ ここまで述べた取り組みによって、高速な横断検索機能を予定期間内に作り上げることができました。今回は従業員ライブラリに特化した仕組みとなってしまったので、今後は他のプロダクトにもこの仕組みを展開しつつ、メッセージベースの変更検知によってサービス間の結合度を下げる取り組みも行っていきたいと考えています。 レバレジーズでは、ソフトウェアの力で人事労務に関わる課題解決に挑戦する仲間を募集しています!ご興味のある方はぜひ 採用サイト をご覧ください!
6月中に、レバレジーズが関わった技術イベントのご紹介です。 自社開催から、共催、スポンサー、運営の手伝いと多様な関わり方で、合計5件のイベントに参加しています! 主催・共催技術イベント イベントグループ「Tech Leverages」始動 イベント開催プラットフォームのconnpassにて、 Tech Leverages グループをリニューアルしました。今後弊社で開催するイベントはこちらで公開していきますので、興味がある方はグループ登録をお願いします。 渋谷一丁目支店・初技術イベント: Agile Effect MeetUp なんちゃってスクラム開発からの脱却 6/27に、弊社の新しい拠点である渋谷一丁目支店のセミナールームで、 Agile Effect MeetUp を開催しました。スクラムマスターの服部 翔太氏や、株式会社aby CTO 向後 澄哉氏にご参加いただき、パネルディスカッションを行いました。 イベントブース出展 AWS Summit 2024 ブース出展 & ミニセッション登壇 6/20,6/21に幕張メッセで開催された AWS Summit 2024 で、レバテックプラットフォームでのAmazon QuickSightの活用事例を紹介するブースを出展しました。 また、ミニステージにて、弊社エンジニアの塚原と内藤が、技術の詳細の発表も行って来ました。 イベント登壇 UX Design Conference 2024:『VoLT:レバテックのデザインシステム』電光石火の構築プロセスと目指す未来 弊社CTO室テックリードの河村とプロダクトとデザイン責任者の山本が、 UX Design Conference 2024で登壇 しました。 イベントスポンサー・手伝い 日本CTO協会 新卒合同研修 会場スポンサー 6/19に日本CTO協会様が実施されている合同新卒研修で、会場スポンサーとしてレバレジーズ本社のセミナールームを提供いたしました。今回の内容は「インテリアデザインを通したアジャイル開発の体験」で、グループワークを通してアジャイル開発がどのように進むかを疑似体験するというものでした。 ScalaMatsuri2024 運営スタッフとして手伝い 6/8,6/9に、国際交流館 プラザ平成で開催された ScalaMatsuri2024 に、弊社テクノロジー戦略室室長 竹下が運営スタッフとして開催を手伝ってきました。コロナ後初のフルリアル開催となり、日本中のScala使いが集結しました。 また、竹下が、酒を飲みながらLeetCodeを解くという「アルコーダー」の発表?を行ってきました。 We are hiring! レバレジーズ株式会社では一緒にサービスを開発してくれる仲間を募集中です。 もしご興味を持っていただけたなら、 こちらのページ からご応募ください。
はじめに こんにちは、レバレジーズ株式会社の檜垣・南です。本記事ではレバレジーズグループ全体のエンジニアが参加するテックフェスの様子をご紹介します。基調講演や、社員によるトークセッションなどについて書いていますので、ぜひ最後までご覧ください。 テックフェスとは レバレジーズグループに所属するエンジニアを対象に、社内で半年に一度行われている技術の祭典です。エンジニアが新しい技術に興味を持ち、勉強をするきっかけを作ることを目的とし、グループ全体の技術力向上を目指します。2月14日に「速さと質の次へ~史上最速でコアコンピタンスを高める組織~」というテーマでテックフェス2024冬を開催しました。 AWS AWSソリューションアーキテクチャの苅野 秀和氏に「AWS を使って価値提供 に集中しよう」というテーマで特別セッションをしていただきました。AWSのサービスに限定せず、AISASフレームワークを使った戦略の考え方などを発表していただきました。また、求人検索のパーソナライズやBedrockを利用した営業活動支援の最適化など、人材業界でのユースケースも紹介していただきました。人材業界にサービスを多く展開するレバレジーズのエンジニアにとって、コアコンピタンスを見つけるきっかけになったのではないかと思います。 アジェンダ AWSを用いたデータ活用 High value & low riskの探索 Personalize Bedrock 人材業界でのユースケース 開発者とAWS セキュリティ CodeCatalyst 基調講演 徳丸浩氏に「今どきのウェブアプリでは脆弱性はどのように発現するのか?」という題名で、現在のアプリケーションにおいて脆弱性がどのように発現するのか、Teratail他のネットの記事のコードを参照しつつ解説していただきました。 登壇者紹介 徳丸浩 氏 EGセキュアソリューションズ株式会社 取締役CTO イー・ガーディアン株式会社 CISO 独立行政法人情報処理推進機構(IPA)非常勤研究員 技術士(情報工学部門) 著書: 「 体系的に学ぶ 安全なWebアプリケーションの作り方脆弱性が生まれる原理と対策の実践(ソフトバンククリエイティブ) 」 1985年京セラ株式会社に入社後、ソフトウェアの開発、企画に従事。1999年に携帯電話向け認証課金基盤の方式設計を担当したことをきっかけにWebアプリケーションのセキュリティに興味を持つ。2004年同分野を事業化。 2008年独立して、Webアプリケーションセキュリティを専門分野とするHASHコンサルティング株式会社(現EGセキュアソリューションズ株式会社)を設立。 脆弱性診断やコンサルティング業務のかたわら、ブログや勉強会などを通じてセキュリティの啓蒙活動をおこなっている。 2023年イー・ガーディアングループのCISOに就任。セキュリティレベル向上だけでなく、活動を通して得たノウハウをサービスやセミナーコンテンツにも還元し、広くセキュリティの啓蒙活動に邁進。 アジェンダ アプリケーションフレームワークと脆弱性対策 フレームワークとSQLインジェクション Teratailの質問から LaravelでSQLインジェクション脆弱にする フレームワークとクロスサイトスクリプティング(XSS) LaravelでXSSが発生するケース ReactのようなSPAフレームワークの場合 SPAとCORS(Cross-Origin Resource Sharing) フレームワークと認可制御 セッション 発表してくださった皆さんありがとうございました。 最優秀の発表について 大規模なORMバージョンアップ作業を乗り越えた話 (レバレジーズ NALYSYSグループ 桐生 直輝さん) speakerdeck.com 概要 大きめの破壊的アップデータがあったTypeORM 0.2 -> 0.3 移行について ts-morph を用いたコードの自動置き換え 移行用ライブラリによる漸進的な移行 自動テストを活用した影響調査 の順序でお話し頂きました。 自作の移行用ライブラリを作成し、徐々に0.2 から 0.3に変更を進めて、 1人月+レビュー工数でアップデート作業を終えられていました。 LT 発表一覧 発表してくださった皆さんありがとうございました。 最優秀の発表について 桃栗3年、レコメンドエンジン5年 (レバレジーズ データ戦略室 阪上 晃幸さん) speakerdeck.com 概要 レコメンドアルゴリズムのリプレイスについて 黎明期 データ戦略室の発足時から将来を見据えて着工 事業部長への提案〜アルゴリズム開発 挫折期 Covid-19がレコメンド プロジェクトを襲う やり直し期 全く新しい観点でアルゴリズムを開発 新体制 アルゴリズムに足りていなかった現場の意見を反映し、使えるものに 熟成期 可用性を高め、LTSF実装に繋げていく1年 離陸期 LTSFの内部でレコメンとAPIを使ってもらう の順序でお話し頂きました。 懇親会 テックフェス終了後は、懇親会も開催。ピザやお寿司、おにぎりを食べながら発表者へ話を聞きに行ったり、他チームの方と交流を深めている様子が見られました。 運営メンバー打ち上げ 後日、運営メンバーで打ち上げに行きました。写真を撮ろうと思っていたのですが、話が盛り上がりすぎてすっかり忘れてしまいました。 最後に 今回の記事では、テックフェスのレポートを書かせていただきました。徳丸浩さんの貴重なお話を聞けたり、社内のエンジニアから普段は聞けない話を聞けて非常に面白かったです。 社内で技術ノウハウの共有を行なうイベントがあったり、外部から著名な方をお呼びして貴重な話が聞ける環境のレバレジーズで皆さんも一緒に働いてみませんか? レバレジーズに少しでも興味を持っていただけた方は、以下のリンクからエントリーをお願いします! recruit.leverages.jp
レバレジーズ株式会社 レバテック開発部の堀内です。 2024/05/29に、PharmaX社、ANDPAD社、弊社の3社による共催イベント「Frontend Night: App Router本番運用企業が語る!Next.js新機能活用法」が開催されました。 Next.jsのApp Routerを実際に本番運用している会社が集まり、App Routerを利用した開発において良かったことや工夫したことを発表しました。 私は『App Routerの開発で気をつけたいこと3選』というテーマで発表しましたので、そのスライドを共有します。 App Routerを利用したプロジェクトを通して、ハマったところや失敗したところがいくつかあったため、気をつけたほうがいいこととして3つ紹介させていただきました。 speakerdeck.com We are hiring 現在レバレジーズでは一緒に働いてくれる仲間を募集しています。 ご興味のある方は、以下のリンクからご応募ください。 recruit.leverages.jp
はじめに レバレジーズ株式会社 テクノロジー戦略室 SREチームの中野です。レバレジーズでは「SRE化を通して、Developer Experienceの改善、事業の拡大への対応、お客様に信頼されるサービスの提供を実現する」をミッションとして、Embedded SREメンバーと協力しながら、サービス改善の文化的土俵の構築や開発生産性の向上を進めています。 この記事では、開発体験を向上させるための取り組みとして、社内標準となるIaCツールの選定、IaC化の負荷軽減への取り組みについてご紹介します。具体的には、社内標準ツールの選定では決定に至るまでのプロセスや方法をご紹介し、IaC化の作業負荷の軽減への取り組みでは、全体最適を狙った下記のライブラリ・テンプレートの作成についてご紹介します。 Terraform Modules GitHub Composite Actions GitHub Repository Template また、この記事を通して、弊社の開発体験の向上における取り組みを知って頂くと共に、全社最適を狙ったIaC化の推進について是非ともご参考頂ければ幸いです。それでは、以下で背景を挟みつつ具体的な取り組みについてご紹介します。 背景 サービス開発体制のSRE化を進めやすくするために、インフラ構築・管理の省力化でIaC化を進めています。しかし、実際にはAWS CDK、AWS CloudFormation、Terraform等の複数のツールが利用されており、開発チーム・SREチームの双方において作業負荷がかかってしまっています。 実際、ツールの乱立により、開発チームではIaCツールの理解度・習熟度がバラついており、開発チーム間でのナレッジ・ノウハウの共有が困難だったりします。SREチームでも、開発チーム毎に異なるサポートが必要となり、サポート負荷が高くなりがちです。 この様な状況を解消するためには、ツールの乱立を最小限に抑え、IaC化を低負荷・低工数で進められる様にする必要があると考え、社内標準となるIaCツールの選定と、IaCツールやCI/CDにおけるライブラリ・テンプレートの作成を進めることになりました。 社内標準となるIaCツールの選定 ツール比較 まずは、社内標準となるIaCツールの比較から始めました。ツールの認知度・利用度の高さを考えてTerraform・AWS CDK・Pulumi・CDKTF・OpenTofuから比較し、Terraform・OpenTofuが最良の選択肢として残りました。理由は下表の通りです。 比較観点 評価理由 成熟度・カバー範囲 殆どのパブリッククラウドに対応しており、SaaSでも対応範囲が広い。 ツールの学習負荷 HCLはJSONライクで学習しやすく、リソース設定が宣言的で見通しが良い。 構築・変更の負荷 リソース設定が宣言的なため、クラウドサービスの構築・更新でコード変更とズレの無い状態差分で期待通りに適用出来る。 状態変更の容易性 import・moved・removed等のブロック設定により、ツールで管理される状態の追加・変更・削除をコードベースで容易に実施出来る。 GenAIとの相性 リソース設定が宣言的なため、簡単なプロンプトで一定以上のクオリティでサンプルコードを生成出来る。 リスク調査 ツール比較でTerraform・OpenTofuが最良の選択肢として残りましたが、今後IaC化を問題無く推進していくためにツールの将来的なリスクも考えておく必要があり、ライセンス変更によるTerraformの利用制限の可能性について調査しました。 ライセンスに関する公式情報によれば、Terraformの利用範囲は従来通りでリスクはありませんでした。実際、HashiCorpの競合製品においてはHashiCorp製品が埋め込まれていれば利用制限が発生しますが、社内/個人によるHashiCorp製品の利用においては制限は無いとのことでした。 一方で、OpenTofuは今後のツールとしての安定性・充実性が現時点では見込めなさそうなため、Terraformの方がより安定的でリスクが低いツールであると判断しました。 www.hashicorp.com www.hashicorp.com www.hashicorp.com 選定結果・例外 以上の比較・調査の結果を踏まえ、Terraform を社内標準ツールとして採用しました。今後はTerraformでIaC化を推進していく予定です。しかし、Terraformの導入・移行における費用対効果が必ずしも高く無いパターンもあり、下表を例外として規定しました。これらを考慮しながらIaC化を進めていきます。 例外パターン 対応方針 Terraformへのツール移行 他ツールで管理されているパブリッククラウドやSaaSでは、移行コストと改善効果性のバランスを考え、Terraformへの移行を検討する。 Terraformによるサポートが弱い部分へのIaC化 Terraformのサポートが未対応、またはサポート範囲が狭い部分では他ツールの利用を認める。 外部サービスの仕組みにおけるTerraformの導入 パブリッククラウドやSaaSで提供される仕組みにおいて、Terraform以外の手段で構築されている場合は、その手段の使用を認める。 一時的な利用のシステムへのTerraformの導入 プロトタイプや実験的な環境等の、一時的な利用が確実に見込まれる様なシステムでは、TerraformによるIaC化は強制しない。 ライブラリ・テンプレートの作成 次に、IaC化を低負荷・低工数で推進するために、IaCの移植性・再利用性等を高める様なプラクティスの検討を進めました。Terraformを利用している開発チームにヒアリングしたところ、下記の課題感が出てきました。 実装の際にクラウドサービスの仕様把握が必要で、実装における作業負荷が高い 宣言的な設定のため、リソースが多くなると設定管理における認知負荷が高まる Git RepositoryやCI/CDにおける社内標準の構成が無く、設計・初期作業で時間がかかる これらを解決するためには、Terraformにおける社内標準のライブラリ・テンプレートを作成する必要があると考え、Terraform Modules・GitHub Composite Actions・GitHub Repository Templateを全社向けに開発することになりました。 管理方針 SREチームがライブラリ・テンプレートをメンテナンスしていく予定のため、テクノロジー戦略室向けのGitHub Organizationの配下でライブラリ・テンプレートを管理することにしました。また、ローカルやCI/CDでライブラリを利用する際に、PATをベースとしたアクセス認証でライブラリをダウンロードする様にしました。 作成方針 Terraform Modules 全社最適のパターンとして、個々に依存しない手段を用いて全社最適を図るか、または個別最適の手段を組み合わせて全社最適を図るかの2種類が考えられ、そこからTerraform Modulesにおける次の構成方針を洗い出しました。 (1) 社内のサービス・システムに合わせたTerraform Modules (2) クラウドサービスのリソースに対応するTerraform Modules 検討の結果、(2)の方針でTerraform Modulesの構成を考えることにしました。実際、(1)の方針ではサービス・システム毎に特化したTerraform Modulesのため、極力少ない設定でインフラ構築・運用が可能です。しかし、サービス毎のシステム構成の変更に追従してTerraform Modulesをメンテナンスしていく必要があり、メンテナンス面で課題がありました。 一方、(2)の方針では、サービス・システムの個別の設定・構成に依存せずに全社に展開出来るため、メンテナンス面の課題は小さめでした。また、社内要件やクラウドサービスにより推奨される設定をベースとして作り込めば、インフラ構築・運用における作業負荷を軽減可能だと考えました。結果として、メンテナンス性・利用者の負荷軽減のバランスの取れた(2)の方針が最良となりました。 とは言え、単にクラウドサービス毎にTerraform Modulesを作ってしまうと、汎用性やメンテナンス性は高められるがサービス・システム毎の最適化には繋がらないため、次の2種類のTerraform Modulesを作成することにしました。 種別 説明 用途例 Component Modules クラウドサービスの単体のインフラリソースに対応するTerraform Modules ELB・ECS・EC2・RDS等のリソース毎にModulesで作成する Catalog Modules クラウドサービスの複数のインフラリソースに対応するTerraform Modules ELB・ECS、CloudFront・WAF等のリソース群をModulesで作成する また、社内のサービス・システムの構成パターンを考えたところ、AWSを利用しているものが大半であり、かつCloudFront・WAF・ELB・ECS・RDS・ElastiCacheを用いた構成が多いため、この様なAWSインフラ構成におけるComponent/Catalog Modulesの開発を優先的に進めることになりました。 GitHub Composite Actions 社内におけるCI/CDツールの利用状況や、CI/CDツールにおけるGitHub向けの連携機能の充実さを考慮し、GitHub Actionsを利用してTerraform CI/CDのパッケージを作成することにしました。 GitHub Actionsの処理共通化を調べると、Custom Actions、Composite Actions、Reusable Workflowsのいずれかを用いれば良いことが分かり、処理共通化が容易かどうか、下記を満たす形で運用が可能かどうかを考え、Composite Actionsを採用しました。 テクノロジー戦略室のOrganization、開発チームのOrganizationは別々である ライブラリ・テンプレートのRepositoryは、テクノロジー戦略室のOrganization管理下である ライブラリ・テンプレートのRepository、開発チーム向けのRepositoryはPrivateである GitHub Repository Template 大半の社内サービス・システムでAWSが利用されているため、Terraform・AWS用のGitHub Repository Templateを優先して作ることにしました。また、開発チームのGitHub Repositoryで最適と思われるものを基準にして、GitHub Repository Templateの構成を考えました。 Repositoryの生成・設定については、テンプレート内のコード・資料等をスクリプトで書き換える様な仕組みを導入し、テンプレートからTerraform用のRepositoryを低工数で設定出来る様にしました。 更に、Terraformの管理基盤を構築する際に、Repositoryの設定だけでなく下記の作業も対応する必要があり、下記における設定手順の資料やTerraformの設定ファイルをテンプレートに含め、Terraformの導入における初期作業を全体的に低工数で済む様にしました。 Slack通知の初期設定 通知チャンネルの作成 Webhook連携の設定 Terraformの初期設定 Terraform Backendの構築 CI/CD用のIAMロールの作成 CI/CDの設定作成・有効化 クラウドサービスの初期設定 月額予算アラートの設定 監査ログ、セキュリティ検知の設定 アラート通知の仕組みの構築 今後の活動 以上の様に、社内標準のIaCツールの選定と、IaCツールのライブラリ・テンプレートの作成を進めてきました。しかし、現状ではライブラリ・テンプレートにおける開発のルール・フローや全社展開・要望吸い上げの体制が整い切れていないため、今後はこれらを整備してIaC化を推進していく予定です。 また、現在はAWSを対象にIaCツールのライブラリ・テンプレートを作成していますが、今後はGoogle Cloud、Datadog、GitHub等のAWS以外のクラウドサービスも検討し、ライブラリ・テンプレートの対象範囲を広げていきたいとも考えています。 最後に レバレジーズでは、全社のSRE導入に向けて、サービス改善の文化的土俵の構築や開発生産性の向上のための取り組みを手伝って頂けるエンジニアを募集しています。 SREの文化・体制に興味があったり創っていきたい方や、これからフルスタックエンジニアになっていきたい方は、是非ともご応募をお待ちしております。
レバレジーズ株式会社 システム本部の檜垣です。 レバレジーズでは、2024/05/11に中野セントラルパークカンファレンスで開催された TSKaigi 2024 で最上位のプラチナスポンサーとしてスポンサーブースを出展しました。 レバレジーズでは、TypeScriptをフロントエンド、バックエンドで幅広く使っていることもあって、日頃の感謝を込めてTypeScriptのコミュニティへの貢献のためにプラチナスポンサーとして支援させていただきました。また、私も微力ながら運営スタッフとして開催をお手伝いしました。 ブース内容 TSKaigiに参加した皆様に楽しんでいただくために、ブースでは、「 スクラム開発のための業務効率化支援ツールの Agile Effect のデモ 」や「 レバ社員を探せ!くじ 」などを行いました。 ブースの様子 くじ 楽しく談笑中 agile-effectのデモの様子 記念撮影 たくさんの人に訪れていただき大盛況でした。 agile-effectのデモでは、大変気に入っていただきその場で契約していただいた会社様もいました。 ブースに来てくださった皆様ありがとうございました。 We are hiring レバレジーズ株式会社ではTypeScript大好きなエンジニアも、それ以外のエンジニアも幅広く募集中です。 もしご興味を持っていただけたなら、 こちらのページ からご応募ください。 recruit.leverages.jp
はじめに TSKaigiプラチナスポンサーであるレバレジーズ株式会社のテクノロジー戦略室室長 & 一般社団法人TSKaigi Association 代表理事 & TSKaigi2024 Speakerの竹下です。 TypeScriptの言語カンファレンスであるTSKaigi2024が5月11日(土)に中野セントラルパークで開催されました。基調講演にはMicrosoftのTypeScript Product ManagerであるDaniel Rosenwasser様を迎え、37名の登壇者、会場での参加者約400名、オンライン参加約2000名の、大規模イベントになりました。 この記事では、私がTSKaigiを立ち上げた経緯と、登壇者として発表してきた 「Step by Stepで学ぶ、ADT(代数的データ型)、モナドからEffect-TSまで」 について、紹介したいと思います。 TSKaigi とは TSKaigi は、TypeScriptをテーマにした、技術カンファレンスです。俗に言語カンファレンスと呼ばれる、特定のプログラミング言語を扱ったカンファレンスで、有名なものではRubyKaigiやPyCon、PHP Conference、ScalaMatsuriなどがあります。(ちなみに私はScalaMatsuriの開催にも理事として関わっていたりします) 運営は、私を含む理事4人を中心に、総勢45名ものボランティアスタッフによって行われました。 ここがすごかったよTSKaigi 初開催でいきなり2400名規模! 技術カンファレンスとしては、日本でも大規模に分類されるイベントです。会場には約400名、オンラインで約2000名の方にご参加いただきました。TypeScriptのイベントとしては現時点で日本一の規模だと思います。初開催でノウハウがない状態から、大きなトラブルもなく無事にイベントを開催できたのは素晴らしいことで、運営を手伝ってくださったスタッフの方々の頑張りの賜物です。感謝の気持ちでいっぱいです。 基調講演 はMicrosoft TypeScriptのProductManagerのDaniel Rosenwasserlさん! 言語の開発者というものは普段あまり意識しないかもしれませんが、DanielさんはTypeScript自体を長年にわたって開発してくださっている方です。また、JavaScriptの標準仕様を策定する団体であるTC39にも関わっておられます。TypeScriptやJavaScriptを使うエンジニアにとっては、足を向けて寝られない方です。そのDanielさんが、TSKaigiの 基調講演 を行ってくれました。 レバレジーズ株式会社を始め38社が協賛! レバレジーズも最上位のプラチナスポンサーとして協賛しましたが、プラチナスポンサー、ゴールドスポンサー、シルバースポンサー、ブロンズスポンサーをはじめ、コーヒー、ビール、リフレッシュメント、イベントツールなどの特殊スポンサーを含め、合計38社に協賛していただきました。スポンサー募集期限後に開催を知って協賛できなかった企業様も多数おられたので、来年は周知を徹底し、TypeScriptを盛り上げてくださる企業様を増やしていきたいです。 立ち上げ経緯 コミュニティの盛り上がりが、人気に比例していない TypeScriptの人気はコロナ禍中にもどんどん高まり、開発者の数も増え、使用範囲もフロントエンドに留まらず、バックエンド、インフラ、AI/ML、IoTと非常に幅広くなっています。しかし、私個人の感想にはなりますが、TypeScriptといえばこの人という存在や、日本発のOSSライブラリは、人気や開発者数に対して少ないと感じていました。また、コミュニティ活動も行われている方は数多くおられましたが、その方々が大々的に知られる機会もあまり無いと感じていました。 コミュニティの核となるイベントを作る TypeScriptの言語カンファレンスは、コロナ禍前にTSConf JPが開催されていましたが、その後中断してしまい、日本では大規模なイベントが開催されていない状態でした。コミュニティが盛り上がらない原因として、コロナ禍も影響し、中核となるイベントやコミュニティがなく、交流の輪が広がっていかないことが挙げられます。 そのような状況の中で、TSKaigiを開催することで、TypeScript開発者に成果を発表してもらう場を提供するとともに、TypeScriptコミュニティの皆さんにどんな人がいて、どんな使い方をされているかを知ってもらう場を提供できると考えました。また、TSKaigiに参加してもらうことで交流が生まれ、そこから交流が続くことでTypeScriptコミュニティ全体の活性化につながると考えました。 団体としてコミュニティの活性化を継続 また、単発イベントではなく継続開催することが、TypeScriptコミュニティの継続した発展に繋がると考え、同時期に同じことを考えていた他の理事と共同で一般社団法人TSKaigi Associationも設立しています。来年以降の開催や、サブイベントの開催も行っていこうと思っていますので、是非この記事をお読みの皆さんご参加下さい。 登壇内容 また、賑やかしのためにセッションの応募したら当選していたので発表も行ってきました。以下が発表スライドです。 スライド おまけ この発表では、Effectの導入する意義に焦点を当てて解説していますが、実際の運用では一歩踏み込み、Effectによる関数の細粒度化と副作用分離によるアーキテクチャーレベルの設計も行っています。機会があればそちらも発表したいと思います。 おまけのおまけ 代表理事として、開幕の挨拶もしたのですが、演台の前からはなれて動きながら喋ってたら演台にもどれって怒られました(笑) オープニングトーク P.S. 書いててレバレジーズ株式会社のエンジニアとしてなのか、TSKaigiの代表理事としてなのかよくわからなくなってきて、ちょっと混乱した文章になっていますがご容赦下さい。また、TSKaigiの代表理事としての思いなどは、改めて TSKaigiのブログ で書きたいと思います。 We are hiring!!! レバレジーズ株式会社では一緒にサービスを開発してくれるエンジニアを幅広く募集中です。 TypeScriptで開発するだけでなく、コミュニティ貢献もしていきたいという人もウェルカムですし、TypeScriptに触ってないけど興味あるよという人もウェルカムです。 もしご興味ありましたら、 こちらのページ からご応募ください。
レバレジーズ株式会社 レバウェル開発部 SREの中村です。 2024/03/13に、設計をテーマに合同勉強会を開催しました。 領域を絞らずに発表いただいたことで、設計について幅広く知見を得られた勉強会になりました。 また、弊社が東京の渋谷に物理出社がメインで、ビザスク社がフルリモートということで Zoomを使用してオンラインでの開催になりました。 この記事では、弊社のエンジニアの発表内容を簡単にご紹介したいと思います。 発表内容 弊社からは、二人が発表しました。 テクノロジー戦略室 室長 竹下 speakerdeck.com EffectというTypeScriptのライブラリを活用して、IOに関する副作用を分離した設計を実現する方法について発表されています。また、その際にEffectを導入する利点についても紹介されています。 レバテック開発部ITSプロダクト開発グループ PdM兼テックリード 古庄 speakerdeck.com レバテックにて、新たに構築中のデザインシステム「VoLT」について発表されています。構築プロセス、システム設計や実装例について紹介されています。 We are hiring レバレジーズ株式会社ではどの領域のエンジニアも幅広く募集中です。 もし今回の勉強会の発表を見てご興味を持っていただけたなら、 こちらのページ からご応募ください。 勉強会の開催も随時受け付け中です 今回は設計をテーマに合同勉強会を開催しましたが、工程を絞ったものだけでなく、フロントエンド、バックエンド、インフラ、機械学習といったように、様々なテーマで弊社と合同勉強会を開催してくれる企業様を募集中です。ご興味ある企業様がいらっしゃいましたらご連絡いただけると嬉しいです。
DALL·Eで生成したLangChainのイメージ画像 LangChainの動作確認済みバージョン(2024/3/26時点では最新) langchain: 0.1.13 langchain-community: 0.0.29 langchain-openai: 0.1.0 langchain-google-vertexai: 0.1.1 はじめに テクノロジー戦略室 AI/MLエンジニアリングチームの稲垣です。 AI/MLエンジニアリングチームでは、レコメンドエンジンの MLOps 基盤の構築や、AWS Personalize などの ML サービスや LLM など生成 AI 活用を、企画から構築まで進めています。 今回は、LangChain の最新バージョン(2024/3/26時点)を使った複数モデルの実装方法について紹介します。 このような実装ニーズは良くあるかと思いますが、案外記事がまだ落ちていないようでしたので記事にしてみました。 現在、社内で LLM を使ったツール開発を行っており、LLM は以下のような複数ベンダー&複数モデルの API を使用しています。 GPT-3.5-turbo, GPT-4 (Azure OpenAI Service) Gemini Pro (Google Cloud VertexAI) Claude 2, Claude3 (AWS Bedrock) それぞれのモデルに対して別個に実装していくことももちろん可能ですが、 API 入力/出力のフォーマット、良くある前処理や後処理、ストリーミングによる出力などの実装方法がモデルごとに異なるケースが多く、 それらを別個に実装していく手間はモデルの数が増えるほど大きくなっていきます。 (実際、 anthropic-sdk-python による Claude モデル実装と、 google-cloud-aiplatform による Gemini モデル実装は根本的な箇所でいくつか大きな差異があります。) このようなモデルごとの実装の差異を吸収してくれるライブラリとして LangChain があり、 社内ツールの実装でも LangChain を利用しています。 LangChain: github.com また、LangChain について最近の動向としては、 2024/1/6 にバージョン 0.0.354 から 0.1.0 へのアップデートがあり、LangChain 初の安定バージョンとなった、というニュースがありました。 (これ以前は破壊的な変更が頻繁に起こったり、公式ドキュメントのクイックスタートの内容が見るたびに変わっていたりしました、、、) ただし、この 0.1 系へのアップデートにより、LangChain のパッケージの構成について大きな変更があったため、この点についても後半で補足しつつ説明をしていきたいと思います。 複数 LLM の切り替え実装 先に補足事項を記載します。 チャットツール等のユースケースではストリーミングによる出力を行うケースが多いかと思いますが、その場合は別途 CallBack 関数を渡す実装が必要になるケースがあるため、今回はストリーミングをオフにしています。 詳細が気になる方は こちらのリンク 等が参考になります。 下記のコード例では分かりやすさ重視のためシークレット情報をベタ書きしています。(実際の自社のコードではシークレット情報は AWS Secrets Manager で管理しています。) AzureChatOpenAI 環境変数 AZURE_OPENAI_ENDPOINT と OPENAI_API_KEY に対しては、 Azure OpenAI Service から取得した値を設定しています。( 参考 ) import os from langchain_openai import AzureChatOpenAI os.environ[ "AZURE_OPENAI_ENDPOINT" ] = https://xxxxxxxxxxxxxx.openai.azure.com/ os.environ[ "OPENAI_API_KEY" ] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx os.environ[ "OPENAI_API_VERSION" ] = "2023-05-15" chat_model = AzureChatOpenAI( streaming= False , deployment_name= "gpt-4" , # 必要であれば # temperature=0.9, # model_kwargs={ # "top_p": 0.9, # }, ) ChatVertexAI Google Cloud への認証は下記2種類の方法があります。( 参考 ) gcloud や workload identity により実行環境に認証情報を紐づける方法 認証情報の json ファイルの格納パスを環境変数 GOOGLE_APPLICATION_CREDENTIALS に設定する方法 今回は後者の方法で実装を行いました。 認証情報の json ファイルの作成方法は こちらのリンク が参考になります。 import os from langchain_google_vertexai import ( ChatVertexAI, HarmBlockThreshold, HarmCategory, ) # 環境変数に認証情報が入った json ファイルのパスを設定 os.environ[ "GOOGLE_APPLICATION_CREDENTIALS" ] = "./credential_file_name.json" chat_model = ChatVertexAI( model_name= "gemini-1.0-pro" , streaming= False , # Geminiはシステムプロンプトに対応していないため、システムプロンプトを入れる場合はここをTrueにする convert_system_message_to_human= True , # 適宜要件に合わせて設定してください。今回はブロックが起こりにくい設定(BLOCK_ONLY_HIGH)にしています safety_settings={ HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_ONLY_HIGH, HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_ONLY_HIGH, HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_ONLY_HIGH, HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: HarmBlockThreshold.BLOCK_ONLY_HIGH, }, # 必要であれば # temperature=0.9, # top_k=0.9, # top_p=32, ) BedrockChat Amazon Bedrock へのアクセス権限を持つ IAM ロールが付与された環境で実行するか、 アクセスキー ID とシークレットアクセスキーを環境変数に設定して実行してください。 from boto3.session import Session from langchain_community.chat_models import BedrockChat BEDROCK_REGION = "ap-northeast-1" session = Session() bedrock_runtime = session.client( "bedrock-runtime" , region_name=BEDROCK_REGION) chat_model = BedrockChat( streaming= False , client=bedrock_runtime, model_id= "anthropic.claude-v2:1" , # 必要であれば # model_kwargs={"temperature": 0.1, "top_p": 0.9, "top_k": 250}, ) チャットモデルから出力を受け取る from langchain.schema import ( AIMessage, HumanMessage, SystemMessage, ) messages = [ SystemMessage( content= "あなたは江戸時代から続く老舗寿司屋の職人です。質問に対してぶっきらぼうに回答してください。" ), HumanMessage(content= "オススメの寿司ネタは?" ), AIMessage(content= "まぁ、季節によるな。今なら鯖が旨い。" ), HumanMessage(content= "その理由は?" ), ] response = chat_model.invoke(messages) print (response.content) # > 鯖はこの時期に脂がのって味が濃くなるんだよ。 やっていることとしては、 使用したい LLM が指定できるクラス AzureChatOpenAI , ChatVertexAI , BedrockChat をそれぞれ import し、それらのクラスのインスタンス化の際に必要な引数や環境変数を設定すれば OK です。 ここまで出来れば、後はモデルごとの実装方法の差異を LangChain がうまく隠蔽してくれるため、 API の入力/出力のフォーマット 良くある前処理や後処理 ストリーミング時の処理 などを共通化することができ、LangChain の恩恵を受けることができます。 また、パッケージのインストールについての補足事項としては、 LangChain のバージョン 0.1 系へのアップデートに従い、LLM の外部プロバイダーとの統合部分の処理は langchain パッケージから langchain_community パッケージもしくは独立した新パッケージに分離がなされました。 こちらは LangChain 公式の以下の記事でも紹介されています。 blog.langchain.dev Specifically we made two large architectural changes: separating out langchain-core and separating out partner packages (either into langchain-community or standalone partner packages) from langchain. (意訳): 具体的には、大きな構造変更を二つ行いました:langchain-core パッケージの分離と、パートナーパッケージの langchain からの分離(langchain-community パッケージに組み込むか、独立したパートナーパッケージとして分離)です。 そのため、上記のコードでは、 AzureChatOpenAI : langchain_openai からインポート ChatVertexAI : langchain_google_vertexai からインポート BedrockChat : langchain_community からインポート としています。 ※ 補足: 0.1 系へのバージョンアップでは後方互換性が担保されているので、例えば ChatVertexAI であれば以下でも import が可能です。 from langchain.chat_models.vertexai import ChatVertexAI from langchain_community.chat_models.vertexai import ChatVertexAI ただし非推奨の warning が出るので、上述のとおり適切なパッケージからの import をおすすめします。 おまけ: AzureChatOpenAI , ChatVertexAI , BedrockChat とも BaseChatModel というクラスのサブクラスになっています。 そして BaseChatModel は langchain_core パッケージに実装されているため、 ここからも LangChain のコア機能は langchain や langchain_core で開発し、外部プロバイダーに依存する機能は langchain_community や独自パッケージで開発する、という意図が汲み取れます。 まとめ LangChain を使った複数 LLM の実装を紹介しました。 レバレジーズでは MLOps 基盤や ML 活用を企画から考え構築までやりたいエンジニアを募集しています! ご興味のある方はぜひ 採用サイト をご覧ください!
はじめに レバレジーズ株式会社 レバウェル開発部 バックエンドチームサブリーダーの山口です。 総合転職サービス「レバウェル」は 転職アドバイザー(転職エージェント) スカウトサービス 求人サイト を1つのサービスで利用できるアプリケーションです。 2024年2月よりCMを放送することとなり、 このマス広告を打つために、広告効果によって増加するユーザーとその負荷に耐えることができるかの検討と対策を行いました。 本記事では、私たちがどのような視点で速度改善に取り組んだのか、そしてその結果として 特定のAPIの処理速度を82倍向上させた経緯 をご紹介します。 はじめに レバウェルについて 技術スタック 導入済みの性能対策 ISR(Incremental Static Regeneration) DataLoader 増加するユーザーとその負荷に耐えられるか 速度改善の必要性はどう判断する? API実行頻度の見積もり 性能目標 どこを改善する? 主要機能の分析 API実行量の観測 負荷テストによる速度調査 どうやって改善する? どういったSQLが実行されているか Slow Queryはあるのか 改善方針決定 実装 100件のSQLを1つのSQLにまとめる 補足 nullハンドリング 設計方針 対策後の計測 API処理速度の検証 おわりに レバウェルについて はじめにレバウェルの基本情報と今回取り組む課題の背景について簡単にご説明します。 技術スタック 今回の内容に関係するレバウェルの技術スタックをご紹介します。 言語 TypeScript フレームワーク Next.js, NestJS ライブラリ Apollo Server インフラストラクチャ AWS(ECS, RDS) Vercel API規格 GraphQL 導入済みの性能対策 ISR(Incremental Static Regeneration) レバウェルでは初期リリース時に ISR(Incremental Static Regeneration) を採用しました。 対象はSEOの観点で重要かつリアルタイム性が高くないページです。 これによりアプリ全体を再ビルドすることなくデータの変化を定期的にページに反映することができます。 DataLoader GraphQLはクライアントが必要とするデータを必要な分だけ一度に取得できるという強みがあります。 しかしその一方で、データを取得する際にN+1問題というパフォーマンスに関する問題も抱えがちです。今回はN+1問題に関する詳細な説明は省略しますが、この問題を解決するためにDataLoaderを導入しています。 DataLoaderを用いて各リレーションごとのバッチ処理を行い、 SQLの実行回数を削減 しています。 増加するユーザーとその負荷に耐えられるか webアプリケーションにおいて表示速度は離脱率と密接な関係にあり、性能を評価する上で重要な指標となります。 どんなにコンテンツが素晴らしくとも、表示速度が遅いと見てもらうことすらできません。 参考: https://www.thinkwithgoogle.com/marketing-strategies/app-and-mobile/mobile-page-speed-new-industry-benchmarks/ マス広告を打つということは、必然的にユーザー数が短期間で増加します。 この負荷によって性能が悪化すると、ユーザーにプロダクトの価値を提供することができなくなってしまいます。 そのような事態を防ぐべく、速度改善の必要性を判断し、必要な対策を講じることとしました。 速度改善の必要性はどう判断する? 速度改善の必要性があるかどうかの判断基準として以下を定めました。 予想されるAPI実行頻度において性能目標を達成しているか これを判断するために、以下の2点を定義する必要があります。 予想されるAPI実行頻度 性能目標 これらの数値に基づいて負荷テストを行い、実行結果が性能目標を満たしていなければ速度改善の必要があると判断することができます。 API実行頻度の見積もり 今回はマス広告の効果によるリクエスト数の増加を考慮する必要があります。 実際の計算の流れは以下の通りです。 *1 とある集計期間における1分間あたりのリクエストレート(単位:RPM)が 5 RPM であった時について考える。 1時間あたりのリクエスト数は以下で表すことができる。 TotalRPH = RPM * 60 つまり 300 RPH となる。 また、集計期間におけるログインユーザー数が50人だった時、 ログインしていないユーザー数をX人とする。 このとき、一人当たりに発生する1時間のリクエスト数は RPH-per-person = TotalRPH / (50 + X) と表すことができる。 ただし、今回はより余裕を持った対策を行いたいため、ログインユーザーを分母としてリクエスト数を計算することとする。 つまり一人当たりに発生する1時間のリクエスト数は RPH-per-person = TotalRPH / 50 となり 6 RPH となる。 この時、広告の掲載によって大量のユーザー増加が見込まれる場合について考える。 TVCMを放映した場合、「CMを認知してもらう」という目的では個人全体視聴率でおよそ500GRPが目安とされている。 *2 GRP500の場合3000万人前後に視聴されるというシミュレーション結果があるため、本検証でもこの数値を使用する。 *3 次にCTRが仮に0.2%だとすると約6万人前後がTVCM放映期間中に流入することになる。 TVCM放映期間がスポットCMの契約最短期間である一週間と仮定すると、 1時間当たりの新規流入数 = 60000 / (24 x 7) ≒ 357 増加するリクエスト数(毎分) = (RPH-per-person * 357) / 60 と表すことができる。 この結果 35.7 RPM となる。 既存のリクエストレートと合算し、性能を担保をすべき最低限のリクエスト数は 41.7 RPM ≒ 0.7 RPS となる。 性能目標 今回レバウェルでは、以下のことから改善対象APIを p95 1秒以下でレスポンスする ことを性能目標として定めました。 主要機能を改善対象とする(後述) 本サイトにメディア的性質がある SEO要件からより速い描画速度が求められる API実行レートはTVCM配信後に波のようなスパイクが来ることを想定し、見積もりよりかなり余裕を持たせて 5 RPS でテストすることにします。 どこを改善する? 主要機能の分析 さて、ここまでで速度改善の必要性を判断するための基準は準備できました。 次にやるべきことは、その基準に基づいて必要性の可否を判断することです。 速度改善の取り組みは時間がかかることが予想されるため、全ての機能について改善することは費用対効果的によろしくありません。 そこでレバウェルでは、まずAPIの実行量を観測し、速度改善に値するものを抽出することにしました。 API実行量の観測 今回は Apollo Studio のAPI統計情報から最も実行されているGraphQL Operationを探しました。 Insightsから統計情報を確認します。 リクエストレートを確認してみると、上位2つが多く実行されていることがわかります。 対応する画面を確認したところレバウェルの中核となる部分と対応しており、システム的にこれらの二つが主要機能と言えます。 本記事では最もレートが高かったリクエスト名をtarget(仮)、 それに対応するAPI名をgetTargetInfo(仮)として説明します。 負荷テストによる速度調査 特定した画面およびAPIについて速度改善の必要性があるかを判断します。 判断基準は決定しているため、そちらに従って負荷テストを行います。テストランナーはk6を使用します。 まず先ほど特定したリクエストレートの高いGraphQL Operationを使用している画面について試験を行います。 対象画面を含めた合計4つの画面に仮想ユーザー数100で繰り返しアクセスすることとします。 http_req_duration(p95)が12秒超という非常によろしくない結果です。 次にバックエンドサーバーに対し、画面で要求しているフィールドと全く同一な状態でAPIを実行します。 getTargetInfo(仮)を5 RPSで実行した結果 avg=7.44s min=430.08ms med=8.62s max=9.73s p(90)=9.47s p(95)=9.53s これはp95 1秒以下でレスポンスするという性能目標を満たしていないため、改善する必要があると判断しました。 どうやって改善する? 基本的なwebアプリケーションであればSQLが最もボトルネックになりやすい箇所です。 そのためまずSQLに注目することにしました。 以下の流れに従って調査します。 1. ボトルネックとなっているSQLを見つける. 2. そのSQLが遅い原因を理解する. 3. 改善する. 4. 改善したSQLを測定する. どういったSQLが実行されているか 対象のAPIを実行した時、どのようなSQLが実行されるのかをチェックします。 ここで明らかな問題(N+1問題や初歩的なWHEREでの絞り忘れなど)があれば、まずはそれを解決できるからです。 今回は以下のようなテーブル構成とGraphQLのqueryを例とします。 query target($getTagetInfoId: Int!) { getTagetInfo(id: $getTagetInfoId) { id name status targetSkills { skillId level skill{ id name } } } } targetテーブルに連なるリレーションはTypeORMのLazy Relationsによって解決します。 この場合、要求されたリレーションのフィールド1つにつき1件のSQLが実行されます。 この例の場合、以下のように少なくとも3回実行されるイメージです。 1. 指定されたIDを持つターゲット情報を取得する。 これはgetTagetInfoフィールドに対応します。 SELECT * FROM target WHERE id = $ 1 ; 2. そのターゲットに関連するtargetSkillsを取得する。 これはtargetSkillsフィールドに対応します。 SELECT * FROM target_skills WHERE target_id = $ 1 ; 3. 各targetSkillsエントリに関連するskillを取得する。 これはskillフィールドに対応します。 targetSkillsの各エントリに対して1つのクエリが実行されるため、このステップでのクエリ数はtargetSkillsのエントリ数に依存します。 SELECT * FROM skills WHERE id = $ 1 ; 実際にレバウェルの該当ページを開いてGraphQLリクエストを発生させたところ、およそ100件を超えるSQLが実行されていました。 これ自体はGraphQLの設計思想上、「要求されたものだけを取得する」ということで間違っていません。また、前述(導入済みの性能対策)の通りDataLoaderを用いた各リレーションごとのバッチ処理は行っています。 しかし該当ページは描画要件の都合により、取得しなければならないフィールドが多く、DataLoaderによる性能改善には限界がありました。 約100テーブルに及ぶ膨大なリレーション情報が必要となると、データ解決手法によってはパフォーマンス問題が発生する恐れがあります。 またコネクションプールの枯渇、ネットワークコストの増加による負荷増の問題も考えられます。 Slow Queryはあるのか 次にSlow Queryがあるかを調査します。 仮に実行時間の大半を占めるようなSlow Queryがあり、それを解消すれば良いなら100件のSQLを実行する形のままでも目下の障害にはならないからです。 今回はpostgresのpg_stat_statementsモジュールを使って分析しました。 対象APIを呼ぶページを開き、以下のSQLでSlow Queryを抽出します SELECT * FROM pg_stat_statements order by total_time desc limit 100 ; 今回は個別のクエリは軽いようで、 一番かかっているもので26msほどでした。 これはindexや個別のSQL最適化が意味をなさず、 100件の分割されたクエリを何らかの方法でまとめなければならない ことを意味しています。 改善方針決定 次は100件のSQLを1つのSQLにまとめるなら、どのようにすれば良いのか考えます。 もちろん単純に100テーブルをJOINしてしまうと結果セットがデカルト積となり、爆発的な量となってしまうので実現不可能です。 そこで今回は以下の点に注目しました。 それぞれのSQLには複雑な条件がない。単純な外部キー結合がメイン 結果セットの多さが問題 ここから考えられる対処法には以下の2つがあると考えました。 1. テーブル設計を変える 2. SQL上のテクニックで結果セットの数を削減する 1の方法は最も高品質なものができる解決法ですが、今回対象となるテーブルはレバウェルの根本となっているため、リプレイスに近い形になってしまうことから見送りました。2の方法はあまり見ない方法ですが、今回のケースではJSONB_AGG集約関数とJSONB_BUILD_OBJECT関数を用いることで結果セットを減らせそうです。 一方でSQLが複雑なものとなり保守性が低下してしまうのがデメリットです。 今回はメリット・デメリットを総合的に判断し 2の方法を採用 することにしました。 実装 100件のSQLを1つのSQLにまとめる 結果セット数を抑えつつ100件のSQLを1つにまとめるために、大きく4つのSQLの文法を使用しました。 Common Table Expressions postgresではWITH ASの構文で表されます。一時的な名前付き結果セット、つまりサブクエリの結果を生成するために使用されます。主な利点は、複雑なクエリをより読みやすくかつ管理しやすくすることです。また、同じサブクエリを一度書いてそれを再利用することができます。 参考: https://www.postgresql.jp/docs/9.5/queries-with.html LATERAL LATERALを付与したサブクエリはそれより前のFROM項目を参照できるようになります。今回はLEFT JOIN LATERALの形で使用しました。これによってサブクエリが外部クエリの行に依存する場合に、それぞれの行に対して異なる結果セットを生成できます。そして、LEFT JOINの性質上サブクエリが結果を返さない場合、nullとして処理されます。 参考: https://www.postgresql.jp/document/9.6/html/queries-table-expressions.html JSONB_BUILD_OBJECT キーと値のペアからJSONBオブジェクトを作成するための関数です。この関数は任意の数の引数を取り、それらを交互にキーと値として扱います。行のデータをJSON形式で出力する必要がある場合など、データを柔軟に扱いたい時に便利です。 参考: https://www.postgresql.jp/document/13/html/functions-json.html JSONB_AGG 引数を受け取り、JSONB配列に集約する関数です。 参考: https://www.postgresql.jp/docs/9.5/functions-aggregate.html 詳細な内容はPostgreSQL公式をご参考ください。 実装SQLはこのような形になります。 WITH r_target AS ( SELECT * FROM target t WHERE t.id = $ 1 AND t.status = ' active ' ), s AS ( SELECT ts.target_id, JSONB_AGG( JSONB_BUILD_OBJECT( ' skill ' , s.obj, ' level ' , ts. level ) ) as target_skills_info FROM target_skills ts INNER JOIN LATERAL( SELECT JSONB_BUILD_OBJECT( ' id ' , s.id, ' name ' , s.name ) AS obj FROM skill s WHERE s.id = ts.skill_id ) s ON true WHERE ts.target_id = ( SELECT id FROM r_target) GROUP BY ts.target_id ) SELECT * FROM r_target LEFT JOIN s ON s.target_id = r_target.id 実行結果イメージ id name status target_id target_skills_info 1 hoge active 1 [{‘skill’: {‘id’: 1 ,‘name’: ‘skill1’}, ‘level’: 5}, … ] 実際には上記の対応を全てのリレーションに適用し、そのSQLを用いることで効果の検証を行います。 補足 nullハンドリング 上述のSQLでLATERALを使用した理由としてネストしたオブジェクトのnullハンドリングがあります。 例えば、 -- v.hogeは存在しない SELECT JSONB_BUILD_OBJECT( ' v_id ' , v.id, ' hoge ' , JSONB_BUILD_OBJECT( ' name ' , h.name) ) FROM v LEFT JOIN hoge h ON h.id = v.hoge_id この結果は{v_id: x, hoge: {name: null}} となります。 この時に、GraphQLで「v.hogeはnullableだが、hoge.nameはnot nullable」のような設定をしている場合は少々困ってしまいます。 そのため以下のようにしてnullハンドリングを行いました。 -- v.hogeは存在しない SELECT JSONB_BUILD_OBJECT( ' v_id ' , v.id, ' hoge ' , h.obj ) FROM v LEFT JOIN LATERAL( SELECT JSONB_BUILD_OBJECT( ' name ' , h.name) AS obj FROM hoge h WHERE h.id = v.hoge_id ) AS h ON true LATERALを使用することで、サブクエリが各vの行に対して独立して評価されます。そしてLEFT JOINであるため、 h.id = v.hoge_id を満たさない場合はobjがnullとして結合されます。 従って {v_id: x, hoge: null} となり、一般的にイメージされるnullableなオブジェクトになります。 設計方針 今回選択した手法はGraphQLの大きな強みである「不要なデータフェッチを防ぐ」にやや反するものとなっています。 つまりGraphQLとSQLが分離できておらず、オーバーフェッチが発生し得る設計となっています。 その上で本方針を選択した理由として以下があります。 該当APIの使用目的が限定されており、実際にはオーバーフェッチが発生しない 工数の都合によりEager Loading的な設計を選択せざるを得なかった プロダクト全体としてはLazy Loadingを使用し「クライアントが必要とするデータを必要な分だけ取得する」という設計方針で実装されています。 対策後の計測 API処理速度の検証 対策の効果を検証するため、上記のSQLを適用した新しいAPIに対して負荷テストを行います。 条件は前回と同様に5 RPS, 同一要求フィールド、同一のレコードです。 avg=59.98ms min=36.26ms med=50.89ms max=201.09ms p(90)=96.25ms p(95)=115.55ms 以前の結果 avg=7.44s min=430.08ms med=8.62s max=9.73s p(90)=9.47s p(95)=9.53s レスポンスタイム(p95)で約82倍の高速化に成功しており、かなり改善をすることができました。 おわりに 以上がレバウェルにおける速度改善の取り組みとなります。 このような性能改善の取り組みは、コストなどの兼ね合いから最も理想的な改善策を選択できないこともあると思います。 しかしながら、 状況に応じて最適な対策を打つことで高い効果を得ること ができます。 本記事が少しでも参考となれば幸いです! 最後までお読みいただきありがとうございました。 現在、私たちと一緒に社会課題に挑戦するエンジニアを募集中です! ご興味のある方はぜひ 採用サイト をご覧ください! *1 : 実際に使用したリクエストレートなどの数値は計測値を使用しています。 今回は説明の都合上、仮の値を使用しています。 *2 : GRPとは「Gross Rating Point(グロス・レイティング・ポイント)」の略語 一定期間に放送されたテレビCMの視聴率を合計したもの≒何回視聴されるか *3 : 500GRPもしくは1,000GRPのCM出稿をしたら、何人に見られるのか?
レバレジーズ株式会社 データ戦略室の森下です。 2024/01/25にTECH PLAY Data Conference 2024にて『営業部門と挑むデータの民主化』について発表したので、そのスライドを共有します。 営業人員が多い当社において、データの民主化にどのように取り組み、データ分析の専門家だけでなく、全社員がデータに基づいた意思決定を行い、成果を向上させた取り組みについて紹介しているので、是非ご覧ください。 イベント概要: techplay.jp We are hiring 現在レバレジーズでは一緒に働いてくれる仲間を募集しています。ご興味のある方は、以下のリンクからご応募ください。 エンジニア採用ページ: recruit.leverages.jp データエンジニア採用ページ: hrmos.co
はじめに テクノロジー戦略室クロスエンジニアリングチームの小林京輔です。業務では主にフロントエンドエンジニアとして、複数チームでフロントエンドのレビュー、ペアプロをしてます。 先日、社内のエンジニアと一緒に参加した(株)サードウェーブ主催第一回24時間AIハッカソン(2023年11月3・4日)で準優勝することができたので、ハッカソンで作成したアプリについて紹介したいと思います。 ハッカソン: connpass.com 記事: forest.watch.impress.co.jp 開発したアプリ せっかく作るなら社会課題を解決するようなアプリケーションを作ろうという話になり、最終的に日常生活におけるストレスや精神的な負担を軽減し、誰もがいつでもどこでも気楽にアクセスできるパーソナルヘルスケアAIと銘打って「Kiraku」というアプリを24時間で作りました。 以前、 看護ケアと現象学的研究 を読んだことがあり、現象学的ケアという概念が新鮮に感じられました。 症状について対処するのではなく、患者さんの意向に沿った形でケアを行うこと(現象学的ケア)は、現象学的な文脈における「志向性」に着目した方法だと考え、現象学の流れを汲んだ概念を社会に実装したいという思いがありました。 上記を踏まえて、作成したアプリには大きく分けて2つの画面があり、問診画面、チャット画面があります。 問診画面では、いくつかの設問に答えてもらう形で、ユーザーの傾向を判定しました。 まずは精神的な悩みを抱えたユーザーに対する理解が必要だと考え、直面している問題に対して寄り添いを期待するタイプと、具体的な課題解決を求めるタイプの2つを想定し、プロンプトデザインをすることで問診を行います。 チャット画面では、各タイプに応じた応答をするようにプロンプトを書き、応答させるように設計しました。 寄り添いを期待するタイプのユーザーに対しては、常に共感とカジュアルな会話で悩みを和らげるように応答させ、具体的な解決を求めるユーザーに対しては問題解決に焦点を当てた直接的な質問とアドバイスをするようにし、ユーザーの傾向に合わせてパーソナライズされたチャットボットを作りました。 さいごに 今回、人生で初めて参加したハッカソンでしたが、24時間という短時間で動くものが作れ、また準優勝という結果に結びついたことは素直に嬉しかったです。 また、深夜まで残ってくれたメンバーと一緒に開発して、組織として一つの目標に夢中になれたことは貴重な体験になりました。 レバレジーズでは社会課題を技術で解決していきたいエンジニアを募集しています。 興味のある方のご応募をお待ちしています!
こんにちは!レバレジーズ株式会社テクノロジー戦略室SREチームの蒲生です。 Datadog導入と監視のイネイブリングによってインフラ監視、アラート運用を開発者向けに民主化した事例を紹介します!! この記事で伝えたいこと インフラ監視をみんなでやるのいいぞ サービスのスケールに柔軟に対応できるぞ インフラのことまで考えて開発ができるぞ ↑の状態を達成するためにやったこと 監視のイネイブリング 監視による開発者への負荷軽減 インフラ構成が簡単に肥大化、複雑化する時代になってきました。 日々成長する事業を支えるために増えていく新規のマイクロサービスやスケールアウトされるサーバーに対して監視の設定をしていくことに悩んだ経験はないでしょうか。 私が主に担当しているレバテックの開発では、インフラ監視に開発者が携われる体制にすることで高速に変化していくインフラ構成に対して柔軟に対応できるようになりました。 当時の課題 当時の開発では以下のような前提と課題を抱えていました。 前提 アーキテクチャ レバテックではAWSのEC2のモノリスアプリケーションからECSなどサーバーレス環境にマイクロサービスとして切り出していくリプレイスプロジェクトが進行中でした。 監視体制 当時の監視ツールはAWS CloudWatchを使用していて、CloudWatch AlarmやLambdaからメトリクスのアラートやエラーログをSlackに流すようにしていました。 アーキテクチャ図 課題 開発スピードに対して監視の対応が追いついていない 前提にある通りECSやLambdaを利用してマイクロサービスに切り出していくため インフラのリソースがどんどん増えていく状態に監視の設定や体制が追いついておらず、計測したいデータが取得できていませんでした。 インフラ関係のインシデントの多さ アクセス負荷やデータ量の変化、不適切な実装によるインフラリソースへの負荷が原因でインシデントが発生してしまうケースが散見されていました。 インシデント発生時にかかる調査工数の肥大化 インシデントが発生したときにログやメトリクスを利用して調査を開始するのですが 先に述べたように取得できていないデータがあったり監視体制が整っていないこともあり 調査工数が肥大化して解決までに時間がかかっていました。 課題分析 当時の課題を以下のようにそれぞれ原因分析してみました。 監視対応の属人化 監視の設定や運用ができる人が社内で限られていて 追加されていくインフラの多さに対してボトルネックになっていました。 設定にかかる負荷が高いため設定漏れなどで取得していないデータがありました。 実際の作業に関する暗黙知だけでなくどの項目に監視の設定をすればいいのか、メトリクスの相関をどう見ればいいのかなどの知見の共有が足りていない状態だったと思います。 インフラリソースの使用状況の曖昧さ 実装者からみてリソースの使用状況が把握しづらい体制でした。 インフラのリソースが普段どのくらい使用されているのかを意識するタイミングが少なく、リリース後しばらく経って変化するメトリクスなどには気づきにくい状態だったと思います。 また当時のCloudWatchだと使い慣れている人でないとデータやメトリクスへのアクセス性が悪く、使用状況をぱっと確認できる手段がなかったのも曖昧になった原因となっていました。 調査時に発生するコミュニケーションコストの肥大化 当時監視設定やメトリクスのモニタリングをSREチームが担当することが多かったのですが、実際に開発をしているのは開発チームというサイロ化した状態でした。 インシデントが発生した際に異変に気づき調査を開始するのはSREチームだけど 何がリリースされたのか、コードがどう実装されているのかまで深く把握していないので開発チームと連携を取る必要があり、そこでコミュニケーションコストが発生していました。 解決策 当時知識があったわけではないですが今から振り返るとDevOpsのCALMSフレームワークでいうC(Culture)、A(Automation)、S(Sharing)を特に意識して解決策を考えたように思えます。 監視設定、運用の負荷軽減 インフラ監視設定の自動/半自動化を進めることで設定漏れと全体の工数を減らし、インフラ監視の知識がない開発者でも設定ができるような状態にすることで属人化の解消を目指しました。 またDatadogの導入によってメトリクスやログの可視性を上げてデータへのアクセス性を向上させました。 監視のイネイブリング 開発チームと一緒にメトリクスやアラートを確認する機会を定期的に作って、開発してリリースしたものがインフラやサービスにどう影響を与えているかを把握してもらうようにしました。 それによって開発者が監視設定や普段のモニタリングを行えるようにして、インシデント発生時に開発者の中である程度対応が完結できるようにしました。 具体的な施策 Datadog導入による監視設定、運用の負荷軽減 普段の設定、運用にかかる負荷を軽減するために 監視SaaSツールであるDatadogの導入を行うことでインフラ監視設定の自動/半自動化による設定工数の削減とメトリクス、ログの可視性向上を進めました。 それまで使用していたCloudWatchでは当時だと取得したいメトリクスの不足や統一的なアラート設定がしにくい、ダッシュボードのUIの使いにくさなどの課題があり、自動/半自動化を進めにくい状態だったのでこのタイミングでツールの切り替えを決断しました。 Datadogのワンちゃん クラウドのリソースに監視用のタグをつけるだけで自動でDatadogにデータを送れるようにし、 新規のサーバーやマイクロサービスに対してはIaCツールによってコード化することで設定にかかる負荷を軽減して開発者によってインフラ監視設定を自走できるようにしました。 それによってSREチームやインフラに詳しい人がいなくても監視設定が進むようになりました。 また監視用のダッシュボードとログ検索機能を用意して、開発者が確認したいタイミングでぱっと見れるようにデータへのアクセス性と可視性を向上させました。 定期的なメトリクス確認会実施による監視のイネイブリング 開発者に監視の知見を深めてもらって運用できる状態にするために メトリクスダッシュボードを使って開発チームと一緒にメトリクス確認会を週次で実施しました。 まず先述したDatadogを使って各サービスごとにダッシュボードを作成し、開発者がいつでもインフラのメトリクスやログを確認できる状態にして そのダッシュボードを利用して週次で開発チームと週次でメトリクスやアラートを確認するメトリクス確認会を実施しました。 ダッシュボード はじめはファシリテーションを私が行ってメトリクスの異常値や状態化したアラートなど会の中で確認したほうがいいものをシェアして、それらに対する調査や改善などのネクストアクションを出すまでを話す時間を作りました。 それによってリリースされたどのコードがインフラやユーザーに影響を及ぼしたかメトリクスやアラートの確認を通して開発者が把握して異変が見つかったら修正行動に移せるようになりました。 Slackでメトリクスについて話されているスレッド 開発者がある程度慣れてきたらファシリテーションをだんだん委譲させることで、SREチーム抜きで会が回るようになっていきました。 今ではインシデント発生時のアラートへの1次アクションは開発チームが行っています。 まとめ 監視設定の負荷が軽減されて開発者が運用に関わりやすい状態になり、サービスのスケールにインフラ監視が追従できるようになりました。 さらに、開発者が週次でメトリクスやアラートを確認する機会を作ることで、開発者が普段の開発がインフラレイヤに及ぼしている影響を把握し、アラートへのアクションを開発チーム内である程度完結できるようになりました。 インフラ監視の民主化の重要性を示すひとつの例となったのではないでしょうか。 なによりSREチームの私としては開発チームの方と共通言語を使ってサービスの課題について話し合えるようになって仕事が楽しくなりましたし 開発チームが独自に監視やログの設計を見直している活動を見たときは嬉しくなりました。 改めてここで伝えたいことのおさらい インフラ監視をみんなでやるのいいぞ サービスのスケールに柔軟に対応できるぞ インフラのことまで考えて開発ができるぞ 今回は監視、アラートに関する取り組みでしたが他にも色々な取り組みを通じてSREチームとしてプロダクトの信頼性を保ちながらより質の高いリリースを可能な限り早くできる状態を目指して頑張っていきます!! レバレジーズではサービスの信頼性を高める活動をしていきたいエンジニアを募集しています。 興味のある方のご応募をお待ちしています!
前日 ~ 2日目は 前編 に書いています。 こちらの記事は、3日目 ~ 帰国までの記事です。 技術的な記事などは こちら から見れます。 3日目 3日目の会場は、MGM Grandで参加しました。 朝食 相変わらずの甘そうなパンとフルーツに加えて、スクランブルエッグ、ベーコン、ソーセージなどが揃ってました。ベーコンはかりかりでした。 ランチ 本日のランチは中華っぽい感じでした。白いお米もあったので日本人的にも良かったです。 デザートもかなり充実してました おやつ? 昼過ぎから、ピンチョスみたいなのやお菓子も会場に出てました。 ナイトパーティ 3日目は、AWS Japanが主催してくれた、日本人向けのClosedパーティーに参加しました。2日目は独り言以外で日本語を話さなかったので、かなり日本語話せました。 料理は、話しているウェイターさんが「一つどう?」って声かけてきてもらって食べるという形でした。 二次会 一次会近く地元の飲み屋街でお互い初対面同士で二次会しました。 お酒を1本買うと1本ついてくるという謎システムと、謎のAsada Friesをつまみに飲みました。 4日目 4日目の会場は、Mandalay bayで参加しました。 朝食 甘いパンが割りと控えめでした。その代わりジャムとかが大量にあるパターン。 ランチ ランチは自分で作るホットドッグ。 そしてなぜかポテチも re:Play 4日目の夜は、AWSが主催のクラブイベント。 ステージが3つあり、フードコートなども併設。飲んで踊っての大宴会でした。 5日目 最終日はVenetianにて参加しました。 朝食 安定の甘いパンとフルーツ。後はマフィンバーガー?的なのと、re:Partyでも出てたPupusaがありました。今回のre:Inventで初めて食べましたが、 エルサルバドルやホンジュラスの郷土料理 だそうです。 昼食 re:Inventは5日目の昼に終了なので、ランチは出ませんでした。なので個人でShake Shackに行ってきました。 バーガーのコンボと、赤ワイン頼みました。お酒を頼んでいるとはいえ、$30超えで日本円で5000円以上の贅沢ランチ。 カジノにて 昼のハンバーガーがお腹に残っていて、お腹減らなかったのでビールだけ。 負けました。 帰国 機内食 よくわからない料理でした。(ラスベガスで食べてたもの、大半名前分からず食べてはいましたがw) さいごに いかがでしたでしょうか?ひたすら食べたもの貼り続けただけのブログなのでなんじゃこりゃって感じかもしれませんが、真面目な記事も書いているのでぜひ こちら からご覧ください。 現在、私たちと一緒に挑戦してくださるグルメなエンジニアを募集しています。記事など読んでご興味持たれた方おられたら、ぜひご応募ください。(グルメじゃなくてもご応募ください) recruit.leverages.jp
はじめに レバレジーズ株式会社 テクノロジー戦略室室長の竹下です。技術的なことだけでなく、ゆるっとした内容もレポートしたいと思ったので、現地の食べ物をレポートしようと思います。AWS re:Inventでは開催期間の朝食、昼食が全部出て、夜もパーティーなどが開催されているため、イベントの料理を中心にご紹介していきます。 AWS re:Invent前日以前 まだ始まっていないので前日は自分で店などを探して食べに行きました 飛行機 2食出ました。Chicken or Beafを期待してましたが、Chicken or PastaとYakisoba or Omletでした。残念です。 Chicken と、Yakisobaを選びました ランチ Outback Steakでランチしました。さすがステーキの国。超肉厚 おやつ? 食べられません(バスソルト) 晩酌 さて突然のクイズです。ビールとビーフジャーキーでいくらでしょう? 答えはこちら(選択反転で見れます) => 約3300円(22$)インフレと円安やばい AWS re:Invent 1日目 朝食 アメリカンな感じで、甘いパンしか無い。。。ヨーグルトとフルーツもありました。 ランチ ランチはメキシコ風でタコスなどがありました。デザートも有り、かなり満足度が高い。 会場はVenetianで食べましたが、昼食会場もめちゃくちゃ広かったです。 あと、Wynnではコーラなどのドリンクも置いてました 晩ごはん? エキスポ(スポンサーブース)で様々な料理とお酒が食べ飲み放題でした。皆酒を片手にスポンサーブースを回ってました(もちろん私も) 2日目 朝食 朝食は、相変わらずフルーツと甘いパンが有りましたが、追加で数種類のソーセージだったり、ポテト炒めたものや、卵白を固めたなにかなどがありました(egg white frittataという料理かも?) 甘いもの以外が出たので食べごたえ有りました。 ランチ 2日目は、セッションの間があまり無かったのでサンドイッチのLanch Boxにしました。りんごが丸々1個入っているあたりすごくアメリカを感じました。 ナイトパーティー 夜はDatadogなど4社がスポンサードしているナイトパーティーにお邪魔しました。 料理に関して、ウェイターが机を回っててピンチョスみたいなのを「ひとつどう?」と進めてくる形でした。そのため、会話に夢中で食事の方は撮り逃してしまいました。すみません。(3日目ではちゃんと写真撮れたのでご容赦を。似た感じでした) ちなみに、お酒でワインを頼むと、white/red以外にぶどうの品種の確認されます。「ピノ・ノワールだけどいい?」とか。日本だとぶどうの品種を聞かれることなんて無いので新鮮でした。 3日目~ AWS re:Invent 2023 グルメ紀行 後編 に続きます。 最後に 来年は自分もAWS re:Inventに出て美味しいごはんを食べたい!という方は、ぜひ下のリンクからご応募ください。 recruit.leverages.jp
はじめに レバレジーズ株式会社 テクノロジー戦略室室長の竹下です。 現在 AWS re:Invent 2023に現地ラスベガスで参加しています。皆さんに少しでも早くラスベガスの風を感じてもらうために、月曜午前の”LLMOps: The lifecycle of an LLM”セッションのレポートを、あの会社や、あのブログより最速でお届けしたいと思います。 他の記事も見たい方は こちらの目次 からお辿りください。 セッション概要 LLMOpsを進めるに当たって、E-mailのサマリーを自動で作成するシステムを例に出しながら、どのような観点でどのように意思決定をするかをシミュレーション。また、AWSのサービスをどのように組み合わせてシステムを実現できるかの構成の紹介もあり セッションの内容 今回は、Toolingと、LLMOpsの構築プロセスについての話をしていく。 E-mailのサマリーを自動で行うシステムを例にして話をしていく。 LLMOpsにおいても、「Start small, think big」は大事。 まずは、ただサマリーを作る部分から始めるものの、最終的には各人のドメインを理解したシステムを考えて作る必要がある MLOpsとLLMOpsまたFMOpsの違いはなにか? どちらもほぼオーバーラップしている LLMOpsには、3タイプのユーザーがいる。 Provider: Tuners, Customer それぞれ必要なスキル、注目点が違っている LLMOps構築までのプロセスと、構築後の改善プロセスがある。 まずは構築段階の話をしていく まずはUseCaseの分析が必要。Criticality, Scale, Task Type, Eloquence, ROIの観点が大きく考えられる。今回のE-mailのサマリーシステムの場合は、 Criticality: Low 内容多少違っていたとしても、メールの本文を読めば良いので、優先度は低い Scale: Low 自分のメールの入力だけで良く、出力もそのユーザーに向けてだけなのでデータ的にスケール要件は低い Task Type: Specific メールの要約というSpecificな範囲 Eloquence: Medium 文章的に自然である必要はある程度ある ROI: 重要。生産性を高めることがちゃんと出来る必要がある LLMモデルを選択するときの判断軸としては以下のような物がある。 この中でUseCaseで重要な項目と優先度を見積もっていく 今回のE-mailのサマリーシステムの場合は Cost > Precision > Speed となる。 また、通常のDeepLearningなどはハイパーパラメーターなどの調整となるが、LLM、GenAIの場合は、プロンプトの調整となる モデルが決定し、調整も出来たら、評価が必要。 モデルは完璧では無いため多層的に、図のようなチーズモデルによって評価し、致命的な問題が無いかを適正にチェックする必要がある。 構築が完了したら、あとは改善のループを回す必要がある。最初の構築はS3がらSageMakerのNoteBookなどを利用し、BedRokSummaryを投げて結果を返す。 システム化する、受け取ったメールのデータを転送、バッチを定期実行、出力された結果をメールする、QuickSightにつなぎこんで評価を可視化するなどをするため、以下のような構成になる 更に進化させるには、Orchestrationも必要となってくる 最後に 現地時間 2023/11/27 12:01 書き上げました。セッション聞きながらリアルタイムでまとめてリリースしたので、きっと世界最速レポートになっていると思います。 聞き漏らしたところもあるので完璧な内容ではない部分もありますが、ご了承ください。 現在、私たちと一緒に挑戦してくださるエンジニアを募集しています。ご興味のある方はぜひ 採用サイト をご覧ください!
AWS re:Invent 2023 に弊社エンジニアが現地ラスベガスで参加しました。 セッションなどのレポート等を随時更新していきます。 こちらはそのレポートなどへのリンクのまとめ記事です。 技術記事 AWS re:Invent 2023 - LLMOps: The lifecycle of an LLM の(おそらく)世界最速レポート 【レバテックLAB】AWS開発文化のベースとなる分散チーム: 組織構造からイノベーションを加速させる仕組み【AWS re:Invent 2023】 おもしろ記事 AWS re:Invent 2023 グルメ紀行 前編 AWS re:Invent 2023 グルメ紀行 後編 さいごに 現在、私たちと一緒に挑戦してくださるエンジニアを募集しています。SREの募集もありますので、記事など読んでご興味持たれた方おられたら、ぜひご応募ください。 recruit.leverages.jp
はじめに こんにちは。レバレジーズ株式会社システム本部の田中です。 2022年11月から新規事業の立ち上げメンバーとして開発業務に携わっており、2023年6月に レバクリ をリリースしました。社内では初となる大規模かつ決済を伴うtoCサービスであり、様々な挑戦をしながら開発を進めてきました。 レバクリは「あなたの自宅をクリニックにする」をコンセプトに、オンラインで診療予約、診察、決済が完結し、自宅に薬が届くオンライン診療プラットフォームサービスです。「医療のあり方を変え、日本の医療における問題解決の主体者となる」ことをミッションとし、提携している医療機関と連携しながら、患者と医療機関の双方への最適な体験を提供できるサービスの実現を目指しています。 レバレジーズではエンジニア一人ひとりが要件定義などの上流から実装まで幅広く担当することはもちろん、マーケティングやデザイン、オペレーションなど様々な領域の業務に関わることがあります。特に新規事業の開発においてはエンジニアに限らず少人数チームで始まることが多いため、エンジニアとしてではなく立ち上げメンバーとして様々なことに主体的に取り組むことができます。この記事では新規事業『レバクリ』の開発にあたって私が取り組んだことについて、以下二つの観点で紹介していきたいと思います。 技術的側面 プロダクトマネージメント的側面 レバレジーズでの新規開発でエンジニアがどのように活躍、成長できるのか、どんな形で貢献できるのか、少しでもイメージが鮮明になると幸いです。 サービスやチームの特徴をベースとした自由な技術選定 技術選定といえば、新規事業のプロダクト開発の際の醍醐味の1つだと思います。レバレジーズでは技術選定は各チームに任されているので、事業の特性やチーム構成、メンバーの経験などをベースに行うことができます。 今回、レバクリ開発チームでは「最速でのリリース」と「開発者体験」を考えた技術選定を行いました。チーム発足からリリース予定まで7ヶ月あまりと短かったことから、できるだけ開発速度が出せるように、またチームメンバーの開発体験をできるだけ高めることができるようにという意図でした。 言語 言語はフロントエンド、バックエンドともに TypeScript を採用しました。 選定理由はかなり一般的な部分になりますが、 社内でも標準技術となりつつある 実装時に型チェックが効いてエラーを未然に防げる フロントエンド、バックエンドで同じ言語が使える ことが挙げられます。 フロントエンド TypeScriptで開発できるFWとして Next.js を採用しました。 Next.jsはFWの大きな特徴として ReactベースでTypeScriptとの相性がいい アップデートやリリースが高頻度でコミュニティも活発 キャッシュ戦略やReact Server Component対応など、高パフォーマンスのアプリケーションを実装するためのベストプラクティスが用意されている ことが挙げられます。 また、私自身入社してから1年半Next.jsを使ったサービスの開発をしていたため、新規プロジェクトへのスムーズな導入が期待できたことがありました。他にNext.jsの経験があるチームメンバーはいませんでしたが、VueやNuxtの経験はあったため順応にさほどコストがかからないと判断しました。 技術面の特徴としては bulletproof-react ベースのディレクトリ構成 featuresディレクトリ内で機能ごとに分けることで、機能間の結合を避けて無駄な共通化を考えずに開発速度を高めることができる GraphQL Code Generator と Apollo Client を組み合わせてデータ取得を実装 バックエンドのスキーマ定義から型を生成できる 自動生成されたApollo ClientのHooksを使ってデータ取得処理やキャッシュ管理の実装工数を削減 App Routerを一部導入 v13.4でstableになったことを受け、一部の機能でApp Routerを採用 といった具合です。 バックエンド/API TypeScriptで開発できる NestJS 、APIは GraphQL を採用しました。 NestJSは TypeScriptで開発されたFW GraphQLと相性がいい Express(もしくはFastify)がベースで実装手法が近い 拡張性を残しつつ、FWとしてほしい機能が一通り揃っている といった特徴があります。私自身はTypeScriptでのバックエンド開発経験がほとんどなく、Expressを少し触ったことがある程度でしたが、ドキュメントが充実していて実装方法に癖があまりないのでスムーズに実装に入ることができました。 GraphQLは 単一のエンドポイントで1リクエストから複数リソースを取得できる 取得する内容をフロントエンドで指定できる バックエンドで定義したスキーマを型としてそのままフロントエンドで使うことができる 特徴があり、ページ数が多く、同じデータを複数箇所で使ったり少し形を変えて取得したりするプロダクトの特性にフィットしていると判断しました。また、バックエンドとフロントエンドで型が一致することは開発者体験を非常に向上させるものとなりました。 技術面の特徴としては オニオンアーキテクチャベース NeverThrow を使って型安全にエラーハンドリング try-catchでエラーに型がつかない問題をResult型を返すことで解消する ORMとして Prisma を採用 多機能ではないが、直感的で実装が簡単なNode.js用のORM GraphQLのN+1問題も解消してくれる といった具合です。 社内スタッフ向けCMS 記事などの動的コンテンツの管理には Strapi というHeadless CMSを採用しました。 Headless CMSというとあまり聞いたことがなかったり、知っていても使ったことはない方も多いかもしれませんが、表示部分(Head)以外の管理画面機能やデータ配信機能(API)を備えたものです。SEO流入獲得のために記事ページを展開する上でCMSの開発は必須ですが、リソースや保守を考えて0からの自作は避けたかったため、カスタマイズ性は確保しつつ実装を最小限に抑えられるCMSを探していました。 Strapiは TypeScriptに対応している オープンソースなので無料で構築できる REST apiもGraphQL apiもどちらも利用可能 という特徴があります。自前で環境構築が必要ではありますが、料金がかからずコードを書けば簡単にカスタマイズや拡張ができる点からStrapiを選択しました。 Strapiについて詳しく書くと長くなるので省略しますが、社内利用に制限されていて機能も最低限の管理画面とAPIが必要な程度だったため、想定よりも手軽に運用に持っていくことができました。 外部サービス 認証に関しては、有名なIDaaSとして Cognito や Auth0 、 Firebase Authentication がありますが 料金が比較的安い Firebase Authentication < Cognito < Auth0 インフラをAWSで構築しているので親和性が高い セキュリティ的な懸念があまりない Firebase Authenticationには 登録しているユーザーが特定できる問題 がある といった特徴からCognitoを採用しました。フロントエンドはAmplifyと組み合わせることで簡単に実装できるのと、サーバーの処理もAWS Admin SDKを使ってシンプルに実装が可能でした。また、AWSでインフラを構築しているので権限周りの設定も楽に行うことができました。CognitoとAmplifyを合わせた実装については 別のスライド で簡単に説明しているのでそちらも合わせてご覧ください。 決済プラットフォームは Stripe を採用しました。実装するサービスやプロダクトの特徴によって大きく変わってくるので一概にはいえませんが、StripeはAPIが充実しており開発者向けのドキュメントも豊富なため、高いカスタマイズ性を求める場合に非常に相性がいいです。 ユーザー体験を第一に考えてサービス設計を主導 技術選定はもちろんですが、新規事業の立ち上げメンバーとしてサービス設計も主導しました。オンライン診療事業としては大きな競合が2社ありました。それらのサービスの機能やフローを分析した上で必要な機能を洗い出し、より良いユーザー体験を届けるためにどうしたらいいか、どの機能がクリティカルで優先すべきかを整理しました。そして、最適なユーザー体験を第一にサービス設計を主導しました。 ここでは特に設計に工夫をしたtoCのメールアドレス認証とtoBの診療画面について紹介します。 メールアドレス認証 メールアドレス認証自体は機能として一般的ですが、社内の他サービスでは導入しているものが少なく、導入してCVRが下がった例もあったため、メールアドレス認証を入れるべきかどうかの議論からスタートしました。 レバクリは基本的に登録したメールアドレスを使ってユーザーとサービス側がコミュニケーションをとる場面が多く、ログイン時のIDとしても使用する場合があるのでメールアドレスが存在しなかったり誤って入力されてしまうことはサービス運営上大きな障壁となります。また、セキュリティ面でもなりすましや第三者にメールが届いてしまうリスクにつながります。医療に関係するサービスであるため、受診歴や問診の回答内容が流出してしまうと大きな問題になってしまいます。ユーザーに安全にサービスを使用してもらうためにもメールアドレス認証は有効な手段でした。 エンジニアとしてはセキュリティリスクを最小限に抑えるためにメールアドレス認証が必要と判断しましたが、事業サイドのCVRにおける懸念がある以上、セキュリティリスクを説明して理解を得る必要があります。以下のようなフローチャートを作成し、リスクを最小限に抑えるためのパターンについて提示した上で、認証を挟むポイントとしてどこがベストか議論をしました。 レバクリには複数の機能がありますが全て診療の予約が起点となります。言い換えると診療を予約するまでは流出がクリティカルになるような情報やなりすます機会はないため、診療予約が完了するまでにメールアドレスが認証できていれば最低限のセキュリティ要件を満たすことができます。ユーザー登録に必要な情報を登録してもらい、最後に予約を確定するタイミングにメールアドレス認証を要求するステップに工夫しました。 toB診察画面 診察を行う医師やクリニックの事務作業を行うスタッフが使用する画面をtoB画面と呼んでいます。toB画面も診察の一覧表示や診察、薬の発送に関する画面など複数の機能が存在していますが、事業の状況やチーム構成によってユーザーが変化する可能性があります。例えば一人で診察から発送まで行う場合と、作業を複数人で分担する場合では導線はもちろん必要な画面の種類や数まで変わってきます。そのため、集客やサービス運営が安定してくるまでに細かい変更が簡単にできるように、あまり作り込まずに最低限の機能を用意してリリースすることを目指しました。 初期のスコープは医師が全て対応するのを基本線として、提携クリニックの医師にヒアリングをしながら設計しました。医師が普段の診察時に使っているシステムについて知見のあるメンバーがほとんどおらず、リファレンスもなかなか見つからずに難しいタスクでしたが、適宜画面の構成や機能についてすり合わせたり、プロトタイプを触ってもらってフィードバックを受けながら進めました。 現在はCSチームが設置されたり、作業者の分担があったりと事業の状況も変わってきていて、初期はスコープから外していた検索機能を利用シーンにあった形で実装したりと日々アップデートが行われています。 今後の課題 最後に今後の課題として取り組んでいきたいことについてご紹介します。 開発組織の体制整備 チーム発足からエンジニア正社員2名+業務委託数名で開発を続けており、初期スコープではあらかじめ全て設計してから進めるウォーターフォールの形で開発していました。現在はチームメンバーも徐々に増え、複数機能を並行して設計、開発、リリースするアジャイル開発に近い形になっていますが、整備されているわけではないのでタスクの管理工数の増大やチームとしてパフォーマンスを最大化できていません。社内で導入しているチームが多いスクラム開発を含めて、機能開発を進めながら開発組織の体制も整備していきたいと考えています。 プロダクトとして競合に対する優位性の確立 レバクリはオンライン診療サービスの中では後発になるため、現在は競合のレベルに追いつくための機能開発が中心になっています。着実に機能開発が進んできており、年内には機能として競合に遜色ない状態になる見通しとなっているため、今後は追いついた先で市場1位をとるためにプロダクトの強みを伸ばしていく必要があります。具体的には、予約やオンラインでの診察といった基本機能だけでなく、医薬品の服用をリマインドしたり服用の中での副作用への不安をサポートできるような機能や、診察の結果や自らの健康状態を確認できる機能など、プロダクトとして何度も使ってもらえるような仕組みを作っていくために、ビジネスサイドに食い込んで事業成長に貢献していけたらと考えています。 さいごに 最後までお読みいただきありがとうございました。レバクリを一番選ばれる最高のサービスにしていくことを目指して、これらの課題に取り組み、より強い開発組織を作っていきたいと考えています。現在、私たちと一緒に挑戦してくださるエンジニアを募集しています。ご興味のある方はぜひ 採用サイト をご覧ください!
はじめに 以前のテックブログまでにやったことと課題 各課題とその解決策の分析 特徴量の再利用性の低さ 学習にかかる時間の長期化 単一モデルデプロイフローしか整備されていない パイプライン実行の煩雑化 PoCからシステムへの初期導入のリードタイムの長期化 これまでの取り組み 特徴量の再利用性の低さ 学習にかかる時間の長期化 単一モデルのデプロイフローしか整備されていない パイプライン実行の煩雑化 これからやりたいこと まとめ はじめに テクノロジー戦略室MLOpsチームの古賀です。MLOpsチームでは、レコメンドエンジンのMLOps基盤の構築や、AWS PersonalizeなどのMLサービスやLLMなどML活用を、企画から構築まで進めています。本テックブログでは前者のMLOps基盤構築の取り組みを紹介します。 以前投稿したテックブログ にあるように、AWS SageMakerとStep Functions Data Science SDKを導入し、データサイエンティスト主導のMLモデル改善フローを構築できました。しかし、ゴールというわけではなく、まだまだ改善の余地がありました。 そこで、本テックブログでは、課題の洗い出しや分析、解決のための取り組みを紹介します。そもそもMLOpsを行う背景は 以前投稿したテックブログの「背景」 に記載しているので、興味ある方はご確認ください。 以前のテックブログまでにやったことと課題 まず前提として、今までのMLOpsシステム構成を知る必要があります。下記のような構成になっています。説明の都合上、図を書き直していますが、構成は一緒です。 一連のMLプロセスがパイプライン化されているため、データサイエンティスト主導でモデル改善フローを実行できます。また、学習-推論時で前処理を共通化しているため、Training-Serving Skewを改善出来ています。 一方で課題がいくつかありました。 特徴量作成 特徴量を再利用できない 学習:開発時、学習パイプライン(前処理から評価まで)の実行時間が長い デプロイ:単一モデルのデプロイフローしか整備されていない 全体 パイプライン実行の複雑化 PoCからシステムへの初期導入のリードタイムが長い 各課題とその解決策の分析 各課題を分析し、必要な解決策を説明します。 特徴量の再利用性の低さ 現状S3に特徴量を出力しています。S3に特徴量を格納している場合、作成者以外の人が特徴量の利用を判断するのが難しくなります。理由は、S3には特徴量のメタデータ管理やバージョン管理の機能がないからです。これらの機能がない状態で作成者以外の人が利用判断するためには、その特徴量が信頼できるデータソースから正しい変換処理により作られているかをソースコードから読み解き確認し、その結果作られる特徴量が正しいかも確認する必要があります。 そこで、特徴量のメタデータ管理機能やバージョン管理機能を持ったデータストアに格納する必要があります。 学習にかかる時間の長期化 学習パイプラインの実行による動作確認に時間がかかっていました。理由は2つあります。 不要なステップも実行されるため。例えば、評価の処理を変更した場合、評価ステップのみ実行すべきですが、前処理ステップから実行してしまいます。 SageMaker Processingの起動に時間がかかるため。1つあたり5分程度かかるため、全て実行すると起動だけで15分程度かかります。 これらの課題を解決するためには、必要なステップだけ実行し、起動時間を減らす必要があります。 単一モデルデプロイフローしか整備されていない 単一モデルのデプロイのみ実装しており、複数モデルのオンライン評価の仕組みが用意されておりませんでした。そのため、複数モデルのデプロイとそれらのオンライン評価の仕組みが必要です。 パイプライン実行の煩雑化 デプロイパイプライン以外の動作確認手順が煩雑でした。例えば、ライブラリをインストールし特徴量変換処理を変更した場合、下記の作業が必要でした。 動作確認用のAWSリソースを作成(データ取得パイプライン、S3バケット) Dockerイメージのbuildとpush 動作確認用のデータ取得パイプライン実行notebookを実行 変更するたびに、動作確認手順が変わるのは認知負荷が高い上、対応漏れも発生します。加えて、変更箇所によっては、AWSリソースは他のパイプラインやLambdaの作成も必要になります。これらの課題を解決するには、変更箇所によらない動作確認手段が必要になります。 PoCからシステムへの初期導入のリードタイムの長期化 レコメンドプロジェクトを下記のように進めていました。 MLOpsとして最優先で解決したいのは、SageMakerへの載せ替えの長期化です。長期化している理由は2つあります。 プロジェクトごとに一からインフラ構築しているため PoC後にMLエンジニアが構築したパイプラインに載せ替えているため 特に後者の工数が大きく、PoCではPoC後の移植を想定したコードを書いておらず、スパゲッティコードのような状態で移行が大変でした。加えて、載せ替えにあたり、データサイエンティストとMLエンジニアのコミュニケーションコストもかかっていました。 これらの課題を解決するためには、データサイエンティストの開発スピードを落とさず、作ったモデルをそのままシステムに組み込めるような基盤が必要になります。 これまでの取り組み 上記課題の中で実際に取り組んだことを紹介します。特徴量の再利用性についてはFeature Store + Dataflowの検証までになりましたが、他の課題はある程度解決できました。Feature Store + Dataflowの検証についても紹介します。 特徴量の再利用性の低さ AWS SageMaker Feature StoreとGoogle Cloud Dataflowを選択し、検証を進めています。AWS SageMaker Feature Storeを採用した理由は下記の通りです。 特徴量のバージョン管理機能やメタデータ機能があり、特徴量の再利用性を高められるため Google Cloud Dataflowを採用した理由は下記の通りです。 データ変更後、リアルタイムに特徴量に変換して格納するため pandas互換のAPIをサポートしており、データサイエンティストも扱えるため 他チームでRDSからBigQueryにETL処理するためにGoogle Cloud Dataflowを導入予定で技術を標準化するため 現在は下記の構成の検証を進めています。 白抜き部分の実装は概ね完了したので、これから検証 / 本番環境にデプロイし問題がないか確認していきます。問題がなければ、稼働中のレコメンドプロジェクトにも導入していく予定です。 学習にかかる時間の長期化 SageMaker Pipelinesを導入し解決しました。導入した理由は下記の通りです。 キャッシュモードが存在し、不要なステップの実行をスキップできるため ローカルモードが存在し、SageMaker Processing Jobの起動時間を短縮できるため 処理を変更したステップのみ実行できるので、最小限の実行時間にできました。 単一モデルのデプロイフローしか整備されていない 複数モデルをデプロイできるようにし、推論エンドポイントであるSageMaker Endpointの前段に配置しているキャッシュサーバーにトラフィックを振り分ける処理を実装しました。なお、トラフィックを振り分ける際は、ユーザーに対して推論するモデルを固定しました。 まず、ユーザーごとにモデルを固定した理由は下記の通りです。 ユーザーを困惑させないため。レコメンド機能を使うたびに結果が変わると、ユーザーが混乱するため。 分析を簡単にするため。もしトラフィックをランダムに振り分けると、どのモデルが推薦したか追う必要があります。この方法よりは、ABテスト期間内でユーザーごとにモデルを固定した方がシンプルで分析しやすいと判断しました。 次に、キャッシュサーバーに実装した理由は、SageMaker Endpointのトラフィック振り分け機能はランダムな振り分けしかなく、ユーザーごとにモデルを固定できないためです。そのため、SageMaker Endpointの前段のサーバーに振り分けロジックを実装しました。 パイプライン実行の煩雑化 どのファイルを変更しても、Github Actionsワークフローを動かせば動作確認できるようにしました。加えて、Model Registryに登録された評価結果を承認し、対象のモデルをデプロイできるようにしました。 Github ActionsワークフローはDockerイメージのbuildとpush、Lambda関数の作成 / 更新、データ取得と学習パイプラインを作成 / 更新し実行します。どこを変更しても、このワークフローを動かせば確認できるため、認知負荷を減らせました。加えて、必要な時のみDockerイメージの構築やLambda関数の更新を実行しているため、不要な実行時間はありません。 Model Registryに登録されたモデルを承認し、デプロイパイプラインを実行します。このようなフローにしてる理由は、人間が評価結果を確認してからデプロイしたいためです。ただし、この判断基準を明確なルールにできるならば、Github Actionsワークフローでデプロイまで実行しても良いと考えています。 これからやりたいこと 短期的には、レコメンドプロジェクトの開発効率を高めるために、解決できてない課題を解決したいです。 特徴量を他プロジェクトで再利用できない Feature Store + Dataflowを本格導入したいです。パフォーマンスに問題が無いことを確認する、他の機能との優先度の兼ね合いなどありますが、実現していきたいです。 PoCからシステムへの初期導入のリードタイムの長期化 MLOpsフレームワークの構築、または、標準構成のテンプレート化などで短縮させたいです。PoCする段階からSageMaker上で開発することで、SageMaker移行の工数を無くすためです。 長期的には、開発効率だけでなく、ビジネスサイドがレコメンドが事業に与える影響を直感的に分かるようにし、ビジネスサイドとデータサイエンティストのコミュニケーションも効率化させ、レコメンドの精度改善スピードを向上させたいです。 まとめ 以前のテックブログ執筆時の課題と解決のために、提案し実行した取り組みを紹介しました。まだGoogleが提唱する MLOps レベル1 に達してないですし、使い勝手も改善していく必要があります。加えて、今回は紹介できませんでしたが、ML活用も推進しています。レバレジーズではMLOps基盤やML活用を企画から考え構築までやりたいエンジニアを募集しています。興味のある方の応募をお待ちしています。
はじめに CTO室が設立された背景 CTO室で実現したいこと CTO室の今後 さいごに はじめに こんにちは、レバテック開発部でテックリードを担当している河村です。 私はレバテック全体のシステム設計を担当しており、今後の事業拡大に向けて、理想のシステムを目指して、技術的負債の解消などの推進を行っています。 レバテックはこれまで、マイクロサービス化を主体においた技術スタックの刷新を行ってきました。これからはユーザー体験、業務プロセス、技術的負債を含めて「痛み」となっている部分の解消を進めていき、プロダクトやサービスとしての最適解を探索していきます。 そこで、今回はレバテックのシステム課題である 「分散されたモノリス」の状態から「日本一のデータとシステムを持つ事業とそれを支えるアーキテクチャ」を目指して どのようなことを行おうとしているのか、そこに合わせて新設されるCTO室がどのような活動を行うとしているのか、レバテックの現状と課題を踏まえてご紹介します。 CTO室が設立された背景 レバテック - 事業ポートフォリオ レバテックは現在、フリーランス・派遣・就転職、新卒の各領域を軸に様々なサービス・事業を展開しています。 ※ 主なサービス、関わるシステム レバテックフリーランス、レバテッククリエイター ITフリーランスとしてのキャリアの可能性を広げるエージェントサービス レバテックキャリア、レバテックダイレクト 正社員としてのキャリアの可能性を広げる転職エージェント・スカウトサービス レバテックルーキー ITエンジニアを目指す学生の可能性を広げる就活エージェント・スカウトサービス レバテックプラットフォーム レバテックに登録いただいたITフリーランスのスカウトから、参画後の契約管理までを実現するプラットフォームサービス レバテックID サービスを継続して使い続けてもらうための根幹となる認証認可基盤システム 参考記事: エンジニアが事業戦略の実現のために認証基盤システムを構築した話 上記レバテックのサービスを支えるマイクロサービス群 参考記事: マイクロサービス化を中心においた技術刷新とその狙い レバテック - 事業進捗・サービス展望 レバテックは5年後、10年後の事業拡大に向けて、様々な事業展開を計画しております。 今までは営業とマーケティングの強みを生かして事業展開を行ってきましたが、今後は開発とデータを活用して事業展開を計画しており、開発とデータが強い組織・システムを構築しなければなりません。そのためにも、 「日本最大級のIT人材プラットフォームの進化を支える」組織やシステムを構築する必要があり、ユーザー体験、業務プロセス、技術的負債の改善 に向けて取り組んでいます。 レバテック - 現状のシステム全体像 レバテックの各サービス・事業を支えるシステムは上記のようになっています。 各システム間の連携や営業支援システム、外部サービスとの連携があり、レバテックに関連したレポジトリだけでも200個以上あり、大規模なシステムになりつつあります。 その中でも システムとして最も課題としているのが「分散されたモノリス」のような状態 (参考記事: What is 分散モノリス(Distributed Monolith) )です。すべての機能がマイクロサービス化されているわけではないので、一般的な「分散されたモノリス」の状態というわけではないのですが、発生している問題としては近い状態です。 上記の図のようにシステムは各サービス・事業ごとに分散されています。ですが、この分散されたシステムは理想的な分割ではなく、既存システムの複製で作られたシステムであったり、人が増えたことにより出来上がったシステム、システムの本来の責務を超えた機能をもっていたりと理想のシステムとかなりギャップがある状態です。 そこで、「分散されたモノリス」となってしまっている原因として以下の問題があります。 密結合なシステム 人材や企業のデータも重複して保持している状態でかつDB直参照やバッチサーバ連携で行っているため、システムの追加や変更を意識して開発しなければならない 非構造化データの存在 文字列やEAVパターンを利用した暗黙的なリレーション構造が存在し、DBに格納される文字列を変更するだけでシステムの障害のきっかけとなり得る マスタデータ(職種やスキルなどのリファレンスデータ)の分散 各システムでマスタデータのIDや項目が異なり、マッピングをして連携や分析を行っている 上記の問題は2、3年前から顕在化していました。ですが、いきなりすべての問題に取り組むのは難しく、また、当時の技術スタックも古い状態で稼働していました。なので、まずは技術スタックの刷新やマイクロサービス化の導入から進めてきました(参考記事: マイクロサービス化を中心においた技術刷新とその狙い 、 レバテックの未来に向けた開発組織の取り組み )。技術スタックの刷新により、静的型付け言語であるTypeScriptをベースとしたシステムにすることができ、負債を貯めにくい・解消しやすい設計手法であるクリーンアーキテクチャやDDD(ドメイン駆動設計)の導入が行いやすくなり、計画的な負債の解消を進めやすい状態にすることができました。 今後は 「分散されたモノリス」から「それぞれのシステムとデータが”独立化”し”疎結合化”された状態」 を目指して、現在のTypeScriptをベースとしたシステムのリニューアルを行い、今後のレバテックを支える組織・システムを構築していきます。 つまり、今まで行ってきた「リプレース」を生かして、今後は「それぞれのシステムとデータが”独立化”し”疎結合化”された状態」に向けて 「リファクタリング」「リプレース」「リニューアル」を計画的に 進めていきます。 ※ リファクタリング・リプレース・リニューアルの定義 リファクタリング 現在のシステムをI/F(IN/OUT)やふるまいを変えずにコードを変更すること 例:MVCからレイヤードアーキテクチャに移行する リプレース 現在のシステムをI/F(IN/OUT)やふるまいを変えずに別のシステムに載せ替えること 例:PHPがベースで動いているシステムをTypeScriptベースのシステムに載せ替える リニューアル 現在のシステムをI/F(IN/OUT)やふるまいを変えて、新しい価値を生み出すこと 例:システム・データの拡張性を向上させるため、ユーザー登録の仕組みや業務プロセスから改善を行う CTO室で実現したいこと レバテック - CTO室ミッション 上記のレバテックにおけるシステム・データの課題を解決をリードしていくため、この度、CTO室を立ち上げることになりました。 大規模なシステムになってきたレバテックの関連サービスを支え、今後の事業拡大に向けて、総合的なアーキテクチャや設計が求められることになります。特に、最も難しいと考えているのが、今のレバテックにおけるユーザー体験、業務プロセス、技術的負債の中で最も「痛み」となっている部分の特定とその「痛み」の解消です。 すべての課題をいきなりすべて解消できる規模ではなく、今後の事業拡大を鑑みて、 最も「痛み」となる部分を分析・特定し、経営や他職種を巻き込んで、この「痛み」を計画的に解消を進めていく必要 があります。なので、ただ単純に技術的負債を解消を進めていくということではありません。現状のユーザー体験や業務プロセスを含めて最適解を探索する必要があります。 レバテック - CTO室が目指す先 レバテックは現在、登録者数50万人、契約社数1万社を突破し、IT人材の2.5人の1人が登録するサービスになっております。上記の「分散されたモノリス」な状態を脱却し、レバテックにおけるユーザー体験、業務プロセス、技術的負債の中で最も「痛み」となっている部分を解消し、 目指す先は「日本一のデータとシステムを持つ事業とそれを支えるアーキテクチャ」を作ること です。 レバテック - コア要素『D-POS』のAsis-Tobe 「日本一のデータとシステムを持つ事業とそれを支えるアーキテクチャ」になるために上記のTobeのような状態が必要だと定義しています。つまり、データを軸にプロダクト/オペレーション/システム(Data→Product/Operation/System)を再設計していく必要があると考えています。 ここまでをまとめると、 レバテックは5年後、10年後の事業拡大に向けて、様々な事業展開を計画している そのためには、「日本最大級のIT人材プラットフォームの進化を支える」組織やシステムを構築する必要がある 現在、組織・システムとして「分散されたモノリス」という状態の課題を抱えている 理想を「日本一のデータとシステムを持つ事業とそれを支えるアーキテクチャ」と定義 そこに紐づくTobeを目指してレバテックを再設計していく CTO室の今後 今後、CTO室は上記の課題から以下の軸をベースに強化していきます。まだまだ具体的な目標などは決められていませんが、以下を軸にCTO室の役割を拡大していけたらなと考えております。 事業戦略に紐づいたシステム戦略のリード テクニカルとドメインを掛け合わせたドメインの最適化 事業横断した組織・システムの最適化 開発者生産性の向上 事業戦略に紐づいたシステム戦略のリード CTO室は、今後ますます事業戦略に連動したシステム戦略を主導する役割を果たします。この取り組みにより、技術戦略がビジネスの長期的な目標と一致し、我々の競争力を向上させ、新たな市場機会を探求します。「日本最大級のIT人材プラットフォームの進化を支える」組織やシステムを構築し、戦略的な成長を支えることを目標に進んでいきます。 テクニカルとドメインを掛け合わせたドメインの最適化 テクニカルな専門知識とビジネスドメイン知識を融合させて、ドメインの最適化に取り組みます。このアプローチにより、特定のドメインに特有の課題に対処するための優れたソリューションを提供します。そこで、レバテックの事業/開発双方の戦略及び戦術に基づく特定のテクニカルドメイン領域における信頼されるスペシャリストを多く輩出していき、新たな可能性を切り拓きます。 事業横断した組織・システムの最適化 CTO室は、組織とシステムを結びつけ、情報共有と協力を促進し、事業全体での最適化を実現します。これにはイネイブリング、SRE、QA、アジャイルCoEによる事業を横断した組織・システムの強化が必要です。冗長性の排除やリソースの最適利用、可観測性の向上により、より効果的に運営し、ビジネス目標の達成を目指します。 開発者生産性の向上 CTO室は開発者生産性の向上に注力します。新しいツール、プロセス、トレーニングを提供し、開発者がより効果的に作業できる環境を整備していきます。これにより、イノベーションが促進され、プロダクト開発をより支援できたらと考えています。 ゆくゆくはエンジニアが選ぶ「開発者体験が良い」イメージのある企業「Developer eXperience AWARD 2023」ランキング上位5にランクインに向けて取り組みを進めていきたいと考えております。 さいごに これらの目標を達成するために、CTO室は積極的な取り組みを進め、テックカンパニーとしてより高いレベルの開発組織にしていきたいと考えています。現在、一緒にCTO室を推進していただけるエンジニアを募集しています!ご興味のある方はぜひ こちら からご連絡ください!