10分で作る Node.js Auto Scale 環境 with CloudFormation

Kazuyuki Honda
Kazuyuki HondaSoftware Engineer at Quipper
Node.js Auto Scaling
      in 10 minutes
with AWS CloudFormation
   2012/6/28 東京Node学園 6時限目
          @hakobera
Question



AWSでNode.jsを何ノードま
で動かしたことありますか?
Node.jsで1億リクエスト/日


 1億リクエスト/日

 => 417万リクエスト/時

 => 7万リクエスト/分

 => 1200リクエスト/秒
AWS なら簡単
AWS なら簡単
EC2

  AMI (VMイメージ)の作成

  Node.js 、依存パッケージのインストール

セキュリティグループ

  ポート番号や接続制限

ELB

  プロトコルとポート番号

Auto Scale

  CloudWatch の設定

  Auto Scale Group ポリシーの設定

アプリケーションのDeployとUpdate
AWS なら簡単
EC2

  AMI (VMイメージ)の作成

  Node.js 、依存パッケージのインストール

セキュリティグループ

  ポート番号や接続制限

ELB      じゃなかった orz
  プロトコルとポート番号

Auto Scale

  CloudWatch の設定

  Auto Scale Group ポリシーの設定

アプリケーションのDeployとUpdate
そこで AWS CloudFormation の出番

 http://aws.amazon.com/jp/cloudformation/


 AWS インフラ構成のテンプレート

 設定の一部をパラメータ化できる

 JSON 形式 (Noder にはお馴染み)


 DynamoDBとCloudFront の先週からサポート開始
                       詳細はこちらを参照
自分だけの PaaS が
  簡単に作れる
とりあえずやってみる


Tempalte:
 https://cf-templates-for-nodejs.s3.amazonaws.com/cf-node-autoscale-tmpl.json

App:
 https://github.com/hakobera/tng6_sample/zipball/master

GitHub:
 https://github.com/hakobera/tng6_sample
Node.js と CloudFormation の勘所


  Node.js の
                  AutoScale
  インストール



                  Elastic Load
    アプリの
                  Balancer と
Deploy と Update
                  WebSocket
Node.js のインストール
Node.jsのインストール
バイナリパッケージを使おう
   ∵ micro インスタンスで Node.js のビルドが遅い


       Installing Node.js via package manager
https://github.com/joyent/node/wiki/Installing-Node.js-
                  via-package-manager
 $ sudo yum localinstall --nogpgcheck http://nodejs.tchol.org/repocfg/amzn1/nodejs-stable-release.noarch.rpm

 $ sudo yum install nodejs-compat-symlinks npm




                                                     残念ながら v0.8 はまだない
Node.jsのインストール
Cloud Init でパッケージ指定
"AppServerLaunchConfig": {
  "Type" : "AWS::AutoScaling::LaunchConfiguration",
  "Metadata": {
   "AWS::CloudFormation::Init": {
    "config": {
     "packages": {
       "rpm" : {
         "nodejs" : "http://nodejs.tchol.org/repocfg/amzn1/nodejs-stable-release.noarch.rpm"
       },
       "yum": {
         "gcc-c++": [],
         "make": [],
         "git" : [],
         "nodejs-compat-symlinks": [],
         "npm": []
       }
     },

     "sources" : {
       "/var/opt/app" : { "Ref": "AppURL" }
     }
    }, ...
Node.jsのインストール
         Cloud Init の起動設定
"Properties": {
    (省略)
    "UserData": {
     "Fn::Base64": {
      "Fn::Base64": {
       "Fn::Join": ["", [
        "#!/bin/bash -vn",
        "yum update -y aws-cfn-bootstrapn",

         "# Helper functionn",
         "function error_exitn",
         "{n",
         " /opt/aws/bin/cfn-signal -e 1 -r "$1" '", { "Ref": "WaitHandle" }, "'n",
         " exit 1n",
         "}n",

         "# Install packagesn",
         "/opt/aws/bin/cfn-init -s ", { "Ref": "AWS::StackName" }, " -r AppServerLaunchConfig ",
         " --access-key ", { "Ref": "HostKeys" },
         " --secret-key ", { "Fn::GetAtt": ["HostKeys", "SecretAccessKey"] },
         " --region ", { "Ref": "AWS::Region" }, " || error_exit 'Failed to run cfn-init'n",
Auto Scale
Cloud Watch
   http://aws.amazon.com/jp/cloudwatch/
   http://aws.amazon.com/jp/autoscaling/


Auto Scale の条件(拡張・縮小のトリガー)は、
Cloud Watch のアラームで実現している

アプリの特性の応じて、チェックする対象を変更

 CPUUtilization, DiskReadBytes, DiskReadOps, DiskWriteBytes,
 DiskWriteOps, NetworkIn, NetworkOut

 Node.js だと、CPUUtilization か NetworkOut のどちらかで大体OK
設定例: CPUUtilization
    "AppServerScaleUpPolicy" : {
     "Type" : "AWS::AutoScaling::ScalingPolicy",
     "Properties" : {
       "AdjustmentType" : "ChangeInCapacity",
       "AutoScalingGroupName" : { "Ref" : "AppServerGroup" },
       "Cooldown" : "60",
       "ScalingAdjustment" : "2"
     }
   },

   "CPUAlarmHigh": {
    "Type": "AWS::CloudWatch::Alarm",
    "Properties": {
      "AlarmDescription": "Scale-up if CPU > 90% for 10 minutes",
      "MetricName": "CPUUtilization",
      "Namespace": "AWS/EC2",
      "Statistic": "Average",
      "Period": "300",
      "EvaluationPeriods": "2",
      "Threshold": "90",
      "AlarmActions": [ { "Ref": "AppServerScaleUpPolicy" } ],
      "Dimensions": [
       {
         "Name": "AutoScalingGroupName",
         "Value": { "Ref": "AppServerGroup" }
       }
      ],
アプリの Deploy と Update
アプリのDeploy
                        "AppServerLaunchConfig": {
                          "Type" : "AWS::AutoScaling::LaunchConfiguration",
                          "Metadata": {
                            "AWS::CloudFormation::Init": {
                               "sources" : {
                                  "/var/opt/app" : { "Ref": "AppURL" }
                                }
                              }, ...
                         指定したフォルダにダウンロード、展開してくれる
                            }
                          },
                          "Properties": {
                            "UserData": {
zipball または tarball   のURL "Fn::Base64": {
                                "Fn::Base64": {
                                  "Fn::Join": ["", [
                                    "# Start applicationn",
                                    "cd /var/opt/appn",
                                    "npm config set PORT ", { "Ref": "AppServerPort" }, "n",
                                    "npm install --productionn",
                                    "NODE_ENV=production npm start > app.log 2>&1 &n",


                                npm start で起動できるアプリならなんでもOK
環境変数の取得
/**                                                                  NPM package config
 * Returns a value related by given key.
 * This method search following priority.                            NPM config (global)
 *                                                                      process.env
 * 1. NPM package config
 * 2. NPM config                                                     の順で環境変数を解決する
 * 3. process.env
 *
 * @param {String} key Environment key
 * @param {String} [defaultValue] Default value if key not found.
 * @return {String}
 */
module.exports = function (key, defaultValue) {
  var NPM_PACKAGE_PREFIX = 'npm_package_config_';
  var NPM_PREFIX = 'npm_config_';

  var value = process.env[NPM_PACKAGE_PREFIX + key];
  if (!value) {
    value = process.env[NPM_PREFIX + key];
    if (!value) {
      value = process.env[key];
    }
  }
  value = (!value && defaultValue) ? defaultValue : value;
  return value;
};
環境変数の取得
                                                                                開発時は package.json を参照

                                                                                {
   var http = require('http'),
                                                                                    "name": "harite",
       env = require(‘./env’);
                                                                                    "version": "0.1.0",
                                                                                    "scripts": {
   var server = http.createServer(function (req, res) {
                                                                                      "start": "node app.js",
     res.writeHead(200, { 'Content-Type': 'text/plain' });
                                                                                      "test": "make test"
     res.end('hello');
                                                                                    },
   });
                                                                                    "config": {
   server.listen(env(‘PORT’), function () {
                                                                                      "PORT": 5100,
     console.log('Server is running on port %d', server.address().port);
                                                                                      "REDIS_URL": "redis://localhost"
   });
                                                                                    }
                                                                                }


"npm config set harite:HOST_NAME `curl http://169.254.169.254/latest/meta-data/public-hostname`", "n",
"npm config set harite:PORT ", { "Ref": "HariteServerPort" }, "n",
"npm config set harite:REDIS_URL ", { "Fn::Join" : [ "", [ "redis://", { "Fn::GetAtt" : [ "RedisServer", "PrivateIp" ]}, n",
"npm install --productionn",                                                   AWS ではCloudInit で指定
"NODE_ENV=production npm start > harite.log 2>&1 &n",


                                   参考資料: http://d.hatena.ne.jp/sugyan/20110909/1315575343
                                            http://d.hatena.ne.jp/Jxck/20120410/1334071898
Github の場合
Branch 単位で zipball が取得できる


https://github.com/hakobera/tng6_sample/zipball/master



                リポジトリ                   ブランチ名
アプリのUpdate
Update Stack =>
                                  LoadBalancer から現行バージョン
                                  のサーバを徐々に切り離す

                                  AutoScale の最低サーバ数以下に
                                  なると、新規サーバが起動

                                  新規サーバは新しいアプリが
    zipball または tarball のURLを更新   デプロイされた状態で起動する

                                  (今回のテンプレートはなっていな
                                  いが)タグにアプリケーションの
                                  バージョンを仕込んでおいて、API
                                  経由で判定 => 停止などやれば自動
                                  化できるかも
WebSocket
ELBと相性が悪い
プロトコルでHTTPを選択すると、HTTP1.1 のUpdate
リクエストが通らないので、WebSocket がつながらな
い

プロトコルをTCPを選択すれば接続はできるが、接続先
サーバを固定できない (Socket.IO で苦労する)

60秒で必ずタイムアウトする(設定の変更はできない)


     参考: Socket.IO or WebSocket を AmazonELB でバランスする検証
                    http://d.hatena.ne.jp/Jxck/20120228/1330444857
AutoScaleと相性が悪い

AutoScale は WebSocket がつながっていても縮退し
てしまう

クライアント側での再接続処理が必要

ただし、普通に再接続すると、EC2インスタンス自体が
落ちているので、つながらない
回避策




WebSocket の URL を返す API に ELB 経由でアクセス (HTTPヘッダで返すのでも良い)

  EC2 の Public DNS名は curl http://169.254.169.254/latest/meta-data/public-hostname で取得可能

クライアントは各EC2インスタンスと直接接続する

再接続時には、また ELB 経由で新しい WebSocket サーバのURLを取得

  これを実現するクライアントライブラリ(WebSocketラッパー)を作成する
閑話休題
Pusher クローン作ってます
https://github.com/hakobera/tuppari           来週公開予定
https://github.com/hakobera/tuppari-servers




 CloudFormation のテンプレートも配布
Any Question ?
1 of 30

Recommended

『How to build a High Performance PSGI/Plack Server』のその後と ISUCON3を受けての話題 by
『How to build a High Performance PSGI/Plack Server』のその後と ISUCON3を受けての話題『How to build a High Performance PSGI/Plack Server』のその後と ISUCON3を受けての話題
『How to build a High Performance PSGI/Plack Server』のその後と ISUCON3を受けての話題Masahiro Nagano
8.6K views41 slides
Tottoruby 20110903 by
Tottoruby 20110903Tottoruby 20110903
Tottoruby 20110903Takashi SAKAGUCHI
807 views35 slides
Webサーバ勉強会03 by
Webサーバ勉強会03Webサーバ勉強会03
Webサーバ勉強会03oranie Narut
1.7K views16 slides
Puppetのススメ by
PuppetのススメPuppetのススメ
PuppetのススメGosuke Miyashita
22.8K views102 slides
Development app-with-elixir by
Development app-with-elixirDevelopment app-with-elixir
Development app-with-elixirk1complete
1K views15 slides
Scala on Hadoop by
Scala on HadoopScala on Hadoop
Scala on HadoopShinji Tanaka
2.5K views34 slides

More Related Content

What's hot

Zabbix API by
Zabbix APIZabbix API
Zabbix APIShuhei Hayashibara
2.1K views16 slides
Ansible quickstart by
Ansible quickstartAnsible quickstart
Ansible quickstartHideki Saito
5.4K views26 slides
omoon.org の裏側 〜FuelPHP の task 活用例〜 by
omoon.org の裏側 〜FuelPHP の task 活用例〜omoon.org の裏側 〜FuelPHP の task 活用例〜
omoon.org の裏側 〜FuelPHP の task 活用例〜Sotaro Omura
10K views81 slides
Perl 非同期プログラミング by
Perl 非同期プログラミングPerl 非同期プログラミング
Perl 非同期プログラミングlestrrat
7.3K views99 slides
15分でCakePHPを始める方法(Nseg 2013-11-09 ) by
15分でCakePHPを始める方法(Nseg 2013-11-09 )15分でCakePHPを始める方法(Nseg 2013-11-09 )
15分でCakePHPを始める方法(Nseg 2013-11-09 )hiro345
4.4K views20 slides
ChefとPuppetの比較 by
ChefとPuppetの比較ChefとPuppetの比較
ChefとPuppetの比較Sugawara Genki
29.4K views47 slides

What's hot(20)

Ansible quickstart by Hideki Saito
Ansible quickstartAnsible quickstart
Ansible quickstart
Hideki Saito5.4K views
omoon.org の裏側 〜FuelPHP の task 活用例〜 by Sotaro Omura
omoon.org の裏側 〜FuelPHP の task 活用例〜omoon.org の裏側 〜FuelPHP の task 活用例〜
omoon.org の裏側 〜FuelPHP の task 活用例〜
Sotaro Omura10K views
Perl 非同期プログラミング by lestrrat
Perl 非同期プログラミングPerl 非同期プログラミング
Perl 非同期プログラミング
lestrrat7.3K views
15分でCakePHPを始める方法(Nseg 2013-11-09 ) by hiro345
15分でCakePHPを始める方法(Nseg 2013-11-09 )15分でCakePHPを始める方法(Nseg 2013-11-09 )
15分でCakePHPを始める方法(Nseg 2013-11-09 )
hiro3454.4K views
ChefとPuppetの比較 by Sugawara Genki
ChefとPuppetの比較ChefとPuppetの比較
ChefとPuppetの比較
Sugawara Genki29.4K views
CMSとPerlで遊ぼう by Daiki Ichinose
CMSとPerlで遊ぼうCMSとPerlで遊ぼう
CMSとPerlで遊ぼう
Daiki Ichinose1.9K views
Ansibleで始めるサーバ管理勉強会(2014年10月1日) by CLARA ONLINE, Inc.
Ansibleで始めるサーバ管理勉強会(2014年10月1日)Ansibleで始めるサーバ管理勉強会(2014年10月1日)
Ansibleで始めるサーバ管理勉強会(2014年10月1日)
Docker+CoreOS+GCEで自動スケール分散レイトレ by peryaudo
Docker+CoreOS+GCEで自動スケール分散レイトレDocker+CoreOS+GCEで自動スケール分散レイトレ
Docker+CoreOS+GCEで自動スケール分散レイトレ
peryaudo15.1K views
Norikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LT by Masahiro Nagano
Norikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LTNorikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LT
Norikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LT
Masahiro Nagano38.8K views
Webサーバのチューニング by Yu Komiya
WebサーバのチューニングWebサーバのチューニング
Webサーバのチューニング
Yu Komiya9.6K views
Web技術勉強会23回目 by 龍一 田中
Web技術勉強会23回目Web技術勉強会23回目
Web技術勉強会23回目
龍一 田中776 views
成長を加速する minne の技術基盤戦略 by Hiroshi SHIBATA
成長を加速する minne の技術基盤戦略成長を加速する minne の技術基盤戦略
成長を加速する minne の技術基盤戦略
Hiroshi SHIBATA9.4K views
Ansible 2.0を使って組む kubernetesクラスタ vol.1 by Hidetoshi Hirokawa
Ansible 2.0を使って組む kubernetesクラスタ vol.1Ansible 2.0を使って組む kubernetesクラスタ vol.1
Ansible 2.0を使って組む kubernetesクラスタ vol.1
Hidetoshi Hirokawa11.7K views
AWSとGCPを使用したインフラ環境 by Katsutoshi Nagaoka
AWSとGCPを使用したインフラ環境AWSとGCPを使用したインフラ環境
AWSとGCPを使用したインフラ環境
Katsutoshi Nagaoka17.4K views

Viewers also liked

Exifの画像方向情報 by
Exifの画像方向情報Exifの画像方向情報
Exifの画像方向情報Atsushi Matsuo
2.1K views16 slides
INTER-Mediator 5.0 by
INTER-Mediator 5.0INTER-Mediator 5.0
INTER-Mediator 5.0Atsushi Matsuo
1.9K views25 slides
INTER-Mediator 5.1の新機能 by
INTER-Mediator 5.1の新機能INTER-Mediator 5.1の新機能
INTER-Mediator 5.1の新機能Atsushi Matsuo
1.7K views17 slides
INTER-Mediatorのポータルアクセスモード by
INTER-MediatorのポータルアクセスモードINTER-Mediatorのポータルアクセスモード
INTER-MediatorのポータルアクセスモードAtsushi Matsuo
1.9K views10 slides
IMCakeの現状と今後 by
IMCakeの現状と今後IMCakeの現状と今後
IMCakeの現状と今後Atsushi Matsuo
1.5K views7 slides
INTER-MediatorによるWebアプリケーション開発入門 by
INTER-MediatorによるWebアプリケーション開発入門INTER-MediatorによるWebアプリケーション開発入門
INTER-MediatorによるWebアプリケーション開発入門Atsushi Matsuo
2.7K views22 slides

Viewers also liked(9)

Exifの画像方向情報 by Atsushi Matsuo
Exifの画像方向情報Exifの画像方向情報
Exifの画像方向情報
Atsushi Matsuo2.1K views
INTER-Mediator 5.1の新機能 by Atsushi Matsuo
INTER-Mediator 5.1の新機能INTER-Mediator 5.1の新機能
INTER-Mediator 5.1の新機能
Atsushi Matsuo1.7K views
INTER-Mediatorのポータルアクセスモード by Atsushi Matsuo
INTER-MediatorのポータルアクセスモードINTER-Mediatorのポータルアクセスモード
INTER-Mediatorのポータルアクセスモード
Atsushi Matsuo1.9K views
INTER-MediatorによるWebアプリケーション開発入門 by Atsushi Matsuo
INTER-MediatorによるWebアプリケーション開発入門INTER-MediatorによるWebアプリケーション開発入門
INTER-MediatorによるWebアプリケーション開発入門
Atsushi Matsuo2.7K views
INTER-MediatorによるWebアプリケーション開発入門(2014年版) by Atsushi Matsuo
INTER-MediatorによるWebアプリケーション開発入門(2014年版)INTER-MediatorによるWebアプリケーション開発入門(2014年版)
INTER-MediatorによるWebアプリケーション開発入門(2014年版)
Atsushi Matsuo1.5K views
FileMaker Server 15の新機能と改善点 by Atsushi Matsuo
FileMaker Server 15の新機能と改善点FileMaker Server 15の新機能と改善点
FileMaker Server 15の新機能と改善点
Atsushi Matsuo3K views

Similar to 10分で作る Node.js Auto Scale 環境 with CloudFormation

AWSとAnsibleで実践!プロビジョニング入門‐Lamp+Laravel- by
AWSとAnsibleで実践!プロビジョニング入門‐Lamp+Laravel-AWSとAnsibleで実践!プロビジョニング入門‐Lamp+Laravel-
AWSとAnsibleで実践!プロビジョニング入門‐Lamp+Laravel-靖 小田島
1.5K views26 slides
densan2014-late01 by
densan2014-late01densan2014-late01
densan2014-late01Takenori Nakagawa
537 views32 slides
13016 n分で作るtype scriptでnodejs by
13016 n分で作るtype scriptでnodejs13016 n分で作るtype scriptでnodejs
13016 n分で作るtype scriptでnodejsTakayoshi Tanaka
2.3K views27 slides
BCPに活かせ!一撃 CloudFormation by
BCPに活かせ!一撃 CloudFormationBCPに活かせ!一撃 CloudFormation
BCPに活かせ!一撃 CloudFormation真吾 吉田
2.9K views33 slides
Nginx by
NginxNginx
NginxYoshikazu Torimoto
2.2K views10 slides
OpenStack + Common Lisp by
OpenStack + Common LispOpenStack + Common Lisp
OpenStack + Common Lispirix_jp
4.6K views44 slides

Similar to 10分で作る Node.js Auto Scale 環境 with CloudFormation(20)

AWSとAnsibleで実践!プロビジョニング入門‐Lamp+Laravel- by 靖 小田島
AWSとAnsibleで実践!プロビジョニング入門‐Lamp+Laravel-AWSとAnsibleで実践!プロビジョニング入門‐Lamp+Laravel-
AWSとAnsibleで実践!プロビジョニング入門‐Lamp+Laravel-
靖 小田島1.5K views
13016 n分で作るtype scriptでnodejs by Takayoshi Tanaka
13016 n分で作るtype scriptでnodejs13016 n分で作るtype scriptでnodejs
13016 n分で作るtype scriptでnodejs
Takayoshi Tanaka2.3K views
BCPに活かせ!一撃 CloudFormation by 真吾 吉田
BCPに活かせ!一撃 CloudFormationBCPに活かせ!一撃 CloudFormation
BCPに活かせ!一撃 CloudFormation
真吾 吉田2.9K views
OpenStack + Common Lisp by irix_jp
OpenStack + Common LispOpenStack + Common Lisp
OpenStack + Common Lisp
irix_jp4.6K views
Azure で Serverless 初心者向けタッチ&トライ by Masanobu Sato
Azure で Serverless 初心者向けタッチ&トライAzure で Serverless 初心者向けタッチ&トライ
Azure で Serverless 初心者向けタッチ&トライ
Masanobu Sato2.4K views
自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみた by Yuki Takei
自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみた自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみた
自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみた
Yuki Takei21.3K views
当社のawsへの取組 by Mercari Inc.
当社のawsへの取組当社のawsへの取組
当社のawsへの取組
Mercari Inc.3.3K views
SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for... by Naoya Ito
SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...
SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...
Naoya Ito5.5K views
ネットワークエンジニアのための Puppet / Chef by npsg
ネットワークエンジニアのための Puppet / Chefネットワークエンジニアのための Puppet / Chef
ネットワークエンジニアのための Puppet / Chef
npsg8.1K views
現場的!AWSとオンプレの違い(赤べこバージョン) by 真吾 吉田
現場的!AWSとオンプレの違い(赤べこバージョン)現場的!AWSとオンプレの違い(赤べこバージョン)
現場的!AWSとオンプレの違い(赤べこバージョン)
真吾 吉田2.7K views
恋に落ちるデプロイツール by totty jp
恋に落ちるデプロイツール恋に落ちるデプロイツール
恋に落ちるデプロイツール
totty jp5.1K views
社内勉強会資料(Varnish Module) by Iwana Chan
社内勉強会資料(Varnish Module)社内勉強会資料(Varnish Module)
社内勉強会資料(Varnish Module)
Iwana Chan7K views
EWD 3トレーニング・コース #4 ewd-xpressのインストールと構成 by Kiyoshi Sawada
EWD 3トレーニング・コース #4 ewd-xpressのインストールと構成EWD 3トレーニング・コース #4 ewd-xpressのインストールと構成
EWD 3トレーニング・コース #4 ewd-xpressのインストールと構成
Kiyoshi Sawada236 views

More from Kazuyuki Honda

5分でできる ebfly by
5分でできる ebfly5分でできる ebfly
5分でできる ebflyKazuyuki Honda
6.5K views15 slides
東の方からきました@鹿駆動勉強会 by
東の方からきました@鹿駆動勉強会東の方からきました@鹿駆動勉強会
東の方からきました@鹿駆動勉強会Kazuyuki Honda
959 views9 slides
Run Multi Version of Node.js on Heroku by
Run Multi Version of Node.js on HerokuRun Multi Version of Node.js on Heroku
Run Multi Version of Node.js on HerokuKazuyuki Honda
1.1K views14 slides
Noder が Titanium Mobile で 作ってみた by
Noder が Titanium Mobile で 作ってみた Noder が Titanium Mobile で 作ってみた
Noder が Titanium Mobile で 作ってみた Kazuyuki Honda
4.1K views24 slides
初心者の初心者による初心者のための JavaScript ゲーム開発入門 by
初心者の初心者による初心者のための  JavaScript ゲーム開発入門初心者の初心者による初心者のための  JavaScript ゲーム開発入門
初心者の初心者による初心者のための JavaScript ゲーム開発入門Kazuyuki Honda
2.6K views42 slides
enchant.js source reading by
enchant.js source readingenchant.js source reading
enchant.js source readingKazuyuki Honda
3.2K views25 slides

More from Kazuyuki Honda(7)

東の方からきました@鹿駆動勉強会 by Kazuyuki Honda
東の方からきました@鹿駆動勉強会東の方からきました@鹿駆動勉強会
東の方からきました@鹿駆動勉強会
Kazuyuki Honda959 views
Run Multi Version of Node.js on Heroku by Kazuyuki Honda
Run Multi Version of Node.js on HerokuRun Multi Version of Node.js on Heroku
Run Multi Version of Node.js on Heroku
Kazuyuki Honda1.1K views
Noder が Titanium Mobile で 作ってみた by Kazuyuki Honda
Noder が Titanium Mobile で 作ってみた Noder が Titanium Mobile で 作ってみた
Noder が Titanium Mobile で 作ってみた
Kazuyuki Honda4.1K views
初心者の初心者による初心者のための JavaScript ゲーム開発入門 by Kazuyuki Honda
初心者の初心者による初心者のための  JavaScript ゲーム開発入門初心者の初心者による初心者のための  JavaScript ゲーム開発入門
初心者の初心者による初心者のための JavaScript ゲーム開発入門
Kazuyuki Honda2.6K views
enchant.js source reading by Kazuyuki Honda
enchant.js source readingenchant.js source reading
enchant.js source reading
Kazuyuki Honda3.2K views

Recently uploaded

マネージドPostgreSQLの実現に向けたPostgreSQL機能向上(PostgreSQL Conference Japan 2023 発表資料) by
マネージドPostgreSQLの実現に向けたPostgreSQL機能向上(PostgreSQL Conference Japan 2023 発表資料)マネージドPostgreSQLの実現に向けたPostgreSQL機能向上(PostgreSQL Conference Japan 2023 発表資料)
マネージドPostgreSQLの実現に向けたPostgreSQL機能向上(PostgreSQL Conference Japan 2023 発表資料)NTT DATA Technology & Innovation
217 views33 slides
JJUG CCC.pptx by
JJUG CCC.pptxJJUG CCC.pptx
JJUG CCC.pptxKanta Sasaki
6 views14 slides
概念モデリングワークショップ 基礎編 by
概念モデリングワークショップ 基礎編概念モデリングワークショップ 基礎編
概念モデリングワークショップ 基礎編Knowledge & Experience
19 views71 slides
「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化 by
「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化
「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化Knowledge & Experience
8 views34 slides
概念モデリングワークショップ 設計編 by
概念モデリングワークショップ 設計編概念モデリングワークショップ 設計編
概念モデリングワークショップ 設計編Knowledge & Experience
10 views37 slides
pgvectorを使ってChatGPTとPostgreSQLを連携してみよう!(PostgreSQL Conference Japan 2023 発表資料) by
pgvectorを使ってChatGPTとPostgreSQLを連携してみよう!(PostgreSQL Conference Japan 2023 発表資料)pgvectorを使ってChatGPTとPostgreSQLを連携してみよう!(PostgreSQL Conference Japan 2023 発表資料)
pgvectorを使ってChatGPTとPostgreSQLを連携してみよう!(PostgreSQL Conference Japan 2023 発表資料)NTT DATA Technology & Innovation
185 views63 slides

Recently uploaded(8)

マネージドPostgreSQLの実現に向けたPostgreSQL機能向上(PostgreSQL Conference Japan 2023 発表資料) by NTT DATA Technology & Innovation
マネージドPostgreSQLの実現に向けたPostgreSQL機能向上(PostgreSQL Conference Japan 2023 発表資料)マネージドPostgreSQLの実現に向けたPostgreSQL機能向上(PostgreSQL Conference Japan 2023 発表資料)
マネージドPostgreSQLの実現に向けたPostgreSQL機能向上(PostgreSQL Conference Japan 2023 発表資料)
「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化 by Knowledge & Experience
「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化
「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化
pgvectorを使ってChatGPTとPostgreSQLを連携してみよう!(PostgreSQL Conference Japan 2023 発表資料) by NTT DATA Technology & Innovation
pgvectorを使ってChatGPTとPostgreSQLを連携してみよう!(PostgreSQL Conference Japan 2023 発表資料)pgvectorを使ってChatGPTとPostgreSQLを連携してみよう!(PostgreSQL Conference Japan 2023 発表資料)
pgvectorを使ってChatGPTとPostgreSQLを連携してみよう!(PostgreSQL Conference Japan 2023 発表資料)
さくらのひやおろし2023 by 法林浩之
さくらのひやおろし2023さくらのひやおろし2023
さくらのひやおろし2023
法林浩之83 views
01Booster Studio ご紹介資料 by ssusere7a2172
01Booster Studio ご紹介資料01Booster Studio ご紹介資料
01Booster Studio ご紹介資料
ssusere7a2172220 views

10分で作る Node.js Auto Scale 環境 with CloudFormation

  • 1. Node.js Auto Scaling in 10 minutes with AWS CloudFormation 2012/6/28 東京Node学園 6時限目 @hakobera
  • 3. Node.jsで1億リクエスト/日 1億リクエスト/日 => 417万リクエスト/時 => 7万リクエスト/分 => 1200リクエスト/秒
  • 5. AWS なら簡単 EC2 AMI (VMイメージ)の作成 Node.js 、依存パッケージのインストール セキュリティグループ ポート番号や接続制限 ELB プロトコルとポート番号 Auto Scale CloudWatch の設定 Auto Scale Group ポリシーの設定 アプリケーションのDeployとUpdate
  • 6. AWS なら簡単 EC2 AMI (VMイメージ)の作成 Node.js 、依存パッケージのインストール セキュリティグループ ポート番号や接続制限 ELB じゃなかった orz プロトコルとポート番号 Auto Scale CloudWatch の設定 Auto Scale Group ポリシーの設定 アプリケーションのDeployとUpdate
  • 7. そこで AWS CloudFormation の出番 http://aws.amazon.com/jp/cloudformation/ AWS インフラ構成のテンプレート 設定の一部をパラメータ化できる JSON 形式 (Noder にはお馴染み) DynamoDBとCloudFront の先週からサポート開始 詳細はこちらを参照
  • 8. 自分だけの PaaS が 簡単に作れる
  • 10. Node.js と CloudFormation の勘所 Node.js の AutoScale インストール Elastic Load アプリの Balancer と Deploy と Update WebSocket
  • 12. Node.jsのインストール バイナリパッケージを使おう ∵ micro インスタンスで Node.js のビルドが遅い Installing Node.js via package manager https://github.com/joyent/node/wiki/Installing-Node.js- via-package-manager $ sudo yum localinstall --nogpgcheck http://nodejs.tchol.org/repocfg/amzn1/nodejs-stable-release.noarch.rpm $ sudo yum install nodejs-compat-symlinks npm 残念ながら v0.8 はまだない
  • 13. Node.jsのインストール Cloud Init でパッケージ指定 "AppServerLaunchConfig": { "Type" : "AWS::AutoScaling::LaunchConfiguration", "Metadata": { "AWS::CloudFormation::Init": { "config": { "packages": { "rpm" : { "nodejs" : "http://nodejs.tchol.org/repocfg/amzn1/nodejs-stable-release.noarch.rpm" }, "yum": { "gcc-c++": [], "make": [], "git" : [], "nodejs-compat-symlinks": [], "npm": [] } }, "sources" : { "/var/opt/app" : { "Ref": "AppURL" } } }, ...
  • 14. Node.jsのインストール Cloud Init の起動設定 "Properties": { (省略) "UserData": { "Fn::Base64": { "Fn::Base64": { "Fn::Join": ["", [ "#!/bin/bash -vn", "yum update -y aws-cfn-bootstrapn", "# Helper functionn", "function error_exitn", "{n", " /opt/aws/bin/cfn-signal -e 1 -r "$1" '", { "Ref": "WaitHandle" }, "'n", " exit 1n", "}n", "# Install packagesn", "/opt/aws/bin/cfn-init -s ", { "Ref": "AWS::StackName" }, " -r AppServerLaunchConfig ", " --access-key ", { "Ref": "HostKeys" }, " --secret-key ", { "Fn::GetAtt": ["HostKeys", "SecretAccessKey"] }, " --region ", { "Ref": "AWS::Region" }, " || error_exit 'Failed to run cfn-init'n",
  • 16. Cloud Watch http://aws.amazon.com/jp/cloudwatch/ http://aws.amazon.com/jp/autoscaling/ Auto Scale の条件(拡張・縮小のトリガー)は、 Cloud Watch のアラームで実現している アプリの特性の応じて、チェックする対象を変更 CPUUtilization, DiskReadBytes, DiskReadOps, DiskWriteBytes, DiskWriteOps, NetworkIn, NetworkOut Node.js だと、CPUUtilization か NetworkOut のどちらかで大体OK
  • 17. 設定例: CPUUtilization "AppServerScaleUpPolicy" : { "Type" : "AWS::AutoScaling::ScalingPolicy", "Properties" : { "AdjustmentType" : "ChangeInCapacity", "AutoScalingGroupName" : { "Ref" : "AppServerGroup" }, "Cooldown" : "60", "ScalingAdjustment" : "2" } }, "CPUAlarmHigh": { "Type": "AWS::CloudWatch::Alarm", "Properties": { "AlarmDescription": "Scale-up if CPU > 90% for 10 minutes", "MetricName": "CPUUtilization", "Namespace": "AWS/EC2", "Statistic": "Average", "Period": "300", "EvaluationPeriods": "2", "Threshold": "90", "AlarmActions": [ { "Ref": "AppServerScaleUpPolicy" } ], "Dimensions": [ { "Name": "AutoScalingGroupName", "Value": { "Ref": "AppServerGroup" } } ],
  • 19. アプリのDeploy "AppServerLaunchConfig": { "Type" : "AWS::AutoScaling::LaunchConfiguration", "Metadata": { "AWS::CloudFormation::Init": { "sources" : { "/var/opt/app" : { "Ref": "AppURL" } } }, ... 指定したフォルダにダウンロード、展開してくれる } }, "Properties": { "UserData": { zipball または tarball のURL "Fn::Base64": { "Fn::Base64": { "Fn::Join": ["", [ "# Start applicationn", "cd /var/opt/appn", "npm config set PORT ", { "Ref": "AppServerPort" }, "n", "npm install --productionn", "NODE_ENV=production npm start > app.log 2>&1 &n", npm start で起動できるアプリならなんでもOK
  • 20. 環境変数の取得 /** NPM package config * Returns a value related by given key. * This method search following priority. NPM config (global) * process.env * 1. NPM package config * 2. NPM config の順で環境変数を解決する * 3. process.env * * @param {String} key Environment key * @param {String} [defaultValue] Default value if key not found. * @return {String} */ module.exports = function (key, defaultValue) { var NPM_PACKAGE_PREFIX = 'npm_package_config_'; var NPM_PREFIX = 'npm_config_'; var value = process.env[NPM_PACKAGE_PREFIX + key]; if (!value) { value = process.env[NPM_PREFIX + key]; if (!value) { value = process.env[key]; } } value = (!value && defaultValue) ? defaultValue : value; return value; };
  • 21. 環境変数の取得 開発時は package.json を参照 { var http = require('http'), "name": "harite", env = require(‘./env’); "version": "0.1.0", "scripts": { var server = http.createServer(function (req, res) { "start": "node app.js", res.writeHead(200, { 'Content-Type': 'text/plain' }); "test": "make test" res.end('hello'); }, }); "config": { server.listen(env(‘PORT’), function () { "PORT": 5100, console.log('Server is running on port %d', server.address().port); "REDIS_URL": "redis://localhost" }); } } "npm config set harite:HOST_NAME `curl http://169.254.169.254/latest/meta-data/public-hostname`", "n", "npm config set harite:PORT ", { "Ref": "HariteServerPort" }, "n", "npm config set harite:REDIS_URL ", { "Fn::Join" : [ "", [ "redis://", { "Fn::GetAtt" : [ "RedisServer", "PrivateIp" ]}, n", "npm install --productionn", AWS ではCloudInit で指定 "NODE_ENV=production npm start > harite.log 2>&1 &n", 参考資料: http://d.hatena.ne.jp/sugyan/20110909/1315575343 http://d.hatena.ne.jp/Jxck/20120410/1334071898
  • 22. Github の場合 Branch 単位で zipball が取得できる https://github.com/hakobera/tng6_sample/zipball/master リポジトリ ブランチ名
  • 23. アプリのUpdate Update Stack => LoadBalancer から現行バージョン のサーバを徐々に切り離す AutoScale の最低サーバ数以下に なると、新規サーバが起動 新規サーバは新しいアプリが zipball または tarball のURLを更新 デプロイされた状態で起動する (今回のテンプレートはなっていな いが)タグにアプリケーションの バージョンを仕込んでおいて、API 経由で判定 => 停止などやれば自動 化できるかも
  • 25. ELBと相性が悪い プロトコルでHTTPを選択すると、HTTP1.1 のUpdate リクエストが通らないので、WebSocket がつながらな い プロトコルをTCPを選択すれば接続はできるが、接続先 サーバを固定できない (Socket.IO で苦労する) 60秒で必ずタイムアウトする(設定の変更はできない) 参考: Socket.IO or WebSocket を AmazonELB でバランスする検証 http://d.hatena.ne.jp/Jxck/20120228/1330444857
  • 26. AutoScaleと相性が悪い AutoScale は WebSocket がつながっていても縮退し てしまう クライアント側での再接続処理が必要 ただし、普通に再接続すると、EC2インスタンス自体が 落ちているので、つながらない
  • 27. 回避策 WebSocket の URL を返す API に ELB 経由でアクセス (HTTPヘッダで返すのでも良い) EC2 の Public DNS名は curl http://169.254.169.254/latest/meta-data/public-hostname で取得可能 クライアントは各EC2インスタンスと直接接続する 再接続時には、また ELB 経由で新しい WebSocket サーバのURLを取得 これを実現するクライアントライブラリ(WebSocketラッパー)を作成する
  • 29. Pusher クローン作ってます https://github.com/hakobera/tuppari 来週公開予定 https://github.com/hakobera/tuppari-servers CloudFormation のテンプレートも配布