Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

服务器小白的我,是如何将 node+mongodb 项目部署在服务器上并进行性能优化的 #18

Open
biaochenxuying opened this issue Nov 25, 2018 · 0 comments
Assignees
Labels
JavaScript JavaScript 相关知识点 MongoDB MongoDB node.js node.js

Comments

@biaochenxuying
Copy link
Owner

biaochenxuying commented Nov 25, 2018

BiaoChenXuYing

前言

本文讲解的是:做为前端开发人员,对服务器的了解还是小白的我,是如何一步步将 node+mongodb 项目部署在阿里云 centos 7.3 的服务器上,并进行性能优化,达到页面 1 秒内看到 loading ,3 秒内看到首屏内容的。

搭建的项目是采用了主流的前后端分离思想的,这里只讲 服务器环境搭建与性能优化。

效果请看 http://biaochenxuying.cn/main.html

1. 流程

  • 开发好前端与后端程序。
  • 购买服务器与域名
  • 服务器上安装所需环境(本项目是 node 和 mongodb )
  • 服务器上开放端口与设置规则
  • 用 nginx、apache 或者tomcat 来提供HTTP服务或者设置代理
  • 上传项目代码 或者 用码云或者 gihub 来拉取你的代码到服务器上
  • 启动 express 服务器
  • 优化页面加载

2. 内容细节

2.1 开发好前端与后端程序

开发好前端与后端程序,这个没什么好说的,就是开发!开发!开发!再开发!

2.2 购买服务器与域名

本人一直觉得程序员应该有一个自己的个人网站,拥有自己的域名与服务器。学知识或者测试项目的时候可以用来测试。

阿里云有个专供学生的云翼计划 阿里云学生套餐,入门级的云服务器原价1400多,学生认证后只要114一年,非常划算。

还是学生的,直接购买;不是学生了,有弟弟、妹妹的,可以用他们的大学生身份,购买,非常便宜实用(我购买的就是学生优惠套餐)。当然阿里云服务器在每年双 11 时都有很大优惠,也很便宜,选什么配置与价格得看自己的用处。

服务器预装环境可以选择 CentOS 或者 windows server,,为了体验和学习 linux 系统,我选择了CentOS。

学生优惠套餐

再次是购买域名 阿里域名购买,本人也是在阿里云购买的。域名是分 国际域名与国内域名的,国际域名是不用备案的,但是国内的域名是必须 ICP备案的 阿里云ICP代备案管理系统,不然不能用,如果是国内域名,如何备案域名,请自己上网查找教程。

域名

当然如果你的网站只用来自己用的话,可以不用买域名,因为可以通过服务器的公网 ip 来访问网站内容的。

如果购买了域名了,还要设置域名映射到相应的公网 ip ,不然也不能用。

域名解析

3. 服务器上安装所需环境(本项目是 node 和 mongodb )

3.1 登录服务器

因本人用的是 MacBook Pro ,所以直接打开 mac 终端,通过下面的命令行连接到服务器。root 是阿里云服务器默认的账号名,连接时候会叫你输入密码,输入你购买时设置的或者后来设置的密码。

ssh root@47.106.20.666   //你的服务器公网 ip,比如 47.106.20.666

如图:

登录成功效果

window 系统的,请用 Putty 或 Xshell 来登录,可以参考一下这篇文章 把 Node.js 项目部署到阿里云服务器(CentOs)

一般在新服务器创建后,建议先升级一下 CentOS:

yum -y update

常用的 Linux 命令

cd 进入目录
cd .. 返回上一个目录
ls -a 查看当前目录
mkdir abc 创建abc文件夹
mv 移动或重命名
rm 删除一个文件或者目录

3.2 安装 node

升级常用库文件, 安装 node.js 需要通过 g++ 进行编译。

yum -y install gcc gcc-c++ autoconf

跳转到目录:/usr/local/src,这个文件夹通常用来存放软件源代码:

cd /usr/local/src

下载 node.js 源码,也可以使用 scp 命令直接上传,因为下载实在太慢了:
下载地址:Downloads,请下载最新的相应版本的源码进行下载,本人下载了 v10.13.0 版本的。

下载 node.js 源码

https://nodejs.org/dist/v10.13.0/node-v10.13.0.tar.gz

下载完成后解压:

tar -xzvf node-v10.13.0.tar.gz

进入解压后的文件夹:

cd node-v10.13.0

执行配置脚本来进行预编译处理:

./configure

编译源代码,这个步骤花的时间会很长,大概需要 5 到 10 分钟:

make

编译完成后,执行安装命令,使之在系统范围内可用:

make install

安装 express 推荐 global 安装

npm -g install express

建立超级链接, 不然 sudo node 时会报 "command not found"

sudo ln -s /usr/local/bin/node /usr/bin/node
sudo ln -s /usr/local/lib/node /usr/lib/node
sudo ln -s /usr/local/bin/npm /usr/bin/npm
sudo ln -s /usr/local/bin/node-waf /usr/bin/node-waf

通过指令查看 node 及 npm 版本:

node -v
npm -v

node.js 到这里就基本安装完成了。

3.2 安装 mongodb

下载地址:mongodb
下载时,请选对相应的环境与版本,因为本人的服务器是 CentOS ,其实本质就是 linux 系统,所以选择了如下图环境与目前最新的版本。

mongodb

mongodb :

软件安装位置:/usr/local/mongodb
数据存放位置:/home/mongodb/data
数据备份位置:/home/mongodb/bak
日志存放位置:/home/mongodb/logs

下载安装包

> cd /usr/local
> wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.4.tgz

解压安装包,重命名文件夹为 mongodb

tar zxvf mongodb-linux-x86_64-4.0.4.tgz
mv mongodb-linux-x86_64-4.0.4 mongodb

在 var 文件夹里建立 mongodb 文件夹,并分别建立文件夹 data 用于存放数据,logs 用于存放日志

mkdir /var/mongodb
mkdir /var/mongodb/data
mkdir /var/mongodb/logs

打开 rc.local 文件,添加 CentOS 开机启动项:

vim /etc/rc.d/rc.local
// 不懂 vim 操作的请自行查看相应的文档教程,比如: vim 模式下,要 按了 i 才能插入内容,输入完之后,要按 shift 加 :wq 才能保存退出。

将 mongodb 启动命令追加到本文件中,让 mongodb 开机自启动:

/usr/local/mongodb/bin/mongod --dbpath=/var/mongodb/data --logpath /var/mongodb/logs/log.log -fork

启动 mongodb

/usr/local/mongodb/bin/mongod --dbpath=/var/mongodb/data --logpath /var/mongodb/logs/log.log -fork

看到如下信息说明已经安装完成并成功启动:

forked process: 18394
all output going to: /var/mongodb/logs/log.log

mongodb 默认的端口号是 27017。

如果你数据库的连接要账号和密码的,要创建数据库管理员,不然直接连接即可。
在 mongo shell 中创建管理员及数据库。

切换到 admin 数据库,创建超级管理员帐号

use admin
db.createUser({ user: "用户名", pwd:"登陆密码", roles:[{ role: "userAdminAnyDatabase", db: "admin" }] })

切换到要使用的数据库,如 taodb 数据库,创建这个数据库的管理员帐号

use taodb
db.createUser({ user: "用户名", pwd:"登陆密码", roles:[ { role: "readWrite", db: "taodb" }] //读写权限 })

重复按两下 control+c ,退出 mongo shell。
到这里 mongodb 基本已经安装设置完成了。

备份与恢复 请看这篇文章:MongoDB 备份(mongodump)与恢复(mongorestore)
安装 node 与 mongodb 也可以参考这篇文章:CentOs搭建NodeJs服务器—Mongodb安装

3.3 服务器上开放端口与设置安全组规则

如果你只放静态的网页,可以参考这个篇文章 通过云虚拟主机控制台设置默认首页

但是我们是要部署后台程序的,所以要看以下的内容:

安全组规则是什么鬼

授权安全组规则可以允许或者禁止与安全组相关联的 ECS 实例的公网和内网的入方向和出方向的访问。 
阿里云安全组应用案例文档

80 端口是为 HTTP(HyperText Transport Protocol) 即超文本传输协议开放的,浏览器 HTTP 访问 IP 或域名的 80 端口时,可以省略 80 端口号

如果我们没有开放相应的端口,

比如我们的服务要用到 3000 ,就要开放 3000 的端口,不然是访问不了的;其他端口同理。

配置安全组规则 1

配置安全组规则 2

配置安全组规则 3

端口都配置对了,以为能用公网 IP 进行访问了么 ? 小兄弟你太天真了 ...
 太天真了

还有 防火墙 这一关呢,如果防火墙没有关闭或者相关的端口没有开放,也是不能用公网 IP 进行访问网站内容的。

和安全组端口同理,比如我们的服务要用到的是 3000 端口,就要开放 3000 的端口,不然是访问不了的;其他端口同理。

出于安全考虑还是把防火墙开上,只开放相应的端口最好。

怎么开放相应的端口 ? 看下面两篇文章足矣,这里就不展开了。

1. 将nodejs项目部署到阿里云ESC服务器,linux系统配置80端口,实现公网IP访问

2. centos出现“FirewallD is not running”怎么办

3.4 用 nginx、apache 或者 tomcat 来提供 HTTP 服务或者设置代理

我是用了 nginx 的,所以这里只介绍 nginx 。
安装 nginx 请看这两篇文章:

1. Centos7安装Nginx实战

2. 阿里云Centos7安装Nginx服务器实现反向代理

开启 ngnx 代理

  • 进入到目录位置
cd /usr/local/nginx
  • 在 nginx 目录下有一个 sbin 目录,sbin 目录下有一个 nginx 可执行程序。
./nginx
  • 关闭 nginx
./nginx -s stop
  • 重启
./nginx -s reload

基本的使用就是这样子了。

如下给出我的 nginx 代理的设置:

我的两个项目是放在 /home/blog/blog-react/build/; 和 /home/blog/blog-react-admin/dist/; 下的,如果你们的路径不是这个,请修改成你们的路径。

#user  nobody;
worker_processes  1;
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
#pid        logs/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    # 如果port_in_redirect为off时,那么始终按照默认的80端口;如果该指令打开,那么将会返回当前正在监听的端口。
    port_in_redirect off;

    # 前台展示打开的服务代理
    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;
        #root /home/blog;

        location  / {
            root   /home/blog/blog-react/build/;
            index  index.html;
            try_files $uri $uri/ @router;
            autoindex on;
        }

        location @router{
            rewrite ^.*$ /index.html last;
        }

        location /api/ {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_pass http://47.106.136.114:3000/ ;
        }
        gzip on;

        gzip_buffers 32 4k;

        gzip_comp_level 6;

        gzip_min_length 200;

        gzip_types text/css text/xml application/javascript;

        gzip_vary on;

        #error_page  404              /404.html;
        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }


    # HTTPS server
    # 管理后台打开的服务代理
    server {
        listen       4444;
        server_name  localhost;
        #   charset koi8-r;
        #   ssl_certificate      cert.pem;
        #   ssl_certificate_key  cert.key;

        #   ssl_session_cache    shared:SSL:1m;
        #    ssl_session_timeout  5m;

        #    ssl_ciphers  HIGH:!aNULL:!MD5;
        #    ssl_prefer_server_ciphers  on;

        location / {
            root   /home/blog/blog-react-admin/dist/;
            index  index.html index.htm;
            try_files $uri $uri/ @router;
            autoindex on;
        }
        location @router{
            rewrite ^.*$ /index.html last;
        }

        location /api/ {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_pass http://47.106.136.114:3000/ ;
        }
        gzip on;

        gzip_buffers 32 4k;

        gzip_comp_level 6;

        gzip_min_length 200;

        gzip_types text/css text/xml application/javascript;

        gzip_vary on;

        error_page   500 502 503 504  /50x.html;
    }
}

我是开了两个代理的:前台展示打开的服务代理和管理后台打开的服务代理,这个项目是分开端口访问的。
比如:我的公网 ip 是 47.106.20.666,那么可以通过 http://47.106.20.666 即可访问前台展示,http://47.106.20.666:4444 即可访问管理后台的登录界面。

至于为什么要写这样的配置:

try_files $uri $uri/ @router;

location @router{
        rewrite ^.*$ /index.html last;
    }

因为进入到文章详情时或者前端路由变化了,再刷新浏览器,发现浏览器出现 404 。刷新页面时访问的资源在服务端找不到,因为 react-router 设置的路径不是真实存在的路径。
所以那样设置是为了可以刷新还可以打到对应的路径的。

刷新出现 404 问题,可以看下这篇文章 react,vue等部署单页面项目时,访问刷新出现404问题

3.5 上传项目代码,或者用码云、 gihub 来拉取你的代码到服务器上

我是创建了码云的账号来管理项目代码的,因为码云上可以创建免费的私有仓库,我在本地把码上传到 Gitee.com 上,再进入服务器用 git 把代码拉取下来就可以了,非常方便。

具体请看:码云(Gitee.com)帮助文档 V1.2

git 的安装请看: CentOS 7.4 系统安装 git

如果不想用 git 进行代码管理,请用其他可以连接服务器上传文件的软件,比如 FileZilla。

3.6 启动 express 服务

启动 express 服务,我用了 pm2, 可以永久运行在服务器上,且不会一报错 express 服务就挂了,而且运行中还可以进行其他操作。

安装:

npm install -g pm2

切换当前工作目录到 express 应用文件夹下,执行 pm2 命令启动 express 服务:

pm2 start ./bin/www

比如我操作项目时的基本操作:

cd /home/blog/blog-node
pm2 start ./bin/www // 开启
pm2 stop ./bin/www // 关闭
pm2 list //查看所用已启动项目:

3.7 页面加载优化

再看刚刚的 nginx 的一些配置:

server {
        gzip on;
        gzip_buffers 32 4k;
        gzip_comp_level 6;
        gzip_min_length 200;
        gzip_types text/css text/xml application/javascript;
        gzip_vary on;
    }

这个就是利用 ngonx 开启 gzip,亲测开启之后,压缩了接近 2/3 的文件大小,本来要 1M 多的文件,开启压缩之后,变成了 300k 左右。

还有其他的优化请看这篇文章 React 16 加载性能优化指南,写的很不错,我的一些优化都是参考了这个篇文章的。

做完一系列的优化处理之后,在网络正常的情况下,页面首屏渲染由本来是接近 5 秒,变成了 3 秒内,首屏渲染之前的 loading 在 1 秒内可见了。

4. 项目地址

本人的个人博客项目地址:

前台展示: https://github.com/biaochenxuying/blog-react

管理后台:https://github.com/biaochenxuying/blog-react-admin

后端:https://github.com/biaochenxuying/blog-node

blog:https://github.com/biaochenxuying/blog

本博客系统的系列文章:

@biaochenxuying biaochenxuying added JavaScript JavaScript 相关知识点 node.js node.js MongoDB MongoDB labels Nov 25, 2018
@biaochenxuying biaochenxuying self-assigned this Nov 25, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
JavaScript JavaScript 相关知识点 MongoDB MongoDB node.js node.js
Projects
None yet
Development

No branches or pull requests

1 participant