読者です 読者をやめる 読者になる 読者になる

望月いちろうのREADME.md

書き溜めておいた技術記事や旅行記のバックアップです。

Node.js入門 - その実績と事例紹介

Node.jsはGoogleが開発した高速なJavaScriptのC++実装のエンジンのV8を利用して、サーバーサイドでJavaScriptを利用できるようにしたものです。もともとJavaScriptはNetScapeによって開発されたブラウザで動的サイトを構築するために開発されたプログラミング言語でも非常に簡易的なものでした。しかし現在ではES6、ES7が発表され、一部で関数型言語の特徴を取り入れるなど、洗練されたモダンな言語へと生まれ変わりつつあります。

まずその特徴を解説しましょう。

ノンブロッキングI/Oを活用し、低スペックのサーバーでもハイパフォーマンスが期待できる。

ネットワークの分野で「C10K問題」という有名なキーワードがあります

それはインターネットが世の中に普及するにつれ、ウェブサーバーへのアクセスが増加して大量のトラフィックを裁かなければいけないことです。

「C10K」とはクライアントが同時に10000台も同時にアクセスした場合に生じる問題です。従来のシングルスレッド型のパラダイムではたとえハードウェアの性能が十分だったとしても、I/O処理の待ち時間によって、サーバーがリスポンスをほとんど返せなくなってしまう問題です。

Node.jsはノンブロッキングI/Oという仕組みでこれを解決しました。イベントループ上で多くのアクセスを同時並行的に裁くことで、シングルスレッド上で、比較的低い性能のマシンでも十分なパフォーマンスを得ることができるのです。

学習コストが低く、開発が用意

Node.jsは基本的にはブラウザで使用するJavaScriptと同じ作法で書くことができます。従来のWeb開発ではフロントエンドとサーバーサイドの開発で別の言語を使用していました。フロントエンドではJavaScript、サーバーサイドではApache+PHPと複数の言語とモジュールを活用する必要がありました。Node.jsはこれを一貫してJavaScriptで記述することが可能です。

加えてNode.jsではnpmと呼ばれるパッケージ管理ツールがあります。このnpmには毎日約400もの新しいライブラリが追加されています。これによって大半の機能は自分自身で実装することなく、気軽に追加することができるのです。

よくある誤解

Node.jsはおもちゃのようなもの、大規模なサービスには使えないし、信頼性もない

このような誤解に基づく偏見はしばしばNode.jsに向けられます。しかし、事実としてNode.jsは多くのテック企業によって使用され、その性能を評価されています。以下は国内外でNode.jsを使用する企業の一覧です。

国内

  • サイバーエージェント
  • Tokyo Otaku Mode

海外

  • PayPal
  • Uber

特に信頼性を求められる決済サービスを展開しているPayPalにNode.jsが使用されていることに驚かれたかもしれません。以下はPayPalのブログ記事からの引用です。

現記事は2013年11月22日に書かれたものです。

PayPalはなぜNode.jsを採用したのか?

PayPalのアプリケーションプラットフォームがNode.jsに移行されたことについていろいろ議論があるようだ。 そして、"私のUIを自由にする"の一部に続いて、僕たちのWEBアプリがJavaからJavaScriptとNode.jsに移行していることについて言及できて幸いだよ。

歴史的に見れば、僕らエンジニアはブラウザ(HTML,CSS,JavaScript)を担当する方と、アプリケーション(Java)を使う方、それぞれが別々に仕事をしてきた。HTMLを担当しているエンジニアがJavaエンジニアにページAからページBにリンクをするように依頼する手間を想像してほしい。これがいままで僕たちが悩まされてきた問題だったんだ。これはフルスタックエンジニアを採用することで解決することができる。彼らは素晴らしいUIを構築して、その背後にあるアプリケーションも作りあげてしまう。彼らをユニコーン(想像上の存在)と呼ぶことにしよう。これがPayPalが常に悩まされてきたブラウザとサーバーの不自然な境界を埋めることができなかった原因だった。

Node.jsがサーバーとブラウザ両方をJavaScriptで書くことを可能にすることで、この問題を解決する手助けをしてくれ、僕たちの技術的な専門性を1つのチームに統合することで、技術的スタックのあらゆるレベルにおける、顧客のニーズを理解して、それに応えることができるようになった。

初期の採用事例

他の多くの例のように、僕たちもすくにNode.jsを試用した。そして他の多くの例のように、非常に優れた性能を発揮し、僕たちはNode.jsを実戦に投入することを決定した。

最初のテストではExpressをルーティング、nconfを設定に、そしてgruntをビルド用に使用した。僕たちが特に気に入ったのはExpressの汎用性だったが、しかし複数のチームでの作業に適していないことも判明した。Expressには規範性が欠けていて、サーバーの設定を個人が好き勝手に変更してしまう危険性があった。

もちろんこれは優れた柔軟性だったけど、大規模チームで一貫性を保つのには不利な特徴だ。チームの数が増えるにつれて、次々と新しいパターンが生まれてしまう現実に直面して、Node.jsをKraken.jsに拡張することにした。これはフレームワークそれ自身ではない。しかしExpress上での規約を守ることによって大規模開発にスケールすることを可能にする。僕たちはエンジニア達に自分自身のアプリケーションに専念して欲しかったし、環境設定に気をとられてほしくなかったんだ。

僕たちはKraken.jsをもう何ヶ月も使用している。オープンソースとして近々公開予定だ。僕らエンジニアチームが構築したnode.jsアプリケーションを皆に使ってもらうことを望んでいる。

Node.jsを実戦投入する

最初のNode.jsの成果物の採用は決してマイナーなアプリケーションではなかった。それはPayPalのアカウント概要ページで、PayPalの中でも特にトラフィックの多いページだった。大きな決断をしたが、同時にJavaアプリケーションを並行に利用することでリスクを軽減することにした。僕たちはJavaをデプロイしてスケールすることに慣れていたから、もしNode.jsのアプリに何か問題が発生したときにJavaに立ち戻ることができるからだ。これはいくつかの興味深いデータを得る結果となった。

開発

1月に開発を開始して、PayPalでNode.jsを運用するための必要なインフラ、たとえばセッション、ログの集中管理、キーストアなど、を整えるのに数ヶ月かかった。この間5人のエンジニアがJavaアプリケーションに従事していた。2ヶ月のJava開発に対して、2人のエンジニアが並行してNode.jsのアプリの開発を始めていた。6月の初旬にはnode.jsが追い付いた。アプリケーションは同じ機能を備えていた。2ヶ月の遅れて開始したたった2人のチームがすぐにJavaのチームに追い付いたのだ。いくつかの違いが目立つ、node.jsのアプリケーションは

  • わずかの人数で2倍の開発スピードだった。
  • 33%コード量を削減できた
  • 40%ファイル量を削減できた。

これが示すのは僕たちのチームがJavaScriptで開発を高速化できるという前向きな証拠である。僕たちはJavaアプリを保留して、本格的にJavaScriptに専念することにした。素晴らしいことに、当初はNode.jsに懐疑的だったJavaエンジニア達が、喜んでNode.jsの並行開発を引き受けるようになったのである。これによって当初見込んでいた2倍の生産性を得ることができた。

パフォーマンス

パフォーマンスについて言えば興味深く、論争を呼ぶような内容である。僕たちは同じ機能でほぼ同じチームで開発した2つのアプリケーションがある。1つはSpringで構築されたJavaアプリケーションで、もう一つは、expressとdust.jsおよびその他のオープンソースJavaScriptフレームワークを利用したKraken.jsのアプリケーションだ。これらのアプリは3つのルートに従い、それぞれのルートは2つから5つのAPIリクエストに応答する。データを統合し、Dustを使用してページをレンダリングするのだ。

僕たちは製品版のハードを利用してテストを実行し、スループットと応答時間についてのデータを集めた。

このデータが示すのは。

  • Node.jsはJavaに比較して1秒あたり2倍のリクエストをさばくことができる これはかなり興味深い結果です。なぜならNode.jsはシングルコアで動作しているのに関わらず、Javaは5コアで動作しているのですから。僕らはさらにこの差を大きくすることができると考えています。

  • 同じページにおける35%の応答時間の削減 これは約0.2秒の削減につながり、ユーザーがはっきりと速さを認識できるくらいです。

Uberでの採用事例

世界68カ国で展開するタクシー配車サービスのUberはシステムの中核にNode.jsを利用しています。このシステムは1日に何百万ものリクエストを裁く必要があり、相当の性能と信頼性を要求されているのです。

Uberは自分たちのサービスのあり方を水道システムに例えて説明しています。

いつでも好きな時に、水道の蛇口をひねればコップに水を入れて飲むことができるし、シャワーを浴びることもできる。Uberのサービスもこのようなものでありたいんだ。

ライフラインである水道が断水すれば、多くの人々の生活が成り立たなくなります。 つまり、Uberのシステムは決してダウンしてはいけないのです。 なぜ、Uberは実績のあるJavaやPHPなどの言語を差し置いてNode.jsを選択したのでしょうか?

それは

1.Node.jsの非同期I/Oが大量のネットワークリクエストを裁かなければいけないUberのシステムとの相性が良かった

これに加えてUberのエンジニア達はNode.jsのエラー対策の簡単さを指摘しています。

Node.jsはメモリー状態を保持している書き込みシステムに特に適している。 それによって分散システムの問題を外部化する必要がない。その結果、データベースへの、読み出し/書き込みとシリアル化を排除することにより、システムの負荷はより軽くなり、 要求に迅速に対応することができる

大規模システムには分散化など、特有の技術的課題が降りかかります。

2.開発、デバッグが用意だから。

Node.jsの大きな長所は生産性の高さです。Node.jsにはREPL(Read Eval Print Loop)という対話的開発環境があります。これによってエンジニアは大きな手間をかけることなくデバッグを行うことができるのです。

Node.jsが実運用に向いている理由は、再起動をすることなく、プログラムの変更をすぐに反映させて実証することが簡単だからです。

同じような能力のある言語は少ない。この機能があることに気づいている人は少ないみたいだけど、実際に再起動させることもなくプログラムを検証できるんだ。

この機能はエンジニアたちの生産性と想像性を飛躍的に上昇させています。

みんなが問題を解決することに前向きになり、コードを書くことに熱意とエネルギー、そして面白みを感じている。

ここには「いくらでも試行錯誤ができる」素晴らしいカルチャーがある。

仕事を終わらせて、デプロイして、クリエイティブなビジネスを、テスト段階でも、すぐに立ち上げることができる。

3.活発なオープンソースコミュニティが常に改善を進めている

Node.jsを特徴づけるのは活発なオープンソースコミュニティの存在です。もし問題が発生すれば、メンバーたちがそれを報告して、すぐに修正に取り組みます 。Node.jsの唯一とも言っていい弱点は、メモリーリークの多さです。それはシステムを急激に遅くして、パフォーマンスを低下させます。

それはサービスを開始してすぐとは限りませんが、Node.jsでシステムを動かしている限り、かならずスピードが低下する現象に見舞われるはずです。

Node.jsのシステムを実運用に入れるのならば、必ず、メモリーリークの対処法を理解・分析しなければいけません。

メモリーリークへの対処法は2つのポイントがあります。

  1. モニタリング システムを常にモニタリングしてメモリーリークをすぐに発見しなければいけません。
  2. 問題箇所の発見 メモリーリークを起こしているNode.jsのプロセスを発見して修正する必要があります。 その修正法は主に2つ、ヒープダンプとコアダンプです。

メモリーリークはNode.jsではありふれた問題ですので、コミュニティはすでに診断ツールを作成しています。Joyent、 Node.jsのオープンソース集団は、まさにこの問題のための分析ツールを用意しています。NodeSourceは別です。彼らは企業レベルでの利用を考慮したNと呼ばれるエンタープライズグレードのNode.jsのバージョンを作成しました。

Node.jsのコミュニティは積極的に同様の問題に取り組んでいます。 Node.jsは、Google V8エンジン、つまりJavaScriptをマシンコードにコンパイルするオープンソースプロジェクトの上に構築されています。Googleは何よりもChromeとGmailを構築するためにV8エンジンに多くのリソースを投入し、日々改善を続けているのです。

Node.jsのコミュニティは膨大なソフトウェアを開発しています。つまり、ほとんどの場合自分自身で開発する必要がなく、ただ他人の開発したパッケージを探し出すだけでよいのです。

Node.jsの活発に開発が行われているオープンソースコミュニティのエコシステム上に構築することにより、私たちは何もせずに、より良いソフトウェアを作ろうとする多くの人々からの努力を得ることができます。 つまり、私たちが何もしなくてもシステムはどんどん改善されていくので、それだけでも素晴らしいことです。

コミュニティに貢献すればするほど面白くなってくる。自分の問題を解決することがコミュニティの問題解決につながるからね。

私たちも完全にクライアント側とサーバー側との間で多くのレイヤーを共有するJavaScriptのポテンシャルを十分に理解していないと思う。

Uberのエンジニア・コワルは言いました。

文字通りどこでも実行するモジュラー、再利用可能なコードの可能性は十分に発揮されていないよ。