主要解決問題:
專案原始碼和更多案例放在github上面,歡迎star.
cluster可以多核監聽同一個埠。實現多程序共用埠,這個在node底層已經做好了。
folk(child_process.fork)方式不能實現多程序共用埠,還需要nginx去做多個埠的負載均衡,一般來說用cluster要好點,folk方式適用與多個程式之間。
建立一個cluster.js檔案
var cluster = require('cluster'); //cluster庫
var os = require('os'); // 獲取CPU 的數量
var numCPUs = os.cpus().length;
var process = require('process') // 管理程序用的
console.log('numCPUs:', numCPUs) // 列印cpu數量 ①
var workers = {};
if (cluster.isMaster) { // 這裡是進入主程序,第一次啟動的時候,執行這裡
// 主程序分支
cluster.on('death', function (worker) { ②
// 當一個工作程序結束時,重新啟動工作程序 delete workers[worker.pid]; 這裡主要是為了讓程式碼即使報錯,也不會影響伺服器執行。故障恢復
worker = cluster.fork();
workers[worker.pid] = worker;
});
// 初始開啟與CPU 數量相同的工作程序 多核利用 ③
for (var i = 0; i < numCPUs; i++) {
var worker = cluster.fork(); // 複製程序,有多少個核,複製多少個子程序,複製的過程會重新執行一遍該檔案(因為是複製程序,程式碼也會複製份在子程序執行)。
workers[worker.pid] = worker;
}
} else { // 這裡是子程序開啟的時候,就是主程序folk之後,會走到這裡。所以這裡會啟動與cpu相同數量的子程序服務。
// 子程序啟動伺服器,多程序共用3000埠 ④
var app = require('./app');
app.use(async (ctx, next) => {
console.log('worker' + cluster.worker.id + ',PID:' + process.pid)
next()
})
app.listen(3000);
}
// 當主程序被終止時,關閉所有工作程序
process.on('SIGTERM', function () { ⑤
for (var pid in workers) {
process.kill(pid);
}
process.exit(0);
});
直接看程式碼,這樣看可能看不太懂。我們用一個流程圖來展示。我在上面程式碼標記了①-⑤ ,5個程式碼塊。
這裡看執行情況,啟動後,列印了5次cpu數量(主程序一次,子程序4次),①這段程式碼執行了5次。
然後我們通過存取localhost:3000,得到當前存取的是第三子程序。
命令列部署方法:
npm install -g pm2
pm2 start app.js --watch -i 2 // watch 監聽⽂檔案變化
// -i 啟動多少個範例例
pm2 stop all
pm2 list
pm2 start app.js -i max # 根據機器器CPU核數,開啟對應數⽬目的程序
process.yml檔案部署方法:
apps:
- script : app.js
instances: 2
watch : true
env :
NODE_ENV: production
執行pm2 start process.yml
pm2設定為開機啟動 pm2 startup
可以看到兩種方式的效果是一樣的,但是大多會選擇以yml檔案來啟動。
特點
對⽐傳統虛擬機器器總結
特性 | 容器器 | 虛擬機器器 |
---|---|---|
啟動 | 秒級 | 分鐘級 |
硬碟使⽤ | 一般為 MB | 一般為 GB |
效能 | 接近原⽣ | 弱於 |
系統支援量 | 單機⽀持上千個容器 | 一般⼏十個 |
三個核⼼心概念
和pm2類似,docker也有兩種方式啟動,一種是命令列方式,一種是Dockerfile客製化映象方式。
DockerFile引數 :
FROM | MAINTAINER | RUN | ADD© | WORKDIR | VOLUME | EXPOSE |
---|---|---|---|---|---|---|
它依賴什麼映象 | 維護者資訊 | 執行命令列命令 | 複製檔案到指定路徑(ADD能解壓) | 指定工作目錄 | 目錄掛載 | 容器的埠 |
常用的doker命令:
檢視docker版本:docker version
顯示docker系統的資訊:docker info
檢索image:docker search image_name
下載image : docker pull image_name
已下載映象列表: docker images
刪除映象: docker rmi image_name
啟動容器:docker run image_name
拉取官⽅方映象
docker pull nginx
檢視映象
docker images nginx
啟動映象
docker run -p 80:80 -d nginx
檢視程序
docker ps
docker ps -a // 檢視全部
停⽌
docker stop id
刪除映象
docker rm id
#Dockerfile
FROM nginx:latest
RUN echo '<h1>Hello, docker</h1>' > /usr/share/nginx/html/index.html
# 客製化映象
docker build -t mynginx .
# 運⾏
# -d 守護態運⾏
docker run -p 80:80 -d mynginx
Docker-Compose專案是Docker官方的開源專案,負責實現對Docker容器叢集的快速編排。
Docker-Compose將所管理的容器分為三層,分別是工程(project),服務(service)以及容器(container)。Docker-Compose執行目錄下的所有檔案(docker-compose.yml,extends檔案或環境變數檔案等)組成一個工程,若無特殊指定工程名即為當前目錄名
docker-compose主要是可以集合多個服務,一起執行。比如一個專案有(前端、後臺、資料庫、nginx)4個服務需要去啟動,如果單獨去啟動的話,我們需要執行4次docker。這裡我們能通過docker-compose,一起執行。
案例:nginx+node+pm2後臺
nginx:
在nginx資料夾裡,裡面建立個conf.d資料夾。新增一個docker.conf檔案
## nginx/conf.d/docker.conf
server {
listen 80;
location / {
root /var/www/html;
index index.html index.htm;
}
location ~ \.(gif|jpg|png)$ {
root /static;
index index.html index.htm;
}
location /api {
proxy_pass http://127.0.0.1:3000;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
node:
// app.js
const Koa = require('koa')
const app = new Koa()
app.use(ctx => {
ctx.body = 'Hello Docker'
})
app.listen(3000, () => {
console.log('app started at http://localhost:3000/')
})
// process.yml
apps:
- script : server.js
instances: 2
watch : true
env :
NODE_ENV: production
// Dockerfile
#Dockerfile
#制定node映象的版本
FROM node:10-alpine
#移動當前目錄下面的檔案到app目錄下
ADD . /app/
#進入到app目錄下面,類似cd
WORKDIR /app
#安裝依賴
RUN npm install
#對外暴露的埠
EXPOSE 3000
#程式啟動指令碼
CMD ["pm2-runtime", "start", "process.yml"]
然後構建docker-compose.yml
## docker-compose.yml
version: '3.1'
services:
app-pm2:
container_name: app-pm2
#構建容器
build: ./node
ports:
- "3000:3000"
nginx:
restart: always
image: nginx
ports:
- 80:80
volumes:
- ./nginx/conf.d/:/etc/nginx/conf.d/ #本地組態檔寫入到nginx設定目錄
- ./www/:/var/www/html/
然後建立一個www資料夾裡面放一個靜態html檔案
//index.html
hello web!!
可以看到在docker-compose檔案裡面,我們執行了兩個映象,一個是打包後的node名為app-pm2的映象,一個是nginx的映象。
同時我們把nginx的組態檔從本地寫到了docker執行的nginx目錄裡面。現在我們來看執行效果:
輸入:docker-compose up -d
後臺啟動命令。
可以看到,兩個容器都被建立。現在我們先存取80埠(nginx對映在80埠)。
存取成功,成功存取到www/index.html
然後我們存取/api路徑,看是否能存取到node伺服器。
存取成功。這裡一個docker-compose的案例就成功執行了。裡面用了nginx反向代理3000埠介面到80埠/api路徑,同時用了pm2去啟動node介面伺服器。
專案搭建好之後,就需要持續整合了,這裡具體請參考我之前寫的文章。Gitlab-CI/CD雲端構建釋出