人間とウェブの未来

「ウェブの歴史は人類の歴史の繰り返し」という観点から色々勉強しています。

ngx_mruby v2のHTTPクライアントをv1よりも最大90倍高速にした

写真のような感じでRubyKaigi2018で登壇し、RubyKaigiを経て、ようやくngx_mrubyのv2をリリースしました。基本的にv1と互換性がありますので、今後はv2を開発していくことになります。

github.com

ngx_mruby v2の目玉機能としては、Rubyスクリプトからノンブロッキングのsleepとhttp[s]クライアントを使えるようになったことです。実装的には、nginxのsub requestという機能をうまく使って、ノンブロッキングのhttp[s]クライアントを汎用的なsub_requestメソッドとして実現しています。

では、本エントリではそのノンブロッキングhttpクライアントがどの程度高速処理可能になったかを実験してみましょう。また最後には、RubyKaigi2018の感想も述べます。

  • 実験
    • proxyサーバのblockingとnon-blockingのhttpクライアントの設定
    • apiサーバの設定
  • 実験結果
    • レスポンスタイムを変化させたベンチマーク
    • 同時接続数を変化させたベンチマーク
  • まとめとRubyKaigi2018の感想
続きを読む

第二回 #wsa研 でHTTPリクエスト単位でコンテナを再配置する仮想化基盤の高速なスケジューリング手法について発表しました

第二回Web System Architecture研究会で、タイトルの内容について発表してきましたので、そのスライドと予稿を以下に公開します。

speakerdeck.com

英文タイトルは以下の通り。

Fast Scheduler for a Cloud Platform to Relocate Containers at Each HTTP Request

クラウドサービスの普及に伴い,個人のWebサイトでもクラウドサービスに類する機能を利用して,突発的なアクセス集中に耐性があり,かつ,利用したリソース使用量に応じて課金するサービスの提供が求められている. 我々はその要求に応じるために,Webサイトをコンテナ上に構築し,コンテナの起動や停止,複製やリソース割り当てといった状態の変更を素早く実行できるコンテナ管理アーキテクチャFastContainerを提案した. 一方で,単一のコンテナが特定のサーバに収容されている状態で,サーバが過負荷に陥ったり停止したりするような状況においては,障害時にコンテナの収容サーバ情報の変更を手動で構成管理データベースに反映させる必要があった. 本研究では,HTTPリクエスト処理時において,収容サーバ,および,その経路までの状態に応じて,自動的にコンテナを収容するサーバを決定し,サービスを継続させる,HTTPリクエスト単位でのコンテナスケジューリング手法を提案する. 提案手法では,FastContainerの状態変化の高速性に基づいて,コンテナが頻繁に収容サーバを変更されてもサービスに影響がないことを利用する. それによって,プロキシサーバから収容サーバに1個のICMPパケットで応答速度を計測し,少ないパケット数と応答速度に基づいた短いタイムアウトで収容サーバの反応時間を計測できる. そのことで,単一のコンテナであっても,HTTPリクエスト単位でのコンテナスケジューリングを実現し,可用性を担保する.

  • 1. はじめに
  • 2. Webサービス基盤の負荷分散と可用性
    • Webホスティングサービス
    • クラウドサービス
    • FastContainerアーキテクチャ
  • 3. 提案手法
  • 4. 実験
    • 予備実験
      • ICMPタイムアウトに関する予備実験
      • Apacheコンテナの起動時間に関する予備実験
    • 再配置時のレスポンスタイムの本実験
  • 5. まとめ
    • 接続待ちソケット生成前のプロセスイメージを利用したWebサーバの汎用的な起動時間短縮手法
    • 参考文献
続きを読む

OSレイヤでWebサーバが起動時に実行するシステムコールを監視し起動完了直前のプロセスをイメージ化する

今回は、Webサーバの実装に依存することなく、OSレイヤでWebサーバソフトウェアが起動時に実行するであろうシステムコールを監視して、そのタイミングでプロセスをイメージ化する方法(PoC)について紹介します。

続きを読む

もうできないと思えた時こそ大きな差をつけるチャンス

ある日、今年は研究開発活動を国際化していくぞ、と意気込んで出した国際会議のreject通知が届いた。そして、その内容も4人の査読者からフルボッコであり、特に英語がなっていないということをかなり強い言葉で指摘されていた。そんな通知をもらった僕は、かつてないほどの悔しさと後悔を感じたのであった。過去に何度か国際会議通していたこともあり、これぐらいでいいだろうとタカをくくって舐めていた、手を抜いていた面もあったからだ。

その1週間後の4/10に、国際会議のワークショップ締め切りがあり、指摘を直してそれに出してみてはどうかとreject通知に書かれていたのだが、その4/10は自分の別の論文1本と共著の2本の合計3本の論文締め切りと同じ日であり、これは流石に無理だと諦めたのであった。きつい。

精神的にも落ち込んでいたし、今年は国際化やっていくぞ!と思っていた矢先の出来事で、なかなか立ち直れなかった。残る3本の論文執筆は達成しなければならないという思いも強かった。でも、改めて自分を見つめ直した時、ただそれだけの気持ちではなかったのだ。

「また英語で出してフルボッコにされるのは嫌だ」「そうならないように納得のいく修正をするのは難しいだろう」「間に合うかもしれないけどもうなんか出したくないな…」「また落ちたら恥ずかしい…」「出せないということにしたい…」「逃げたい」そんなシンプルな感情に溢れかえっていた。

そんなとき、ふと博士課程時代の先生の言葉を思い出しつつ、自分が本当に得意としていることはなんであったのかを考えていた。

「ここまでせっかく書いたのだから直せるだけ直してとりあえず出してみましょう」

「そのちょっとした努力をこの状況だからこそやってみるのですよ」

「普通の人はここで諦めるでしょう。だからこそ我々はここでやってみないと」

「それがいずれ大きな差となる」

「もうできないと思えた時こそ大きな差をつけるチャンス」

「その時にやったことは全てがもれなく成長となる」

それぞれの言葉は細かいところでは違っているとはいえ、そのような内容の言葉を沢山やりとりしていたことが思い出された。

僕自身、社内の立場や外から見られる立ち位置も少しずつ上がってきていて、いつのまにかその立場が大きな鎧となり、身動きが取れず、がむしゃらに動くことを諦めはじめていた。でも、自分が多くの技術を学び、ただひたすら前を見て研究していたあの頃はそんな気持ちではなかった。少しでもチャンスがあれば手を伸ばし、指が引っかかることを信じて、とにかく掴む努力を誰よりも、特に普通なら諦めかける状況であればあるほど、手を伸ばし続けていたはずだった。何度でも失敗したっていい。その時の全力を尽くすだけだ。僕のような別段頭が良いわけではない人間が一歩先へ進むにはそれしかなかったはずだ。そんなことを思い出しはじめた。

そして、僕は4/10に国際会議の論文をできる限り修正し提出した。同時に、ギリギリまで共著論文を2本レビューし、自分の論文も含めて合計4本の新しい論文も提出できた。ちゃんと提出できたのだ。なんてことはない、ほんの少しやろうとするだけ、重い鎧を脱ぐだけで、できないと思えてもやってみると案外できるものだ。もうできないと思えた時にこそ、自分を矮小化することなく、ほんの少しだけ勇気を出して、格好をつけるのをやめて、踏ん張ってみる。すると、もう一歩だけ進むことができるのだ。その一歩の積み重ねが大きな力となっていく。

僕が唯一人と差をつけられることはこれだったはずだ。今日はもう眠い。でもそこでもう少しだけ踏ん張ってこのエントリを書く。本質的にはそれと変わらない。たったそれだけのことをを再び忘れないように、ここに行動し、記しておく。

プログラミングにおける不安と学びのプロセス

僕の場合、実現したいことをコードで書けない時には、ひたすら似たコードを読んで理解して写して…を繰り返す。そのうちに手元に大量の自分のサンプルが溜まっていく。その繰り返しがパターンの細分化を促し、書けるコードの幅を広げていく。書けるコードを気持ちよく書き続けてるだけでは新しいコードは書けないからだ....と、向き合えるようになるには時間がかかった。

書き慣れたコードの延長で書いていると、自分でコードを書けている実感があって、リファレンスなど何も見ずに自分の力でプログラミングできている感があるのだが、ある時これはただ「慣れ」の感覚を高めているように思えた。素早く書けること自体は、それはそれで一種のスキルで素晴らしいのだけど、実現したいことをコードで書けるようになる、という観点で振り返ったときに、どうしても成長を感じなかったのだ。それ以来、まずいと思い、実現したいことを思い描き、それを実現するために自分が書けないコードを探しては読み、写しては学ぶようにした。しかしそこには常に不安がつきまとう。

書けないコードを読んで真似をするという行為を繰り返している状態は、自分でコードを書けている実感がとても弱くなる。だからこそ、その漠然とした不安を払拭するためにそのプロセスを続けるのだけど、ある時振り返ると、出来ないことをできるようになっていた、という結果とその成長を実感できる。とはいえ不安はまだまだあるし、満たされることもないので、継続的に取り組み続ける。実はこれは満足感と払拭されない不安がうまく両立されている状態なのだ。

自信や実感の無さにいかに向き合ってそれをエネルギーに変えるか、その際に周りとの相対比較による無駄な雑念をどれだけ取り除けるか、というのはとても大事で、そのような状態でプログラミングに向き合えたら、自分のために、実現したいことのためにただ書けないコードを書けるようにと学び続けられる。遅くたって構わない。ただひたすらに継続してやっていくだけだ。

業務でもプログラミングでもそうだけど、専門性という意味合いのない、ある特定の狭い領域にのめり込むと割と簡単に全能感を得られてしまう。その全能感は気持ちよくて癖になってなかなかやめられないのだけど、その全能感故にその狭い領域や今出来ることから抜けられない。いかに簡単にその全能感を捨てられるかがポイントに思う。

周りよりも速く全能感を得られたのなら、次は自分のできないことに取り組みながら、俺が俺がとやってきたことを適切に周りに頼り任せていく。そうすると、自分ができないことができるようになる間に、周りのできることが自分も少しずつできなくなっていくし、それどころか、忘れてすらいく。でも実は、そのように生じる役割分担とその連鎖は、実現したいことの限界を突破していくという意味では、集合知として専門性を高める作業にほかならないのだ。

このテーマで何が言いたかったというと、そうやってコードを読んで理解して真似してる時はコードを書けてない実感が強く不安だから、それを避けて出来る方や慣れる方を優先しがちだけど、実はその不安は正しい学びのプロセスであって成長の角度が比較的大きくなるので、その不安と向き合ってしまうと良いと思うのであった。

そしてこれは、プログラミングに限らずあらゆることに適用できそうな学びのプロセスであるかもな、とも思う。

GMOペパボ株式会社のチーフエンジニアに就任いたしました

2018年3月18日付でペパボのチーフエンジニアに就任しました。

ペパボのエンジニア職位制度におけるNo.1エンジニアとして、引き続きテクノロジーによってペパボのプロダクトを成長させていきます。

私はペパボ研究所の主席研究員でもありますので、基本的には研究開発を通じて事業を差別化する技術を作り上げ、研究開発によって産学に影響を与えながらプロダクトを作り上げていくことになります。

インターネット技術の変化というものは、これまでの常識を簡単に塗り替えていきます。その為、エンジニアの道を選んだ我々は、常にその変化を追い続け、学び続けなくてはなりません。ペパボのエンジニア組織は、mizzyさんをはじめ、あんちぽさんや柴田さんを中心に、多くの方々のご尽力により、インターネット技術の変化・高度化に強い、小回りのきく組織として成長してきました。それに伴い、組織の規模が拡大しようとも、効率的にプロダクトをより強くしていけるような基盤の整備もなされました。

では次に何が必要か。それは、このインターネット技術の変化について行くことはもとより、私自ら、ひいては、ペパボ自ら、そのインターネット技術の変化そのものをおこしていける存在になることです。そして、その技術によって、プロダクトの価値を最大化し、これまでにないような価値あるペパボのプロダクトを生み出していくことです。

私のチーフエンジニア就任の使命は、インターネット技術にペパボ自ら変化をおこして業界を巻き込むこと、その技術によって世にない価値あるプロダクトをペパボから生み出していくことだと思っています。そして、その活動そのものが実はとてもおもしろいことだということを、まわりのエンジニアに伝えながら、組織として共に、自発的に、成長していける基盤を作ることです。

これらの使命を果たすこと、そして、学ぶこと自体が実はとてもおもしろいことなのだということを伝えられるように、日々精進して参りますので、今後ともmatsumotoryをどうぞよろしくお願いいたします。

HTTPリクエスト単位でmrubyのバイトコードをProcとFiberで包みなおして実行した場合の性能とv2について

ngx_mrubyのv2の4月リリースに向けて、HTTPリクエスト単位で実行されるRubyのコードを、FiberとProcで包んだオブジェクト経由で実行する実行方式に実装しなおしています。これまでのngx_mrubyのv1系は、Rubyのコードをnginx起動時にstruct RPocにコンパイルしておき、リクエスト毎にそのバイトコードを実行していました。

一方v2では、nginx起動時にコンパイルされたstruct RProcを、HTTPリクエスト時にprocオブジェクトに変換した上で、そのprocオブジェクトをcallする処理をfiberで包み、そのfiberオブジェクトをresumeする処理をさらにprocで包んで、procをcallで実行するようにしました。それをC側とRubyのコードを行き来しながらうまいことnginxとmruby間のイベントループの上に乗るようにします。今のところはCとRubyの世界のコンテキストを現状のmrubyでうまく行き来するために、こういった複雑な方式にしています。その理由については一旦省略します。

github.com

続きを読む