开发一个服务和全面部署还是有很大差距的。主要体现在三个方面。
本文案例取自在笔者腾讯云服务器上的实践。上线部署在大公司里其实是专人操作的,一个产品从构思到发布,许许多多的坑要踩。
对于前端(伪全栈)来说,想要流畅的上手部署。命令行知识还是基础。其次是及时收藏不会的知识点。第三是多在服务器上玩玩,只要胆大心细,玩不坏的。
本地的话可以用cp(copy)命令。但是上传怎么办?
# 上传文件
scp docker-compose.yml 用户名@ip地址:/root/sourse/
# 上传文件夹
scp -r 文件 root@ip地址:文件夹目录
实际工作中,我有可能从git上拉取代码。那就给服务器装一个git吧。
腾讯云centos 7安装git:https://cloud.tencent.com/developer/article/1404128
推荐从git拉取。
下载
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.4.9.tgz
解压
tar -xvzf mongodb-linux-x86_64-3.4.9.tgz
重命名
mv mongodb-linux-x86_64-3.4.9 mongodb
配置命令到全局
vi /etc/profile
# 增加 注意,这里的路径是你安装的路径
export PATH=$PATH:/mongodb/bin
# 重载
source /etc/profile
在mongodb下创建文件夹:
mkdir /data/db
mkdir log
启动mongod
mongod --dbpath=/mongodb/data/db --fork --logpath=/mongodb/data/logs
启动成功。
腾讯云
在robot3T中
线程和进程的关系:
https://www.liaoxuefeng.com/wiki/1016959663602400/1017627212385376
众所周知,一个蹩脚后端写的程序,bug贼多。时不时奔溃是常见的事情。
先写一个会报错的程序,它有十分之一的几率执行一个不存在的方法 aaa
,也就是有10%的几率报错:
// app.js
const Koa=require('Koa')
const app =new Koa();
app.use(async (ctx,next)=>{
Math.random()>0.9?aaa():2
await next();
ctx.response.type='text/html';
ctx.response.body='<h1>hello</h1>';
})
if(!module.parent){
app.listen(3000,()=>{
console.log('服务已启动');
})
}else{
module.exports=app;
}
很简单是不。因为这不是主要的。
在根目录下新建一个 cluster.js
const cluster=require('cluster');
const os=require('os');
const process=require('process');
const numCpus=os.cpus().length;
console.log(`服务器cpu核心数`,numCpus)
let workers={}
if(cluster.isMaster){
// 主进程分支
// 当被进程杀死时,自动重启该核心进程
cluster.on('death',function(worker){
worker=cluster.fork();
workers[worker.pid]=worker;
})
// 复制多个进程
for(let i=0;i<numCpus;i++){
let worker=cluster.fork();
workers[worker.pid]=worker;
}
}else{
// 工作进程
const app =require('./app');
// 注册一个测试中间件
app.use(async (ctx,next)=>{
console.log('worker'+cluster.worker.id)+',PID:'+process.pid;
next();
});
app.listen(3000);
}
// 杀死进程时(ctrl+c)
process.on('SIGTERM',function(){
for(let pid in workers){
process.kill(pid)
}
process.exit(0);
})
require('./test')
然后再写一个定时器,定时发http请求
// 根目录下test.js
const http=require('http');
setInterval(async ()=>{
await http.get('http://localhost:3000');
},500);
运行 node cluster.js
就可以看到先是主进程。然后生成了多个4个进程(4核心)。
cluster是一个node原生模块,它允许多个进程共享一个3000端口而不冲突。当一个故障发生时,其它进程也会把这个死掉的进程重启。因此看上去是个"永不崩溃"的守护服务。
fork模式是通过子进程来守护的。
// fork.js
const child_process=require('child_process');
require('./test.js');
const fork=[];
// 开启2个子进程
for(let i=0;i<2;i++){
let worker_process=child_process.fork('app.js',[3000+i]);
worker_process.on('close',function(code){
console.log('子进程已退出,退出码'+code);
});
fork.push(worker_process);
}
process.on('SIGTERM',function(){
fork.forEach(()=>{
worker_process.kill();
});
process.exit(0)
});
显然缺点是需要启动多个端口。无法共享。
pm2在这里不是什么环境指标。而是一个软件。
pm2常用命令:
# 安装
sudo npm i pm2 -g
# --watch:坚挺文件变化
# 2表示启动多少实例
pm2 start app.js --watch i 2
# 根据机器cpu核心数最大限度利用资源
pm2 start app.js -i max
# 查看运行的进程
pm2 list
# 关闭
pm2 stop xxx
pm2 stop all
完全可以在项目中建一个process.yml配置文件。
apps:
- script : app.js
intance : 2
watch : true
env :
NODE_ENV : production
然后 pm2 start process.yml
### Nginx配置
我有一个前端文件,想要分离部署。怎么办?
nginx的主配置文件在 /etc/nginx/nginx.conf
。其中有这么两行可以配置一下:
# Virtual Host Configs
include /etc/nginx/conf.d/*.config;
include /etc/nginx/sites-enabled/*;
实际上我们不会去动主配置文件。不妨在 /etc/nginx/sites-enabled
新建一个test.conf
server {
listen 80;
server_name test.djtao.com;
location / {
root /root/applications/test;
index index.html index.htm;
}
}
配置完成后,就可以重启和重载nginx了。
# 验证 Nginx 配置
nginx -t
# 重新启动 Nginx
service nginx restart
nginx -s reload
正常情况应该是这样:
如果出现如下报错:
Job for nginx.service failed because the control process exited with error code. See “systemctl status nginx.service” and “journalctl -xe” for details
尝试:
1.systemctl status nginx
2.netstat -tnlp
3.ps -ef | grep nginx
4.pkill -9 被占用的端口号(如23890)
所谓反向代理,是跨域问题的究极解决方案。
前端需要调用后端接口。假设这个是跨域的(不同端口,不同二级域名,比如说3000)
server {
listen 80;
server_name test.djtao.net;
location / {
root /applications/test;
index index.html index.htm;
}
location /api {
proxy_pass http://127.0.0.1:3000;
proxy_redirect off;
proxy_set_header Host
proxy_set_header X-Real-IP
proxy_set_header X-Forwarded-For
$host;
$remote_addr;
$proxy_add_x_forwarded_for;
}
}
这样我们在3000端口的后端就代理到test.djtao.net下了。
众所周知,nginx不配置。history路由刷新后会报404。加上这么一句:
location / {
root /applications/TaoDoc/fe/dist;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}