私は仕事でNode.jsを使用していますが、非常に強力であることがわかりました。Node.jsを表す1つの単語を選択することを余儀なくされたので、「興味深い」と言います(これは純粋に肯定的な形容詞ではありません)。コミュニティは活発で成長しています。JavaScriptは、その奇妙な点にもかかわらず、コーディングに最適な言語になる可能性があります。そして、「ベストプラクティス」と適切に構造化されたコードのパターンについての自分自身の理解を毎日再考します。現在、Node.jsには膨大なアイデアのエネルギーが流れ込んでおり、そこで作業することで、このすべての考え方、つまり素晴らしい精神的な重量挙げに触れることができます。
本番環境でNode.jsを使用することは間違いなく可能ですが、ドキュメントで約束されている「ターンキー」デプロイメントとはかけ離れています。Node.js v0.6.xを使用すると、「クラスター」がプラットフォームに統合され、重要なビルディングブロックの1つが提供されますが、「production.js」スクリプトは、ログの作成などを処理するロジックの150行までです。ディレクトリ、デッドワーカーのリサイクルなど。「深刻な」本番環境サービスでは、着信接続を抑制し、ApacheがPHPに対して行うすべてのことを実行する準備も必要です。公平を期すために、Ruby on Railsにはこの正確な問題があります。これは、2つの補完的なメカニズムによって解決されます。1)Ruby on Rails / Nodeを置く。Apache / Lighttd)。ウェブサーバーは、静的コンテンツの提供、ログへのアクセス、URLの書き換え、SSLの終了、アクセスルールの適用、複数のサブサービスの管理を効率的に行うことができます。実際のノードサービスにヒットするリクエストの場合、ウェブサーバーはリクエストをプロキシします。2)ワーカープロセスを管理し、定期的にリサイクルするなど、Unicornのようなフレームワークを使用します。完全に焼き尽くされているように見えるNode.jsサービスフレームワークをまだ見つけていません。存在する可能性がありますが、まだ見つかりません。手巻きの "production.js"で150行まで使用しています。
Expressのようなフレームワークを読むと、標準的な方法は、すべてのトレードの1つのNode.jsサービスを介してすべてにサービスを提供することであるように見えます... "app.use(express.static(__ dirname + '/ public'))" 。低負荷のサービスと開発については、おそらくそれで問題ありません。しかし、サービスに多大な時間をかけて24時間365日稼働させようとすると、Nginxがサイトの前面に立ち、すべてを処理するように、大規模なサイトに焼き付けられ、強化されたCコードを導入する動機がすぐにわかります。静的コンテンツ要求(... Amazon CloudFrontのようにCDNを設定するまで))。これに対するややユーモラスで恥ずかしくない否定的な見方については、この人を参照してください。
Node.jsは、サービス以外の用途もますます見つけています。Webコンテンツを提供するために別のものを使用している場合でも、Node.jsをビルドツールとして使用し、npmモジュールを使用してコードを整理し、Browserifyを使用して単一のアセットにステッチし、uglify-jsを使用してデプロイ用に縮小することができます。 。JavaScriptはWebを扱う場合、完全なインピーダンスマッチングであり、多くの場合、最も簡単な攻撃経路になります。たとえば、一連のJSON応答ペイロードを調べたい場合は、構造化データのユーティリティベルトであるアンダースコアCLIモジュールを使用する必要があります。
長所短所:
- プロ:サーバーの人にとって、バックエンドでJavaScriptを書くことは、最新のUIパターンを学ぶための「ゲートウェイドラッグ」でした。私はもはやクライアントコードを書くことを恐れません。
- プロ:適切なエラーチェックを奨励する傾向があります(errは実質的にすべてのコールバックによって返され、プログラマーはそれを処理するように強要されます。また、async.jsおよび他のライブラリーは、「これらのサブタスクのいずれかが失敗した場合の失敗」パラダイムを通常の同期コードよりもはるかに適切に処理します)
- 利点:実行中のタスクのステータスの取得、ワーカー間の通信、キャッシュ状態の共有など、いくつかの興味深い通常は難しいタスクが簡単になります。
- プロ:強固なパッケージマネージャー(npm)に基づく巨大なコミュニティと多数の優れたライブラリ
- 欠点:JavaScriptには標準ライブラリがありません。JSON.parseまたはnpmモジュールを追加する必要のないその他の組み込みメソッドを使用すると、奇妙に感じる機能のインポートに慣れます。これは、すべてのバージョンが5つあることを意味します。Node.jsの「コア」に含まれるモジュールでさえ、デフォルトの実装に不満がある場合は、さらに5つのバリアントがあります。これは急速な進化につながりますが、ある程度の混乱も伴います。
単純なリクエストごとの1プロセスモデルと比較して(LAMP):
- プロ:何千ものアクティブな接続に拡張可能。非常に高速で非常に効率的です。Webフリートの場合、これは必要なボックスの数がPHPまたはRubyに比べて10分の1になることを意味します
- プロ:平行パターンを書くのは簡単です。Memcachedから3つ(またはN)のblobをフェッチする必要があると想像してください。これをPHPで行います...最初のblobをフェッチし、次に2番目、次に3番目をフェッチするコードを記述しましたか?うわー、それは遅いです。Memcachedの特定の問題を修正する特別なPECLモジュールがありますが、データベースクエリと並行してMemcachedデータをフェッチしたい場合はどうでしょうか。Node.jsでは、パラダイムは非同期であるため、Webリクエストで複数の処理を並行して実行するのは自然なことです。
- 短所:非同期コードは基本的に同期コードよりも複雑であり、同時実行が実際に何を意味するのかをしっかり理解していない開発者にとって、事前の学習曲線は難しい場合があります。それでも、ロック付きのあらゆる種類のマルチスレッドコードを記述するよりもはるかに簡単です。
- 欠点:計算集中型のリクエストが、たとえば100ミリ秒間実行されると、同じNode.jsプロセスで処理されている他のリクエストの処理が停止します... AKA、cooperative-multitasking。これは、Web Workersパターン(サブプロセスを切り離して高価なタスクを処理する)で軽減できます。または、多数のNode.jsワーカーを使用して、それぞれに単一のリクエストを同時に処理させることもできます(プロセスのリサイクルがないため、かなり効率的です)。
- 短所:本番システムの実行は、Apache + PHP、Perl、RubyなどのCGIモデルよりもはるかに複雑です。未処理の例外はプロセス全体を停止させ、失敗したワーカーを再起動するロジックが必要になります(clusterを参照)。バグのあるネイティブコードを含むモジュールは、プロセスをハードクラッシュさせる可能性があります。ワーカーが死ぬと、そのワーカーが処理していたリクエストはすべて破棄されるため、バグのある1つのAPIが他の共同ホストされたAPIのサービスを簡単に低下させる可能性があります。
Java / C#/ Cで「実際の」サービスを作成する場合(C?本当に?)
- 長所:Node.jsで非同期を実行することは、他の場所でスレッドセーフを実行するよりも簡単で、間違いなく大きなメリットをもたらします。Node.jsは、私がこれまで作業した中で最も苦痛の少ない非同期パラダイムです。優れたライブラリーを使用すると、同期コードを書くよりも少しだけ難しくなります。
- プロ:マルチスレッド/ロックのバグはありません。確かに、ブロック操作なしで適切な非同期ワークフローを表現する、より詳細なコードを作成するために、前もって投資します。そして、いくつかのテストを記述して動作させる必要があります(これはスクリプト言語であり、ファットフィンガーリング変数名は単体テスト時にのみ捕捉されます)。しかし、一度動作させると、heisenbugsの表面積(100万回の実行で1度だけ現れる奇妙な問題)の表面積は、はるかに小さくなります。Node.jsコードを作成する税金は、コーディングフェーズにかなり前倒しされています。次に、安定したコードが作成される傾向があります。
- 長所:JavaScriptは、機能を表現するのにはるかに軽量です。これを言葉で証明するのは難しいですが、JSON、動的型付け、ラムダ表記、プロトタイプ継承、軽量モジュールなど、同じアイデアを表現するのに必要なコードが少なくなる傾向があります。
- 短所:Javaでのコーディングサービスが本当に好きなのでしょうか。
JavaScriptとNode.jsの別の見方については、Java開発者の感想とNode.jsの学習に関するブログ投稿の「JavaからNode.jsへ」をご覧ください。
モジュール
ノードを検討するときは、JavaScriptライブラリの選択がエクスペリエンスを定義することに注意してください。ほとんどの人は、少なくとも2つ、非同期パターンヘルパー(Step、Futures、Async)とJavaScriptシュガーモジュール(Underscore.js)を使用します。
ヘルパー/ JavaScriptシュガー:
- Underscore.js-これを使用してください。早くやれよ。_.isString()や_.isArray()などを使用して、コードを見やすく読みやすくします。それ以外の方法で安全なコードを作成する方法がよくわかりません。また、拡張されたcommand-line-fuについては、自分のUnderscore-CLIを確認してください。
非同期パターンモジュール:
- ステップ -シリアルアクションとパラレルアクションの組み合わせを表現する非常にエレガントな方法。私の個人的な推薦。ステップコードがどのように見えるかについての私の投稿を参照してください。
- 先物 -要件を通して注文を表現するためのはるかに柔軟な(それは本当に良いことですか?)「a、b、cを並行して開始します。A、Bが終了したら、ABを開始します。A、Cが終了したら、ACを開始します」のような表現ができます。このような柔軟性を実現するには、ワークフローのバグを回避するために、さらに注意が必要です(コールバックを呼び出さない、またはコールバックを複数回呼び出すなど)。先物を使用することに関するレイノスの投稿を参照してください(これは私に先物を「取得」させた投稿です)。
- Async-パターンごとに1つのメソッドを持つ、より伝統的なライブラリ。ステップへの宗教的な変換と、それに続く非同期のすべてのパターンが単一のより読みやすいパラダイムでステップで表現できることに気づく前に、私はこれから始めました。
- TameJS - OKCupidによって書かれた、プリコンパイラであり、直列および並列ワークフローをエレガントに書くための新しい言語プリミティブ "await"を追加します。パターンはすばらしいように見えますが、事前コンパイルが必要です。私はまだこれについて決心しています。
- StreamlineJS -TameJSのライバル。私は飼いならしに傾いていますが、あなた自身の決心をすることができます。
または、非同期ライブラリのすべてを読むには、作者とのこのパネルインタビューを参照してください。
Webフレームワーク:
- Webサイトを編成するためのGreat Ruby on Rails-eskフレームワークを表現します。JADEをXML / HTMLテンプレートエンジンとして使用しているため、HTMLの構築ははるかに簡単で、ほとんどエレガントです。
- jQuery技術的にはノードモジュールではありませんが、jQueryはすぐにクライアント側ユーザーインターフェイスの事実上の標準になりつつあります。jQueryは、操作できるDOM要素のセット(セットハンドラー、プロパティ、スタイルなど)を「クエリ」するためのCSSのようなセレクターを提供します。同様に、TwitterのBootstrap CSSフレームワーク、MVCパターン用のBackbone.js、およびすべてのJavaScriptファイルを1つのファイルにつなぐBrowserify.js。これらのモジュールはすべて事実上の標準になっているので、聞いたことがない場合は、少なくともそれらを確認する必要があります。
テスト:
- JSHint-使用する必要があります。最初はこれを使用しませんでしたが、今では理解しにくいようです。JSLintは、Javaのようなコンパイルされた言語で得られる基本的な検証の束を追加します。括弧の不一致、宣言されていない変数、多くの形状とサイズのタイプ。また、私が「アナルモード」と呼ぶさまざまな形式をオンにして、空白のスタイルなどを確認することもできます。これは、お茶のカップであれば問題ありません。コードの実行を忘れて問題の行にぶつからずに、「)」の終わりを忘れました。「JSHint」は、Douglas CrockfordのJSLintのより構成可能なバリアントです。
- 私が好むようになったVowsのモカライバル。どちらのフレームワークも基本を十分に処理しますが、複雑なパターンはMochaで表現する方が簡単です。
- Vows Vowsは本当にとてもエレガントです。そして、どのテストケースが成功/失敗したかを示す素敵なレポート(--spec)を出力します。30分かけて学習すると、最小限の労力でモジュールの基本的なテストを作成できます。
- ゾンビ-JSDomを仮想「ブラウザ」として使用したHTMLおよびJavaScriptのヘッドレステスト。非常に強力なもの。これをReplayと組み合わせて、ブラウザー内のコードの高速で確定的なテストを取得します。
- テストを「考える」方法に関するコメント:
- テストはオプションではありません。JavaScriptのような動的言語では、静的チェックはほとんどありません。たとえば、4を期待するメソッドに2つのパラメーターを渡しても、コードが実行されるまでブレークしません。JavaScriptでバグを作成するためのかなり低いバー。コンパイルされた言語との検証ギャップを埋めるためには、基本的なテストが不可欠です。
- 検証を忘れて、コードを実行させるだけです。どの方法でも、最初の検証ケースは「何も壊れない」で、これが最も頻繁に発生するケースです。コードをスローせずに実行できることを証明すると、バグの80%が検出され、コードの信頼性が大幅に向上するため、スキップして微妙な検証ケースを追加することができます。
- 小さく始めて、慣性障壁を破ります。私たちは皆怠惰で時間を切望されており、テストを「余計な仕事」と見なすのは簡単です。だから小さなものから始めましょう。テストケース0を作成-モジュールをロードして成功を報告します。自分でこれだけをやるように強制すると、テストに対する慣性の壁が破られます。ドキュメントを読むことを含めて、初めての場合は30分未満です。次に、テストケース1を記述します。いずれかのメソッドを呼び出して、「何も壊れない」こと、つまりエラーが返されないことを確認します。テストケース1の所要時間は1分未満です。慣性がなくなったので、テストの対象範囲を段階的に拡大することが容易になります。
- コードでテストを進化させましょう。「正しい」エンドツーエンドテストがモックサーバーなどでどのように表示されるかにおびえないでください。コードは単純に始まり、新しいケースを処理するように進化します。テストもすべきです。コードに新しいケースと複雑さを追加したら、新しいコードを実行するためのテストケースを追加します。バグを見つけたら、検証や新しいケースを追加して、欠陥のあるコードをカバーします。デバッグ中にコードの一部に自信がなくなった場合は、戻ってテストを追加し、意図したとおりに動作していることを確認してください。サンプルデータの文字列(呼び出した他のサービス、スクレイピングしたWebサイトなど)をキャプチャして、解析コードにフィードします。ここでのいくつかのケースでは、検証が改善され、信頼性の高いコードが作成されます。
また、推奨されるNode.jsモジュールの公式リストも確認してください。ただし、GitHubの Node Modules Wikiははるかに完全であり、優れたリソースです。
Nodeを理解するには、いくつかの主要な設計選択を検討することが役立ちます。
Node.jsは、イベントベースで非同期 / 非ブロッキング。着信HTTP接続などのイベントは、少しの作業を行うJavaScript関数を起動し、データベースへの接続や別のサーバーからのコンテンツのプルなどの他の非同期タスクを開始します。これらのタスクが開始されると、イベント関数が終了し、Node.jsがスリープ状態に戻ります。データベース接続が確立されたり、外部サーバーがコンテンツで応答したりするなど、何か他のことが発生するとすぐに、コールバック関数が起動し、さらに多くのJavaScriptコードが実行され、さらに多くの非同期タスク(データベースクエリなど)が開始される可能性があります。このようにして、Node.jsは複数の並列ワークフローのアクティビティを楽しくインターリーブし、任意の時点でブロックされていないアクティビティを実行します。これがNode.jsが数千の同時接続を管理するこのような素晴らしい仕事をする理由です。
他の人のように、接続ごとに1つのプロセス/スレッドを使用しないのはなぜですか?Node.jsでは、新しい接続は非常に小さなヒープ割り当てです。新しいプロセスを起動すると、メモリが大幅に増加します(一部のプラットフォームではメガバイト)。しかし、実際のコストは、コンテキスト切り替えに関連するオーバーヘッドです。カーネルスレッドが10 ^ 6の場合、カーネルは次に実行する必要がある人を見つけるために多くの作業を行わなければなりません。Linux用のO(1)スケジューラを構築するために多くの作業が行われましたが、最終的には、CPU時間を競合する10 ^ 6プロセスよりも単一のイベント駆動型プロセスを使用する方がはるかに効率的です。また、過負荷状態では、マルチプロセスモデルの動作が非常に悪くなり、重要な管理および管理サービス、特にSSHDが不足します(つまり、ボックスにログインして、それが実際にどの程度ねじ込まれているかを把握することもできません)。
Node.jsはシングルスレッドでロックフリーです。Node.jsは、非常に慎重に設計されているため、プロセスごとに1つのスレッドしかありません。このため、複数のスレッドが同時にデータにアクセスすることは基本的に不可能です。したがって、ロックは必要ありません。スレッドは難しいです。本当に大変です。信じられない場合は、十分なスレッドプログラミングを行っていません。ロックを正しく行うことは難しく、バグを追跡することは非常に困難です。ロックとマルチスレッドを排除することで、厄介なバグの1つがなくなります。これがノードの最大の利点の1つかもしれません。
しかし、16コアボックスを活用するにはどうすればよいですか?
二通り:
- 画像のエンコーディングなどの非常に重いコンピューティングタスクの場合、Node.jsは子プロセスを起動したり、追加のワーカープロセスにメッセージを送信したりできます。この設計では、イベントのフローを管理する1つのスレッドと、重い計算タスクを実行し、他の15個のCPUを消費するN個のプロセスがあります。
- ウェブサービスのスループットをスケーリングするには、クラスターを使用して、コアごとに1つのボックスで複数のNode.jsサーバーを実行する必要があります(Node.js v0.6.xでは、ここにリンクされている公式の「クラスター」モジュールが、別のAPI)。これらのローカルNode.jsサーバーは、新しい接続を受け入れるためにソケット上で競合し、それらの間で負荷を分散できます。接続が受け入れられると、これらの共有プロセスの1つにしっかりとバインドされます。理論的にはこれは悪いように聞こえますが、実際には非常にうまく機能し、スレッドセーフなコードを書く頭痛を回避することができます。また、これは、Node.jsが優れたCPUキャッシュアフィニティを取得し、メモリ帯域幅をより効果的に使用することを意味します。
Node.jsを使用すると、汗をかくことなく、非常に強力なことができます。さまざまなタスクを実行し、コマンドを TCPポートでリッスンし、いくつかの画像をエンコードするNode.jsプログラムがあるとします。5行のコードで、アクティブなタスクの現在のステータスを表示するHTTPベースのWeb管理ポータルに追加できます。これは簡単です:
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(myJavascriptObject.getSomeStatusInfo());
}).listen(1337, "127.0.0.1");
これで、URLにアクセスして、実行中のプロセスのステータスを確認できます。いくつかのボタンを追加すると、「管理ポータル」ができます。実行中のPerl / Python / Rubyスクリプトがある場合、「管理ポータルに投入する」だけでは正確ではありません。
しかし、JavaScriptは遅い/悪い/悪/ spawn-of-the-devilでないのですか?JavaScriptには奇妙な奇妙な点がいくつかありますが、「良い部分」には非常に強力な言語があり、JavaScriptはクライアント(ブラウザー)の言語です。JavaScriptは今後も存続します。他の言語はそれをILとしてターゲットにしており、世界クラスの才能が最先端のJavaScriptエンジンを生み出すために競争しています。ブラウザーでのJavaScriptの役割のため、JavaScriptの高速化に多大なエンジニアリング努力が費やされています。 V8少なくとも今月は、最新かつ最高のJavaScriptエンジンです。Rubyの効率性と安定性の両方で他のスクリプト言語を吹き飛ばします。そして、Microsoft、Google、およびMozillaで問題に取り組んでいる巨大なチームで最高のJavaScriptエンジンを構築するために競争するだけで良くなります(すべての最新のエンジンが大量のJITを実行するため、もはやJavaScriptの「インタープリター」ではありません)一度だけ実行されるコードのフォールバックとしてのみ解釈される内部でのコンパイル)。ええ、私たちは皆、奇妙なJavaScript言語の選択のいくつかを修正できればいいのにと思っていますが、実際にはそれほど悪くはありません。また、この言語は非常に柔軟性が高いため、JavaScriptを実際にコーディングするのではなく、StepまたはjQueryをコーディングしています。JavaScriptでは、他のどの言語よりも、ライブラリがエクスペリエンスを定義します。Webアプリケーションを構築するには、とにかくJavaScriptを知っている必要があるため、サーバーでJavaScriptを使用してコーディングすると、ある程度の相乗効果があります。それは私がクライアントコードを書くことを恐れないようにしました。
さらに、JavaScriptが本当に嫌いな場合は、CoffeeScriptのような構文糖を使用できます。または、Google Web Toolkit(GWT)など、JavaScriptコードを作成するその他のもの。
JavaScriptといえば、「クロージャ」とは何ですか?-呼び出しチェーン全体でレキシカルにスコープされた変数を保持するというかなり凝った言い回し。;) このような:
var myData = "foo";
database.connect( 'user:pass', function myCallback( result ) {
database.query("SELECT * from Foo where id = " + myData);
} );
// Note that doSomethingElse() executes _BEFORE_ "database.query" which is inside a callback
doSomethingElse();
「myData」をオブジェクトに隠しておくような厄介なことをせずに、「myData」を使用する方法をご覧ください。また、Javaとは異なり、「myData」変数は読み取り専用である必要はありません。この強力な言語機能により、非同期プログラミングの冗長性と苦痛が大幅に軽減されます。
非同期コードの記述は、単純なシングルスレッドスクリプトの記述よりも常に複雑になりますが、Node.jsを使用すると、それほど難しくはなく、数千の同時接続に対する効率とスケーラビリティに加えて、多くの利点が得られます。 ..