LIVESENSE ENGINEER BLOG

リブセンスエンジニアの活動や注目していることを発信しています

画像配信システムにCDNの導入を試みた話

こんにちは。9月よりインターンとして参加しているインフラグループの幸田です。
現在リブセンスでは、高速化の取り組みを進めており、その一環として今回は画像配信システムへのCDN導入検証を行いました。

この記事では導入検証を通して見つけた、最低限確認しておきたい キャッシュヒット率 に関わる設定を2つ紹介します。

検証の背景とか

ステージング環境での検証 というフェーズで、インターン課題として取り組みました。
最低限キャッシュを無視する設定(PASS設定)しかされておらず、まさに「とりあえず通してある」という感じです。

ここから本番環境へ導入を進めるための導入検証をはじめました。

前提とか設定とか

前提として、今回導入検証を行うのは画像の配信を専門に行う 画像配信システム です。
CDNには Fastly を使用しました。
(以下Fastlyに合わせて画像配信システムのことを Origin と表現します)

ステージング環境は社内からしかアクセスできないので、そのままだとキャッシュヒット率の計測がうまく行えません。
そのため今回検証するステージングのOriginには、本番トラフィックの1/3をミラーリングし、ある程度トラフィックを確保した状態で、動作確認や検証を行いました。
この時点でのキャッシュヒット率は平均で30%~35%程でした。

とりあえずやってみよう

「キャッシュさせて高速にコンテンツを配信する」という観点で見た時、キャッシュヒット率が低くCDNとしての役割を果たせていないと思ったので「 思い当たる設定を見てみる 」ことにしました。

まずはTTLの設定を見てみる

キャッシュの話になった時、初めに思い浮かぶ設定値といえばTTL(Time to live)ではないでしょうか。
TTLは「どのくらいの期間キャッシュとして保持するか」という設定です。

Origin側の設定ファイルを確認しましたが指定はなく、更に前提でも書いたようにFastlyで明示的な設定も施していませんでした。

TTL指定しなかったらどうなる?

Fastlyではデフォルト値としてTTLが 120s に設定されています。
OriginやFastlyで特に指定がない場合はこの数値が適用されます。

つまり2分間だけキャッシュとして保持され、期限が切れるとOriginから取得して再度2分間キャッシュするという動きになります。
そのためキャッシュヒット率低下に繋がります。

TTLを設定する

「明示的にTTLを設定しなかったために 120s が適用され、キャッシュされる時間が短かった」というのが今回の原因なので、 明示的にTTLの値を設定 してみましょう。

TTLの設定方法はいくつかありますが、今回はOriginで Surrogate-Control というヘッダを付与して設定しました。
ヘッダに関する詳しい内容はこちらを参照してください。

nginxでの設定例です。

+    add_header Surrogate-Control "max-age=604800";

Surrogate-Control は今回で言うとFastlyなど 間に入るProxyサーバにのみ有効なTTL値を設定するためのヘッダ です。

通常 Cache-Control で設定したTTLはブラウザなどにも適用されますが、 Surrogate-Control は今回の場合だと、Fastlyだけで取り扱われ、その後取り除かれます。
そのためブラウザからこのヘッダは確認できません。

今回の Surrogate-Control の値は 604800s1 にしてみました。

TTLの設定値について

今回は「検証のために、ある程度長くしてみよう」という考えから 604800s を指定しましたが、本当にこの設定値が適切なのでしょうか。

個人的には正解がないような気がしていて、扱うコンテンツによっても変わってくるものだと思います。
なのでこのあたりの設定値は、コンテンツの種類や更新頻度を総合的に判断した上で設定する必要があります。

例えば、

  • あまり更新されることがないから、(仮に、少しの間古い情報が返されたとしても)大きな問題がない場合
  • そこそこ高頻度で更新されるので、数日間保持されると困る場合

など。
「すぐに更新してくれないと困るものなのか?」や「逆にちょっとくらい遅れても困らないものなのか?」という点に着目するとより適切な設定ができるかと思います。

極端な話をすると「何ヶ月も更新されることがないのであれば、何ヶ月も保持していい」ので。

キャッシュの更新どうする?

またキャッシュの更新をTTLだけに任せると「TTLが過ぎるまではOriginでコンテンツが更新されても、キャッシュされた古いコンテンツを返すのか?」という話も出てきます。

これについては、 CacheBusting と呼ばれる手法を用いることで解決することができます。
GETパラメータで更新日時などを付け加えて別のURLにすることによって、再取得させる方法です。

それ以外にもFastlyには 強力なPurge機能 が備わっています。Purge機能とはキャッシュを削除する機能です。
Originでコンテンツを更新した時にこのAPIを叩くような実装をすると、すぐ(ミリ秒単位)にFastly上からキャッシュを削除することができます。
CacheBusting の場合だとTTLが過ぎるまではサーバ上に残ることになるので、少しだけセンシティブな内容を扱う時はPurgeするやり方がオススメです。

ん?ブラウザ変えたらHITしなくなるな?

キャッシュのHIT,MISSの洗い出しをしようと思い、主にGoogleChromeのDevToolsを眺めていました。
普段はFirefoxを使用しているのですが、DevToolsが優秀なのでこういう検証をする時にはChromeも使っています。

その過程で「Firefoxで何度も表示させていたページを、Chromeで確認するとMISSになる」という現象から、User-Agent(以下UA)を取り扱うVaryヘッダに目をつけました。

Varyヘッダを取り扱うとどうなるか

そもそもVaryヘッダは「同一のURLでもヘッダの内容が違うから、別のコンテンツとして扱ったよ。キャッシュとかするならそこらへんよろしくね」という命令にあたります。
よくある例だと、UAのデバイスの情報をもとにコンテンツの出し分けを行っている時、CDNやL7LBに別物として認識させるようなケースでしょうか。

Fastlyでは2特に指定をしない限り、Varyヘッダを取り扱います。
つまりUAなどが含まれていた場合、 UA毎にキャッシュを生成します
UAはクライアントの様々な情報を格納しているため種類が多く、キャッシュヒット率に影響します。

今回の場合だとOriginでUAが付与されていたため、まさに「UA毎にキャッシュが生成されている」という状態でした。

じゃあVaryヘッダ消そう

この問題に対する対処法はいくつかあります。

  • FastlyでVaryヘッダを削除してキャッシュする
  • OriginでVaryヘッダを適切に設定する
  • FastlyでUAを正規化する

など。

今回は1つ目の、 FastlyでVaryヘッダを削除してキャッシュする という方法を採用しました。

前提でも話したように、今回対象となるのは画像配信システムであり画像以外のコンテンツを扱っていません。
またUAを利用してのコンテンツの出し分けも行っていないため 「 Varyヘッダを扱う必要がない 」 という理由から、削除する方法を取りました。
VaryヘッダにはUA以外にも Accept-Encoding なども含まれていますが、今回の場合は不要なので削除しました。

それ以外にも「FastlyのダッシュボードからGUIで設定可能であり、素早く試せる」というのも理由の1つです。

設定

Fastlyの設定画面からGUIで設定することができます。

1.対象のダッシュボード画面を開きます。
2.[CONFIGURE]を開いて、CONFIGURATION > Clone activeをクリックします。これで現在の設定がCloneされます。
3.サイドメニューより[Content]を開き、CREATE HEADERから画像のように設定します。
f:id:livesense-blog:20180914173330p:plain

効果を確認

時系列で話すと、Varyヘッダの削除→TTLの設定という順番で検証を行いました。
なので、Varyヘッダの設定を入れたのが左の赤ラインで、TTLの設定を入れたのが右の赤ラインです。
当初平均で30%程だったヒット率が今だと平均で80%近くまで上がってきています。

  • Varyヘッダの設定単体で見ると、約20%UP
  • TTLの設定単体で見ると、約25%UP

といった感じです。 f:id:livesense-blog:20180914173345p:plain

おわりに

この記事では最低限チェックしたいポイントを上げましたが、他にもヒット率を上げるための方法はいくつもあると思います。
また今回は画像配信だけを行うシステムを対象にしたのであまり複雑な設定をしなくても済みましたが、他のコンテンツも扱う場合だとUAが必要になったりなど色々複雑になってきます。
特に 個人情報などセンシティブな内容が絡んでくる場合は、設定を慎重に行う必要があります。

FastlyではVCLと呼ばれる言語を利用して複雑な処理を行うこともできるので、工夫次第でもっと最適な設定ができそうですね。

おまけ:感想的な何か

2週間という短い期間でしたが、内容の濃いインターンでした。
「なんかFastly流行ってるしカッコいいからこれがいい」という理由で、インターン課題を選定しましたがCDNに対する理解がより一層深まりました。
また技術的な部分はもちろん、ドキュメントを作成する時のコツなどそれ以外のこともたくさん学べました。

インターン時は「コーヒーの伝道師」と呼ばれ、社員の方に慕われたりなどすごく楽しかったです(笑)

最終日の焼肉も美味しかったです!関わってくださった社員の皆様ありがとうございました!


  1. 604800s = 1週間

  2. デフォルトのVaryヘッダの取り扱い方については、各CDNによって異なるので注意が必要です。

GopherCon 2018に行ってきました!

イエシルでサーバーサイドエンジニアをしている@mom0tomoです。
コロラド州デンバーで行われたGopherCon 2018に、会社から支援金を受けて行ってきました。

海外カンファレンスに参加するのは初めてだったので、新鮮なことばかりで毎日がとても刺激的でした。 今回は中でも特に印象に残った出来事をご紹介します。

なぜGopherConなのか?

わたしはふだんRuby on Railsを使っていますが、リブセンスでは一部のシステムでGoが使われています。

また、わたしはプライベートでWomen Who Go Tokyoというコミュニティの運営スタッフとしてイベントを主催しており、国際的なカンファレンスに参加して世界のGopherと会うことで、自分自身の技術に対するモチベーションをあげること、またそこで受けた刺激を社内外に伝えることを目的として参加しました。

f:id:mom0tomo:20180913053302j:plain
Women Who Goの仲間と

カンファレンスの日程

2018年のGopherConは4日間にわたって開催されました。

1日目はプレイベントとして、様々なワークショップが開かれました。
ワークショップのチケットは別に購入する必要があるため、ワークショップには参加しないけれども会場内をぶらぶらするという人も見られました。

わたしはBuffaloというRails likeなフレームワークを使ったWeb Developmentのワークショップに参加しました。
朝から1日かけて一通りの開発ができるようになるまで、開発者自ら講師になっていただきながら、初心者でもわかるように丁寧に教えていただきました。

他にも機械学習やパフォーマンス改善など、同時開催なのでひとつしか参加できないのが惜しいほど多種多様なワークショップが開催されていました。

f:id:mom0tomo:20180913052606j:plain
会場外観

2日目と3日目が本編で、大小のルームでセッションやトークが行われました。
また、2日目の夜には公式のパーティが野外で盛大に行われました。「Gopher Band」というバンドが登場し、迫力あるロックの生演奏を前にみんなでお酒を飲んだりご飯を食べたり、夜もふけるまで楽しく過ごしました。

f:id:mom0tomo:20180911221343p:plain
Gopher Band

最終日はコミュニティデーということで、OSSへのコントリビュートの仕方や実際に機器を使ったIoT開発のワークショップ、GoogleのGo開発チームの議論に参加できる時間などが取られていました。

最終日を待たずに帰ってしまう方もいるようで、コミュニティデーは本編よりも参加者は少なめでしたが、少人数だからこそのメリットを生かし、参加者同士やOSS開発者、コミュニティのリーダーの方との交流をじっくり取ることができて、充実感のある内容でした。

f:id:mom0tomo:20180911214649p:plain
コミュニティデー

わたしはOSSにコントリビュートするワークショップに参加し、athensというプロジェクトを用いてコントリビュートの基本的な方法を学びました。

ワークショップでははじめに、OSSにコントリビュートする上での心構え(気張らずに、みんなのためにコントリビュートしよう)や、初めてのコントリビュートまでの流れやオススメポイントなどをお話しいただきました。OSSへの熱い想いのこもったトークはわくわくするもので、その後すぐに同じテーブルの参加者とわいわい楽しく開発をはじめました。

華々しいオープニング・クロージングトーク

2日目の本編は、TEDさながらの迫力あるトークで幕を上げました。

f:id:mom0tomo:20180911214709p:plain
オープニング

トーク中はリアルタイムで正確な文章起こしがディスプレイに流れており、会場はみな驚きました。

Goを使った何らかの技術を使っているのか、はたまた人間が文字起こしをしているのか?と話題になっていましたが、どうやらプロの筆記者の方が数名その場でタイピングしていたようです。

いずれにせよ、オープニングおよびクロージングトークは非英語ネイティブでも容易に内容が理解できて楽しめる一つのコンテンツになっていました。

LTを含む全てのトークはyoutubeで視聴することができます。
Gopher Academy - YouTube

コミュニケーション、ネットワーキングの時間

日本で自身が参加したことのあるカンファレンスや技術イベントと比べて特に違いが目立ったのは、参加者の方々が対面でのコミュニケーションに注力していることでした。

いままでわたしが国内で参加した技術イベントでは、Twitterのタイムラインを追うとイベントの流れがわかるというほど、Twitterでのコミュニケーションが盛んでした。
しかし、GopherConは参加者の人数が多い割にハッシュタグを追ってもあまり情報が流れて来ません。

不思議に思って仲良くなったアメリカからの参加者の方に聞いて見たところ、普段会えない人と対面でコミュニケーションをとり、ネットワークをつなぐことで今後のコミュニケーションを円滑にしたり仕事に繋げることが目的としていると教えてもらい、違いに納得しました。

ネットワーキングの時間は朝食、ランチ、パーティなどふんだんに用意されていて、参加者の皆さんも気さくな方が多いのでテーブルで話が弾みます。 またコミュニケーションの時間にはセッションの感想等を話し合ったり、人によっては直接スピーカーに話しかけに行ったり、対面での会話や議論が多数交わされていました。

参加していない人も楽しめるTwitter実況は便利だと思う一方、対面でコミュニケーションの輪を広げて行くスタイルも参加する醍醐味を感じられて良いと思いました。

もちろん参加者全員がコミュニケーションが得意というわけではなく、大勢の知らない人と話すのは苦手だという人もいたり、自分なりのトーク技術を公開している人もいました。

わたしも初対面の人と話すのは得意ではありませんが、参加者はオープンに話題を振ってくれる気さくな人ばかりだったので、居心地よく過ごすことができました。

また公式のパーティに加え、現地のGopherによるmeet upやWomen Who Goディナーなど、知り合いをつくって交流するためのイベントが複数開かれていました。

印象的だったセッション

全てのセッションとトークが魅力的でしたが、ここでは特に気づきの大きかったものとして、アクセシビリティについてのセッションをご紹介します。

このセッションでは、目の不自由な方がエディタのコード読み上げ機能を使ってプログラミングをする例を挙げ、実際の読み上げ音声を使いながらアクセシブルなコードとは何かを説明していただきました。

一例を挙げれば、Goでは変数名を短くする、また型名の後ろに変数名を書くという特徴があります。

短い変数名が先に来て型名が後に来ることにより、エディタ等のコード読み上げ機能を使うプログラマにとって、素早く変数名を聞き取りすぐに意味を捉えることができます。


ロジカルに書くこと。
発音できるように書くこと。
首尾一貫して書くこと。


どれもコードを書く上で意識すべきと言われている基本的な原則ですが、アクセシビリティと関連づけて考えられたことはあまりないのではないでしょうか。

アクセシビリティに配慮して書かれたコードは、みんなにとって良いコードになる。

この言葉がひときわ輝く、すばらしいセッションでした。

下記にセッションの内容がアップされています。
ぜひ皆さんもご覧ください。

Writing Accessible Go

Go2に向けてのドラフトの話

2日目の午前のセッションが終わったと同時に、突如ビデオメッセージが流れ始めました。

話し手はあのRuss Coxさん!内容はGo2のドラフト構想についての発表で、会場は興奮の渦に包まれました。

f:id:mom0tomo:20180913052845p:plain
Russ Cox氏

詳しくは下記のページからアクセスできます。 https://go.googlesource.com/proposal/+/master/design/go2draft.md

また、日本語で意見を述べることが可能なフォームもあるので、興味のある方はのぞいてみてはいかがでしょうか。

おわりに

リブセンスでは半期に1名海外カンファレンスのための渡航費等を支援しており、誰でも立候補することができます。 もちろん, 海外カンファレンスには登壇者として招待されて行くのが憧れですが、すべてのエンジニアにチャンスが与えられるのは意義深いことです。

今回のGopherCon参加では概算で40万円ほどかかりましたが、その費用のほとんどを会社に負担してもらいました。
4日間のカンファレンス参加チケットに宿代等を合わせると小さくない金額になるので、支援してくれた会社に感謝しています。

今回の記事を読んでいただき、海外カンファレンスに行きたいと思った方、自分ならこんなものを持ち帰ってくるというアイディアのある方は、 ぜひリブセンスにお越しください。

リブセンスでは一緒に働きたい!という方をお待ちしています。

Tech Award 2018を開催しました

こんにちは、就活会議でエンジニアをしている大政です。 リブセンスでは、昨年からTech Awardという技術表彰をはじめました。

Tech Awardとは

技術的に優れた取り組みであったり、事業のKPIに直接的にはつながりにくいレガシー改善について、直近1年間の業務として行った取り組みを表彰するイベントです。 Edge (先進的)とLegacy (レガシー改善) という2部門を設けて、プロジェクトごとにエントリーしてもらい、当日プレゼン発表をするというものです。 プレゼン発表はノウハウの共有・質疑応答を目的としたもので、詳細な内容はエントリー時に社内Wikiにドキュメントを記載していただき、プレゼンの上手さではなく、取り組みの内容で審査をしています。

f:id:taise:20180827143426j:plain
Tech Award 2018 の メインビジュアル

審査員のみなさん

社外からも素晴らしいエンジニアの方を招致して審査をしました。

f:id:taise:20180829140908j:plain
左から藤 吾郎さん(Bit Journey, Inc.) 、能登 信晴さん (Livesense Engineer Leader)、田中 勇輔さん (Akatsuki Inc.)

f:id:taise:20180829140938j:plain
谷村 琢也さん (Livesense 執行役員)、中野 悦史さん (Livesense インフラストラクチャーグループリーダー)

プログラム

Edge部門で3エントリー、Legacy部門で5エントリーありました。 どのエントリーも創意工夫であったり、技術的なチャレンジに溢れるものでした。そのうちのいくつかは、後日こちらのブログでもご紹介できると思います。

Edge部門

タイトル 概要
AB テスト : 多腕バンディット基盤 "Brain Optimizer” ABテスト / 多腕バンディットを社内の複数のサービスで実施出来る基盤の実装 / 構築
メルマガ配信基盤 KiKi キューワーカー型の大規模メルマガ配信基盤を作成し、10 年来の PHP フレームワーク上のバッチで動いていたメールマガジン群を移行
Heroku Private Spaces移行 HerokuのCommon Runtime環境(米国リージョンにある)で運用中のサービスを、Heroku Private Spaces(AWSの東京リージョン)に移行

Legacy部門

タイトル 概要
人は1年でAWSの環境をモダンに改善できるのか 設定内容や構築ドキュメントが残っていないAWS設定や運用サーバ自身の設定を「可視化」及び「コード管理」をして「変更のしやすさ」、「設定の適用」を容易にする
転職会議 同時登録フルリニューアル セキュリティサポートの切れた会員登録の基盤のアーキテクチャリニューアル
【転職会議】契約管理業務のシステム化 バックオフィスの方々が手動で運用・管理していた、転職会議BUSINESSの契約から請求までの一連のフローをシステム化
転職ドラフト:問い合わせ効率化 問い合わせフォームによくある単語を入力すると解決方法が表示される仕組み
転職会議 新商品:Business PR 開発(Cosmeticsプロジェクト) レガシーを避けながらAPIサーバーを作って新機能追加

プレゼン発表

プレゼン発表当日は、エンジニア・ディレクターを含めて50名以上がオーディエンスとして参加し、プレゼン発表は笑いあり感嘆ありで、リブセンスらしい大変あたたかい雰囲気で行われました。

Edge部門にエントリーされたプロジェクトは、まだ誰も踏み抜いていない技術的な問題に取り組んでノウハウが蓄積されていたり、スケーリングの問題を分散システムの構築で真っ向から解決して運用までしっかりのせていたりと、聴き応えのあるプレゼンばかりでした。

Legacy部門にエントリーされたプロジェクトは、避けることができないレガシーなコード/インフラとの戦いであったり、リブセンスの事業環境に依存した課題をエンジニアリングで解決したものが多く、表に出てきにくい工夫が詰まっていて非常に興味深いプレゼンばかりでした。

また、藤さん・田中さんから、本質的な鋭い質問をたくさんいただきました。発表者だけでなく、オーディエンスのエンジニアも大変刺激になったと思います。

f:id:taise:20180829141326j:plain

Tech Award 2018 大賞

昨年と今年のTech Awardは、Edge部門とLegacy部門の2部門で、それぞれ大賞を決めています。 両部門を合わせた総合1位のような賞を作っていないのは、技術的に先進的な取り組みも、レガシー改善も、今のリブセンスにはとても重要なもので、優劣つけられないと考えているためです。 なお、大賞を受賞すると少なくない額のAmazonギフト券が贈呈されます。

Edge部門: メルマガ配信基盤 KiKi

受賞者

KiKi 開発チーム

  • 岡前 直由
  • 山内 雅斗

受賞理由

  • 分散処理、並行処理、スケーラブルなアーキテクチャをちゃんと設計して作っている
  • 止まった時のリカバリや運用のことまで見据えて作っている

f:id:taise:20180829141240j:plain

Legacy部門: 人は1年でAWSの環境をモダンに改善できるのか

受賞者

  • 藤村 宗彦
  • 山浦 清透

受賞理由

  • AWS の改善に追従する仕組みを作っている、レガシーになりにくい仕組みになっている
  • 運用ルール決めるのが難しいが、それもやりきっている
  • コードで管理するのが当たり前となっている

f:id:taise:20180829141412j:plain

まとめ

リブセンスは、様々な事業領域で「新しいあたりまえを発明」して、ユーザーに価値を届けるべく日々試行錯誤をしています。 そしてそれには、いま以上に高い技術力が必要だと考えており、今回ご紹介したTech Awardを始めとした様々な施策が社内で行われています。

今年で2回目を迎えたTech Awardは、昨年から進化をして開催することができました。
果たして来年はどんな技術的に優れた事例が大賞を取るのか、いまから楽しみですね。
もしかしたら、この文章を読んでくださったあなたが手にしているかもしれません。

リブセンスでは優秀なエンジニアを募集しております。
ご応募お待ちしております。

募集情報 | 株式会社リブセンス | 採用情報

f:id:taise:20180829141735j:plain

回転寿司が会社にやってきた

はじめまして。 転職ナビでエンジニアをしている、negitorosanと申します。
事務職として 2015年6月リブセンスに入社しましたが、2016年1月からエンジニアに転向しました。

5月末、リブセンスのエンジニアを集めて『Engineer Drink UP』を行いました。
今回は、『Engineer Drink Up』を開催するまでのエピソードをご紹介します。

f:id:livesense-blog:20180615184546j:plain

Engineer Drink UPとは?

四半期ごとに開催される、リブセンスのエンジニアのための懇親会です。
エンジニアがあつまってお酒を飲みながら、LTをしたり、聞いたりして盛り上がり、普段なかなか交流のない別チームのエンジニア同士の横のつながりを強くすることを目的としています。
そして、毎回新鮮さを追求するために、下記の方針で開催しています。

  • 事業部毎の持ち回り制
  • 事業部の個性を発揮する

運営メンバーで話し合ったこと

まずは目標として、下記を設定しました。

  • 参加率の改善
  • 記憶に残る楽しい懇親会にする
  • LTの実施

参加率の改善

今までの懇親会では、エンジニア80名中30〜50名弱と、50%ほどの参加率でした。
どうして参加率が向上しないのかを話し合ったところ、下記のような問題点が見えてきました。

  1. 業務後に拘束されるのが嫌...
  2. オフィスから移動するのが嫌...
  3. 家庭があるため、夜は早めに帰らないといけない...
  4. 行かない人も多いのだから、自分も参加しなくてもいいだろうという気持ち...

2.に関しては大人数を収容できるセミナールームがオフィス内にあるため、大きな問題にならない見込みが立ちました。
そうなると、1.と3.を解決するにはどうしたらよいか。

私達が導き出した答えは・・・

業務時間に開催すればよい

業務時間内であれば、仕事の一環!
早く帰らないといけない人も参加できる!
あの人が行くなら自分も行こうかなと心揺れる人も増えるはず!
※ 弊社エンジニアは裁量労働制です。

記憶に残る楽しい懇親会にする

楽しいだけではなく、自分たちらしさ も出さなければいけません。
他の事業部と内容がカブってしまわないように注意が必要だったため、少し難航しました...
色々な案がでましたが、なかでもとびきりインパクトのあるものを選びました。

結論からいうと、会社内でお寿司を回しました。
自分たちでレーンを作りましたといえたら素敵ですが、出張回転寿司といったものがあるので、発注して当日設置してもらいました。

f:id:livesense-blog:20180615184724j:plain

今回利用したのは、サキガケサービスさんの「出張回転寿司(くるくる)」です。
https://www.sakigake-s.co.jp/sushi

実施時間は業務時間内の17:00〜19:00、場所はリブセンスのセミナールームで行いました。

結果

f:id:livesense-blog:20180615184833j:plain

70人弱のエンジニアが参加してくれました!!
回転寿司も好評だったようで、みなさん写真を撮ったりして楽しんでいたようです。
LTは、弊社の海外カンファレンス支援制度 を利用して Rails Conf 2018に参加した内山の体験談 や、今年度入社した新卒エンジニアからの熱い意気込みなど、様々なLTがありました。

ちなみに、 Engineer Drink Up 開催後に実施したアンケートの結果はこちらです。

f:id:livesense-blog:20180615184855p:plain f:id:livesense-blog:20180615184907p:plain f:id:livesense-blog:20180615184919p:plain

概ね、みなさんに楽しんでいただくことができました!!よかった!

懇親会を運営して得たもの

いままで話したことがなかった人と話す良いきっかけとなり、懇親会を開くことの大変さを知ることができました。
そして、この経験は業務にも活かしていくべきだなと感じました。

  • 問題点をみつけ
  • 改善策を練り
  • 準備を行い
  • 実行し
  • 振り返る

まさにPDCAですね。
参加メンバーが発言しやすい環境づくりを行い、準備し、実行する。
言葉にしてしまえばとても単純なことですが、その難しさと楽しさを再確認することができました!!

f:id:livesense-blog:20180619111155g:plain:w500

おまけ

出張回転寿司を頼む際の注意点

f:id:livesense-blog:20180619111219j:plain

1. 場所

回転寿司台を設置する関係、どうしても場所(テーブル 45cm × 180cmくらいのものを4~5台)と、職人さんの握り場所(1.8m四方位)が必要となります。
※さらにレーンなどを運んだ機材を置いておく場所も必要です。

2. 水場

調理器具などを洗う場所が必要になりますので、近くに水場があることも確認してください。

3. ネタ

各ネタの注文数には制限(最低参加人数の半分程度)があり、ネタの種類を多くし、それぞれの数を少なくする際は注意する必要があります。

DNS over HTTPSを使ってDNSレコードを外形監視

こんにちは、インフラグループの水野です。

みなさん、DNSのレコードの監視を行っていますか? DNSレコードの変更ミス等を検知することはもちろん、自分たちの運営しているサービスの名前解決がユーザ側でどのように見えているのかというのを確認することは大切です。

しかしながら、DNSレコードを外形監視してくれる監視ツールは数が少なく中々コレといったものがありません。 外部からの監視をしたいがためにパブリッククラウドに監視専用のインスタンスを建てるのももったいないです。

弊社ではメインの監視ツールとして Mackerel を利用していますが、MackerelにはURL外形監視はありますが、DNS外形監視はありません。 別途 pingdom のDNS外形監視を利用していましたが、pingdomではIPアドレスとのマッチしかできません。 IPアドレスもひとつしか登録できないため、ELBのようにIPアドレスが定期的に変わるCNAMEレコードなどを監視する際にはあまり相性がよくないという課題を抱えていました。

今回はDNS over HTTPSを使ってこの課題を解決した取り組みをご紹介したいと思います。

f:id:nashiox:20180518113217p:plain

DNS over HTTPS

DNS over HTTPS とは IETF1が標準化を進めているHTTPSを用いてDNSの通信を行う技術です。

従来のDNSの通信は主にUDPを用いて平文でやり取りされます。 この特徴はセキュリティ的にもプライバシー的にも問題視されており、その対策として誕生したのがDNS over HTTPSです。 既にGoogle Public DNSや先日話題となったCloudflareが提供を始めたパブリックDNSでもこの機能が提供されています。

従来のDNSのプロトコルで外形監視を行おうと思うと専用の機能が必要となりますが、HTTPのプロトコルを利用したURL外形監視であれば多くの監視ツールでサポートされています。 今回はこのDNS over HTTPSとMackerelのURL外形監視の機能を利用してDNSレコードの外形監視を実現します。

まずはDNS over HTTPSの動作を確認

今回はGoogle Public DNSCloudflareのパブリックDNS(1.1.1.1) 2つのDNS over HTTPSの機能を試してみたいと思います。 標準化が進んでるだけあってどちらもほとんど同じ使い勝手で使うことができます。

Google Public DNS

Google Public DNSのDNS over HTTPSではAPI版のURL(https://dns.google.com/resolve)、GUI版のURL(https://dns.google.com/query)が用意されています。 今回はAPI版を利用します。

サポートされているパラメータはいくつかありますが、name にFQDNを指定することでレコードを引くことができます。

$ curl -s 'https://dns.google.com/resolve?name=made.livesense.co.jp' | jq .
{
  "Status": 0,
  "TC": false,
  "RD": true,
  "RA": true,
  "AD": false,
  "CD": false,
  "Question": [
    {
      "name": "made.livesense.co.jp.",
      "type": 1
    }
  ],
  "Answer": [
    {
      "name": "made.livesense.co.jp.",
      "type": 5,
      "TTL": 195,
      "data": "hatenablog.com."
    },
    {
      "name": "hatenablog.com.",
      "type": 1,
      "TTL": 31,
      "data": "13.230.115.161"
    },
    {
      "name": "hatenablog.com.",
      "type": 1,
      "TTL": 31,
      "data": "13.115.18.61"
    }
  ]
}

上記のようにレコードを引くことができます。 Answer 部分が応答になっており、 type がレコードタイプ(1がAレコード、5がCNAMEレコード)、 data がレコードの値になります。

パラメータで type を指定すると指定タイプのレコードを引くこともできます。

$ curl -s 'https://dns.google.com/resolve?name=made.livesense.co.jp&type=CNAME' | jq .
{
  "Status": 0,
  "TC": false,
  "RD": true,
  "RA": true,
  "AD": false,
  "CD": false,
  "Question": [
    {
      "name": "made.livesense.co.jp.",
      "type": 5
    }
  ],
  "Answer": [
    {
      "name": "made.livesense.co.jp.",
      "type": 5,
      "TTL": 298,
      "data": "hatenablog.com."
    }
  ]
}

CloudflareのパブリックDNS(1.1.1.1)

CloudflareのパブリックDNSのDNS over HTTPS(https://cloudflare-dns.com/dns-query)ではDNS WireformatとJSONフォーマットがAPIで用意されています。 今回はJSONフォーマットを利用します。

パラメータはGoogle Public DNS同様、 nametype 、更にMIME Typeを指定する ct がサポートされています。

$ curl -s 'https://cloudflare-dns.com/dns-query?ct=application/dns-json&name=made.livesense.co.jp' | jq .
{
  "Status": 0,
  "TC": false,
  "RD": true,
  "RA": true,
  "AD": false,
  "CD": false,
  "Question": [
    {
      "name": "made.livesense.co.jp.",
      "type": 1
    }
  ],
  "Answer": [
    {
      "name": "made.livesense.co.jp.",
      "type": 5,
      "TTL": 300,
      "data": "hatenablog.com."
    },
    {
      "name": "hatenablog.com.",
      "type": 1,
      "TTL": 24,
      "data": "13.115.18.61"
    },
    {
      "name": "hatenablog.com.",
      "type": 1,
      "TTL": 24,
      "data": "13.230.115.161"
    }
  ]
}

出力はGoogle Public DNSとほとんど同じです。 標準化って素晴らしいですね。

レコードタイプの指定も同様にできます。

$ curl -s 'https://cloudflare-dns.com/dns-query?ct=application/dns-json&name=made.livesense.co.jp&type=CNAME' | jq .
{
  "Status": 0,
  "TC": false,
  "RD": true,
  "RA": true,
  "AD": false,
  "CD": false,
  "Question": [
    {
      "name": "made.livesense.co.jp.",
      "type": 5
    }
  ],
  "Answer": [
    {
      "name": "made.livesense.co.jp.",
      "type": 5,
      "TTL": 246,
      "data": "hatenablog.com."
    }
  ]
}

MackerelでDNS外形監視

ここまで来れば勘のいい人は大体お気づきだとは思いますが、MackerelのURL外形監視にDNS over HTTPSのURLを指定し、レスポンスボディのチェックでDNSレコードの外形監視をやってしまおうという魂胆です。

監視ルールを追加から外形監視を設定して新規監視ルールを作成します。 監視対象のURLに先ほど試した Google Public DNS または Cloudflare DNS のURLをパラメータを設定して入力します。

f:id:nashiox:20180517205103p:plain

レスポンスボディのチェックに監視したいレコードの内容を入れます。

f:id:nashiox:20180517205519p:plain

非常に簡単ですね。

後は実際に動作を確認するだけです。 レスポンスボディのチェックと実際に引ける内容が異なるときちんと通知されました。

f:id:nashiox:20180517211016p:plain

おわりに

DNS外形監視は今までこれというものが中々見つかりませんでしたが、今回のDNS over HTTPSを使った外形監視は結構使い勝手が良いんじゃないかと思っています。

DNS over HTTPSはまだドラフト段階ですが、2018年中には標準化を完了させる目標になっているそうです。 HTTPで利用できると言うのは他にも色々活用方法がありそうなので今後も色々試していきたいと思います。


  1. Internet Engineering Task Force (https://www.ietf.org/)

ビジョン合宿はやはり良かった

はじめまして。
昨年の11月にリブセンスにジョインして、今は転職会議のエンジニアをしたり、その他イロイロやっている しらかわ と申します。

先日 (といっても先月ですが) 、わたしの所属する組織では、One-DAYビジョン合宿というものが行われました。
そのときの様子と、なぜ合宿までしてビジョンを追求するのか。という話をしようと思います。

f:id:livesense-blog:20180427153342j:plain

なぜやるのか

この合宿を実施する上で、4つの理由がある。すべてはそこから始まりました。
開催にあたってのリーダーの言葉を借ります。

  1. 誰かがプロダクトを作るのではない。自分たちが作るんだ。
  2. ひとつ屋根の下、1日しゃべってお互いの理解を深めよう。
  3. 事業領域理解・自社理解を深めよう。
  4. 転職会議の進むべき方向性を決めるための素材を集めよう。

どんな準備が必要か

1. みんなが知っていることをそろえる

2時間くらい "合宿事前セミナー" というものを実施しました。
転職会議というプロダクトは人材業界と切り離して考えることはできません。
わたしたちが携わるプロダクトについて業界のプロに本格的な話をしてもらうことで、より理解や深まり、課題を掘り下げやすくなったと思います。

2. ひとりでじっくり考えてくる

シートを埋めました。宿題です。
項目はこんな感じでした。

  • なぜ存在するのか
  • ミッションはなにか
    • 誰に対して
    • どんな価値を
    • どのように提供するか
  • どうありたいか

この "どうありたいか" がビジョンになります。
これを、転職会議に訪れてくれるユーザと、転職会議に求人情報を載せてくれているクライアントに対して、それぞれ考えてみました。

3. 時間割をきめる

数名が "プレ合宿" と称して、合宿のリハーサルを行い、当日の時間割を考えました。
これがあったおかげで、当日の流れが大変スムーズになったと思います。

どんなことをしたのか

f:id:livesense-blog:20180427155029j:plain

阿佐ヶ谷の古民家!を丸一日借り切っての合宿となりました。
6〜7名くらいのグループを複数作り、お互いの宿題を見せ合いながら議論し、グループで一つの方向まで導きました。

f:id:livesense-blog:20180427153437j:plain

そして最後にグループ別に発表をして、1日を終えました。

もたらされたもの

まず、とにかく楽しい。楽しいというのはそれだけでも正義ですよね。
そして、普段多くを語らないようなメンバが本当は何を大切に思ってこのプロダクトに携わっているのか、お互いに気づくことができたと思います。自分では到底思いつかないようなアイデアもたくさん生まれ、何よりも視座が高まりました。

さらに、思いを持って仕事をしているモノ同士、大きな一体感を感じることができました。
これって会社の会議室ではない非日常な空間だからこそ、得られるものだったのではないでしょうか。

そして目的は達成されたでしょうか。

  1. 自分たちがプロダクトを作るんだ!という気持ちがより高まった!
  2. ひとつ屋根の下、1日話し合うことで、普段一緒に仕事をしていない仲間の考え方を知ることができた!
  3. セミナーを受けて、さらに自分で考える事で、そしてみんなでじっくり話し合うことで、事業領域理解・自社理解が深まった!
  4. 転職会議の進むべき方向性を決めるための素材がたくさん集まった!

なぜビジョンが大切か

ビジョンがあると、迷ったときの拠り所になるのではないでしょうか。
わたしたちは生まれも育ちも年齢も何もかも異なります。そして、迷ったり間違ったりする生き物です。
そんなバラバラでフワフワなわたしたちが一つのプロダクトを産み、育てていくのですから、やっぱりビジョンは大切なんだなぁ...と思います。

f:id:livesense-blog:20180427153229j:plain

またビジョン合宿やりたい!
ʕ•ᴥ•ʔ<やろうやろう!

付録

ビジョン合宿のあと、みんなと一緒にバスに乗って帰りました。
「バスっていいなあ。」と強く思ったので、社内でLTをしました。
こういう気持ちも、この合宿がもたらしたものの一つかもしれないです。

speakerdeck.com

リブセンスの海外カンファレンス渡航支援制度でRailsConf2018に参加しました

こんにちは。マッハバイトでエンジニア/マネージャーをしている内山です。

この度リブセンスでは「海外カンファレンス渡航支援制度」が始まりました。 当制度を利用して4/17(火)~4/19(木)にアメリカで行われたRailsConf2018に参加することができたので、それについて書きたいと思います。

海外カンファレンス渡航支援制度とは?

その名の通り、海外にて開催されるカンファレンスに、オーディエンスとして参加するにあたっての交通費や滞在費等を会社が支給してくれる制度です。
希望者は行きたい海外カンファレンスを宣言し、半年に1度、1名を対象に支援が行われます。 初回となる今回は僕のRailsConf行きを支援してもらうことになりました。

RailsConfとは?

これまたその名の通り、Ruby on Railsの国際カンファレンスで、年に1度開催されています。

railsconf.com

開催場所は毎年アメリカ国内を転々としているようで、去年はアリゾナ州フェニックスで、今年はペンシルベニア州ピッツバーグでの開催となりました。

来年はミネソタ州ミネアポリスで行われることが発表されています。

また、例年オープニングKeynoteをRails創始者であるDHH氏が務め、クロージングKeynoteをRubyとRailsのコアコミッターであるAaron Patterson氏が務めるというのが慣習のようです。

日本でもRubyの国際カンファレンスとしてRubyKaigiがありますが、Railsについてのセッションが行われることは稀です。
最近は日本でもRails Developers MeetupというRailsの知見が共有されるイベントが開催されていますが、やはりRailsコアコミッター自ら最新動向を話してくれる機会はなかなかないように思い、RailsConfに一度参加したいと思うようになりました。
(特にDHHはあんまり日本に来ないんですよね...)

ピッツバーグはどんな街?

アメリカ北東部に位置する人口30万人ほどの街です。 日本との時差は-13時間で、ニューヨークやワシントンD.C.と同じタイムゾーンに位置します。

南北を流れる2つの川にかかる橋や、川の合流地点を高台から眺められるインクライン(ケーブルカー)などで知られており、今回のRailsConfの各種デザインにもそれらがあしらわれていました。

f:id:livesense-blog:20180426020552j:plain
RailsConfのノベルティ

今回カンファレンスが行われたのは北側の川に面したDavid Lawrence Convention Centerです。 国際展示場や幕張メッセを小さくしたような施設と想像してもらえるといいのかもしれません。

ピッツバーグはアメリカでも「住みやすい街No.1」に選ばれたこともあるらしく、治安がとても良く、その点では会期中快適に過ごすことができました。 ただ一方で、関東暮らしが長い僕にとっては、なかなか厳しい4月の天候となりました。

f:id:livesense-blog:20180426014649j:plain
雪の降りしきるピッツバーグ

やはりそれは、世界中から集った多くのRubyistにとっても同じだったようで、オーガナイザーからの冒頭挨拶では「会場から上着が買える場所までの道順」をスライドに映し出して笑いを誘っていました。

セッションについて

RubyKaigiのセッションが「正直、難しくて理解できないとこもたくさんあったけど、なんか楽しかった!」となることが少なくない(個人的な感想です)一方で、どちらかと言えば、RailsConfのセッションはより多くの人が理解しやすいようになっているものが多かったように思います。

冒頭、オーガナイザーの「RailsConfに初めて来た人?」という問いに、自分を含む大半の人が手を上げていたので、それらの人への配慮もあるのかもしれません。
僕はリスニングスキルに長けているとは言い難いので、その点では、内容面が難しすぎないというのはありがたかったと思います。

f:id:livesense-blog:20180426035342j:plain
メインのホール

また、いわゆるTechTalkだけでなく、開発をめぐる"エモい"話などが多いのも特徴でしょうか。 TechTalkの傾向としては、テスト関連の話題、RailsアプリケーションにおけるJavaScript開発のTips、Kubernetesを始めとしたコンテナ技術の事例...などが目立ったように思います。

印象的だったセッションをいくつか取り上げます。
※これらのセッションの様子は一ヶ月以内にYoutubeで公開されるとのことです。興味を持たれた方は是非チェックしてみてください!

Turbo Boosting Real-world Applications - Akira Matsuda

  • 日本からもRubyとRailsのCommitterである松田さんが発表をされていました。
  • DBへのクエリ発行やPartialのレンダリングを、子スレッドを利用して行うことでRailsを高速化するというアプローチについて紹介されていました
  • スライド: Turbo Boosting Real-world Applications // Speaker Deck

Keynote: The Future of Rails 6: Scalable by Default - Eileen M. Uchitelle

  • GitHubのエンジニアであり、RailsコアチームでもあるEileenによる2日目のKeynoteです
  • Rails6で追加される並列テストや、複数DBのサポートについての話がありました
  • そのうえで「Scaling should make us happy」といった言葉とともに、スケーリングに応えるRailsであろうとする姿勢を力強く話されていました。
  • スライド: RailsConf 2018 | The Future of Rails 6: Scalable by Default // Speaker Deck

Inside Active Storage: a code review of Rails' new framework - Claudio Baccigalupo

  • Railsのissue対応を行っているClaudioからは、Rails5.2で追加されたActiveStorageについてのトークがありました。
  • ActiveStorageの使い方を踏まえた上でのコードの解説がとてもわかりやすく、勉強になりました
  • スライド: Active Storage // Speaker Deck

その他、ClaudioがRails公式サイトのブログにまとめ記事をあげています。併せてご確認ください!

weblog.rubyonrails.org

参加してみて

海外カンファレンス初参加となりましたが、慣れない英語を集中して聞き続けるというのはやはりドッと疲れるなぁ...というのが、恥ずかしながらも正直な感想です...。 事実、会期3日間のうち2日間は、カンファレンスが終わるとフラフラとホテルに直行し、夕食も取らずに寝てしまいました。

f:id:livesense-blog:20180426034703j:plain
元気があったカンファレンス前日に撮った夜景

最終日は、RailsConfに毎年来られている日本の方と夕食をご一緒する機会がありました。 全てのセッションを聞きつつもスピーカーとさほどコミュニケーションを取らず、夕飯以降の機会でも他の参加者らと交流を取っていない僕のことを、その方は冗談めかして「もったいない」と笑っていました。

確かに、Youtubeで全てのセッションが公開されることを考えれば、セッションにかじりついているだけでなく、その場での交流や情報交換までできてこそ、カンファレンスに参加した甲斐があったと言えるのかもしれません。 ...とは言っても、スピーカーの方らに拙い英語で話しかけることに気後れを感じてしてしまうのも事実です。 カンファレンスの準備として語学学習だけでなく、誰と話したいか、どんなことを話したいかといったことを予め考えておくのも重要だったのかもしれないなぁと今では思っています。

とは言え、もちろん現地でしか得られない経験もできました。 「How We Made Our App So Fast it Went Viral in Japan」というトークをしたdev.toのファウンダーの方に「I'm from Japan」と伝えて笑ってもらったり、自分がWebエンジニアを目指すにあたっての大きな拠り所となったRails Tutorialの作者に感謝を伝えたりすることもできました。 ランチタイムに他の参加者の方らと、日本とアメリカ各州の住宅費用やエンジニア年収について談笑したことも心に残っています。

本当はスポンサーによるエキシビジョンブースの様子なども書きたいのですが、長くなってきたのでこれくらいで...。

最後に

f:id:livesense-blog:20180426012356j:plain
帰りの空港にて

海外カンファレンスに参加すること自体も貴重な経験でしたが、今回「会社の金で行くぞ」という適度なプレッシャーが自分にとって英語学習のきっかけになったことも事実です。 日本にもRubyKaigiを始めとした国際カンファレンスがありますし、せっかくですから自分のペースでもう少し学習を続けたいと思っています。
来月は仙台でのRubyKaigiですね!楽しみです。

最後になりますが、リブセンスではエンジニアを募集中です!
海外カンファレンスに行ってみたいエンジニアの方からのご応募もお待ちしております!!

4Kモニターを仕事で使い始めたらやっぱり最高だった

こんにちは、マッハバイトエンジニアの黒川です。 今日は、最近会社で買ってもらって仕事で使っている4Kモニターが最高だという話をします。 エンジニアブログというよりは商品レポートなので、お気軽に読んでいただければ幸いです。

入社時点での設備

9月に入社した時点で私には、タッチバーつきスペックマシマシのMacBook Proが支給されました(デフォルトがそれなだけで、他のが良ければもちろん任意のマシンも申請可能でした)。 またモニターはオフィスにたくさん置いてあり、好きなだけ持っていって使って良いという状態でした。

しかしそこにはちょっとした問題点がありました。モニターのサイズが少し小さくて、解像度が低かったのです。 最強のMacBook Proがあるのに、USB-C変換アダプターをぶら下げてHDの解像度のモニターで仕事をするのは、せっかくマシンに投資してもらっているのにもったいないなと思っていました。

良いモニターがほしい!

もし良いモニターがあれば、最強のMacをさらに活かし良いものを作れるはずだということで、チームリーダーに相談してみました。するとリーダーがすぐに総務に相談してくれました。 その後はチーム内で他にも4Kモニターがほしい人がいないかアンケートを取ったうえで、無事購入してもらえました。

要望を言える空気、そして前向きに検討してもらえて叶える方向で動いてもらえる空気感の弊社は最高だなと思いました。 実際仕事場にモニターが来たらさらに最高でした。

どんな感じに最高なのよ

ここからは、仕事場に新しいMacBook Proと4Kモニターがあるとどう最高なのかを説明していきます。 ちなみに買ってもらったのはLGの27UD88-Wです。

まず何より、デカい

私は今までモニターを2枚並べて使っていましたが、2枚を横に並べると横幅が大きくなりすぎて、ひと目で全体を把握できませんでした。 またその関係上、よくマウスポインターがモニター上のどこにあるかわからなくなっていました。 これらの問題を、新しいモニターはそのデカさで補ってくれます。

f:id:blackawa:20171114171906j:plain

(左: 新しいモニター / 右: オフィスによく置いてあるモニター) 新しいモニターは、オフィスに置いてあるものに比べて一回りほど大きいです。 おかげで今は、1枚の大きなモニターに情報をまとめて表示できています。

文字が潰れない

今まで使っていたモニターはサイズが小さかったので、Mac側で文字サイズを小さくしてたくさんの情報を表示できるようにしていました。 しかしそうすると新たな別の問題が発生します。それは「文字が潰れる」ということです。 まずオフィスに置いてあるモニターを、手元のiPhone SEで写真に撮ってみました。

f:id:blackawa:20171114172100j:plain

画像も粗いし、「新妻」の「妻」の字は潰れてしまっています。 文字が潰れてしまう状態で大量の文字を読むと、だんだん目が疲れてきます。

次に、新しいモニターを見てみます。

f:id:blackawa:20171114172103j:plain

ひと目で分かるレベルで画像も文字もきれいに表示できています。 カメラ越しでもこの差!実際にはもっと見やすいです。 今もこの記事を新しいモニターで書いていますが、爽快な書き心地を体験できます。 いわんや、これがソースコードなら。

なめらかな角度調節・高さ調節

オフィスに置いてあるモニターの中には、高さの調節ができるものとできないものが混在しています。 高さが調節できないと目線が常に下になるので肩や首が疲れやすくなります。 また、姿勢も悪くなってしまいます。私は身長が190cm近くあるので、余計負担が大きかったです。 新しいモニターの要件にはもちろん高さ調節機能があります。

f:id:blackawa:20171114172445g:plain

もちろんモニターの角度も片手で滑らかに変えられます。

f:id:blackawa:20171114172448g:plain

これで、体格に合った高さと角度で業務に取り掛かることができます。

さらばケーブル・アダプター地獄

最後は少しTIPS感のある良さですが、これもこれでとても良いので紹介させてください。

Mac Book Pro 2016から、外部インターフェースがUSB Type-C限定になりました。 今まで通りのHDMIやUSBケーブル、Thunderboltケーブルを使うためには、専用のアダプターが必要でした。 このアダプターだけで1万円近くかかるという、便利になったのかなっていないのかよくわからない状態でした。

しかし、新しいモニターはUSB-Cがいかに優れモノかを見せてくれます。

f:id:blackawa:20171114172609j:plain

なんとモニターとMacをUSB-Cケーブルで接続するだけで、 - 画面表示できる - 充電できる - ディプレイのUSBポートに挿したキーボードを使える

のです。 下の写真のように、モニターにUSBケーブルを接続するとあたかもMacに挿しているのと同じように使えます。

f:id:blackawa:20171114172714j:plain

これで、離席する時にはMacに挿してある1本のケーブルを抜けば良いだけです。 席に戻ってきたら再び挿せばすぐに画面が表示されて充電が始まり、外付けキーボードのHHKBで作業ができます。 おかげでテーブルのまわりのケーブルがこんなにシンプルになりました。

f:id:blackawa:20171114172755j:plain

これで離席があってもストレスなく作業を再開できそうです。

まとめ

ここまで、4Kモニターとそれを買ってくれる弊社最高という話をしてきました。 ぜひ皆様のチームでも良いマシンと良い機材を導入してみてください。 全力で集中して長い時間使うオフィスの機材が良くなるのは最高の体験です。

CircleCI 2.0でbundle updateを定期実行してみた話

こんにちは、IESHILでエンジニアをしている須貝です。
今回は先月ローンチしたIESHIL CONNECT(イエシルコネクト)の運用で、CircleCI 2.0を使ってbundle updateを自動で実行するようにした話をします。CircleCI 1.0ではなく2.0というのがちょっとしたポイントです。

ところで、みなさんCircleCI 2.0を使っていますか? 2.0では純粋なDockerベースになっていてローカルでも実行可能、より柔軟に設定を記述できる、とにかく速いなど1.0と比較すると大幅に進化しています。どんどん使っていきましょう。

やろうとした背景

そもそも何でこれをやろうとしたの?という話なんですが、 IESHIL CONNECTはIESHILとは別に新規開発したRailsアプリです。せっかくの新規開発ですから、IESHIL本体の開発では手を回せていないことをやろう、というのが個人的にやりたいことでした。たとえばLint(rubocop, slim-lintなど)をCIで実行するなどです。

そのひとつが「bundle updateを定期的に実行する」ことでした。
依存しているライブラリの更新はこまめに実行したいところですが、こうした作業はどうしても忘れがち、後回しになりがちだと思います。 しかし、後でまとめてアップデートしようとすると、動作確認などのコストが非常に大きくなり負担となってしまいます。
ですので、リリースしたての今のうちにこの作業を自動化しよう、というのが今回の背景になります。

実現したいこと

やりたいことのおおまかな流れは下の図のとおりです。

f:id:ssugai:20171025164025p:plain

今回の場合、4, 5の部分はすでに設定済みなので、図の背景が緑の部分を作っていきます。

手順

ここからは手順とポイントを簡単に解説していきたいと思います。

1. Circle CIを起動する

Circle CI 1.0の場合はCircle CIの公式ドキュメントにあるように、Parameterized Build APIを利用して、Web API経由で任意の環境変数がセットされている場合に通常のCI以外の処理を走らせる、という方法で実現することができます。
以下、1.0の場合の例(公式ドキュメントより引用)です。

test:
  post:
    - >
      if [ -n "${RUN_NIGHTLY_BUILD}" ]; then
        ./bin/run-functional-tests.sh ${FUNCTIONAL_TEST_TARGET};
      fi

ややトリッキーですね。

一方、2.0の場合はもっとシンプルです。Parameterized Builds APIを利用するのは同じですが、設定ファイルに通常のCIとは別の任意のjobを定義しておいて、そのjob名をCIRCLE_JOBというパラメータにセットしてAPIを呼び出すだけで簡単に実現できます。
以下、2.0の設定ファイル例です。

# .circleci/config.yml
version: 2
jobs:
  build: # デフォルトで実行されるjob
  ...
  hello: # 任意のjob
    docker:
      - image: circleci/ruby:2.4.2
    steps:
      - run:
          name: Hello World
          command: |
            echo 'Hello, World'

上記のような設定を.circleci/config.ymlに記述しておくと、下記のようにAPIをコールすることでCircle CI上で任意のjobを実行できるようになります。

curl \
  -X POST \
  --header "Content-Type: application/json" \
  --data '{ "build_parameters": { "CIRCLE_JOB": "hello" } }' \
  https://circleci.com/api/v1.1/project/github/:username/:project/tree/master?circle-token=:token

これをcron的なもので定期実行するわけですが、IESHIL CONNECTはHerokuを使っているのでHeroku Schedulerを使ってAPIを呼び出しています。

なお、Circle CIのAPIを利用するにはトークンが必要なので、プロジェクトのSettingsからAPI Permissionsに遷移してCreate Tokenからトークンを発行しておく必要があります。

2. Circle CI上でbundle updateを実行する

次にCircle CI上でbundle updateを実行できるようにしていきます。

# .circleci/config.yml
  bundle_update: # bundle update用のjob
    docker:
      - image: circleci/ruby:2.4.2
    ... # 中略
    steps:
      - checkout
      ... # 中略
      - run:
          name: Run bundle update
          command: |
            if [ "${CIRCLE_BRANCH}" = "master" ]; then
              bundle update
              ... # 中略
            fi

念のためmasterブランチかどうかを確認しています。

3-1. Gemfile.lockに変更があればGitHubにpushする

続いてbundle updateした結果、Gemfile.lockに変更があればGitHubにpushします。
GitHubとCircle CIを連携済みであれば簡単にpushできるのでは?と思うところですが、ここは少し設定が必要です。 なぜなら、GitHubに登録されているCircle CIのdeploy keyがread権限のみだとCircle CIからpushできないからです。
というわけでwrite権限のあるdeploy keyを新たに追加しましょう。GitHubで対象プロジェクトの SettingsからDeploy keysを選択し、Add deploy keyボタンでdeploy keyを新たに追加します。

f:id:ssugai:20171025185023p:plain

その際に、Allow write accessにチェックを入れるのを忘れずに。
deploy keyを追加したら、公式ドキュメントを参考にconfig.ymlにwrite権限のあるdeploy keyを設定します。

# .circleci/config.yml
    steps:
      - checkout
      - add-ssh-keys:
          fingerprints:
            - "xx:xx:xx:xx:xx:xx:xx:xx"
      ...

ここで注意したいのが、- add-ssh-keys:の次行のfingerprints:のインデントです。

# NG
- add-ssh-keys:
  fingerprints:
    - "xx:xx:xx:xx:xx:xx:xx:xx"

# これだと評価した結果が下記のようになってしまう。
# => [{"add-ssh-keys"=>nil, "fingerprints"=>["xx:xx:xx:xx:xx:xx:xx:xx"]}]

# OK
- add-ssh-keys:
    fingerprints:
      - "xx:xx:xx:xx:xx:xx:xx:xx"

# => [{"add-ssh-keys"=>{"fingerprints"=>["xx:xx:xx:xx:xx:xx:xx:xx"]}}]

というわけでfingerprints:- add-ssh-keys:先頭の-から半角スペース4つ下げる必要があります。 私はややハマりました。

3-2. pushが成功したらPull Requestを作成する

最後にGitHubにプルリクエストを作ります。いろいろなやり方があると思いますが、今回はGitHubのWebAPIを利用することにしました。

curl \
  --header "Accept: application/vnd.github.v3+json" \
  --data "{\"title\": \"${BRANCH}\", \"head\": \"${CIRCLE_PROJECT_USERNAME}:${BRANCH}\", \"base\":\"${CIRCLE_BRANCH}\" }" \
  https://api.github.com/repos/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/pulls?access_token=${GITHUB_ACCESS_TOKEN}

なお、GitHubのAPIアクセストークンが必要なので取得しておく必要があります。
トークンはCircleCIの設定画面で環境変数として設定しておくと良いでしょう。私はGITHUB_ACCESS_TOKENという名前で登録しました。

最終的にできあがったconfig.yml(一部抜粋)は以下になります。

version: 2
jobs:
  build:
  ... # 中略
  bundle_update:
    docker:
      - image: circleci/ruby:2.4.2
        environment:
          TZ: "/usr/share/zoneinfo/Asia/Tokyo"
        environment:
          - RAILS_ENV=development
          - RACK_ENV=development
    working_directory: ~/ieshil-connect-dev
    steps:
      - checkout
      - add-ssh-keys:
          fingerprints:
            - "xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx"
      - run:
          name: Run bundle update
          command: |
            if [ "${CIRCLE_BRANCH}" = "master" ]; then
              bundle update
              if [ -n "`git status -sb | grep Gemfile.lock`" ]; then
                BRANCH=bundle-update-`date -u "+%Y%m%d"`
                git config --global user.email ${BOT_EMAIL}
                git config --global user.name ${BOT_NAME}
                git checkout -b ${BRANCH}
                git add Gemfile.lock
                git commit -m "Bundle update `date -u '+%Y-%m-%d'`"
                if git push ${CIRCLE_REPOSITORY_URL} ${BRANCH}
                then
                  curl \
                    --header "Accept: application/vnd.github.v3+json" \
                    --data "{\"title\": \"${BRANCH}\", \"head\": \"${CIRCLE_PROJECT_USERNAME}:${BRANCH}\", \"base\":\"${CIRCLE_BRANCH}\" }" \
                    https://api.github.com/repos/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/pulls?access_token=${GITHUB_ACCESS_TOKEN}
                fi
              fi
            fi

Circle CI側が用意している機能を利用すればもっとスッキリと書けそうな感じもするので、改善の余地がありそうです。

実際にやってみた感想

月並みですが、「やっぱり自動化しておくと楽だなあ」という一言に尽きます。
現在は日次でbundle updateの実行をしていて、一度に更新されるgemの数も少なくそこまで負担は感じていません。

もちろん、ライブラリのアップデートをしたことが原因で不具合が発生するリスクもあります。そうしたリスクを軽減するためにもまず「テストを書く」ことが大切なのかなと思いました。今回のような仕組みを導入できたのも、高いテストカバレッジを保てていることが前提にあります。きちんとテストを書いている開発陣に感謝。

改めて今回やってみたことを書き起こして見るとそこそこ手間がかかるなあという印象もありますが、一回作ってしまったら後は非常に楽なのでぜひ試してみてください!

入社後、いきなりのサイトリニューアル

はじめに

みなさん、こんにちは。 アルバイト事業部で「マッハバイト」のフロントエンドエンジニアをやっています、山田と申します。 私は7月の頭に入社したばかりなのですが、入社後最初のミッションがサイトリニューアルでした。 今回はその話に触れていきたいと思います。

サイトリニューアルで行ったこと

リニューアルと言っても、フルスクラッチでプロダクトコードを全て書き直すわけではありません。 アーキテクチャの見直しなどは別チームが並行で進めており、僕らの行うことは画面のデザイン変更が主です。

その対応を、9/28のリリースに向けて進めていかなければいけませんでした。

その工程は困りごとの連続

作業を始めたはいいものの、その工程は困りごとの連続でした。

  • CSSの修正が想像よりもやりづらい。
  • 修正が必要な画面がどれくらいあるの把握出来ていない。
  • プロダクトコードがPHP(Symfony)とRuby(Ruby on Rails)に分離していて、戸惑う。
  • プロダクトが複雑で、一機能の仕様把握だけでもかなりエネルギーを使う。

一つずつ触れていこうと思います。

CSSの修正が想像よりもやりづらい

デザイン変更を始めて最初にぶつかった問題がこれでした。

マッハバイトはPCとSP(モバイル)でCSSが分離しています。 PCとSPのそれぞれで、CSSの設計思想が違っていたことが初期の参入コストを高めていました。

  • PC : FLOCSSベースの設計
  • SP : オリジナル設計

といった具合です。

これだけ見るとPCの方が修正しやすく思えるかもしれませんが、そうでもなかったりします。 マッハバイト(当時はリニューアル前のジョブセンスでしたが)はSPの方がユーザーが多く、 CVR向上のためのABテストが繰り返し行われてきました。そのため、設計自体は今風なPC側よりも こまめな整理がされてきたSP側の方が直しやすい場面が度々ありました。

それを踏まえつつ、以下のような方針で地道に修正を重ねました。

  • 不要物の削除
    • 使われなくなったページ、CSSがそのままになっているので消す。
  • 命名規則の統一
    • 今はハイフン区切りで運用しているが、数年前に作った古いページはキャメルケースになっている。
    • CSS用のクラス名が、JavaScriptのイベントトリガーで使われている箇所があるので分ける。
  • デバイス間の設計思想の統一
    • SPの思想を、PCに徐々に寄せていく。
  • 後回しにして放置してしまう展開を避けるため、「後で直す」をなるべくやらない。
    • 影響範囲の広い箇所も直すメリットが大きそうなら、恐れずに直す。リニューアル後になると、直しずらくなってしまう。

ありがちな話ではありますが、方針と対応を列挙してみました。 上記以外にも細かい課題はまだ残っているのですが、日々の小さな積み重ねの中で少しずつでも解決していけるように取り組みを進めています。

修正が必要な画面がどれくらいか把握出来ていない

次にぶつかった問題がこれでした。

入社して間もなかった人間が、プロダクトの機能を全て把握しているわけもなく、 画面数がどれくらいか把握しているわけでもない。 どの程度のペースで作業を進めていけばリリースに間に合うのか分からず、頭を抱えました。

しかし、この問題はすぐに解決しました。 僕の入社前に対応が必要な画面の洗い出しは既にGoogleスプレッドシートに纏まっており、 それらを片っ端からやっていけばOKという訳です。

最終的に、画面名を書いたポストイットをホワイトボードに全部張り出し、 修正が済んだらポストイットを剥がすという運用にしました。 (進捗の確認は毎日行っている夕会で各自報告し合う、というルールになっています) こうしておくことで、体の向きを少し変えるだけで残作業が一目で確認出来るようになりました。

「状況はスプレッドシートで確認出来ます」と言っても、案外見てもらえなかったりもします。 場合によっては、こうしたアナログなやり方の方が上手く機能することもあるので、今後も柔軟に考えていきたいです。

プロダクトコードがPHP(Symfony)とRuby(Ruby on Rails)に分離していて、戸惑う

マッハバイトのプロダクトコードはSymfonyとRailsが混在しています。

ジョブセンス時代は元々PHPで開発されており、それらのコードを順次Rubyに置き換えているため、 現在はそれぞれが混在している状況になっているという訳です。

「この画面のViewはPHPだけど、こっちの画面はRailsにあるSlimを触らないといけない・・」

こうした場面が度々あり、参加初期は混乱の連続でした。

PHPは経験があったので、手探りでSymfony実装に潜っていくことが出来たのですが、 Railsは数年前に少し触ったきりだったので、全く実装を追えませんでした。 そこに危機感を感じた僕は、プライベートでやっていた他言語の勉強を一旦全て中断。 PHPとRubyの学習に充てることにしました。

その甲斐もあってか、今はSlimの記法にも慣れ、 RailsのControllerの処理を追うこともなんとか出来るようになってきている実感があります。

これからもPHPやRubyに対する理解を深め、 プロダクトの改善に貢献できるように心がけようと考えています。

プロダクトが複雑で、一機能の仕様把握だけでもかなりエネルギーを使う。

長年続いている事業ならよくある話なのかもしれませんが、 以前はWeb制作の会社で働いていた僕にとっては結構な衝撃でした。

「求人を探し、バイトを見つける」

ユーザがサービス内で行う行動を言葉にするとシンプルに思えるのですが、 それを取り巻く様々な機能や仕様が存在しており、それらは長年の運用によって非常に複雑なものになっています。

サイトリニューアルを行う中で様々な画面を見て、そこに存在している事を知りました。 フロントエンド領域が僕の主戦場ではありますが、事業内で関われる領域を広げるためにも ビジネスロジックに対する深い理解は欠かせないと思うようになりました。

まとめ

3ヶ月弱の期間でサイトリニューアルをやると聞いた時は少し不安がありましたが、 周りの方々の助けを大いにアテにし、なんとか完遂することが出来ました。

今になって思えば、新参者が全画面を一通り触れたのは今後のサービス改善を進める上で 非常に有り難い機会だったとも感じています。

今後はリニューアルのタイミングで手が回らなかったCSS周りの設計整理や、TypeScriptの導入等に挑戦していく予定です。