# 部署
## 采用云服務器
比如阿里云,coding其實也可以湊合著用
* server
* db
* slb
* 監控
推薦ubuntu 14.10 LTS
## 登錄遠端服務器
ssh root@ip
## 創建用戶
~~~
# sudo useradd -m -d /home/sang -s /bin/bash -c "the sang user" -U sang
# passwd sang
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
~~~
* useradd創建登錄用戶
* passwd設置用戶登錄密碼
## 賦予sudo權限
如果有必要使用sudu權限,請修改
~~~
# sudo vi /etc/sudoers
~~~
復制root行改為sang即可
~~~
# User privilege specification
root ALL=(ALL:ALL) ALL
sang ALL=(ALL:ALL) ALL
~~~
## 切換用戶
~~~
# su - sang
$ ls
$
$ pwd
/home/sang
$
~~~
## 安裝必備軟件
### 安裝git
如果上面沒有復制給sang賬戶sudo權限,請切換到root賬戶操作
~~~
sudo apt-get update
sudo apt-get install git
~~~
### 安裝nginx
~~~
sudo apt-get install nginx
~~~
開機啟動([http://www.jianshu.com/p/2e03255cfabb)](http://www.jianshu.com/p/2e03255cfabb%EF%BC%89)
~~~
sudo apt-get install sysv-rc-conf
sudo sysv-rc-conf nginx on
~~~
### 準備工作目錄
~~~
mkdir -p workspace/github
cd workspace/github
~~~
## 安裝nodejs
### 安裝nvm
~~~
$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.0/install.sh | bash
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 7766 100 7766 0 0 28614 0 --:--:-- --:--:-- --:--:-- 28656
=> Downloading nvm as script to '/home/sang/.nvm'
=> Appending source string to /home/sang/.bashrc
=> Close and reopen your terminal to start using nvm
$ source ~/.bashrc
$ nvm
Node Version Manager
~~~
安裝nodejs lts版本
~~~
$ nvm install 4
Downloading https://nodejs.org/dist/v4.3.2/node-v4.3.2-linux-x64.tar.xz...
######################################################################## 100.0%
Now using node v4.3.2 (npm v2.14.12)
Creating default alias: default -> 4 (-> v4.3.2)
$ node -v
v4.3.2
~~~
使之成為默認
~~~
$ nvm alias default 4.3
default -> 4.3 (-> v4.3.2)
~~~
### 確認npm版本
~~~
$ npm -v
2.14.12
~~~
只要大于2.9.1即可,如不是,請`npm i -g npm@2.9.1`
### 安裝nrm
~~~
$ npm i -g nrm
npm WARN deprecated npmconf@0.1.16: this package has been reintegrated into npm and is now out of date with respect to npm
/home/sang/.nvm/versions/node/v4.3.2/bin/nrm -> /home/sang/.nvm/versions/node/v4.3.2/lib/node_modules/nrm/cli.js
nrm@0.3.0 /home/sang/.nvm/versions/node/v4.3.2/lib/node_modules/nrm
├── ini@1.3.4
├── only@0.0.2
├── extend@1.3.0
├── async@0.7.0
├── open@0.0.5
├── commander@2.9.0 (graceful-readlink@1.0.1)
├── npmconf@0.1.16 (inherits@2.0.1, osenv@0.0.3, ini@1.1.0, semver@2.3.2, mkdirp@0.3.5, once@1.3.3, nopt@2.2.1, config-chain@1.1.10)
├── node-echo@0.0.6 (jistype@0.0.3, mkdirp@0.3.5, coffee-script@1.7.1)
└── request@2.69.0 (aws-sign2@0.6.0, forever-agent@0.6.1, tunnel-agent@0.4.2, oauth-sign@0.8.1, is-typedarray@1.0.0, caseless@0.11.0, stringstream@0.0.5, isstream@0.1.2, json-stringify-safe@5.0.1, extend@3.0.0, tough-cookie@2.2.1, node-uuid@1.4.7, qs@6.0.2, combined-stream@1.0.5, form-data@1.0.0-rc3, mime-types@2.1.10, aws4@1.3.2, hawk@3.1.3, bl@1.0.3, http-signature@1.1.1, har-validator@2.0.6)
~~~
測速
~~~
$ nrm test
* npm ---- 274ms
cnpm --- 6868ms
taobao - 716ms
edunpm - 5598ms
eu ----- Fetch Error
au ----- Fetch Error
sl ----- 1234ms
nj ----- 2228ms
pt ----- Fetch Error
~~~
切換源
~~~
$ nrm use npm
Registry has been set to: https://registry.npmjs.org/
~~~
## 部署nodejs應用
### 基礎
* git clone
* npm i
* pm2 start
### 修改nginx
~~~
cat /etc/nginx/sites-enabled/default
upstream backend_nodejs {
server 127.0.0.1:3019 max_fails=0 fail_timeout=10s;
#server 127.0.0.1:3001;
keepalive 512;
}
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
#root /usr/share/nginx/html;
root /home/sang/workspace/oschina/base2-wechat-jssdk/public;
index index.html index.htm;
# Make site accessible from http://localhost/
server_name nodeonly.mengxiaoban.cn at35.com;
client_max_body_size 16M;
keepalive_timeout 10;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
#try_files $uri $uri/ =404;
# Uncomment to enable naxsi on this location
# include /etc/nginx/naxsi.rules
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_pass http://backend_nodejs;
}
}
~~~
注意
* upstream backend_nodejs定義的代理轉發的api地址
* location /下面的proxy_pass,從upstream里取
* root下面放的是靜態資源,比如express下的public目錄
然后重啟nginx即可
~~~
sudo nginx -s reload
~~~
## 阿里云服務器掛載數據硬盤
購買普通阿里云服務器的時候,本機默認自帶的系統盤大小為20G,但是這樣的大小是不滿足部署產品服務器的需求, 所以可以購買阿里云數據盤,一半大小為200G
* 首先使用root用戶查看系統版本,本文是在centos中部署使用
在終端中使用下面命令查看系統版本
~~~
$ lsb_release -a
LSB Version: :core-4.1-amd64:core-4.1-noarch
Distributor ID: CentOS
Description: CentOS Linux release 7.2.1511 (Core)
Release: 7.2.1511
Codename: Core
~~~
確定系統版本之后在終端中確認系統盤情況(注:使用root用戶):
~~~
$ fdisk -l
Disk /dev/xvda: 21.5 GB, 21474836480 bytes, 41943040 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x0009e68a
Device Boot Start End Blocks Id System
/dev/xvda1 * 2048 41943039 20970496 83 Linux
Disk /dev/xvdb: 214.7 GB, 214748364800 bytes, 419430400 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0xd0c73cf7
Device Boot Start End Blocks Id System
/dev/xvdb1 2048 419430399 209714176 83 Linux
~~~
首先確認在阿里云中購買了數據盤,上面的Disk /dev/xvda是自帶的系統盤,/dev/xvda1表示已經掛載并且在使用中,Disk /dev/xvdb是數據盤, 上面的情況是已經掛載好的,如果沒有掛載情況,只顯示Disk /dev/xvdb: 214.7 GB, 214748364800 bytes, 419430400 sectors,表示未被 使用
* 將未被分區掛載的數據盤進行分區掛載
~~~
$ fdisk /dev/xvdb
~~~
根據提示,輸入"n","p","1",兩次回車,"wq",分區開始,很快就會結束
* 查看新的分區:
~~~
$ fdisk -l
~~~
此時應該顯示/dev/xvdb已被分區, like this:
~~~
Device Boot Start End Blocks Id System
/dev/xvdb1 2048 419430399 209714176 83 Linux
~~~
* 格式化新的分區
以ext3為例:使用“mkfs.ext3 /dev/xvdb1”命令對新分區進行格式化,格式化的時間根據硬盤大小有所不同。 (也可自主決定選用其它文件格式,如ext4等)
~~~
$ mkfs.ext3 /dev/xvdb1
~~~
需要等一段時間等待格式化完畢
* 添加新的分區信息
~~~
$ echo '/dev/xvdb1 /mnt ext3 defaults 0 0' >> /etc/fstab
~~~
* 查看分區
~~~
$ cat /etc/fstab
~~~
出現/dev/xvdb1 /mnt ext3 defaults 0 0 說明成功
* 掛載新的分區
~~~
$ mount -a
~~~
* 查看分區的情況
~~~
$ df -h
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/xvda1 20510332 2031552 17413872 11% /
devtmpfs 934320 0 934320 0% /dev
tmpfs 942004 0 942004 0% /dev/shm
tmpfs 942004 98724 843280 11% /run
tmpfs 942004 0 942004 0% /sys/fs/cgroup
/dev/xvdb1 206292664 1065720 194724852 1% /mnt
~~~
/dev/xvdb1已經成功啟用,掛載成功
## pm2
[https://github.com/Unitech/pm2](https://github.com/Unitech/pm2)
~~~
$ npm install pm2 -g # Install PM2
$ pm2 start app.js # Start, Daemonize and auto restart application
$ pm2 start app.js -i 4 # Start 4 instances of application in cluster mode
# it will load balance network queries to each app
$ pm2 start app.js --name="api" # Start application and name it "api"
$ pm2 start app.js --watch # Restart application on file change
$ pm2 start script.sh # Start bash script
$ pm2 list # List all processes started with PM2
$ pm2 monit # Display memory and cpu usage of each app
$ pm2 show [app-name] # Show all informations about application
$ pm2 logs # Display logs of all apps
$ pm2 logs [app-name] # Display logs for a specific app
$ pm2 flush
$ pm2 stop all # Stop all apps
$ pm2 stop 0 # Stop process with id 0
$ pm2 restart all # Restart all apps
$ pm2 reload all # Reload all apps in cluster mode
$ pm2 gracefulReload all # Graceful reload all apps in cluster mode
$ pm2 delete all # Kill and delete all apps
$ pm2 delete 0 # Delete app with id 0
$ pm2 scale api 10 # Scale app with name api to 10 instances
$ pm2 reset [app-name] # Reset number of restart for [app-name]
$ pm2 startup # Generate a startup script to respawn PM2 on boot
$ pm2 save # Save current process list
$ pm2 resurrect # Restore previously save processes
$ pm2 update # Save processes, kill PM2 and restore processes
$ pm2 generate # Generate a sample json configuration file
$ pm2 deploy app.json prod setup # Setup "prod" remote server
$ pm2 deploy app.json prod # Update "prod" remote server
$ pm2 deploy app.json prod revert 2 # Revert "prod" remove server by 2
$ pm2 module:generate [name] # Generate sample module with name [name]
$ pm2 install pm2-logrotate # Install module (here a log rotation system)
$ pm2 uninstall pm2-logrotate # Uninstall module
$ pm2 publish # Increment version, git push and npm publish
~~~
pm2 是一個帶有負載均衡功能的Node應用的進程管理器. 當你要把你的獨立代碼利用全部的服務器上的所有CPU,并保證進程永遠都活著,0秒的重載, PM2是完美的。 可以感受一下[官方的部署文檔示例](http://pm2.keymetrics.io/docs/usage/deployment/),?[github項目地址](https://github.com/Unitech/pm2)。
主要的特點:
* 內建負載均衡(使用Node cluster 集群模塊)
* 后臺運行
* 0秒停機重載,我理解大概意思是維護升級的時候不需要停機.
* 具有Ubuntu和CentOS 的啟動腳本
* 停止不穩定的進程(避免無限循環)
* 控制臺檢測
* 提供 HTTP API
* 遠程控制和實時的接口API ( Nodejs 模塊,允許和PM2進程管理器交互 )
## pm2部署簡單應用
### 安裝pm2
~~~
npm install -g pm2
~~~
### 使用pm2部署簡單的項目
~~~
$ pm2 start app.js --name "heheda" -i 0 --watch
~~~
* pm2 start app.js : 使用pm2啟動app.js
* -i 0 : 使用最大進程數啟動
* --name : 指定一個你喜歡的名字
* --watch : 開啟監視模式,如果代碼有變動pm2自動重啟
### 查看pm2部署
~~~
pm2 ls
~~~
## pm2自動部署遠程服務器
目前我們部署服務器的方式是使用oschina托管項目,然后在服務器中安裝git將項目克隆到服務器中,然后 使用pm2部署項目,如果項目有任何的修改,就會需要跑到幾個服務器中pull代碼,然后pm2 reload項目, 蛋疼的要死。 現在就使用pm2的遠程部署方式,解決這個蛋疼的問題!
### 準備工作
#### 將本地機器和線上服務器建立ssh信任,免密碼登陸
* 生成git ssh公鑰(本地機器和服務器操作一樣)
~~~
$ git config --global user.name "heheda"
$ git config --global user.email "heheda@mail.com"
$ ssh-keygen -t rsa -C "heheda@mail.com"
~~~
連續三次回車,這樣生成的ssh公鑰添加到github
* 查看生成的ssh公鑰
~~~
$ ls ~/.ssh/
authorized_keys id_rsa id_rsa.pub known_hosts
~~~
理論上已經生成ssh公鑰,在用戶主目錄下的.ssh中生成的id_rsa.pub就是生成的公鑰 authorized_keys文件是通過授權的ssh公鑰,在使用ssh協議進行遠程訪問的時候,如果該機器的ssh公鑰在 這個文件中,那么能直接進行訪問
* 將ssh公鑰拷貝到服務器
~~~
$ scp ~/.ssh/id_rsa.pub username@ip:用戶主目錄/.ssh/authorized_keys
~~~
執行這個命令是將本地的id_rsa.pub拷貝到服務器的.ssh/目錄下并命名為authorized_keys 這樣就能不需要密碼訪問遠程服務器了 上一步已經將服務器的ssh公鑰添加到 github 中了,這樣服務器中clone項目也不需要密碼
### pm2配置文件ecosystem.json
* [官方的部署文檔示例](http://pm2.keymetrics.io/docs/usage/deployment/)
~~~
{
/**
* Deployment section
* http://pm2.keymetrics.io/docs/usage/deployment/
*/
"deploy" : {
"yourprojectname" : {
"user" : "node",
"host" : ["ip"],
"ref" : "origin/master",
"repo" : "git.oschina.net",
"path" : "/your/deploy/folder/",
"post-deploy" : "npm install ; pm2 start bin/www --name 'hz-frontend' --watch",
"env" : {
"NODE_ENV": "dev"
}
}
}
}
~~~
* user : 你登陸到遠程主機的用戶名
* host : 服務器的ip地址
* ref : 部署的分支
* repo : github或oschina中托管的地址
* path : 部署到服務器的目錄
* post-deploy : 部署時的命令
### 執行部署
* 首次在服務器中部署(服務器中沒有需要部署的項目,需要將代碼克隆到服務器)
~~~
pm2 deploy ecosystem.json yourprojectname setup
~~~
上面命令是將項目從github或oschina中克隆到指定path中,需要注意一下的是,pm2 將目錄結構分為 :
|current | shared |source |
* 克隆好之后執行安裝和啟動
~~~
pm2 deploy ecosystem.json yourprojectname
~~~
官方推薦在部署的項目中也使用ecosystem.json進行啟動項目 :
~~~
{
"apps" : [{
// Application #1
"name" : "hz-mq",
"script" : "index.js",
"args" : "--toto=heya coco -d 1",
"watch" : true,
"node_args" : "--harmony",
"merge_logs" : true,
"cwd" : "/Users/zxy/work/hz-mq",
"env": {
"NODE_ENV": "development",
"AWESOME_SERVICE_API_TOKEN": "xxx"
},
"env_production" : {
"NODE_ENV": "production"
},
"env_staging" : {
"NODE_ENV" : "staging",
"TEST" : true
},
"exec_mode" : "cluster_mode"
}]
}
~~~
這個相對來說就簡單了,就不一一說。 沒有使用的原因是放在項目中在本地和服務器中使用需要來回修改啟動目錄。
- 前言
- 1 skill
- 1.1 Coding WebIDE
- 1.2 git
- 1.3 extra practice
- 1.4 預習
- 2 nodejs入門
- 2.1 入門
- 2.2 安裝
- 2.3 helloworld
- 2.4 commonJS規范
- 2.5 模塊導出
- 2.6 Nodejs代碼調試
- 2.7 編寫Nodejs模塊
- 2.8 最小化問題
- 2.9 隨堂練習
- 3 異步流程控制
- 3.1 什么時候會用到異步流程控制
- 3.2 簡單做法async模塊
- 3.3 Promise/a+規范
- 3.4 Node.js Promise/a+實現
- 3.5 生成器Generators/yield
- 3.6 Async函數/Await
- 3.7 神奇的co
- 3.8 5種 yieldable
- 3.9 學習重點
- 3.10 隨堂練習
- 4 express和微信開發入門
- 4.1 入門
- 4.2 connect
- 4.3 靜態Http服務器
- 4.4 那些預處理器
- 4.5 路由
- 4.6 視圖與模塊引擎
- 4.7 中間件
- 4.8 更多實踐
- 4.9 微信入門
- 4.10 隨堂練習:完成登錄、注冊功能
- 5 微信實例與H5實踐
- 5.1 微信基礎和sandbox
- 5.2 公眾號菜單和自動回復
- 5.3 微信OAuth用戶授權
- 5.4 微信分享
- 5.5 wechat-api
- 5.6 H5-上篇
- 5.7 H5-下篇
- 5.8 隨堂練習
- 6 weui實戰
- 6.1 使用bower
- 6.2 移動端抽象
- 6.3 優化滑動列表
- 6.4 weui
- 6.5 讓weui和iscroll結婚
- 6.6 優化事件
- 6.7 how-to-write-h5
- 6.8 優化無止境
- 6.9 隨堂練習
- 7 微信支付
- 7.1 吹個牛
- 7.2 支付概述
- 7.3 科普幾個概念
- 7.4 準備
- 7.5 調試
- 7.6 公眾號支付(JSAPI)
- 7.7 對賬單
- 7.8 數據處理
- 7.9 隨堂練習
- 8 項目實戰《付費課程系統MVP》
- 8.1 需求分析
- 8.2 ui/ue
- 8.3 技術棧
- 8.4 模型
- 8.5 靜態api
- 8.6 開發
- 8.7 部署
- 8.8 監控
- 8.9 數據統計
- 8.10 demo
- 9 高級篇
- 9.1 前后端分離實踐?
- 9.2 如何展望未來的大前端
- 9.3 容器和微服務
- 10 答疑問題收集