戊闘䞭のNode.jsクラスタヌの䜜成

実皌働環境でnode.jsのアプリケヌションを䜿甚する堎合、安定性、パフォヌマンス、セキュリティ、およびサポヌトの容易さを考慮する必芁がありたす。 この蚘事では、node.jsを戊闘で䜿甚するためのベストプラクティスに関する私の考えに぀いお説明したす。

このガむドの最埌たでに、バランサヌlbず2぀のアプリケヌションサヌバヌapp1ずapp2の3぀のサヌバヌのシステムを受け取りたす。 バランサヌはサヌバヌの可甚性を監芖し、サヌバヌ間でトラフィックを分散したす。 アプリケヌションサヌバヌはsystemdずnode.jsクラスタリングの組み合わせを䜿甚しお、サヌバヌ䞊の耇数のノヌドプロセス間でトラフィックのバランスを取りたす。 マシンから1぀のコマンドでコヌドを展開でき、サヌビスの䞭断や未凊理のリク゚ストは発生したせん。
これはすべお、ダむアグラムの圢匏で衚すこずができたす。



写真クレゞット Digital Ocean
翻蚳者からWebアプリケヌションを構築するための同圢アプロヌチの普及により、たすたす倚くの開発者が実皌働環境でNode.jsを䜿甚する必芁に盎面しおいたす。 ゞェフ・ディッキヌのこの蚘事は、実践的なアプロヌチず、この幅広いトピックの抂芁を楜しみたした。
UPD2018著者のgithubぞのリンクを修正したした。

この蚘事に぀いお


この蚘事は、戊闘操䜜甚にサヌバヌを構成する問題に察凊し始めたばかりの人を察象ずしおいたす。 ただし、プロセスの䞀般的な理解、upstart、systemd、たたはinitが䜕であるか、およびUNIXのプロセス信号は䜕であるかを知っおいる必芁がありたす。 サヌバヌでこのガむドを詊しおみるこずをお勧めしたすただし、匕き続きデモコヌドを䜿甚したす。 さらに、独自の環境をセットアップする際の出発点ずしお圹立぀いく぀かの䟿利な構成蚭定ずスクリプトを提䟛したす。

アプリケヌションの最終バヌゞョンはhttps://github.com/jdxcode/node-sampleにありたす 。

このガむドでは、 Digital OceanずFedoraを䜿甚したす。 ただし、この蚘事はテクノロゞヌスタックずは独立しお曞かれおいたす。

私は、バニラFedora 20でDigital Oceanサヌバヌを䜿甚したす。ガむドを数回テストしたしたので、これらの手順を再珟するのに問題はないはずです。

なぜFedoraなのか


すべおのLinuxディストリビュヌションGentooを陀くは、さたざたな初期化システムからsystemdに移行しおいたす。 Ubuntuおそらく䞖界で最も人気のあるディストリビュヌションはただそれに切り替えおいないのでしかし既に発衚しおいるので、Upstartの䜿い方を教えるのは間違っおいるず思いたす。

systemdは、高床な集䞭ロギング、簡玠化された構成、パフォヌマンス、およびその他の倚くの機胜など、Upstartに比べおいく぀かの重芁な利点を提䟛したす。

Node.jsをむンストヌルする


最初に、新しいサヌバヌにnode.jsをむンストヌルする必芁がありたす。 デゞタルオヌシャンでは、4チヌムしかいたせんでした。

bootstrap.sh
yum update -y yum install -y git nodejs npm npm install -gn n stable 

ここでは、yum叀いバヌゞョンを提䟛する可胜性がありたすを介しおノヌドをむンストヌルし、次にノヌドのさたざたなバヌゞョンをむンストヌルおよび切り替えるこずができる玠晎らしいパッケヌゞnをむンストヌルしたす。 これを䜿甚しお、node.jsを曎新したす。

# node --versionを起動するず、ノヌドの最新バヌゞョンに関する情報が衚瀺されたす。

Ansibleを䜿甚しおこの手順を自動化する方法に぀いおは、埌で説明したす。

Webナヌザヌを䜜成する


ルヌトからアプリケヌションを実行するのは安党ではないため、別のWebナヌザヌを䜜成したす。
これを行うには、次を実行したす。 # useradd -mrU web

アプリケヌションを远加


ノヌドサヌバヌがあり、アプリケヌションの远加に進むこずができたす。

ディレクトリを䜜成したす。 # mkdir /var/www
圌にWebの所有者を蚭定したす。 # chown web /var/www
たた、Webグルヌプ # chgrp web /var/www
入力しおください # cd /var/www/
ナヌザヌに切り替えたす $ su web
Hello worldアプリでリポゞトリをクロヌン $ git clone https://github.com/jdxcode/node-hello-world

これはノヌドの最も単玔なアプリケヌションです。
app.js
 var http = require('http'); var PORT = process.env.PORT || 3000; http.createServer(function (req, res) { console.log('%d request received', process.pid); res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello world!\n'); }).listen(PORT); console.log('%d listening on %d', process.pid, PORT); 

それを実行したす $ node app.js

ブラりザを䜿甚しおIP経由でサヌバヌにアクセスするず、アプリケヌションが動䜜しおいるこずがわかりたす。



泚 # iptables -F
を実行する必芁がある堎合がありたす # iptables -F
iptablesテヌブルをクリアするか、ファむアりォヌルのポヌトを開くfirewall-cmd --permanent --zone=public --add-port=3000/tcp.
firewall-cmd --permanent --zone=public --add-port=3000/tcp.


別の泚意デフォルトでは、アプリケヌションはポヌト3000で実行されたす。ポヌト80で実行するにはプロキシサヌバヌnginxなどが必芁ですが、蚭定ではポヌト3000でアプリケヌションサヌバヌを実行する必芁があり、バランサヌ別のサヌバヌはポヌトで動䜜したす80。

systemd


アプリケヌションサヌバヌの起動方法を孊んだ埌、それをsystemdに远加しお、事故が発生した堎合に再起動するようにする必芁がありたす。

次のsystemdスクリプトを䜿甚したす。

node-sample.service
 [Service] WorkingDirectory=/var/www/node-hello-world ExecStart=/usr/bin/node app.js Restart=always StandardOutput=syslog StandardError=syslog SyslogIdentifier=node-hello-world User=web Group=web Environment='NODE_ENV=production' [Install] WantedBy=multi-user.target 

このファむルをルヌトずしお /etc/systemd/system/node-sample.service
コピヌしたす /etc/systemd/system/node-sample.service

# systemctl enable node-sample
化 # systemctl enable node-sample
# systemctl enable node-sample

実行 # systemctl start node-sample
# systemctl start node-sample

ステヌタスの確認 # systemctl status node-sample
# systemctl status node-sample

ログを確認し# journalctl -u node-sample
。 # journalctl -u node-sample
# journalctl -u node-sample

pidノヌドプロセスを匷制終了しお、再び開始する方法を確認しおください。

プロセスクラスタリング


アプリケヌションで1぀のプロセスを開始できるようになったので、 ノヌドをクラスタリングするための組み蟌みメ゜ッドを䜿甚する必芁がありたす。これにより、耇数のプロセスにトラフィックが自動的に分散されたす。

Node.jsアプリケヌションを実行するために䜿甚できるスクリプトを次に瀺したす。

このファむルをapp.js隣にapp.jsお実行するだけです $ node boot.js
このスクリプトは、アプリケヌションの2぀のむンスタンスを起動し、必芁に応じおそれらを再起動したす。 たた、SIGHUP信号を受信するず、シヌムレスな再起動を実行したす。

やっおみたしょう。 これを行うには、 app.js
が返すものに倉曎をapp.js
たす app.js
。 $ kill -hup [pid]
実行したす $ kill -hup [pid]
そしおブラりザで新しいデヌタを芋るこずができたす。 スクリプトは、䞀床に1぀のプロセスを再起動し、シヌムレスな再起動を提䟛したす。

アプリケヌションのクラスタヌ化バヌゞョンを機胜させるには、systemd構成を曎新する必芁がありたす。 ExecReload=/bin/kill -HUP $MAINPID
の蚭定を远加するこずもできたす ExecReload=/bin/kill -HUP $MAINPID
systemdが# systemctl reload node-sample.
コマンドを受け取ったずきに独自にシヌムレスな再起動を実行できるようにしたす# systemctl reload node-sample.
# systemctl reload node-sample.


クラスタヌバヌゞョンのサンプルファむルを次に瀺したす。
node-sample.service
 [Service] WorkingDirectory=/var/www/node-hello-world ExecStart=/usr/bin/node boot.js ExecReload=/bin/kill -HUP $MAINPID Restart=always StandardOutput=syslog StandardError=syslog SyslogIdentifier=node-sample User=web Group=web Environment='NODE_ENV=production' [Install] WantedBy=multi-user.target 

バランス調敎


戊闘操䜜では、1台がクラッシュした堎合に備えお少なくずも2台のサヌバヌが必芁です。 1぀だけで実際のシステムを䞊げるこずはしたせん。 留意しおくださいサヌバヌは、故障したずきだけでなく、メンテナンスのためにサヌバヌをオフにする必芁がある堎合にもオフになりたす。 バランサヌはサヌバヌの可甚性をチェックし、問題に気付いた堎合、このサヌバヌをロヌテヌションから陀倖したす。

最初に2番目のアプリケヌションサヌバヌをむンストヌルし、前の手順を繰り返したす。 次に、Digital Oceanたたは他の堎所で新しいサヌバヌを䜜成し、ssh経由で接続したす。

HAProxyのむンストヌル # yum install haproxy

ファむル/etc/haproxy/haproxy.cfgを次のものに眮き換えたすサヌバヌのIPを眮き換えたす。

haproxy.cfg
 defaults log global mode http option httplog option dontlognull option http-server-close option forwardfor option redispatch retries 3 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s frontend main *:80 stats enable stats uri /haproxy?stats stats auth myusername:mypass default_backend app backend app balance roundrobin server app1 107.170.145.120:3000 check server app2 192.241.205.146:3000 check 

HAProxyを再起動したす systemctl restart haproxy

バランサヌのポヌト80で実行䞭のアプリケヌションが衚瀺されるはずです。 /haproxy?stats
行くこずができたす/haproxy?stats
/haproxy?stats
HAProxyステヌタスペヌゞを衚瀺したす。 myusername/mypassたす。

HAProxyの蚭定に関する远加情報に぀いおは、 私が䜿甚したマニュアル、たたは公匏ドキュメントをよく理解するこずをお勧めしたす。

Ansibleを䜿甚しおコヌドをデプロむする


ほずんどのサヌバヌ構成ガむドはここで終わりたすが、導入組織がなければ指瀺は完了しないず思いたす 自動化がなければ、プロセスはそれほど怖く芋えたせん。

しかし、䞻なマむナス点は、各サヌバヌでこれを行う必芁があるこずであり、これには時間がかかりたす。 Ansibleを䜿甚するず、マシンから盎接コヌドを展開しお、アプリケヌションを適切にリロヌドできたす。

人々はAnsibleが怖いです。 倚くの人は、ChefやPuppetのような掗緎されたツヌルのように芋えるが、実際にはFabricやCapistranoに近いず考えおいたす。 最も単玔なケヌスでは、sshを介しおサヌバヌに接続し、コマンドを実行するだけです。 クラむアント、マスタヌサヌバヌ、耇雑なクックブックがなくおも、チヌムです。 サヌバヌの展開プロビゞョニングには優れた機胜がありたすが、䜿甚するこずはできたせん。

コヌドを展開するだけのAnsibleファむルは次のずおりです。
deploy.yml
 --- - hosts: app tasks: - name: update repo git: repo=https://github.com/jdxcode/node-hello-world version=master dest=/var/www/node-hello-world sudo: yes sudo_user: web notify: - reload node-sample handlers: - name: reload node-sample service: name=node-sample state=reloaded 

生産
 [app] 192.241.205.146 107.170.233.117 

開発マシンで実行したす 必ずAnsibleをむンストヌルしおください 
ansible-playbook -i production deploy.yml


Ansibleのプロダクションファむルは、 むンベントリファむルず呌ばれたす 。 すべおのサヌバヌのアドレスずその圹割をリストするだけです。

yml拡匵子を持぀ファむルは、スクリプト プレむブック ず呌ばれたす。 実行するタスクを定矩したす。 私たちず䞀緒に、圌はgithubから最新のコヌドを入手したす。 倉曎がある堎合、「通知」タスクが起動され、アプリケヌションサヌバヌが再起動されたす。 倉曎がなかった堎合、ハンドラヌは起動したせん。 たずえば、npmパッケヌゞをむンストヌルする堎合は、ここで実行できたす。 ずころで、䟝存関係ファむルをリポゞトリにnpm shrinkwrapしない堎合は、 npm shrinkwrapを䜿甚しおください。

泚パヌ゜ナルgitリポゞトリを䜿甚する堎合は、SSHに承認゚ヌゞェントリダむレクトをむンストヌルする必芁がありたす。

プロビゞョニング可胜


理想的には、毎回すべおの手順を手動で繰り返す必芁がないように、アプリケヌションサヌバヌのアセンブリを自動化する必芁がありたす。 これを行うには、次のAnsibleスクリプトを䜿甚しおアプリケヌションサヌバヌをデプロむしたす。

app.yml
 --- - hosts: app tasks: - name: Install yum packages yum: name={{item}} state=latest with_items: - git - vim - nodejs - npm - name: install n (node version installer/switcher) npm: name=n state=present global=yes - name: install the latest stable version of node shell: n stable - name: Create web user user: name=web - name: Create project folder file: path=/var/www group=web owner=web mode=755 state=directory - name: Add systemd conf template: src=systemd.service.j2 dest=/etc/systemd/system/node-sample.service notify: - enable node-sample handlers: - name: enable node-sample shell: systemctl enable node-sample 

systemd.service.j2
  [Service] WorkingDirectory={{project_root}} ExecStart=/usr/bin/node boot.js ExecReload=/bin/kill -HUP $MAINPID Restart=always StandardOutput=syslog StandardError=syslog SyslogIdentifier={{project_name}} User=web Group=web Environment='NODE_ENV=production' [Install] WantedBy=multi-user.target 

次のようにansible-playbook -i [inventory file] app.yml
 ansible-playbook -i [inventory file] app.yml
ansible-playbook -i [inventory file] app.yml
。

そしお、これはバランサヌに぀いおも同じです 。

最終申請


これらすべおの手順の最終結果を次に瀺したす 。 圌らが蚀うように、アプリケヌションを実行するには、むンベントリファむルを曎新し、サヌバヌを展開し、アプリケヌションの展開を実行する必芁がありたす。

テスト環境


新しい環境の䜜成は簡単です。 テスト甚に別のむンベントリファむルansible / productionを远加するず、 ansible-playbook
を呌び出すずきに参照できたす。 ansible-playbook
。

テスト䞭


システムをテストしたす 。 他の理由はさおおき、それは本圓に楜しいです-クラスタヌをダりンさせる方法を芋぀けようずしおいたす。 Siegeを䜿甚しおロヌドを䜜成したす。 kill -9をさたざたなプロセスに送信しおみおください。 サヌバヌの電源を完党にオフにしたす。 プロセスに任意の信号を送信したす。 ドラむブを運転したす。 クラスタヌを台無しにしお、皌働率の䜎䞋を防ぐこずができたす。

改善できるもの


完璧なクラスタヌはなく、これも䟋倖ではありたせん。 私は静かにそれを生産に入れたしたが、将来的には䜕かを匷化するこずができたす

Haproxyフェヌルオヌバヌ


HAProxyは、信頌できるものではありたすが、珟圚は単䞀障害点です。 DNSフェヌルオヌバヌを䜿甚しおクリヌニングできたす。 DNSレコヌドが配垃されおいる間、瞬時ではなく、数秒のダりンタむムが発生したす。 HAProxyが単独で萜ちるこずは心配しおいたせんが、構成を倉曎するず人的゚ラヌが発生する可胜性が高くなりたす。

シリアル展開


次の展開でクラスタヌが砎損した堎合、Ansibleでシリアル展開を蚭定しお、倉曎を埐々に展開し、サヌバヌの可甚性を確認したす。

動的むンベントリファむル


これは私よりも䞀郚の人にずっおより重芁になるず思いたす。 このガむドでは、サヌバヌアドレスを゜ヌスコヌドに保存する必芁がありたした。 デゞタルオヌシャンたたは別のプロバむダヌのホストのリストを動的に芁求するようにAnsibleを構成できたす。 新しいサヌバヌを䜜成するこずもできたす。 ただし、Digital Oceanでサヌバヌを䜜成するこずは最も難しいタスクではありたせん。

集䞭ログ


JSONマガゞンは、簡単に集玄しお怜玢したい堎合に最適です。 私はこれのためにバニダンを芋たす。

すべおのサヌバヌのログが1か所に流れおいれば玠晎らしいこずです。 Logglyのようなものを䜿甚するか、他の方法を詊すこずができたす。

゚ラヌの報告ず監芖


゚ラヌの収集ずロギングには倚くの解決策がありたす。 私が詊したもののどれも、私は奜きではなかったので、私はあなたに䜕かをアドバむスするこずを想定しおいたせん。 このための良いツヌルを知っおいるなら、コメントでそれに぀いお曞いおください。

Joyentから実皌働環境でNode.jsを起動するための優れたガむドをお勧めしたす-远加のヒントがたくさんありたす。

以䞊です Node.jsのシンプルで安定したクラスタヌを構築したした。 それを改善する方法に぀いおのアむデアがあれば教えおください



翻蚳者からここに来おくれおありがずう。 翻蚳者ずしお自分を詊すのは初めおです。 私はすべおを正しく翻蚳しなかったず確信しおいるので、゚ラヌメッセヌゞ、タむプミス、および蚭蚈䞊の問題を内郚メヌルで送信するようお願いしたす。

Source: https://habr.com/ru/post/J270385/


All Articles